* tree-ssa.c (target_for_debug_bind, verify_phi_args,
[official-gcc.git] / gcc / omp-low.c
blob202f0bd5f2a81890fc3f98b5b7e048dafcf5eccd
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 || TYPE_ATOMIC (TREE_TYPE (decl)))
1125 return true;
1127 /* We can only use copy-in/copy-out semantics for shared variables
1128 when we know the value is not accessible from an outer scope. */
1129 if (shared_ctx)
1131 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1133 /* ??? Trivially accessible from anywhere. But why would we even
1134 be passing an address in this case? Should we simply assert
1135 this to be false, or should we have a cleanup pass that removes
1136 these from the list of mappings? */
1137 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1138 return true;
1140 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1141 without analyzing the expression whether or not its location
1142 is accessible to anyone else. In the case of nested parallel
1143 regions it certainly may be. */
1144 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1145 return true;
1147 /* Do not use copy-in/copy-out for variables that have their
1148 address taken. */
1149 if (TREE_ADDRESSABLE (decl))
1150 return true;
1152 /* lower_send_shared_vars only uses copy-in, but not copy-out
1153 for these. */
1154 if (TREE_READONLY (decl)
1155 || ((TREE_CODE (decl) == RESULT_DECL
1156 || TREE_CODE (decl) == PARM_DECL)
1157 && DECL_BY_REFERENCE (decl)))
1158 return false;
1160 /* Disallow copy-in/out in nested parallel if
1161 decl is shared in outer parallel, otherwise
1162 each thread could store the shared variable
1163 in its own copy-in location, making the
1164 variable no longer really shared. */
1165 if (shared_ctx->is_nested)
1167 omp_context *up;
1169 for (up = shared_ctx->outer; up; up = up->outer)
1170 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1171 break;
1173 if (up)
1175 tree c;
1177 for (c = gimple_omp_taskreg_clauses (up->stmt);
1178 c; c = OMP_CLAUSE_CHAIN (c))
1179 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1180 && OMP_CLAUSE_DECL (c) == decl)
1181 break;
1183 if (c)
1184 goto maybe_mark_addressable_and_ret;
1188 /* For tasks avoid using copy-in/out. As tasks can be
1189 deferred or executed in different thread, when GOMP_task
1190 returns, the task hasn't necessarily terminated. */
1191 if (is_task_ctx (shared_ctx))
1193 tree outer;
1194 maybe_mark_addressable_and_ret:
1195 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1196 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1198 /* Taking address of OUTER in lower_send_shared_vars
1199 might need regimplification of everything that uses the
1200 variable. */
1201 if (!task_shared_vars)
1202 task_shared_vars = BITMAP_ALLOC (NULL);
1203 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1204 TREE_ADDRESSABLE (outer) = 1;
1206 return true;
1210 return false;
1213 /* Construct a new automatic decl similar to VAR. */
1215 static tree
1216 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1218 tree copy = copy_var_decl (var, name, type);
1220 DECL_CONTEXT (copy) = current_function_decl;
1221 DECL_CHAIN (copy) = ctx->block_vars;
1222 /* If VAR is listed in task_shared_vars, it means it wasn't
1223 originally addressable and is just because task needs to take
1224 it's address. But we don't need to take address of privatizations
1225 from that var. */
1226 if (TREE_ADDRESSABLE (var)
1227 && task_shared_vars
1228 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1229 TREE_ADDRESSABLE (copy) = 0;
1230 ctx->block_vars = copy;
1232 return copy;
1235 static tree
1236 omp_copy_decl_1 (tree var, omp_context *ctx)
1238 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1241 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1242 as appropriate. */
1243 static tree
1244 omp_build_component_ref (tree obj, tree field)
1246 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1247 if (TREE_THIS_VOLATILE (field))
1248 TREE_THIS_VOLATILE (ret) |= 1;
1249 if (TREE_READONLY (field))
1250 TREE_READONLY (ret) |= 1;
1251 return ret;
1254 /* Build tree nodes to access the field for VAR on the receiver side. */
1256 static tree
1257 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1259 tree x, field = lookup_field (var, ctx);
1261 /* If the receiver record type was remapped in the child function,
1262 remap the field into the new record type. */
1263 x = maybe_lookup_field (field, ctx);
1264 if (x != NULL)
1265 field = x;
1267 x = build_simple_mem_ref (ctx->receiver_decl);
1268 TREE_THIS_NOTRAP (x) = 1;
1269 x = omp_build_component_ref (x, field);
1270 if (by_ref)
1272 x = build_simple_mem_ref (x);
1273 TREE_THIS_NOTRAP (x) = 1;
1276 return x;
1279 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1280 of a parallel, this is a component reference; for workshare constructs
1281 this is some variable. */
1283 static tree
1284 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1286 tree x;
1288 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1289 x = var;
1290 else if (is_variable_sized (var))
1292 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1293 x = build_outer_var_ref (x, ctx, lastprivate);
1294 x = build_simple_mem_ref (x);
1296 else if (is_taskreg_ctx (ctx))
1298 bool by_ref = use_pointer_for_field (var, NULL);
1299 x = build_receiver_ref (var, by_ref, ctx);
1301 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1302 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1304 /* #pragma omp simd isn't a worksharing construct, and can reference even
1305 private vars in its linear etc. clauses. */
1306 x = NULL_TREE;
1307 if (ctx->outer && is_taskreg_ctx (ctx))
1308 x = lookup_decl (var, ctx->outer);
1309 else if (ctx->outer)
1310 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1311 if (x == NULL_TREE)
1312 x = var;
1314 else if (lastprivate && is_taskloop_ctx (ctx))
1316 gcc_assert (ctx->outer);
1317 splay_tree_node n
1318 = splay_tree_lookup (ctx->outer->field_map,
1319 (splay_tree_key) &DECL_UID (var));
1320 if (n == NULL)
1322 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1323 x = var;
1324 else
1325 x = lookup_decl (var, ctx->outer);
1327 else
1329 tree field = (tree) n->value;
1330 /* If the receiver record type was remapped in the child function,
1331 remap the field into the new record type. */
1332 x = maybe_lookup_field (field, ctx->outer);
1333 if (x != NULL)
1334 field = x;
1336 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1337 x = omp_build_component_ref (x, field);
1338 if (use_pointer_for_field (var, ctx->outer))
1339 x = build_simple_mem_ref (x);
1342 else if (ctx->outer)
1344 omp_context *outer = ctx->outer;
1345 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1347 outer = outer->outer;
1348 gcc_assert (outer
1349 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1351 x = lookup_decl (var, outer);
1353 else if (is_reference (var))
1354 /* This can happen with orphaned constructs. If var is reference, it is
1355 possible it is shared and as such valid. */
1356 x = var;
1357 else if (omp_member_access_dummy_var (var))
1358 x = var;
1359 else
1360 gcc_unreachable ();
1362 if (x == var)
1364 tree t = omp_member_access_dummy_var (var);
1365 if (t)
1367 x = DECL_VALUE_EXPR (var);
1368 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1369 if (o != t)
1370 x = unshare_and_remap (x, t, o);
1371 else
1372 x = unshare_expr (x);
1376 if (is_reference (var))
1377 x = build_simple_mem_ref (x);
1379 return x;
1382 /* Build tree nodes to access the field for VAR on the sender side. */
1384 static tree
1385 build_sender_ref (splay_tree_key key, omp_context *ctx)
1387 tree field = lookup_sfield (key, ctx);
1388 return omp_build_component_ref (ctx->sender_decl, field);
1391 static tree
1392 build_sender_ref (tree var, omp_context *ctx)
1394 return build_sender_ref ((splay_tree_key) var, ctx);
1397 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1398 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1400 static void
1401 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1402 bool base_pointers_restrict = false)
1404 tree field, type, sfield = NULL_TREE;
1405 splay_tree_key key = (splay_tree_key) var;
1407 if ((mask & 8) != 0)
1409 key = (splay_tree_key) &DECL_UID (var);
1410 gcc_checking_assert (key != (splay_tree_key) var);
1412 gcc_assert ((mask & 1) == 0
1413 || !splay_tree_lookup (ctx->field_map, key));
1414 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1415 || !splay_tree_lookup (ctx->sfield_map, key));
1416 gcc_assert ((mask & 3) == 3
1417 || !is_gimple_omp_oacc (ctx->stmt));
1419 type = TREE_TYPE (var);
1420 /* Prevent redeclaring the var in the split-off function with a restrict
1421 pointer type. Note that we only clear type itself, restrict qualifiers in
1422 the pointed-to type will be ignored by points-to analysis. */
1423 if (POINTER_TYPE_P (type)
1424 && TYPE_RESTRICT (type))
1425 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1427 if (mask & 4)
1429 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1430 type = build_pointer_type (build_pointer_type (type));
1432 else if (by_ref)
1434 type = build_pointer_type (type);
1435 if (base_pointers_restrict)
1436 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1438 else if ((mask & 3) == 1 && is_reference (var))
1439 type = TREE_TYPE (type);
1441 field = build_decl (DECL_SOURCE_LOCATION (var),
1442 FIELD_DECL, DECL_NAME (var), type);
1444 /* Remember what variable this field was created for. This does have a
1445 side effect of making dwarf2out ignore this member, so for helpful
1446 debugging we clear it later in delete_omp_context. */
1447 DECL_ABSTRACT_ORIGIN (field) = var;
1448 if (type == TREE_TYPE (var))
1450 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1451 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1452 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1454 else
1455 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1457 if ((mask & 3) == 3)
1459 insert_field_into_struct (ctx->record_type, field);
1460 if (ctx->srecord_type)
1462 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1463 FIELD_DECL, DECL_NAME (var), type);
1464 DECL_ABSTRACT_ORIGIN (sfield) = var;
1465 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1466 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1467 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1468 insert_field_into_struct (ctx->srecord_type, sfield);
1471 else
1473 if (ctx->srecord_type == NULL_TREE)
1475 tree t;
1477 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1478 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1479 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1481 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1482 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1483 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1484 insert_field_into_struct (ctx->srecord_type, sfield);
1485 splay_tree_insert (ctx->sfield_map,
1486 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1487 (splay_tree_value) sfield);
1490 sfield = field;
1491 insert_field_into_struct ((mask & 1) ? ctx->record_type
1492 : ctx->srecord_type, field);
1495 if (mask & 1)
1496 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1497 if ((mask & 2) && ctx->sfield_map)
1498 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1501 static tree
1502 install_var_local (tree var, omp_context *ctx)
1504 tree new_var = omp_copy_decl_1 (var, ctx);
1505 insert_decl_map (&ctx->cb, var, new_var);
1506 return new_var;
1509 /* Adjust the replacement for DECL in CTX for the new context. This means
1510 copying the DECL_VALUE_EXPR, and fixing up the type. */
1512 static void
1513 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1515 tree new_decl, size;
1517 new_decl = lookup_decl (decl, ctx);
1519 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1521 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1522 && DECL_HAS_VALUE_EXPR_P (decl))
1524 tree ve = DECL_VALUE_EXPR (decl);
1525 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1526 SET_DECL_VALUE_EXPR (new_decl, ve);
1527 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1530 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1532 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1533 if (size == error_mark_node)
1534 size = TYPE_SIZE (TREE_TYPE (new_decl));
1535 DECL_SIZE (new_decl) = size;
1537 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1538 if (size == error_mark_node)
1539 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1540 DECL_SIZE_UNIT (new_decl) = size;
1544 /* The callback for remap_decl. Search all containing contexts for a
1545 mapping of the variable; this avoids having to duplicate the splay
1546 tree ahead of time. We know a mapping doesn't already exist in the
1547 given context. Create new mappings to implement default semantics. */
1549 static tree
1550 omp_copy_decl (tree var, copy_body_data *cb)
1552 omp_context *ctx = (omp_context *) cb;
1553 tree new_var;
1555 if (TREE_CODE (var) == LABEL_DECL)
1557 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1558 DECL_CONTEXT (new_var) = current_function_decl;
1559 insert_decl_map (&ctx->cb, var, new_var);
1560 return new_var;
1563 while (!is_taskreg_ctx (ctx))
1565 ctx = ctx->outer;
1566 if (ctx == NULL)
1567 return var;
1568 new_var = maybe_lookup_decl (var, ctx);
1569 if (new_var)
1570 return new_var;
1573 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1574 return var;
1576 return error_mark_node;
1580 /* Debugging dumps for parallel regions. */
1581 void dump_omp_region (FILE *, struct omp_region *, int);
1582 void debug_omp_region (struct omp_region *);
1583 void debug_all_omp_regions (void);
1585 /* Dump the parallel region tree rooted at REGION. */
1587 void
1588 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1590 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1591 gimple_code_name[region->type]);
1593 if (region->inner)
1594 dump_omp_region (file, region->inner, indent + 4);
1596 if (region->cont)
1598 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1599 region->cont->index);
1602 if (region->exit)
1603 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1604 region->exit->index);
1605 else
1606 fprintf (file, "%*s[no exit marker]\n", indent, "");
1608 if (region->next)
1609 dump_omp_region (file, region->next, indent);
1612 DEBUG_FUNCTION void
1613 debug_omp_region (struct omp_region *region)
1615 dump_omp_region (stderr, region, 0);
1618 DEBUG_FUNCTION void
1619 debug_all_omp_regions (void)
1621 dump_omp_region (stderr, root_omp_region, 0);
1625 /* Create a new parallel region starting at STMT inside region PARENT. */
1627 static struct omp_region *
1628 new_omp_region (basic_block bb, enum gimple_code type,
1629 struct omp_region *parent)
1631 struct omp_region *region = XCNEW (struct omp_region);
1633 region->outer = parent;
1634 region->entry = bb;
1635 region->type = type;
1637 if (parent)
1639 /* This is a nested region. Add it to the list of inner
1640 regions in PARENT. */
1641 region->next = parent->inner;
1642 parent->inner = region;
1644 else
1646 /* This is a toplevel region. Add it to the list of toplevel
1647 regions in ROOT_OMP_REGION. */
1648 region->next = root_omp_region;
1649 root_omp_region = region;
1652 return region;
1655 /* Release the memory associated with the region tree rooted at REGION. */
1657 static void
1658 free_omp_region_1 (struct omp_region *region)
1660 struct omp_region *i, *n;
1662 for (i = region->inner; i ; i = n)
1664 n = i->next;
1665 free_omp_region_1 (i);
1668 free (region);
1671 /* Release the memory for the entire omp region tree. */
1673 void
1674 free_omp_regions (void)
1676 struct omp_region *r, *n;
1677 for (r = root_omp_region; r ; r = n)
1679 n = r->next;
1680 free_omp_region_1 (r);
1682 root_omp_region = NULL;
1686 /* Create a new context, with OUTER_CTX being the surrounding context. */
1688 static omp_context *
1689 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1691 omp_context *ctx = XCNEW (omp_context);
1693 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1694 (splay_tree_value) ctx);
1695 ctx->stmt = stmt;
1697 if (outer_ctx)
1699 ctx->outer = outer_ctx;
1700 ctx->cb = outer_ctx->cb;
1701 ctx->cb.block = NULL;
1702 ctx->depth = outer_ctx->depth + 1;
1704 else
1706 ctx->cb.src_fn = current_function_decl;
1707 ctx->cb.dst_fn = current_function_decl;
1708 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1709 gcc_checking_assert (ctx->cb.src_node);
1710 ctx->cb.dst_node = ctx->cb.src_node;
1711 ctx->cb.src_cfun = cfun;
1712 ctx->cb.copy_decl = omp_copy_decl;
1713 ctx->cb.eh_lp_nr = 0;
1714 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1715 ctx->depth = 1;
1718 ctx->cb.decl_map = new hash_map<tree, tree>;
1720 return ctx;
1723 static gimple_seq maybe_catch_exception (gimple_seq);
1725 /* Finalize task copyfn. */
1727 static void
1728 finalize_task_copyfn (gomp_task *task_stmt)
1730 struct function *child_cfun;
1731 tree child_fn;
1732 gimple_seq seq = NULL, new_seq;
1733 gbind *bind;
1735 child_fn = gimple_omp_task_copy_fn (task_stmt);
1736 if (child_fn == NULL_TREE)
1737 return;
1739 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1740 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1742 push_cfun (child_cfun);
1743 bind = gimplify_body (child_fn, false);
1744 gimple_seq_add_stmt (&seq, bind);
1745 new_seq = maybe_catch_exception (seq);
1746 if (new_seq != seq)
1748 bind = gimple_build_bind (NULL, new_seq, NULL);
1749 seq = NULL;
1750 gimple_seq_add_stmt (&seq, bind);
1752 gimple_set_body (child_fn, seq);
1753 pop_cfun ();
1755 /* Inform the callgraph about the new function. */
1756 cgraph_node *node = cgraph_node::get_create (child_fn);
1757 node->parallelized_function = 1;
1758 cgraph_node::add_new_function (child_fn, false);
1761 /* Destroy a omp_context data structures. Called through the splay tree
1762 value delete callback. */
1764 static void
1765 delete_omp_context (splay_tree_value value)
1767 omp_context *ctx = (omp_context *) value;
1769 delete ctx->cb.decl_map;
1771 if (ctx->field_map)
1772 splay_tree_delete (ctx->field_map);
1773 if (ctx->sfield_map)
1774 splay_tree_delete (ctx->sfield_map);
1776 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1777 it produces corrupt debug information. */
1778 if (ctx->record_type)
1780 tree t;
1781 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1782 DECL_ABSTRACT_ORIGIN (t) = NULL;
1784 if (ctx->srecord_type)
1786 tree t;
1787 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1788 DECL_ABSTRACT_ORIGIN (t) = NULL;
1791 if (is_task_ctx (ctx))
1792 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1794 XDELETE (ctx);
1797 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1798 context. */
1800 static void
1801 fixup_child_record_type (omp_context *ctx)
1803 tree f, type = ctx->record_type;
1805 if (!ctx->receiver_decl)
1806 return;
1807 /* ??? It isn't sufficient to just call remap_type here, because
1808 variably_modified_type_p doesn't work the way we expect for
1809 record types. Testing each field for whether it needs remapping
1810 and creating a new record by hand works, however. */
1811 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1812 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1813 break;
1814 if (f)
1816 tree name, new_fields = NULL;
1818 type = lang_hooks.types.make_type (RECORD_TYPE);
1819 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1820 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1821 TYPE_DECL, name, type);
1822 TYPE_NAME (type) = name;
1824 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1826 tree new_f = copy_node (f);
1827 DECL_CONTEXT (new_f) = type;
1828 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1829 DECL_CHAIN (new_f) = new_fields;
1830 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1831 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1832 &ctx->cb, NULL);
1833 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1834 &ctx->cb, NULL);
1835 new_fields = new_f;
1837 /* Arrange to be able to look up the receiver field
1838 given the sender field. */
1839 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1840 (splay_tree_value) new_f);
1842 TYPE_FIELDS (type) = nreverse (new_fields);
1843 layout_type (type);
1846 /* In a target region we never modify any of the pointers in *.omp_data_i,
1847 so attempt to help the optimizers. */
1848 if (is_gimple_omp_offloaded (ctx->stmt))
1849 type = build_qualified_type (type, TYPE_QUAL_CONST);
1851 TREE_TYPE (ctx->receiver_decl)
1852 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1855 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1856 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1857 restrict. */
1859 static void
1860 scan_sharing_clauses (tree clauses, omp_context *ctx,
1861 bool base_pointers_restrict = false)
1863 tree c, decl;
1864 bool scan_array_reductions = false;
1866 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1868 bool by_ref;
1870 switch (OMP_CLAUSE_CODE (c))
1872 case OMP_CLAUSE_PRIVATE:
1873 decl = OMP_CLAUSE_DECL (c);
1874 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1875 goto do_private;
1876 else if (!is_variable_sized (decl))
1877 install_var_local (decl, ctx);
1878 break;
1880 case OMP_CLAUSE_SHARED:
1881 decl = OMP_CLAUSE_DECL (c);
1882 /* Ignore shared directives in teams construct. */
1883 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1885 /* Global variables don't need to be copied,
1886 the receiver side will use them directly. */
1887 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1888 if (is_global_var (odecl))
1889 break;
1890 insert_decl_map (&ctx->cb, decl, odecl);
1891 break;
1893 gcc_assert (is_taskreg_ctx (ctx));
1894 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1895 || !is_variable_sized (decl));
1896 /* Global variables don't need to be copied,
1897 the receiver side will use them directly. */
1898 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1899 break;
1900 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1902 use_pointer_for_field (decl, ctx);
1903 break;
1905 by_ref = use_pointer_for_field (decl, NULL);
1906 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1907 || TREE_ADDRESSABLE (decl)
1908 || by_ref
1909 || is_reference (decl))
1911 by_ref = use_pointer_for_field (decl, ctx);
1912 install_var_field (decl, by_ref, 3, ctx);
1913 install_var_local (decl, ctx);
1914 break;
1916 /* We don't need to copy const scalar vars back. */
1917 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1918 goto do_private;
1920 case OMP_CLAUSE_REDUCTION:
1921 decl = OMP_CLAUSE_DECL (c);
1922 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1923 && TREE_CODE (decl) == MEM_REF)
1925 tree t = TREE_OPERAND (decl, 0);
1926 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1927 t = TREE_OPERAND (t, 0);
1928 if (TREE_CODE (t) == INDIRECT_REF
1929 || TREE_CODE (t) == ADDR_EXPR)
1930 t = TREE_OPERAND (t, 0);
1931 install_var_local (t, ctx);
1932 if (is_taskreg_ctx (ctx)
1933 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1934 && !is_variable_sized (t))
1936 by_ref = use_pointer_for_field (t, ctx);
1937 install_var_field (t, by_ref, 3, ctx);
1939 break;
1941 goto do_private;
1943 case OMP_CLAUSE_LASTPRIVATE:
1944 /* Let the corresponding firstprivate clause create
1945 the variable. */
1946 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1947 break;
1948 /* FALLTHRU */
1950 case OMP_CLAUSE_FIRSTPRIVATE:
1951 case OMP_CLAUSE_LINEAR:
1952 decl = OMP_CLAUSE_DECL (c);
1953 do_private:
1954 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1955 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1956 && is_gimple_omp_offloaded (ctx->stmt))
1958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1959 install_var_field (decl, !is_reference (decl), 3, ctx);
1960 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1961 install_var_field (decl, true, 3, ctx);
1962 else
1963 install_var_field (decl, false, 3, ctx);
1965 if (is_variable_sized (decl))
1967 if (is_task_ctx (ctx))
1968 install_var_field (decl, false, 1, ctx);
1969 break;
1971 else if (is_taskreg_ctx (ctx))
1973 bool global
1974 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1975 by_ref = use_pointer_for_field (decl, NULL);
1977 if (is_task_ctx (ctx)
1978 && (global || by_ref || is_reference (decl)))
1980 install_var_field (decl, false, 1, ctx);
1981 if (!global)
1982 install_var_field (decl, by_ref, 2, ctx);
1984 else if (!global)
1985 install_var_field (decl, by_ref, 3, ctx);
1987 install_var_local (decl, ctx);
1988 break;
1990 case OMP_CLAUSE_USE_DEVICE_PTR:
1991 decl = OMP_CLAUSE_DECL (c);
1992 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1993 install_var_field (decl, true, 3, ctx);
1994 else
1995 install_var_field (decl, false, 3, ctx);
1996 if (DECL_SIZE (decl)
1997 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1999 tree decl2 = DECL_VALUE_EXPR (decl);
2000 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2001 decl2 = TREE_OPERAND (decl2, 0);
2002 gcc_assert (DECL_P (decl2));
2003 install_var_local (decl2, ctx);
2005 install_var_local (decl, ctx);
2006 break;
2008 case OMP_CLAUSE_IS_DEVICE_PTR:
2009 decl = OMP_CLAUSE_DECL (c);
2010 goto do_private;
2012 case OMP_CLAUSE__LOOPTEMP_:
2013 gcc_assert (is_taskreg_ctx (ctx));
2014 decl = OMP_CLAUSE_DECL (c);
2015 install_var_field (decl, false, 3, ctx);
2016 install_var_local (decl, ctx);
2017 break;
2019 case OMP_CLAUSE_COPYPRIVATE:
2020 case OMP_CLAUSE_COPYIN:
2021 decl = OMP_CLAUSE_DECL (c);
2022 by_ref = use_pointer_for_field (decl, NULL);
2023 install_var_field (decl, by_ref, 3, ctx);
2024 break;
2026 case OMP_CLAUSE_DEFAULT:
2027 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2028 break;
2030 case OMP_CLAUSE_FINAL:
2031 case OMP_CLAUSE_IF:
2032 case OMP_CLAUSE_NUM_THREADS:
2033 case OMP_CLAUSE_NUM_TEAMS:
2034 case OMP_CLAUSE_THREAD_LIMIT:
2035 case OMP_CLAUSE_DEVICE:
2036 case OMP_CLAUSE_SCHEDULE:
2037 case OMP_CLAUSE_DIST_SCHEDULE:
2038 case OMP_CLAUSE_DEPEND:
2039 case OMP_CLAUSE_PRIORITY:
2040 case OMP_CLAUSE_GRAINSIZE:
2041 case OMP_CLAUSE_NUM_TASKS:
2042 case OMP_CLAUSE__CILK_FOR_COUNT_:
2043 case OMP_CLAUSE_NUM_GANGS:
2044 case OMP_CLAUSE_NUM_WORKERS:
2045 case OMP_CLAUSE_VECTOR_LENGTH:
2046 if (ctx->outer)
2047 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2048 break;
2050 case OMP_CLAUSE_TO:
2051 case OMP_CLAUSE_FROM:
2052 case OMP_CLAUSE_MAP:
2053 if (ctx->outer)
2054 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2055 decl = OMP_CLAUSE_DECL (c);
2056 /* Global variables with "omp declare target" attribute
2057 don't need to be copied, the receiver side will use them
2058 directly. However, global variables with "omp declare target link"
2059 attribute need to be copied. */
2060 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2061 && DECL_P (decl)
2062 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2063 && (OMP_CLAUSE_MAP_KIND (c)
2064 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2065 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2066 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2067 && varpool_node::get_create (decl)->offloadable
2068 && !lookup_attribute ("omp declare target link",
2069 DECL_ATTRIBUTES (decl)))
2070 break;
2071 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2072 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2074 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2075 not offloaded; there is nothing to map for those. */
2076 if (!is_gimple_omp_offloaded (ctx->stmt)
2077 && !POINTER_TYPE_P (TREE_TYPE (decl))
2078 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2079 break;
2081 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2082 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2083 || (OMP_CLAUSE_MAP_KIND (c)
2084 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2086 if (TREE_CODE (decl) == COMPONENT_REF
2087 || (TREE_CODE (decl) == INDIRECT_REF
2088 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2089 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2090 == REFERENCE_TYPE)))
2091 break;
2092 if (DECL_SIZE (decl)
2093 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2095 tree decl2 = DECL_VALUE_EXPR (decl);
2096 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2097 decl2 = TREE_OPERAND (decl2, 0);
2098 gcc_assert (DECL_P (decl2));
2099 install_var_local (decl2, ctx);
2101 install_var_local (decl, ctx);
2102 break;
2104 if (DECL_P (decl))
2106 if (DECL_SIZE (decl)
2107 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2109 tree decl2 = DECL_VALUE_EXPR (decl);
2110 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2111 decl2 = TREE_OPERAND (decl2, 0);
2112 gcc_assert (DECL_P (decl2));
2113 install_var_field (decl2, true, 3, ctx);
2114 install_var_local (decl2, ctx);
2115 install_var_local (decl, ctx);
2117 else
2119 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2120 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2121 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2122 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2123 install_var_field (decl, true, 7, ctx);
2124 else
2125 install_var_field (decl, true, 3, ctx,
2126 base_pointers_restrict);
2127 if (is_gimple_omp_offloaded (ctx->stmt)
2128 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2129 install_var_local (decl, ctx);
2132 else
2134 tree base = get_base_address (decl);
2135 tree nc = OMP_CLAUSE_CHAIN (c);
2136 if (DECL_P (base)
2137 && nc != NULL_TREE
2138 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2139 && OMP_CLAUSE_DECL (nc) == base
2140 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2141 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2144 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2146 else
2148 if (ctx->outer)
2150 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2151 decl = OMP_CLAUSE_DECL (c);
2153 gcc_assert (!splay_tree_lookup (ctx->field_map,
2154 (splay_tree_key) decl));
2155 tree field
2156 = build_decl (OMP_CLAUSE_LOCATION (c),
2157 FIELD_DECL, NULL_TREE, ptr_type_node);
2158 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2159 insert_field_into_struct (ctx->record_type, field);
2160 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2161 (splay_tree_value) field);
2164 break;
2166 case OMP_CLAUSE__GRIDDIM_:
2167 if (ctx->outer)
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2170 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2172 break;
2174 case OMP_CLAUSE_NOWAIT:
2175 case OMP_CLAUSE_ORDERED:
2176 case OMP_CLAUSE_COLLAPSE:
2177 case OMP_CLAUSE_UNTIED:
2178 case OMP_CLAUSE_MERGEABLE:
2179 case OMP_CLAUSE_PROC_BIND:
2180 case OMP_CLAUSE_SAFELEN:
2181 case OMP_CLAUSE_SIMDLEN:
2182 case OMP_CLAUSE_THREADS:
2183 case OMP_CLAUSE_SIMD:
2184 case OMP_CLAUSE_NOGROUP:
2185 case OMP_CLAUSE_DEFAULTMAP:
2186 case OMP_CLAUSE_ASYNC:
2187 case OMP_CLAUSE_WAIT:
2188 case OMP_CLAUSE_GANG:
2189 case OMP_CLAUSE_WORKER:
2190 case OMP_CLAUSE_VECTOR:
2191 case OMP_CLAUSE_INDEPENDENT:
2192 case OMP_CLAUSE_AUTO:
2193 case OMP_CLAUSE_SEQ:
2194 break;
2196 case OMP_CLAUSE_ALIGNED:
2197 decl = OMP_CLAUSE_DECL (c);
2198 if (is_global_var (decl)
2199 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2200 install_var_local (decl, ctx);
2201 break;
2203 case OMP_CLAUSE_TILE:
2204 case OMP_CLAUSE__CACHE_:
2205 default:
2206 gcc_unreachable ();
2210 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2212 switch (OMP_CLAUSE_CODE (c))
2214 case OMP_CLAUSE_LASTPRIVATE:
2215 /* Let the corresponding firstprivate clause create
2216 the variable. */
2217 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2218 scan_array_reductions = true;
2219 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2220 break;
2221 /* FALLTHRU */
2223 case OMP_CLAUSE_FIRSTPRIVATE:
2224 case OMP_CLAUSE_PRIVATE:
2225 case OMP_CLAUSE_LINEAR:
2226 case OMP_CLAUSE_IS_DEVICE_PTR:
2227 decl = OMP_CLAUSE_DECL (c);
2228 if (is_variable_sized (decl))
2230 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2231 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2232 && is_gimple_omp_offloaded (ctx->stmt))
2234 tree decl2 = DECL_VALUE_EXPR (decl);
2235 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2236 decl2 = TREE_OPERAND (decl2, 0);
2237 gcc_assert (DECL_P (decl2));
2238 install_var_local (decl2, ctx);
2239 fixup_remapped_decl (decl2, ctx, false);
2241 install_var_local (decl, ctx);
2243 fixup_remapped_decl (decl, ctx,
2244 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2245 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2246 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2247 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2248 scan_array_reductions = true;
2249 break;
2251 case OMP_CLAUSE_REDUCTION:
2252 decl = OMP_CLAUSE_DECL (c);
2253 if (TREE_CODE (decl) != MEM_REF)
2255 if (is_variable_sized (decl))
2256 install_var_local (decl, ctx);
2257 fixup_remapped_decl (decl, ctx, false);
2259 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2260 scan_array_reductions = true;
2261 break;
2263 case OMP_CLAUSE_SHARED:
2264 /* Ignore shared directives in teams construct. */
2265 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2266 break;
2267 decl = OMP_CLAUSE_DECL (c);
2268 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2269 break;
2270 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2272 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2273 ctx->outer)))
2274 break;
2275 bool by_ref = use_pointer_for_field (decl, ctx);
2276 install_var_field (decl, by_ref, 11, ctx);
2277 break;
2279 fixup_remapped_decl (decl, ctx, false);
2280 break;
2282 case OMP_CLAUSE_MAP:
2283 if (!is_gimple_omp_offloaded (ctx->stmt))
2284 break;
2285 decl = OMP_CLAUSE_DECL (c);
2286 if (DECL_P (decl)
2287 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2288 && (OMP_CLAUSE_MAP_KIND (c)
2289 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2290 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2291 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2292 && varpool_node::get_create (decl)->offloadable)
2293 break;
2294 if (DECL_P (decl))
2296 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2297 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2298 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2299 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2301 tree new_decl = lookup_decl (decl, ctx);
2302 TREE_TYPE (new_decl)
2303 = remap_type (TREE_TYPE (decl), &ctx->cb);
2305 else if (DECL_SIZE (decl)
2306 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2308 tree decl2 = DECL_VALUE_EXPR (decl);
2309 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2310 decl2 = TREE_OPERAND (decl2, 0);
2311 gcc_assert (DECL_P (decl2));
2312 fixup_remapped_decl (decl2, ctx, false);
2313 fixup_remapped_decl (decl, ctx, true);
2315 else
2316 fixup_remapped_decl (decl, ctx, false);
2318 break;
2320 case OMP_CLAUSE_COPYPRIVATE:
2321 case OMP_CLAUSE_COPYIN:
2322 case OMP_CLAUSE_DEFAULT:
2323 case OMP_CLAUSE_IF:
2324 case OMP_CLAUSE_NUM_THREADS:
2325 case OMP_CLAUSE_NUM_TEAMS:
2326 case OMP_CLAUSE_THREAD_LIMIT:
2327 case OMP_CLAUSE_DEVICE:
2328 case OMP_CLAUSE_SCHEDULE:
2329 case OMP_CLAUSE_DIST_SCHEDULE:
2330 case OMP_CLAUSE_NOWAIT:
2331 case OMP_CLAUSE_ORDERED:
2332 case OMP_CLAUSE_COLLAPSE:
2333 case OMP_CLAUSE_UNTIED:
2334 case OMP_CLAUSE_FINAL:
2335 case OMP_CLAUSE_MERGEABLE:
2336 case OMP_CLAUSE_PROC_BIND:
2337 case OMP_CLAUSE_SAFELEN:
2338 case OMP_CLAUSE_SIMDLEN:
2339 case OMP_CLAUSE_ALIGNED:
2340 case OMP_CLAUSE_DEPEND:
2341 case OMP_CLAUSE__LOOPTEMP_:
2342 case OMP_CLAUSE_TO:
2343 case OMP_CLAUSE_FROM:
2344 case OMP_CLAUSE_PRIORITY:
2345 case OMP_CLAUSE_GRAINSIZE:
2346 case OMP_CLAUSE_NUM_TASKS:
2347 case OMP_CLAUSE_THREADS:
2348 case OMP_CLAUSE_SIMD:
2349 case OMP_CLAUSE_NOGROUP:
2350 case OMP_CLAUSE_DEFAULTMAP:
2351 case OMP_CLAUSE_USE_DEVICE_PTR:
2352 case OMP_CLAUSE__CILK_FOR_COUNT_:
2353 case OMP_CLAUSE_ASYNC:
2354 case OMP_CLAUSE_WAIT:
2355 case OMP_CLAUSE_NUM_GANGS:
2356 case OMP_CLAUSE_NUM_WORKERS:
2357 case OMP_CLAUSE_VECTOR_LENGTH:
2358 case OMP_CLAUSE_GANG:
2359 case OMP_CLAUSE_WORKER:
2360 case OMP_CLAUSE_VECTOR:
2361 case OMP_CLAUSE_INDEPENDENT:
2362 case OMP_CLAUSE_AUTO:
2363 case OMP_CLAUSE_SEQ:
2364 case OMP_CLAUSE__GRIDDIM_:
2365 break;
2367 case OMP_CLAUSE_TILE:
2368 case OMP_CLAUSE__CACHE_:
2369 default:
2370 gcc_unreachable ();
2374 gcc_checking_assert (!scan_array_reductions
2375 || !is_gimple_omp_oacc (ctx->stmt));
2376 if (scan_array_reductions)
2378 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2379 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2380 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2383 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2385 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2386 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2387 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2388 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2389 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2390 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2394 /* Create a new name for omp child function. Returns an identifier. If
2395 IS_CILK_FOR is true then the suffix for the child function is
2396 "_cilk_for_fn." */
2398 static tree
2399 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2401 if (is_cilk_for)
2402 return clone_function_name (current_function_decl, "_cilk_for_fn");
2403 return clone_function_name (current_function_decl,
2404 task_copy ? "_omp_cpyfn" : "_omp_fn");
2407 /* Returns the type of the induction variable for the child function for
2408 _Cilk_for and the types for _high and _low variables based on TYPE. */
2410 static tree
2411 cilk_for_check_loop_diff_type (tree type)
2413 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2415 if (TYPE_UNSIGNED (type))
2416 return uint32_type_node;
2417 else
2418 return integer_type_node;
2420 else
2422 if (TYPE_UNSIGNED (type))
2423 return uint64_type_node;
2424 else
2425 return long_long_integer_type_node;
2429 /* Build a decl for the omp child function. It'll not contain a body
2430 yet, just the bare decl. */
2432 static void
2433 create_omp_child_function (omp_context *ctx, bool task_copy)
2435 tree decl, type, name, t;
2437 tree cilk_for_count
2438 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2439 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2440 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2441 tree cilk_var_type = NULL_TREE;
2443 name = create_omp_child_function_name (task_copy,
2444 cilk_for_count != NULL_TREE);
2445 if (task_copy)
2446 type = build_function_type_list (void_type_node, ptr_type_node,
2447 ptr_type_node, NULL_TREE);
2448 else if (cilk_for_count)
2450 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2451 cilk_var_type = cilk_for_check_loop_diff_type (type);
2452 type = build_function_type_list (void_type_node, ptr_type_node,
2453 cilk_var_type, cilk_var_type, NULL_TREE);
2455 else
2456 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2458 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2460 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2461 || !task_copy);
2462 if (!task_copy)
2463 ctx->cb.dst_fn = decl;
2464 else
2465 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2467 TREE_STATIC (decl) = 1;
2468 TREE_USED (decl) = 1;
2469 DECL_ARTIFICIAL (decl) = 1;
2470 DECL_IGNORED_P (decl) = 0;
2471 TREE_PUBLIC (decl) = 0;
2472 DECL_UNINLINABLE (decl) = 1;
2473 DECL_EXTERNAL (decl) = 0;
2474 DECL_CONTEXT (decl) = NULL_TREE;
2475 DECL_INITIAL (decl) = make_node (BLOCK);
2476 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2477 if (cgraph_node::get (current_function_decl)->offloadable)
2478 cgraph_node::get_create (decl)->offloadable = 1;
2479 else
2481 omp_context *octx;
2482 for (octx = ctx; octx; octx = octx->outer)
2483 if (is_gimple_omp_offloaded (octx->stmt))
2485 cgraph_node::get_create (decl)->offloadable = 1;
2486 if (ENABLE_OFFLOADING)
2487 g->have_offload = true;
2489 break;
2493 if (cgraph_node::get_create (decl)->offloadable
2494 && !lookup_attribute ("omp declare target",
2495 DECL_ATTRIBUTES (current_function_decl)))
2496 DECL_ATTRIBUTES (decl)
2497 = tree_cons (get_identifier ("omp target entrypoint"),
2498 NULL_TREE, DECL_ATTRIBUTES (decl));
2500 t = build_decl (DECL_SOURCE_LOCATION (decl),
2501 RESULT_DECL, NULL_TREE, void_type_node);
2502 DECL_ARTIFICIAL (t) = 1;
2503 DECL_IGNORED_P (t) = 1;
2504 DECL_CONTEXT (t) = decl;
2505 DECL_RESULT (decl) = t;
2507 /* _Cilk_for's child function requires two extra parameters called
2508 __low and __high that are set the by Cilk runtime when it calls this
2509 function. */
2510 if (cilk_for_count)
2512 t = build_decl (DECL_SOURCE_LOCATION (decl),
2513 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2514 DECL_ARTIFICIAL (t) = 1;
2515 DECL_NAMELESS (t) = 1;
2516 DECL_ARG_TYPE (t) = ptr_type_node;
2517 DECL_CONTEXT (t) = current_function_decl;
2518 TREE_USED (t) = 1;
2519 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2520 DECL_ARGUMENTS (decl) = t;
2522 t = build_decl (DECL_SOURCE_LOCATION (decl),
2523 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2524 DECL_ARTIFICIAL (t) = 1;
2525 DECL_NAMELESS (t) = 1;
2526 DECL_ARG_TYPE (t) = ptr_type_node;
2527 DECL_CONTEXT (t) = current_function_decl;
2528 TREE_USED (t) = 1;
2529 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2530 DECL_ARGUMENTS (decl) = t;
2533 tree data_name = get_identifier (".omp_data_i");
2534 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2535 ptr_type_node);
2536 DECL_ARTIFICIAL (t) = 1;
2537 DECL_NAMELESS (t) = 1;
2538 DECL_ARG_TYPE (t) = ptr_type_node;
2539 DECL_CONTEXT (t) = current_function_decl;
2540 TREE_USED (t) = 1;
2541 TREE_READONLY (t) = 1;
2542 if (cilk_for_count)
2543 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2544 DECL_ARGUMENTS (decl) = t;
2545 if (!task_copy)
2546 ctx->receiver_decl = t;
2547 else
2549 t = build_decl (DECL_SOURCE_LOCATION (decl),
2550 PARM_DECL, get_identifier (".omp_data_o"),
2551 ptr_type_node);
2552 DECL_ARTIFICIAL (t) = 1;
2553 DECL_NAMELESS (t) = 1;
2554 DECL_ARG_TYPE (t) = ptr_type_node;
2555 DECL_CONTEXT (t) = current_function_decl;
2556 TREE_USED (t) = 1;
2557 TREE_ADDRESSABLE (t) = 1;
2558 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2559 DECL_ARGUMENTS (decl) = t;
2562 /* Allocate memory for the function structure. The call to
2563 allocate_struct_function clobbers CFUN, so we need to restore
2564 it afterward. */
2565 push_struct_function (decl);
2566 cfun->function_end_locus = gimple_location (ctx->stmt);
2567 init_tree_ssa (cfun);
2568 pop_cfun ();
2571 /* Callback for walk_gimple_seq. Check if combined parallel
2572 contains gimple_omp_for_combined_into_p OMP_FOR. */
2574 static tree
2575 find_combined_for (gimple_stmt_iterator *gsi_p,
2576 bool *handled_ops_p,
2577 struct walk_stmt_info *wi)
2579 gimple *stmt = gsi_stmt (*gsi_p);
2581 *handled_ops_p = true;
2582 switch (gimple_code (stmt))
2584 WALK_SUBSTMTS;
2586 case GIMPLE_OMP_FOR:
2587 if (gimple_omp_for_combined_into_p (stmt)
2588 && gimple_omp_for_kind (stmt)
2589 == *(const enum gf_mask *) (wi->info))
2591 wi->info = stmt;
2592 return integer_zero_node;
2594 break;
2595 default:
2596 break;
2598 return NULL;
2601 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2603 static void
2604 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2605 omp_context *outer_ctx)
2607 struct walk_stmt_info wi;
2609 memset (&wi, 0, sizeof (wi));
2610 wi.val_only = true;
2611 wi.info = (void *) &msk;
2612 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2613 if (wi.info != (void *) &msk)
2615 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2616 struct omp_for_data fd;
2617 extract_omp_for_data (for_stmt, &fd, NULL);
2618 /* We need two temporaries with fd.loop.v type (istart/iend)
2619 and then (fd.collapse - 1) temporaries with the same
2620 type for count2 ... countN-1 vars if not constant. */
2621 size_t count = 2, i;
2622 tree type = fd.iter_type;
2623 if (fd.collapse > 1
2624 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2626 count += fd.collapse - 1;
2627 /* If there are lastprivate clauses on the inner
2628 GIMPLE_OMP_FOR, add one more temporaries for the total number
2629 of iterations (product of count1 ... countN-1). */
2630 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2631 OMP_CLAUSE_LASTPRIVATE))
2632 count++;
2633 else if (msk == GF_OMP_FOR_KIND_FOR
2634 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2635 OMP_CLAUSE_LASTPRIVATE))
2636 count++;
2638 for (i = 0; i < count; i++)
2640 tree temp = create_tmp_var (type);
2641 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2642 insert_decl_map (&outer_ctx->cb, temp, temp);
2643 OMP_CLAUSE_DECL (c) = temp;
2644 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2645 gimple_omp_taskreg_set_clauses (stmt, c);
2650 /* Scan an OpenMP parallel directive. */
2652 static void
2653 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2655 omp_context *ctx;
2656 tree name;
2657 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2659 /* Ignore parallel directives with empty bodies, unless there
2660 are copyin clauses. */
2661 if (optimize > 0
2662 && empty_body_p (gimple_omp_body (stmt))
2663 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2664 OMP_CLAUSE_COPYIN) == NULL)
2666 gsi_replace (gsi, gimple_build_nop (), false);
2667 return;
2670 if (gimple_omp_parallel_combined_p (stmt))
2671 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2673 ctx = new_omp_context (stmt, outer_ctx);
2674 taskreg_contexts.safe_push (ctx);
2675 if (taskreg_nesting_level > 1)
2676 ctx->is_nested = true;
2677 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2678 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2679 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2680 name = create_tmp_var_name (".omp_data_s");
2681 name = build_decl (gimple_location (stmt),
2682 TYPE_DECL, name, ctx->record_type);
2683 DECL_ARTIFICIAL (name) = 1;
2684 DECL_NAMELESS (name) = 1;
2685 TYPE_NAME (ctx->record_type) = name;
2686 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2687 if (!gimple_omp_parallel_grid_phony (stmt))
2689 create_omp_child_function (ctx, false);
2690 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2693 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2694 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2696 if (TYPE_FIELDS (ctx->record_type) == NULL)
2697 ctx->record_type = ctx->receiver_decl = NULL;
2700 /* Scan an OpenMP task directive. */
2702 static void
2703 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2705 omp_context *ctx;
2706 tree name, t;
2707 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2709 /* Ignore task directives with empty bodies. */
2710 if (optimize > 0
2711 && empty_body_p (gimple_omp_body (stmt)))
2713 gsi_replace (gsi, gimple_build_nop (), false);
2714 return;
2717 if (gimple_omp_task_taskloop_p (stmt))
2718 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2720 ctx = new_omp_context (stmt, outer_ctx);
2721 taskreg_contexts.safe_push (ctx);
2722 if (taskreg_nesting_level > 1)
2723 ctx->is_nested = true;
2724 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2725 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2726 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2727 name = create_tmp_var_name (".omp_data_s");
2728 name = build_decl (gimple_location (stmt),
2729 TYPE_DECL, name, ctx->record_type);
2730 DECL_ARTIFICIAL (name) = 1;
2731 DECL_NAMELESS (name) = 1;
2732 TYPE_NAME (ctx->record_type) = name;
2733 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2734 create_omp_child_function (ctx, false);
2735 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2737 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2739 if (ctx->srecord_type)
2741 name = create_tmp_var_name (".omp_data_a");
2742 name = build_decl (gimple_location (stmt),
2743 TYPE_DECL, name, ctx->srecord_type);
2744 DECL_ARTIFICIAL (name) = 1;
2745 DECL_NAMELESS (name) = 1;
2746 TYPE_NAME (ctx->srecord_type) = name;
2747 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2748 create_omp_child_function (ctx, true);
2751 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2753 if (TYPE_FIELDS (ctx->record_type) == NULL)
2755 ctx->record_type = ctx->receiver_decl = NULL;
2756 t = build_int_cst (long_integer_type_node, 0);
2757 gimple_omp_task_set_arg_size (stmt, t);
2758 t = build_int_cst (long_integer_type_node, 1);
2759 gimple_omp_task_set_arg_align (stmt, t);
2764 /* If any decls have been made addressable during scan_omp,
2765 adjust their fields if needed, and layout record types
2766 of parallel/task constructs. */
2768 static void
2769 finish_taskreg_scan (omp_context *ctx)
2771 if (ctx->record_type == NULL_TREE)
2772 return;
2774 /* If any task_shared_vars were needed, verify all
2775 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2776 statements if use_pointer_for_field hasn't changed
2777 because of that. If it did, update field types now. */
2778 if (task_shared_vars)
2780 tree c;
2782 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2783 c; c = OMP_CLAUSE_CHAIN (c))
2784 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2785 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2787 tree decl = OMP_CLAUSE_DECL (c);
2789 /* Global variables don't need to be copied,
2790 the receiver side will use them directly. */
2791 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2792 continue;
2793 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2794 || !use_pointer_for_field (decl, ctx))
2795 continue;
2796 tree field = lookup_field (decl, ctx);
2797 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2798 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2799 continue;
2800 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2801 TREE_THIS_VOLATILE (field) = 0;
2802 DECL_USER_ALIGN (field) = 0;
2803 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2804 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2805 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2806 if (ctx->srecord_type)
2808 tree sfield = lookup_sfield (decl, ctx);
2809 TREE_TYPE (sfield) = TREE_TYPE (field);
2810 TREE_THIS_VOLATILE (sfield) = 0;
2811 DECL_USER_ALIGN (sfield) = 0;
2812 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2813 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2814 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2819 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2821 layout_type (ctx->record_type);
2822 fixup_child_record_type (ctx);
2824 else
2826 location_t loc = gimple_location (ctx->stmt);
2827 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2828 /* Move VLA fields to the end. */
2829 p = &TYPE_FIELDS (ctx->record_type);
2830 while (*p)
2831 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2832 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2834 *q = *p;
2835 *p = TREE_CHAIN (*p);
2836 TREE_CHAIN (*q) = NULL_TREE;
2837 q = &TREE_CHAIN (*q);
2839 else
2840 p = &DECL_CHAIN (*p);
2841 *p = vla_fields;
2842 if (gimple_omp_task_taskloop_p (ctx->stmt))
2844 /* Move fields corresponding to first and second _looptemp_
2845 clause first. There are filled by GOMP_taskloop
2846 and thus need to be in specific positions. */
2847 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2848 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2849 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2850 OMP_CLAUSE__LOOPTEMP_);
2851 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2852 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2853 p = &TYPE_FIELDS (ctx->record_type);
2854 while (*p)
2855 if (*p == f1 || *p == f2)
2856 *p = DECL_CHAIN (*p);
2857 else
2858 p = &DECL_CHAIN (*p);
2859 DECL_CHAIN (f1) = f2;
2860 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2861 TYPE_FIELDS (ctx->record_type) = f1;
2862 if (ctx->srecord_type)
2864 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2865 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2866 p = &TYPE_FIELDS (ctx->srecord_type);
2867 while (*p)
2868 if (*p == f1 || *p == f2)
2869 *p = DECL_CHAIN (*p);
2870 else
2871 p = &DECL_CHAIN (*p);
2872 DECL_CHAIN (f1) = f2;
2873 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2874 TYPE_FIELDS (ctx->srecord_type) = f1;
2877 layout_type (ctx->record_type);
2878 fixup_child_record_type (ctx);
2879 if (ctx->srecord_type)
2880 layout_type (ctx->srecord_type);
2881 tree t = fold_convert_loc (loc, long_integer_type_node,
2882 TYPE_SIZE_UNIT (ctx->record_type));
2883 gimple_omp_task_set_arg_size (ctx->stmt, t);
2884 t = build_int_cst (long_integer_type_node,
2885 TYPE_ALIGN_UNIT (ctx->record_type));
2886 gimple_omp_task_set_arg_align (ctx->stmt, t);
2890 /* Find the enclosing offload context. */
2892 static omp_context *
2893 enclosing_target_ctx (omp_context *ctx)
2895 for (; ctx; ctx = ctx->outer)
2896 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2897 break;
2899 return ctx;
2902 /* Return true if ctx is part of an oacc kernels region. */
2904 static bool
2905 ctx_in_oacc_kernels_region (omp_context *ctx)
2907 for (;ctx != NULL; ctx = ctx->outer)
2909 gimple *stmt = ctx->stmt;
2910 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2911 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2912 return true;
2915 return false;
2918 /* Check the parallelism clauses inside a kernels regions.
2919 Until kernels handling moves to use the same loop indirection
2920 scheme as parallel, we need to do this checking early. */
2922 static unsigned
2923 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2925 bool checking = true;
2926 unsigned outer_mask = 0;
2927 unsigned this_mask = 0;
2928 bool has_seq = false, has_auto = false;
2930 if (ctx->outer)
2931 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2932 if (!stmt)
2934 checking = false;
2935 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2936 return outer_mask;
2937 stmt = as_a <gomp_for *> (ctx->stmt);
2940 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2942 switch (OMP_CLAUSE_CODE (c))
2944 case OMP_CLAUSE_GANG:
2945 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2946 break;
2947 case OMP_CLAUSE_WORKER:
2948 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2949 break;
2950 case OMP_CLAUSE_VECTOR:
2951 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2952 break;
2953 case OMP_CLAUSE_SEQ:
2954 has_seq = true;
2955 break;
2956 case OMP_CLAUSE_AUTO:
2957 has_auto = true;
2958 break;
2959 default:
2960 break;
2964 if (checking)
2966 if (has_seq && (this_mask || has_auto))
2967 error_at (gimple_location (stmt), "%<seq%> overrides other"
2968 " OpenACC loop specifiers");
2969 else if (has_auto && this_mask)
2970 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2971 " OpenACC loop specifiers");
2973 if (this_mask & outer_mask)
2974 error_at (gimple_location (stmt), "inner loop uses same"
2975 " OpenACC parallelism as containing loop");
2978 return outer_mask | this_mask;
2981 /* Scan a GIMPLE_OMP_FOR. */
2983 static void
2984 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2986 omp_context *ctx;
2987 size_t i;
2988 tree clauses = gimple_omp_for_clauses (stmt);
2990 ctx = new_omp_context (stmt, outer_ctx);
2992 if (is_gimple_omp_oacc (stmt))
2994 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2996 if (!tgt || is_oacc_parallel (tgt))
2997 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2999 char const *check = NULL;
3001 switch (OMP_CLAUSE_CODE (c))
3003 case OMP_CLAUSE_GANG:
3004 check = "gang";
3005 break;
3007 case OMP_CLAUSE_WORKER:
3008 check = "worker";
3009 break;
3011 case OMP_CLAUSE_VECTOR:
3012 check = "vector";
3013 break;
3015 default:
3016 break;
3019 if (check && OMP_CLAUSE_OPERAND (c, 0))
3020 error_at (gimple_location (stmt),
3021 "argument not permitted on %qs clause in"
3022 " OpenACC %<parallel%>", check);
3025 if (tgt && is_oacc_kernels (tgt))
3027 /* Strip out reductions, as they are not handled yet. */
3028 tree *prev_ptr = &clauses;
3030 while (tree probe = *prev_ptr)
3032 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3034 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3035 *prev_ptr = *next_ptr;
3036 else
3037 prev_ptr = next_ptr;
3040 gimple_omp_for_set_clauses (stmt, clauses);
3041 check_oacc_kernel_gwv (stmt, ctx);
3045 scan_sharing_clauses (clauses, ctx);
3047 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3048 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3050 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3053 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3055 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3058 /* Scan an OpenMP sections directive. */
3060 static void
3061 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3063 omp_context *ctx;
3065 ctx = new_omp_context (stmt, outer_ctx);
3066 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3067 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3070 /* Scan an OpenMP single directive. */
3072 static void
3073 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3075 omp_context *ctx;
3076 tree name;
3078 ctx = new_omp_context (stmt, outer_ctx);
3079 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3080 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3081 name = create_tmp_var_name (".omp_copy_s");
3082 name = build_decl (gimple_location (stmt),
3083 TYPE_DECL, name, ctx->record_type);
3084 TYPE_NAME (ctx->record_type) = name;
3086 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3087 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3089 if (TYPE_FIELDS (ctx->record_type) == NULL)
3090 ctx->record_type = NULL;
3091 else
3092 layout_type (ctx->record_type);
3095 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3096 used in the corresponding offloaded function are restrict. */
3098 static bool
3099 omp_target_base_pointers_restrict_p (tree clauses)
3101 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3102 used by OpenACC. */
3103 if (flag_openacc == 0)
3104 return false;
3106 /* I. Basic example:
3108 void foo (void)
3110 unsigned int a[2], b[2];
3112 #pragma acc kernels \
3113 copyout (a) \
3114 copyout (b)
3116 a[0] = 0;
3117 b[0] = 1;
3121 After gimplification, we have:
3123 #pragma omp target oacc_kernels \
3124 map(force_from:a [len: 8]) \
3125 map(force_from:b [len: 8])
3127 a[0] = 0;
3128 b[0] = 1;
3131 Because both mappings have the force prefix, we know that they will be
3132 allocated when calling the corresponding offloaded function, which means we
3133 can mark the base pointers for a and b in the offloaded function as
3134 restrict. */
3136 tree c;
3137 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3139 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3140 return false;
3142 switch (OMP_CLAUSE_MAP_KIND (c))
3144 case GOMP_MAP_FORCE_ALLOC:
3145 case GOMP_MAP_FORCE_TO:
3146 case GOMP_MAP_FORCE_FROM:
3147 case GOMP_MAP_FORCE_TOFROM:
3148 break;
3149 default:
3150 return false;
3154 return true;
3157 /* Scan a GIMPLE_OMP_TARGET. */
3159 static void
3160 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3162 omp_context *ctx;
3163 tree name;
3164 bool offloaded = is_gimple_omp_offloaded (stmt);
3165 tree clauses = gimple_omp_target_clauses (stmt);
3167 ctx = new_omp_context (stmt, outer_ctx);
3168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3171 name = create_tmp_var_name (".omp_data_t");
3172 name = build_decl (gimple_location (stmt),
3173 TYPE_DECL, name, ctx->record_type);
3174 DECL_ARTIFICIAL (name) = 1;
3175 DECL_NAMELESS (name) = 1;
3176 TYPE_NAME (ctx->record_type) = name;
3177 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3179 bool base_pointers_restrict = false;
3180 if (offloaded)
3182 create_omp_child_function (ctx, false);
3183 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3185 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3186 if (base_pointers_restrict
3187 && dump_file && (dump_flags & TDF_DETAILS))
3188 fprintf (dump_file,
3189 "Base pointers in offloaded function are restrict\n");
3192 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3195 if (TYPE_FIELDS (ctx->record_type) == NULL)
3196 ctx->record_type = ctx->receiver_decl = NULL;
3197 else
3199 TYPE_FIELDS (ctx->record_type)
3200 = nreverse (TYPE_FIELDS (ctx->record_type));
3201 if (flag_checking)
3203 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3204 for (tree field = TYPE_FIELDS (ctx->record_type);
3205 field;
3206 field = DECL_CHAIN (field))
3207 gcc_assert (DECL_ALIGN (field) == align);
3209 layout_type (ctx->record_type);
3210 if (offloaded)
3211 fixup_child_record_type (ctx);
3215 /* Scan an OpenMP teams directive. */
3217 static void
3218 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3220 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3221 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3222 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3225 /* Check nesting restrictions. */
3226 static bool
3227 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3229 tree c;
3231 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3232 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3233 the original copy of its contents. */
3234 return true;
3236 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3237 inside an OpenACC CTX. */
3238 if (!(is_gimple_omp (stmt)
3239 && is_gimple_omp_oacc (stmt))
3240 /* Except for atomic codes that we share with OpenMP. */
3241 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3242 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3244 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3246 error_at (gimple_location (stmt),
3247 "non-OpenACC construct inside of OpenACC routine");
3248 return false;
3250 else
3251 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3252 if (is_gimple_omp (octx->stmt)
3253 && is_gimple_omp_oacc (octx->stmt))
3255 error_at (gimple_location (stmt),
3256 "non-OpenACC construct inside of OpenACC region");
3257 return false;
3261 if (ctx != NULL)
3263 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3264 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3266 c = NULL_TREE;
3267 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3269 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3270 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3272 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3273 && (ctx->outer == NULL
3274 || !gimple_omp_for_combined_into_p (ctx->stmt)
3275 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3276 || (gimple_omp_for_kind (ctx->outer->stmt)
3277 != GF_OMP_FOR_KIND_FOR)
3278 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3280 error_at (gimple_location (stmt),
3281 "%<ordered simd threads%> must be closely "
3282 "nested inside of %<for simd%> region");
3283 return false;
3285 return true;
3288 error_at (gimple_location (stmt),
3289 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3290 " may not be nested inside %<simd%> region");
3291 return false;
3293 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3295 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3296 || (gimple_omp_for_kind (stmt)
3297 != GF_OMP_FOR_KIND_DISTRIBUTE))
3298 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3300 error_at (gimple_location (stmt),
3301 "only %<distribute%> or %<parallel%> regions are "
3302 "allowed to be strictly nested inside %<teams%> "
3303 "region");
3304 return false;
3308 switch (gimple_code (stmt))
3310 case GIMPLE_OMP_FOR:
3311 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3312 return true;
3313 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3315 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3317 error_at (gimple_location (stmt),
3318 "%<distribute%> region must be strictly nested "
3319 "inside %<teams%> construct");
3320 return false;
3322 return true;
3324 /* We split taskloop into task and nested taskloop in it. */
3325 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3326 return true;
3327 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3329 bool ok = false;
3331 if (ctx)
3332 switch (gimple_code (ctx->stmt))
3334 case GIMPLE_OMP_FOR:
3335 ok = (gimple_omp_for_kind (ctx->stmt)
3336 == GF_OMP_FOR_KIND_OACC_LOOP);
3337 break;
3339 case GIMPLE_OMP_TARGET:
3340 switch (gimple_omp_target_kind (ctx->stmt))
3342 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3343 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3344 ok = true;
3345 break;
3347 default:
3348 break;
3351 default:
3352 break;
3354 else if (get_oacc_fn_attrib (current_function_decl))
3355 ok = true;
3356 if (!ok)
3358 error_at (gimple_location (stmt),
3359 "OpenACC loop directive must be associated with"
3360 " an OpenACC compute region");
3361 return false;
3364 /* FALLTHRU */
3365 case GIMPLE_CALL:
3366 if (is_gimple_call (stmt)
3367 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3368 == BUILT_IN_GOMP_CANCEL
3369 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3370 == BUILT_IN_GOMP_CANCELLATION_POINT))
3372 const char *bad = NULL;
3373 const char *kind = NULL;
3374 const char *construct
3375 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376 == BUILT_IN_GOMP_CANCEL)
3377 ? "#pragma omp cancel"
3378 : "#pragma omp cancellation point";
3379 if (ctx == NULL)
3381 error_at (gimple_location (stmt), "orphaned %qs construct",
3382 construct);
3383 return false;
3385 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3386 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3387 : 0)
3389 case 1:
3390 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3391 bad = "#pragma omp parallel";
3392 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3393 == BUILT_IN_GOMP_CANCEL
3394 && !integer_zerop (gimple_call_arg (stmt, 1)))
3395 ctx->cancellable = true;
3396 kind = "parallel";
3397 break;
3398 case 2:
3399 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3400 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3401 bad = "#pragma omp for";
3402 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3403 == BUILT_IN_GOMP_CANCEL
3404 && !integer_zerop (gimple_call_arg (stmt, 1)))
3406 ctx->cancellable = true;
3407 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3408 OMP_CLAUSE_NOWAIT))
3409 warning_at (gimple_location (stmt), 0,
3410 "%<#pragma omp cancel for%> inside "
3411 "%<nowait%> for construct");
3412 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3413 OMP_CLAUSE_ORDERED))
3414 warning_at (gimple_location (stmt), 0,
3415 "%<#pragma omp cancel for%> inside "
3416 "%<ordered%> for construct");
3418 kind = "for";
3419 break;
3420 case 4:
3421 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3422 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3423 bad = "#pragma omp sections";
3424 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3425 == BUILT_IN_GOMP_CANCEL
3426 && !integer_zerop (gimple_call_arg (stmt, 1)))
3428 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3430 ctx->cancellable = true;
3431 if (find_omp_clause (gimple_omp_sections_clauses
3432 (ctx->stmt),
3433 OMP_CLAUSE_NOWAIT))
3434 warning_at (gimple_location (stmt), 0,
3435 "%<#pragma omp cancel sections%> inside "
3436 "%<nowait%> sections construct");
3438 else
3440 gcc_assert (ctx->outer
3441 && gimple_code (ctx->outer->stmt)
3442 == GIMPLE_OMP_SECTIONS);
3443 ctx->outer->cancellable = true;
3444 if (find_omp_clause (gimple_omp_sections_clauses
3445 (ctx->outer->stmt),
3446 OMP_CLAUSE_NOWAIT))
3447 warning_at (gimple_location (stmt), 0,
3448 "%<#pragma omp cancel sections%> inside "
3449 "%<nowait%> sections construct");
3452 kind = "sections";
3453 break;
3454 case 8:
3455 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3456 bad = "#pragma omp task";
3457 else
3459 for (omp_context *octx = ctx->outer;
3460 octx; octx = octx->outer)
3462 switch (gimple_code (octx->stmt))
3464 case GIMPLE_OMP_TASKGROUP:
3465 break;
3466 case GIMPLE_OMP_TARGET:
3467 if (gimple_omp_target_kind (octx->stmt)
3468 != GF_OMP_TARGET_KIND_REGION)
3469 continue;
3470 /* FALLTHRU */
3471 case GIMPLE_OMP_PARALLEL:
3472 case GIMPLE_OMP_TEAMS:
3473 error_at (gimple_location (stmt),
3474 "%<%s taskgroup%> construct not closely "
3475 "nested inside of %<taskgroup%> region",
3476 construct);
3477 return false;
3478 default:
3479 continue;
3481 break;
3483 ctx->cancellable = true;
3485 kind = "taskgroup";
3486 break;
3487 default:
3488 error_at (gimple_location (stmt), "invalid arguments");
3489 return false;
3491 if (bad)
3493 error_at (gimple_location (stmt),
3494 "%<%s %s%> construct not closely nested inside of %qs",
3495 construct, kind, bad);
3496 return false;
3499 /* FALLTHRU */
3500 case GIMPLE_OMP_SECTIONS:
3501 case GIMPLE_OMP_SINGLE:
3502 for (; ctx != NULL; ctx = ctx->outer)
3503 switch (gimple_code (ctx->stmt))
3505 case GIMPLE_OMP_FOR:
3506 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3507 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3508 break;
3509 /* FALLTHRU */
3510 case GIMPLE_OMP_SECTIONS:
3511 case GIMPLE_OMP_SINGLE:
3512 case GIMPLE_OMP_ORDERED:
3513 case GIMPLE_OMP_MASTER:
3514 case GIMPLE_OMP_TASK:
3515 case GIMPLE_OMP_CRITICAL:
3516 if (is_gimple_call (stmt))
3518 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3519 != BUILT_IN_GOMP_BARRIER)
3520 return true;
3521 error_at (gimple_location (stmt),
3522 "barrier region may not be closely nested inside "
3523 "of work-sharing, %<critical%>, %<ordered%>, "
3524 "%<master%>, explicit %<task%> or %<taskloop%> "
3525 "region");
3526 return false;
3528 error_at (gimple_location (stmt),
3529 "work-sharing region may not be closely nested inside "
3530 "of work-sharing, %<critical%>, %<ordered%>, "
3531 "%<master%>, explicit %<task%> or %<taskloop%> region");
3532 return false;
3533 case GIMPLE_OMP_PARALLEL:
3534 case GIMPLE_OMP_TEAMS:
3535 return true;
3536 case GIMPLE_OMP_TARGET:
3537 if (gimple_omp_target_kind (ctx->stmt)
3538 == GF_OMP_TARGET_KIND_REGION)
3539 return true;
3540 break;
3541 default:
3542 break;
3544 break;
3545 case GIMPLE_OMP_MASTER:
3546 for (; ctx != NULL; ctx = ctx->outer)
3547 switch (gimple_code (ctx->stmt))
3549 case GIMPLE_OMP_FOR:
3550 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3551 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3552 break;
3553 /* FALLTHRU */
3554 case GIMPLE_OMP_SECTIONS:
3555 case GIMPLE_OMP_SINGLE:
3556 case GIMPLE_OMP_TASK:
3557 error_at (gimple_location (stmt),
3558 "%<master%> region may not be closely nested inside "
3559 "of work-sharing, explicit %<task%> or %<taskloop%> "
3560 "region");
3561 return false;
3562 case GIMPLE_OMP_PARALLEL:
3563 case GIMPLE_OMP_TEAMS:
3564 return true;
3565 case GIMPLE_OMP_TARGET:
3566 if (gimple_omp_target_kind (ctx->stmt)
3567 == GF_OMP_TARGET_KIND_REGION)
3568 return true;
3569 break;
3570 default:
3571 break;
3573 break;
3574 case GIMPLE_OMP_TASK:
3575 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3576 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3577 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3578 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3580 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3581 error_at (OMP_CLAUSE_LOCATION (c),
3582 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3583 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3584 return false;
3586 break;
3587 case GIMPLE_OMP_ORDERED:
3588 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3589 c; c = OMP_CLAUSE_CHAIN (c))
3591 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3593 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3594 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3595 continue;
3597 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3598 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3599 || kind == OMP_CLAUSE_DEPEND_SINK)
3601 tree oclause;
3602 /* Look for containing ordered(N) loop. */
3603 if (ctx == NULL
3604 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3605 || (oclause
3606 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3607 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3609 error_at (OMP_CLAUSE_LOCATION (c),
3610 "%<ordered%> construct with %<depend%> clause "
3611 "must be closely nested inside an %<ordered%> "
3612 "loop");
3613 return false;
3615 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3617 error_at (OMP_CLAUSE_LOCATION (c),
3618 "%<ordered%> construct with %<depend%> clause "
3619 "must be closely nested inside a loop with "
3620 "%<ordered%> clause with a parameter");
3621 return false;
3624 else
3626 error_at (OMP_CLAUSE_LOCATION (c),
3627 "invalid depend kind in omp %<ordered%> %<depend%>");
3628 return false;
3631 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3632 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3634 /* ordered simd must be closely nested inside of simd region,
3635 and simd region must not encounter constructs other than
3636 ordered simd, therefore ordered simd may be either orphaned,
3637 or ctx->stmt must be simd. The latter case is handled already
3638 earlier. */
3639 if (ctx != NULL)
3641 error_at (gimple_location (stmt),
3642 "%<ordered%> %<simd%> must be closely nested inside "
3643 "%<simd%> region");
3644 return false;
3647 for (; ctx != NULL; ctx = ctx->outer)
3648 switch (gimple_code (ctx->stmt))
3650 case GIMPLE_OMP_CRITICAL:
3651 case GIMPLE_OMP_TASK:
3652 case GIMPLE_OMP_ORDERED:
3653 ordered_in_taskloop:
3654 error_at (gimple_location (stmt),
3655 "%<ordered%> region may not be closely nested inside "
3656 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3657 "%<taskloop%> region");
3658 return false;
3659 case GIMPLE_OMP_FOR:
3660 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3661 goto ordered_in_taskloop;
3662 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3663 OMP_CLAUSE_ORDERED) == NULL)
3665 error_at (gimple_location (stmt),
3666 "%<ordered%> region must be closely nested inside "
3667 "a loop region with an %<ordered%> clause");
3668 return false;
3670 return true;
3671 case GIMPLE_OMP_TARGET:
3672 if (gimple_omp_target_kind (ctx->stmt)
3673 != GF_OMP_TARGET_KIND_REGION)
3674 break;
3675 /* FALLTHRU */
3676 case GIMPLE_OMP_PARALLEL:
3677 case GIMPLE_OMP_TEAMS:
3678 error_at (gimple_location (stmt),
3679 "%<ordered%> region must be closely nested inside "
3680 "a loop region with an %<ordered%> clause");
3681 return false;
3682 default:
3683 break;
3685 break;
3686 case GIMPLE_OMP_CRITICAL:
3688 tree this_stmt_name
3689 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3690 for (; ctx != NULL; ctx = ctx->outer)
3691 if (gomp_critical *other_crit
3692 = dyn_cast <gomp_critical *> (ctx->stmt))
3693 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3695 error_at (gimple_location (stmt),
3696 "%<critical%> region may not be nested inside "
3697 "a %<critical%> region with the same name");
3698 return false;
3701 break;
3702 case GIMPLE_OMP_TEAMS:
3703 if (ctx == NULL
3704 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3705 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3707 error_at (gimple_location (stmt),
3708 "%<teams%> construct not closely nested inside of "
3709 "%<target%> construct");
3710 return false;
3712 break;
3713 case GIMPLE_OMP_TARGET:
3714 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3715 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3716 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3717 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3719 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3720 error_at (OMP_CLAUSE_LOCATION (c),
3721 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3722 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3723 return false;
3725 if (is_gimple_omp_offloaded (stmt)
3726 && get_oacc_fn_attrib (cfun->decl) != NULL)
3728 error_at (gimple_location (stmt),
3729 "OpenACC region inside of OpenACC routine, nested "
3730 "parallelism not supported yet");
3731 return false;
3733 for (; ctx != NULL; ctx = ctx->outer)
3735 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3737 if (is_gimple_omp (stmt)
3738 && is_gimple_omp_oacc (stmt)
3739 && is_gimple_omp (ctx->stmt))
3741 error_at (gimple_location (stmt),
3742 "OpenACC construct inside of non-OpenACC region");
3743 return false;
3745 continue;
3748 const char *stmt_name, *ctx_stmt_name;
3749 switch (gimple_omp_target_kind (stmt))
3751 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3752 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3753 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3754 case GF_OMP_TARGET_KIND_ENTER_DATA:
3755 stmt_name = "target enter data"; break;
3756 case GF_OMP_TARGET_KIND_EXIT_DATA:
3757 stmt_name = "target exit data"; break;
3758 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3759 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3760 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3761 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3762 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3763 stmt_name = "enter/exit data"; break;
3764 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3765 break;
3766 default: gcc_unreachable ();
3768 switch (gimple_omp_target_kind (ctx->stmt))
3770 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3771 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3772 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3773 ctx_stmt_name = "parallel"; break;
3774 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3775 ctx_stmt_name = "kernels"; break;
3776 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3777 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3778 ctx_stmt_name = "host_data"; break;
3779 default: gcc_unreachable ();
3782 /* OpenACC/OpenMP mismatch? */
3783 if (is_gimple_omp_oacc (stmt)
3784 != is_gimple_omp_oacc (ctx->stmt))
3786 error_at (gimple_location (stmt),
3787 "%s %qs construct inside of %s %qs region",
3788 (is_gimple_omp_oacc (stmt)
3789 ? "OpenACC" : "OpenMP"), stmt_name,
3790 (is_gimple_omp_oacc (ctx->stmt)
3791 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3792 return false;
3794 if (is_gimple_omp_offloaded (ctx->stmt))
3796 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3797 if (is_gimple_omp_oacc (ctx->stmt))
3799 error_at (gimple_location (stmt),
3800 "%qs construct inside of %qs region",
3801 stmt_name, ctx_stmt_name);
3802 return false;
3804 else
3806 warning_at (gimple_location (stmt), 0,
3807 "%qs construct inside of %qs region",
3808 stmt_name, ctx_stmt_name);
3812 break;
3813 default:
3814 break;
3816 return true;
3820 /* Helper function scan_omp.
3822 Callback for walk_tree or operators in walk_gimple_stmt used to
3823 scan for OMP directives in TP. */
3825 static tree
3826 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3828 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3829 omp_context *ctx = (omp_context *) wi->info;
3830 tree t = *tp;
3832 switch (TREE_CODE (t))
3834 case VAR_DECL:
3835 case PARM_DECL:
3836 case LABEL_DECL:
3837 case RESULT_DECL:
3838 if (ctx)
3840 tree repl = remap_decl (t, &ctx->cb);
3841 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3842 *tp = repl;
3844 break;
3846 default:
3847 if (ctx && TYPE_P (t))
3848 *tp = remap_type (t, &ctx->cb);
3849 else if (!DECL_P (t))
3851 *walk_subtrees = 1;
3852 if (ctx)
3854 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3855 if (tem != TREE_TYPE (t))
3857 if (TREE_CODE (t) == INTEGER_CST)
3858 *tp = wide_int_to_tree (tem, t);
3859 else
3860 TREE_TYPE (t) = tem;
3864 break;
3867 return NULL_TREE;
3870 /* Return true if FNDECL is a setjmp or a longjmp. */
3872 static bool
3873 setjmp_or_longjmp_p (const_tree fndecl)
3875 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3876 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3877 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3878 return true;
3880 tree declname = DECL_NAME (fndecl);
3881 if (!declname)
3882 return false;
3883 const char *name = IDENTIFIER_POINTER (declname);
3884 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3888 /* Helper function for scan_omp.
3890 Callback for walk_gimple_stmt used to scan for OMP directives in
3891 the current statement in GSI. */
3893 static tree
3894 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3895 struct walk_stmt_info *wi)
3897 gimple *stmt = gsi_stmt (*gsi);
3898 omp_context *ctx = (omp_context *) wi->info;
3900 if (gimple_has_location (stmt))
3901 input_location = gimple_location (stmt);
3903 /* Check the nesting restrictions. */
3904 bool remove = false;
3905 if (is_gimple_omp (stmt))
3906 remove = !check_omp_nesting_restrictions (stmt, ctx);
3907 else if (is_gimple_call (stmt))
3909 tree fndecl = gimple_call_fndecl (stmt);
3910 if (fndecl)
3912 if (setjmp_or_longjmp_p (fndecl)
3913 && ctx
3914 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3915 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3917 remove = true;
3918 error_at (gimple_location (stmt),
3919 "setjmp/longjmp inside simd construct");
3921 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3922 switch (DECL_FUNCTION_CODE (fndecl))
3924 case BUILT_IN_GOMP_BARRIER:
3925 case BUILT_IN_GOMP_CANCEL:
3926 case BUILT_IN_GOMP_CANCELLATION_POINT:
3927 case BUILT_IN_GOMP_TASKYIELD:
3928 case BUILT_IN_GOMP_TASKWAIT:
3929 case BUILT_IN_GOMP_TASKGROUP_START:
3930 case BUILT_IN_GOMP_TASKGROUP_END:
3931 remove = !check_omp_nesting_restrictions (stmt, ctx);
3932 break;
3933 default:
3934 break;
3938 if (remove)
3940 stmt = gimple_build_nop ();
3941 gsi_replace (gsi, stmt, false);
3944 *handled_ops_p = true;
3946 switch (gimple_code (stmt))
3948 case GIMPLE_OMP_PARALLEL:
3949 taskreg_nesting_level++;
3950 scan_omp_parallel (gsi, ctx);
3951 taskreg_nesting_level--;
3952 break;
3954 case GIMPLE_OMP_TASK:
3955 taskreg_nesting_level++;
3956 scan_omp_task (gsi, ctx);
3957 taskreg_nesting_level--;
3958 break;
3960 case GIMPLE_OMP_FOR:
3961 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3962 break;
3964 case GIMPLE_OMP_SECTIONS:
3965 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3966 break;
3968 case GIMPLE_OMP_SINGLE:
3969 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3970 break;
3972 case GIMPLE_OMP_SECTION:
3973 case GIMPLE_OMP_MASTER:
3974 case GIMPLE_OMP_TASKGROUP:
3975 case GIMPLE_OMP_ORDERED:
3976 case GIMPLE_OMP_CRITICAL:
3977 case GIMPLE_OMP_GRID_BODY:
3978 ctx = new_omp_context (stmt, ctx);
3979 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3980 break;
3982 case GIMPLE_OMP_TARGET:
3983 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3984 break;
3986 case GIMPLE_OMP_TEAMS:
3987 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3988 break;
3990 case GIMPLE_BIND:
3992 tree var;
3994 *handled_ops_p = false;
3995 if (ctx)
3996 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3997 var ;
3998 var = DECL_CHAIN (var))
3999 insert_decl_map (&ctx->cb, var, var);
4001 break;
4002 default:
4003 *handled_ops_p = false;
4004 break;
4007 return NULL_TREE;
4011 /* Scan all the statements starting at the current statement. CTX
4012 contains context information about the OMP directives and
4013 clauses found during the scan. */
4015 static void
4016 scan_omp (gimple_seq *body_p, omp_context *ctx)
4018 location_t saved_location;
4019 struct walk_stmt_info wi;
4021 memset (&wi, 0, sizeof (wi));
4022 wi.info = ctx;
4023 wi.want_locations = true;
4025 saved_location = input_location;
4026 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4027 input_location = saved_location;
4030 /* Re-gimplification and code generation routines. */
4032 /* Build a call to GOMP_barrier. */
4034 static gimple *
4035 build_omp_barrier (tree lhs)
4037 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4038 : BUILT_IN_GOMP_BARRIER);
4039 gcall *g = gimple_build_call (fndecl, 0);
4040 if (lhs)
4041 gimple_call_set_lhs (g, lhs);
4042 return g;
4045 /* If a context was created for STMT when it was scanned, return it. */
4047 static omp_context *
4048 maybe_lookup_ctx (gimple *stmt)
4050 splay_tree_node n;
4051 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4052 return n ? (omp_context *) n->value : NULL;
4056 /* Find the mapping for DECL in CTX or the immediately enclosing
4057 context that has a mapping for DECL.
4059 If CTX is a nested parallel directive, we may have to use the decl
4060 mappings created in CTX's parent context. Suppose that we have the
4061 following parallel nesting (variable UIDs showed for clarity):
4063 iD.1562 = 0;
4064 #omp parallel shared(iD.1562) -> outer parallel
4065 iD.1562 = iD.1562 + 1;
4067 #omp parallel shared (iD.1562) -> inner parallel
4068 iD.1562 = iD.1562 - 1;
4070 Each parallel structure will create a distinct .omp_data_s structure
4071 for copying iD.1562 in/out of the directive:
4073 outer parallel .omp_data_s.1.i -> iD.1562
4074 inner parallel .omp_data_s.2.i -> iD.1562
4076 A shared variable mapping will produce a copy-out operation before
4077 the parallel directive and a copy-in operation after it. So, in
4078 this case we would have:
4080 iD.1562 = 0;
4081 .omp_data_o.1.i = iD.1562;
4082 #omp parallel shared(iD.1562) -> outer parallel
4083 .omp_data_i.1 = &.omp_data_o.1
4084 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4086 .omp_data_o.2.i = iD.1562; -> **
4087 #omp parallel shared(iD.1562) -> inner parallel
4088 .omp_data_i.2 = &.omp_data_o.2
4089 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4092 ** This is a problem. The symbol iD.1562 cannot be referenced
4093 inside the body of the outer parallel region. But since we are
4094 emitting this copy operation while expanding the inner parallel
4095 directive, we need to access the CTX structure of the outer
4096 parallel directive to get the correct mapping:
4098 .omp_data_o.2.i = .omp_data_i.1->i
4100 Since there may be other workshare or parallel directives enclosing
4101 the parallel directive, it may be necessary to walk up the context
4102 parent chain. This is not a problem in general because nested
4103 parallelism happens only rarely. */
4105 static tree
4106 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4108 tree t;
4109 omp_context *up;
4111 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4112 t = maybe_lookup_decl (decl, up);
4114 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4116 return t ? t : decl;
4120 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4121 in outer contexts. */
4123 static tree
4124 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4126 tree t = NULL;
4127 omp_context *up;
4129 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4130 t = maybe_lookup_decl (decl, up);
4132 return t ? t : decl;
4136 /* Construct the initialization value for reduction operation OP. */
4138 tree
4139 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4141 switch (op)
4143 case PLUS_EXPR:
4144 case MINUS_EXPR:
4145 case BIT_IOR_EXPR:
4146 case BIT_XOR_EXPR:
4147 case TRUTH_OR_EXPR:
4148 case TRUTH_ORIF_EXPR:
4149 case TRUTH_XOR_EXPR:
4150 case NE_EXPR:
4151 return build_zero_cst (type);
4153 case MULT_EXPR:
4154 case TRUTH_AND_EXPR:
4155 case TRUTH_ANDIF_EXPR:
4156 case EQ_EXPR:
4157 return fold_convert_loc (loc, type, integer_one_node);
4159 case BIT_AND_EXPR:
4160 return fold_convert_loc (loc, type, integer_minus_one_node);
4162 case MAX_EXPR:
4163 if (SCALAR_FLOAT_TYPE_P (type))
4165 REAL_VALUE_TYPE max, min;
4166 if (HONOR_INFINITIES (type))
4168 real_inf (&max);
4169 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4171 else
4172 real_maxval (&min, 1, TYPE_MODE (type));
4173 return build_real (type, min);
4175 else if (POINTER_TYPE_P (type))
4177 wide_int min
4178 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4179 return wide_int_to_tree (type, min);
4181 else
4183 gcc_assert (INTEGRAL_TYPE_P (type));
4184 return TYPE_MIN_VALUE (type);
4187 case MIN_EXPR:
4188 if (SCALAR_FLOAT_TYPE_P (type))
4190 REAL_VALUE_TYPE max;
4191 if (HONOR_INFINITIES (type))
4192 real_inf (&max);
4193 else
4194 real_maxval (&max, 0, TYPE_MODE (type));
4195 return build_real (type, max);
4197 else if (POINTER_TYPE_P (type))
4199 wide_int max
4200 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4201 return wide_int_to_tree (type, max);
4203 else
4205 gcc_assert (INTEGRAL_TYPE_P (type));
4206 return TYPE_MAX_VALUE (type);
4209 default:
4210 gcc_unreachable ();
4214 /* Construct the initialization value for reduction CLAUSE. */
4216 tree
4217 omp_reduction_init (tree clause, tree type)
4219 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4220 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4223 /* Return alignment to be assumed for var in CLAUSE, which should be
4224 OMP_CLAUSE_ALIGNED. */
4226 static tree
4227 omp_clause_aligned_alignment (tree clause)
4229 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4230 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4232 /* Otherwise return implementation defined alignment. */
4233 unsigned int al = 1;
4234 machine_mode mode, vmode;
4235 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4236 if (vs)
4237 vs = 1 << floor_log2 (vs);
4238 static enum mode_class classes[]
4239 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4240 for (int i = 0; i < 4; i += 2)
4241 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4242 mode != VOIDmode;
4243 mode = GET_MODE_WIDER_MODE (mode))
4245 vmode = targetm.vectorize.preferred_simd_mode (mode);
4246 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4247 continue;
4248 while (vs
4249 && GET_MODE_SIZE (vmode) < vs
4250 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4251 vmode = GET_MODE_2XWIDER_MODE (vmode);
4253 tree type = lang_hooks.types.type_for_mode (mode, 1);
4254 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4255 continue;
4256 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4257 / GET_MODE_SIZE (mode));
4258 if (TYPE_MODE (type) != vmode)
4259 continue;
4260 if (TYPE_ALIGN_UNIT (type) > al)
4261 al = TYPE_ALIGN_UNIT (type);
4263 return build_int_cst (integer_type_node, al);
4266 /* Return maximum possible vectorization factor for the target. */
4268 static int
4269 omp_max_vf (void)
4271 if (!optimize
4272 || optimize_debug
4273 || !flag_tree_loop_optimize
4274 || (!flag_tree_loop_vectorize
4275 && (global_options_set.x_flag_tree_loop_vectorize
4276 || global_options_set.x_flag_tree_vectorize)))
4277 return 1;
4279 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4280 if (vs)
4282 vs = 1 << floor_log2 (vs);
4283 return vs;
4285 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4286 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4287 return GET_MODE_NUNITS (vqimode);
4288 return 1;
4291 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4292 privatization. */
4294 static bool
4295 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4296 tree &idx, tree &lane, tree &ivar, tree &lvar)
4298 if (max_vf == 0)
4300 max_vf = omp_max_vf ();
4301 if (max_vf > 1)
4303 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4304 OMP_CLAUSE_SAFELEN);
4305 if (c
4306 && (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST
4307 || tree_int_cst_sgn (OMP_CLAUSE_SAFELEN_EXPR (c)) != 1))
4308 max_vf = 1;
4309 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4310 max_vf) == -1)
4311 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4313 if (max_vf > 1)
4315 idx = create_tmp_var (unsigned_type_node);
4316 lane = create_tmp_var (unsigned_type_node);
4319 if (max_vf == 1)
4320 return false;
4322 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4323 tree avar = create_tmp_var_raw (atype);
4324 if (TREE_ADDRESSABLE (new_var))
4325 TREE_ADDRESSABLE (avar) = 1;
4326 DECL_ATTRIBUTES (avar)
4327 = tree_cons (get_identifier ("omp simd array"), NULL,
4328 DECL_ATTRIBUTES (avar));
4329 gimple_add_tmp_var (avar);
4330 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4331 NULL_TREE, NULL_TREE);
4332 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4333 NULL_TREE, NULL_TREE);
4334 if (DECL_P (new_var))
4336 SET_DECL_VALUE_EXPR (new_var, lvar);
4337 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4339 return true;
4342 /* Helper function of lower_rec_input_clauses. For a reference
4343 in simd reduction, add an underlying variable it will reference. */
4345 static void
4346 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4348 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4349 if (TREE_CONSTANT (z))
4351 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4352 get_name (new_vard));
4353 gimple_add_tmp_var (z);
4354 TREE_ADDRESSABLE (z) = 1;
4355 z = build_fold_addr_expr_loc (loc, z);
4356 gimplify_assign (new_vard, z, ilist);
4360 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4361 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4362 private variables. Initialization statements go in ILIST, while calls
4363 to destructors go in DLIST. */
4365 static void
4366 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4367 omp_context *ctx, struct omp_for_data *fd)
4369 tree c, dtor, copyin_seq, x, ptr;
4370 bool copyin_by_ref = false;
4371 bool lastprivate_firstprivate = false;
4372 bool reduction_omp_orig_ref = false;
4373 int pass;
4374 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4375 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4376 int max_vf = 0;
4377 tree lane = NULL_TREE, idx = NULL_TREE;
4378 tree ivar = NULL_TREE, lvar = NULL_TREE;
4379 gimple_seq llist[2] = { NULL, NULL };
4381 copyin_seq = NULL;
4383 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4384 with data sharing clauses referencing variable sized vars. That
4385 is unnecessarily hard to support and very unlikely to result in
4386 vectorized code anyway. */
4387 if (is_simd)
4388 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4389 switch (OMP_CLAUSE_CODE (c))
4391 case OMP_CLAUSE_LINEAR:
4392 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4393 max_vf = 1;
4394 /* FALLTHRU */
4395 case OMP_CLAUSE_PRIVATE:
4396 case OMP_CLAUSE_FIRSTPRIVATE:
4397 case OMP_CLAUSE_LASTPRIVATE:
4398 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4399 max_vf = 1;
4400 break;
4401 case OMP_CLAUSE_REDUCTION:
4402 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4403 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4404 max_vf = 1;
4405 break;
4406 default:
4407 continue;
4410 /* Do all the fixed sized types in the first pass, and the variable sized
4411 types in the second pass. This makes sure that the scalar arguments to
4412 the variable sized types are processed before we use them in the
4413 variable sized operations. */
4414 for (pass = 0; pass < 2; ++pass)
4416 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4418 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4419 tree var, new_var;
4420 bool by_ref;
4421 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4423 switch (c_kind)
4425 case OMP_CLAUSE_PRIVATE:
4426 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4427 continue;
4428 break;
4429 case OMP_CLAUSE_SHARED:
4430 /* Ignore shared directives in teams construct. */
4431 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4432 continue;
4433 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4435 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4436 || is_global_var (OMP_CLAUSE_DECL (c)));
4437 continue;
4439 case OMP_CLAUSE_FIRSTPRIVATE:
4440 case OMP_CLAUSE_COPYIN:
4441 break;
4442 case OMP_CLAUSE_LINEAR:
4443 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4444 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4445 lastprivate_firstprivate = true;
4446 break;
4447 case OMP_CLAUSE_REDUCTION:
4448 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4449 reduction_omp_orig_ref = true;
4450 break;
4451 case OMP_CLAUSE__LOOPTEMP_:
4452 /* Handle _looptemp_ clauses only on parallel/task. */
4453 if (fd)
4454 continue;
4455 break;
4456 case OMP_CLAUSE_LASTPRIVATE:
4457 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4459 lastprivate_firstprivate = true;
4460 if (pass != 0 || is_taskloop_ctx (ctx))
4461 continue;
4463 /* Even without corresponding firstprivate, if
4464 decl is Fortran allocatable, it needs outer var
4465 reference. */
4466 else if (pass == 0
4467 && lang_hooks.decls.omp_private_outer_ref
4468 (OMP_CLAUSE_DECL (c)))
4469 lastprivate_firstprivate = true;
4470 break;
4471 case OMP_CLAUSE_ALIGNED:
4472 if (pass == 0)
4473 continue;
4474 var = OMP_CLAUSE_DECL (c);
4475 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4476 && !is_global_var (var))
4478 new_var = maybe_lookup_decl (var, ctx);
4479 if (new_var == NULL_TREE)
4480 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4481 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4482 tree alarg = omp_clause_aligned_alignment (c);
4483 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4484 x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
4485 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4486 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4487 gimplify_and_add (x, ilist);
4489 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4490 && is_global_var (var))
4492 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4493 new_var = lookup_decl (var, ctx);
4494 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4495 t = build_fold_addr_expr_loc (clause_loc, t);
4496 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4497 tree alarg = omp_clause_aligned_alignment (c);
4498 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4499 t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
4500 t = fold_convert_loc (clause_loc, ptype, t);
4501 x = create_tmp_var (ptype);
4502 t = build2 (MODIFY_EXPR, ptype, x, t);
4503 gimplify_and_add (t, ilist);
4504 t = build_simple_mem_ref_loc (clause_loc, x);
4505 SET_DECL_VALUE_EXPR (new_var, t);
4506 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4508 continue;
4509 default:
4510 continue;
4513 new_var = var = OMP_CLAUSE_DECL (c);
4514 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4516 var = TREE_OPERAND (var, 0);
4517 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4518 var = TREE_OPERAND (var, 0);
4519 if (TREE_CODE (var) == INDIRECT_REF
4520 || TREE_CODE (var) == ADDR_EXPR)
4521 var = TREE_OPERAND (var, 0);
4522 if (is_variable_sized (var))
4524 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4525 var = DECL_VALUE_EXPR (var);
4526 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4527 var = TREE_OPERAND (var, 0);
4528 gcc_assert (DECL_P (var));
4530 new_var = var;
4532 if (c_kind != OMP_CLAUSE_COPYIN)
4533 new_var = lookup_decl (var, ctx);
4535 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4537 if (pass != 0)
4538 continue;
4540 /* C/C++ array section reductions. */
4541 else if (c_kind == OMP_CLAUSE_REDUCTION
4542 && var != OMP_CLAUSE_DECL (c))
4544 if (pass == 0)
4545 continue;
4547 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4548 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4549 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4551 tree b = TREE_OPERAND (orig_var, 1);
4552 b = maybe_lookup_decl (b, ctx);
4553 if (b == NULL)
4555 b = TREE_OPERAND (orig_var, 1);
4556 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4558 if (integer_zerop (bias))
4559 bias = b;
4560 else
4562 bias = fold_convert_loc (clause_loc,
4563 TREE_TYPE (b), bias);
4564 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4565 TREE_TYPE (b), b, bias);
4567 orig_var = TREE_OPERAND (orig_var, 0);
4569 if (TREE_CODE (orig_var) == INDIRECT_REF
4570 || TREE_CODE (orig_var) == ADDR_EXPR)
4571 orig_var = TREE_OPERAND (orig_var, 0);
4572 tree d = OMP_CLAUSE_DECL (c);
4573 tree type = TREE_TYPE (d);
4574 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4575 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4576 const char *name = get_name (orig_var);
4577 if (TREE_CONSTANT (v))
4579 x = create_tmp_var_raw (type, name);
4580 gimple_add_tmp_var (x);
4581 TREE_ADDRESSABLE (x) = 1;
4582 x = build_fold_addr_expr_loc (clause_loc, x);
4584 else
4586 tree atmp
4587 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4588 tree t = maybe_lookup_decl (v, ctx);
4589 if (t)
4590 v = t;
4591 else
4592 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4593 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4594 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4595 TREE_TYPE (v), v,
4596 build_int_cst (TREE_TYPE (v), 1));
4597 t = fold_build2_loc (clause_loc, MULT_EXPR,
4598 TREE_TYPE (v), t,
4599 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4600 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4601 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4604 tree ptype = build_pointer_type (TREE_TYPE (type));
4605 x = fold_convert_loc (clause_loc, ptype, x);
4606 tree y = create_tmp_var (ptype, name);
4607 gimplify_assign (y, x, ilist);
4608 x = y;
4609 tree yb = y;
4611 if (!integer_zerop (bias))
4613 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4614 bias);
4615 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4617 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4618 pointer_sized_int_node, yb, bias);
4619 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4620 yb = create_tmp_var (ptype, name);
4621 gimplify_assign (yb, x, ilist);
4622 x = yb;
4625 d = TREE_OPERAND (d, 0);
4626 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4627 d = TREE_OPERAND (d, 0);
4628 if (TREE_CODE (d) == ADDR_EXPR)
4630 if (orig_var != var)
4632 gcc_assert (is_variable_sized (orig_var));
4633 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4635 gimplify_assign (new_var, x, ilist);
4636 tree new_orig_var = lookup_decl (orig_var, ctx);
4637 tree t = build_fold_indirect_ref (new_var);
4638 DECL_IGNORED_P (new_var) = 0;
4639 TREE_THIS_NOTRAP (t);
4640 SET_DECL_VALUE_EXPR (new_orig_var, t);
4641 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4643 else
4645 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4646 build_int_cst (ptype, 0));
4647 SET_DECL_VALUE_EXPR (new_var, x);
4648 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4651 else
4653 gcc_assert (orig_var == var);
4654 if (TREE_CODE (d) == INDIRECT_REF)
4656 x = create_tmp_var (ptype, name);
4657 TREE_ADDRESSABLE (x) = 1;
4658 gimplify_assign (x, yb, ilist);
4659 x = build_fold_addr_expr_loc (clause_loc, x);
4661 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4662 gimplify_assign (new_var, x, ilist);
4664 tree y1 = create_tmp_var (ptype, NULL);
4665 gimplify_assign (y1, y, ilist);
4666 tree i2 = NULL_TREE, y2 = NULL_TREE;
4667 tree body2 = NULL_TREE, end2 = NULL_TREE;
4668 tree y3 = NULL_TREE, y4 = NULL_TREE;
4669 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4671 y2 = create_tmp_var (ptype, NULL);
4672 gimplify_assign (y2, y, ilist);
4673 tree ref = build_outer_var_ref (var, ctx);
4674 /* For ref build_outer_var_ref already performs this. */
4675 if (TREE_CODE (d) == INDIRECT_REF)
4676 gcc_assert (is_reference (var));
4677 else if (TREE_CODE (d) == ADDR_EXPR)
4678 ref = build_fold_addr_expr (ref);
4679 else if (is_reference (var))
4680 ref = build_fold_addr_expr (ref);
4681 ref = fold_convert_loc (clause_loc, ptype, ref);
4682 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4683 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4685 y3 = create_tmp_var (ptype, NULL);
4686 gimplify_assign (y3, unshare_expr (ref), ilist);
4688 if (is_simd)
4690 y4 = create_tmp_var (ptype, NULL);
4691 gimplify_assign (y4, ref, dlist);
4694 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4695 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4696 tree body = create_artificial_label (UNKNOWN_LOCATION);
4697 tree end = create_artificial_label (UNKNOWN_LOCATION);
4698 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4699 if (y2)
4701 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4702 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4703 body2 = create_artificial_label (UNKNOWN_LOCATION);
4704 end2 = create_artificial_label (UNKNOWN_LOCATION);
4705 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4707 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4709 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4710 tree decl_placeholder
4711 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4712 SET_DECL_VALUE_EXPR (decl_placeholder,
4713 build_simple_mem_ref (y1));
4714 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4715 SET_DECL_VALUE_EXPR (placeholder,
4716 y3 ? build_simple_mem_ref (y3)
4717 : error_mark_node);
4718 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4719 x = lang_hooks.decls.omp_clause_default_ctor
4720 (c, build_simple_mem_ref (y1),
4721 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4722 if (x)
4723 gimplify_and_add (x, ilist);
4724 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4726 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4727 lower_omp (&tseq, ctx);
4728 gimple_seq_add_seq (ilist, tseq);
4730 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4731 if (is_simd)
4733 SET_DECL_VALUE_EXPR (decl_placeholder,
4734 build_simple_mem_ref (y2));
4735 SET_DECL_VALUE_EXPR (placeholder,
4736 build_simple_mem_ref (y4));
4737 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4738 lower_omp (&tseq, ctx);
4739 gimple_seq_add_seq (dlist, tseq);
4740 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4742 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4743 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4744 x = lang_hooks.decls.omp_clause_dtor
4745 (c, build_simple_mem_ref (y2));
4746 if (x)
4748 gimple_seq tseq = NULL;
4749 dtor = x;
4750 gimplify_stmt (&dtor, &tseq);
4751 gimple_seq_add_seq (dlist, tseq);
4754 else
4756 x = omp_reduction_init (c, TREE_TYPE (type));
4757 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4759 /* reduction(-:var) sums up the partial results, so it
4760 acts identically to reduction(+:var). */
4761 if (code == MINUS_EXPR)
4762 code = PLUS_EXPR;
4764 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4765 if (is_simd)
4767 x = build2 (code, TREE_TYPE (type),
4768 build_simple_mem_ref (y4),
4769 build_simple_mem_ref (y2));
4770 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4773 gimple *g
4774 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4775 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4776 gimple_seq_add_stmt (ilist, g);
4777 if (y3)
4779 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4780 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4781 gimple_seq_add_stmt (ilist, g);
4783 g = gimple_build_assign (i, PLUS_EXPR, i,
4784 build_int_cst (TREE_TYPE (i), 1));
4785 gimple_seq_add_stmt (ilist, g);
4786 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4787 gimple_seq_add_stmt (ilist, g);
4788 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4789 if (y2)
4791 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4792 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4793 gimple_seq_add_stmt (dlist, g);
4794 if (y4)
4796 g = gimple_build_assign
4797 (y4, POINTER_PLUS_EXPR, y4,
4798 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4799 gimple_seq_add_stmt (dlist, g);
4801 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4802 build_int_cst (TREE_TYPE (i2), 1));
4803 gimple_seq_add_stmt (dlist, g);
4804 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4805 gimple_seq_add_stmt (dlist, g);
4806 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4808 continue;
4810 else if (is_variable_sized (var))
4812 /* For variable sized types, we need to allocate the
4813 actual storage here. Call alloca and store the
4814 result in the pointer decl that we created elsewhere. */
4815 if (pass == 0)
4816 continue;
4818 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4820 gcall *stmt;
4821 tree tmp, atmp;
4823 ptr = DECL_VALUE_EXPR (new_var);
4824 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4825 ptr = TREE_OPERAND (ptr, 0);
4826 gcc_assert (DECL_P (ptr));
4827 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4829 /* void *tmp = __builtin_alloca */
4830 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4831 stmt = gimple_build_call (atmp, 2, x,
4832 size_int (DECL_ALIGN (var)));
4833 tmp = create_tmp_var_raw (ptr_type_node);
4834 gimple_add_tmp_var (tmp);
4835 gimple_call_set_lhs (stmt, tmp);
4837 gimple_seq_add_stmt (ilist, stmt);
4839 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4840 gimplify_assign (ptr, x, ilist);
4843 else if (is_reference (var))
4845 /* For references that are being privatized for Fortran,
4846 allocate new backing storage for the new pointer
4847 variable. This allows us to avoid changing all the
4848 code that expects a pointer to something that expects
4849 a direct variable. */
4850 if (pass == 0)
4851 continue;
4853 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4854 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4856 x = build_receiver_ref (var, false, ctx);
4857 x = build_fold_addr_expr_loc (clause_loc, x);
4859 else if (TREE_CONSTANT (x))
4861 /* For reduction in SIMD loop, defer adding the
4862 initialization of the reference, because if we decide
4863 to use SIMD array for it, the initilization could cause
4864 expansion ICE. */
4865 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4866 x = NULL_TREE;
4867 else
4869 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4870 get_name (var));
4871 gimple_add_tmp_var (x);
4872 TREE_ADDRESSABLE (x) = 1;
4873 x = build_fold_addr_expr_loc (clause_loc, x);
4876 else
4878 tree atmp
4879 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4880 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4881 tree al = size_int (TYPE_ALIGN (rtype));
4882 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4885 if (x)
4887 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4888 gimplify_assign (new_var, x, ilist);
4891 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4893 else if (c_kind == OMP_CLAUSE_REDUCTION
4894 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4896 if (pass == 0)
4897 continue;
4899 else if (pass != 0)
4900 continue;
4902 switch (OMP_CLAUSE_CODE (c))
4904 case OMP_CLAUSE_SHARED:
4905 /* Ignore shared directives in teams construct. */
4906 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4907 continue;
4908 /* Shared global vars are just accessed directly. */
4909 if (is_global_var (new_var))
4910 break;
4911 /* For taskloop firstprivate/lastprivate, represented
4912 as firstprivate and shared clause on the task, new_var
4913 is the firstprivate var. */
4914 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4915 break;
4916 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4917 needs to be delayed until after fixup_child_record_type so
4918 that we get the correct type during the dereference. */
4919 by_ref = use_pointer_for_field (var, ctx);
4920 x = build_receiver_ref (var, by_ref, ctx);
4921 SET_DECL_VALUE_EXPR (new_var, x);
4922 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4924 /* ??? If VAR is not passed by reference, and the variable
4925 hasn't been initialized yet, then we'll get a warning for
4926 the store into the omp_data_s structure. Ideally, we'd be
4927 able to notice this and not store anything at all, but
4928 we're generating code too early. Suppress the warning. */
4929 if (!by_ref)
4930 TREE_NO_WARNING (var) = 1;
4931 break;
4933 case OMP_CLAUSE_LASTPRIVATE:
4934 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4935 break;
4936 /* FALLTHRU */
4938 case OMP_CLAUSE_PRIVATE:
4939 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4940 x = build_outer_var_ref (var, ctx);
4941 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4943 if (is_task_ctx (ctx))
4944 x = build_receiver_ref (var, false, ctx);
4945 else
4946 x = build_outer_var_ref (var, ctx);
4948 else
4949 x = NULL;
4950 do_private:
4951 tree nx;
4952 nx = lang_hooks.decls.omp_clause_default_ctor
4953 (c, unshare_expr (new_var), x);
4954 if (is_simd)
4956 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4957 if ((TREE_ADDRESSABLE (new_var) || nx || y
4958 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4959 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4960 idx, lane, ivar, lvar))
4962 if (nx)
4963 x = lang_hooks.decls.omp_clause_default_ctor
4964 (c, unshare_expr (ivar), x);
4965 if (nx && x)
4966 gimplify_and_add (x, &llist[0]);
4967 if (y)
4969 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4970 if (y)
4972 gimple_seq tseq = NULL;
4974 dtor = y;
4975 gimplify_stmt (&dtor, &tseq);
4976 gimple_seq_add_seq (&llist[1], tseq);
4979 break;
4982 if (nx)
4983 gimplify_and_add (nx, ilist);
4984 /* FALLTHRU */
4986 do_dtor:
4987 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4988 if (x)
4990 gimple_seq tseq = NULL;
4992 dtor = x;
4993 gimplify_stmt (&dtor, &tseq);
4994 gimple_seq_add_seq (dlist, tseq);
4996 break;
4998 case OMP_CLAUSE_LINEAR:
4999 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5000 goto do_firstprivate;
5001 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5002 x = NULL;
5003 else
5004 x = build_outer_var_ref (var, ctx);
5005 goto do_private;
5007 case OMP_CLAUSE_FIRSTPRIVATE:
5008 if (is_task_ctx (ctx))
5010 if (is_reference (var) || is_variable_sized (var))
5011 goto do_dtor;
5012 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5013 ctx))
5014 || use_pointer_for_field (var, NULL))
5016 x = build_receiver_ref (var, false, ctx);
5017 SET_DECL_VALUE_EXPR (new_var, x);
5018 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5019 goto do_dtor;
5022 do_firstprivate:
5023 x = build_outer_var_ref (var, ctx);
5024 if (is_simd)
5026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5027 && gimple_omp_for_combined_into_p (ctx->stmt))
5029 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5030 tree stept = TREE_TYPE (t);
5031 tree ct = find_omp_clause (clauses,
5032 OMP_CLAUSE__LOOPTEMP_);
5033 gcc_assert (ct);
5034 tree l = OMP_CLAUSE_DECL (ct);
5035 tree n1 = fd->loop.n1;
5036 tree step = fd->loop.step;
5037 tree itype = TREE_TYPE (l);
5038 if (POINTER_TYPE_P (itype))
5039 itype = signed_type_for (itype);
5040 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5041 if (TYPE_UNSIGNED (itype)
5042 && fd->loop.cond_code == GT_EXPR)
5043 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5044 fold_build1 (NEGATE_EXPR, itype, l),
5045 fold_build1 (NEGATE_EXPR,
5046 itype, step));
5047 else
5048 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5049 t = fold_build2 (MULT_EXPR, stept,
5050 fold_convert (stept, l), t);
5052 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5054 x = lang_hooks.decls.omp_clause_linear_ctor
5055 (c, new_var, x, t);
5056 gimplify_and_add (x, ilist);
5057 goto do_dtor;
5060 if (POINTER_TYPE_P (TREE_TYPE (x)))
5061 x = fold_build2 (POINTER_PLUS_EXPR,
5062 TREE_TYPE (x), x, t);
5063 else
5064 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5067 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5068 || TREE_ADDRESSABLE (new_var))
5069 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5070 idx, lane, ivar, lvar))
5072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5074 tree iv = create_tmp_var (TREE_TYPE (new_var));
5075 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5076 gimplify_and_add (x, ilist);
5077 gimple_stmt_iterator gsi
5078 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5079 gassign *g
5080 = gimple_build_assign (unshare_expr (lvar), iv);
5081 gsi_insert_before_without_update (&gsi, g,
5082 GSI_SAME_STMT);
5083 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5084 enum tree_code code = PLUS_EXPR;
5085 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5086 code = POINTER_PLUS_EXPR;
5087 g = gimple_build_assign (iv, code, iv, t);
5088 gsi_insert_before_without_update (&gsi, g,
5089 GSI_SAME_STMT);
5090 break;
5092 x = lang_hooks.decls.omp_clause_copy_ctor
5093 (c, unshare_expr (ivar), x);
5094 gimplify_and_add (x, &llist[0]);
5095 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5096 if (x)
5098 gimple_seq tseq = NULL;
5100 dtor = x;
5101 gimplify_stmt (&dtor, &tseq);
5102 gimple_seq_add_seq (&llist[1], tseq);
5104 break;
5107 x = lang_hooks.decls.omp_clause_copy_ctor
5108 (c, unshare_expr (new_var), x);
5109 gimplify_and_add (x, ilist);
5110 goto do_dtor;
5112 case OMP_CLAUSE__LOOPTEMP_:
5113 gcc_assert (is_taskreg_ctx (ctx));
5114 x = build_outer_var_ref (var, ctx);
5115 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5116 gimplify_and_add (x, ilist);
5117 break;
5119 case OMP_CLAUSE_COPYIN:
5120 by_ref = use_pointer_for_field (var, NULL);
5121 x = build_receiver_ref (var, by_ref, ctx);
5122 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5123 append_to_statement_list (x, &copyin_seq);
5124 copyin_by_ref |= by_ref;
5125 break;
5127 case OMP_CLAUSE_REDUCTION:
5128 /* OpenACC reductions are initialized using the
5129 GOACC_REDUCTION internal function. */
5130 if (is_gimple_omp_oacc (ctx->stmt))
5131 break;
5132 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5134 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5135 gimple *tseq;
5136 x = build_outer_var_ref (var, ctx);
5138 if (is_reference (var)
5139 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5140 TREE_TYPE (x)))
5141 x = build_fold_addr_expr_loc (clause_loc, x);
5142 SET_DECL_VALUE_EXPR (placeholder, x);
5143 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5144 tree new_vard = new_var;
5145 if (is_reference (var))
5147 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5148 new_vard = TREE_OPERAND (new_var, 0);
5149 gcc_assert (DECL_P (new_vard));
5151 if (is_simd
5152 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5153 idx, lane, ivar, lvar))
5155 if (new_vard == new_var)
5157 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5158 SET_DECL_VALUE_EXPR (new_var, ivar);
5160 else
5162 SET_DECL_VALUE_EXPR (new_vard,
5163 build_fold_addr_expr (ivar));
5164 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5166 x = lang_hooks.decls.omp_clause_default_ctor
5167 (c, unshare_expr (ivar),
5168 build_outer_var_ref (var, ctx));
5169 if (x)
5170 gimplify_and_add (x, &llist[0]);
5171 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5173 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5174 lower_omp (&tseq, ctx);
5175 gimple_seq_add_seq (&llist[0], tseq);
5177 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5178 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5179 lower_omp (&tseq, ctx);
5180 gimple_seq_add_seq (&llist[1], tseq);
5181 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5182 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5183 if (new_vard == new_var)
5184 SET_DECL_VALUE_EXPR (new_var, lvar);
5185 else
5186 SET_DECL_VALUE_EXPR (new_vard,
5187 build_fold_addr_expr (lvar));
5188 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5189 if (x)
5191 tseq = NULL;
5192 dtor = x;
5193 gimplify_stmt (&dtor, &tseq);
5194 gimple_seq_add_seq (&llist[1], tseq);
5196 break;
5198 /* If this is a reference to constant size reduction var
5199 with placeholder, we haven't emitted the initializer
5200 for it because it is undesirable if SIMD arrays are used.
5201 But if they aren't used, we need to emit the deferred
5202 initialization now. */
5203 else if (is_reference (var) && is_simd)
5204 handle_simd_reference (clause_loc, new_vard, ilist);
5205 x = lang_hooks.decls.omp_clause_default_ctor
5206 (c, unshare_expr (new_var),
5207 build_outer_var_ref (var, ctx));
5208 if (x)
5209 gimplify_and_add (x, ilist);
5210 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5212 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5213 lower_omp (&tseq, ctx);
5214 gimple_seq_add_seq (ilist, tseq);
5216 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5217 if (is_simd)
5219 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5220 lower_omp (&tseq, ctx);
5221 gimple_seq_add_seq (dlist, tseq);
5222 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5224 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5225 goto do_dtor;
5227 else
5229 x = omp_reduction_init (c, TREE_TYPE (new_var));
5230 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5231 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5233 /* reduction(-:var) sums up the partial results, so it
5234 acts identically to reduction(+:var). */
5235 if (code == MINUS_EXPR)
5236 code = PLUS_EXPR;
5238 tree new_vard = new_var;
5239 if (is_simd && is_reference (var))
5241 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5242 new_vard = TREE_OPERAND (new_var, 0);
5243 gcc_assert (DECL_P (new_vard));
5245 if (is_simd
5246 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5247 idx, lane, ivar, lvar))
5249 tree ref = build_outer_var_ref (var, ctx);
5251 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5253 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5254 ref = build_outer_var_ref (var, ctx);
5255 gimplify_assign (ref, x, &llist[1]);
5257 if (new_vard != new_var)
5259 SET_DECL_VALUE_EXPR (new_vard,
5260 build_fold_addr_expr (lvar));
5261 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5264 else
5266 if (is_reference (var) && is_simd)
5267 handle_simd_reference (clause_loc, new_vard, ilist);
5268 gimplify_assign (new_var, x, ilist);
5269 if (is_simd)
5271 tree ref = build_outer_var_ref (var, ctx);
5273 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5274 ref = build_outer_var_ref (var, ctx);
5275 gimplify_assign (ref, x, dlist);
5279 break;
5281 default:
5282 gcc_unreachable ();
5287 if (lane)
5289 tree uid = create_tmp_var (ptr_type_node, "simduid");
5290 /* Don't want uninit warnings on simduid, it is always uninitialized,
5291 but we use it not for the value, but for the DECL_UID only. */
5292 TREE_NO_WARNING (uid) = 1;
5293 gimple *g
5294 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5295 gimple_call_set_lhs (g, lane);
5296 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5297 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5298 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5299 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5300 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5301 gimple_omp_for_set_clauses (ctx->stmt, c);
5302 g = gimple_build_assign (lane, INTEGER_CST,
5303 build_int_cst (unsigned_type_node, 0));
5304 gimple_seq_add_stmt (ilist, g);
5305 for (int i = 0; i < 2; i++)
5306 if (llist[i])
5308 tree vf = create_tmp_var (unsigned_type_node);
5309 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5310 gimple_call_set_lhs (g, vf);
5311 gimple_seq *seq = i == 0 ? ilist : dlist;
5312 gimple_seq_add_stmt (seq, g);
5313 tree t = build_int_cst (unsigned_type_node, 0);
5314 g = gimple_build_assign (idx, INTEGER_CST, t);
5315 gimple_seq_add_stmt (seq, g);
5316 tree body = create_artificial_label (UNKNOWN_LOCATION);
5317 tree header = create_artificial_label (UNKNOWN_LOCATION);
5318 tree end = create_artificial_label (UNKNOWN_LOCATION);
5319 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5320 gimple_seq_add_stmt (seq, gimple_build_label (body));
5321 gimple_seq_add_seq (seq, llist[i]);
5322 t = build_int_cst (unsigned_type_node, 1);
5323 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5324 gimple_seq_add_stmt (seq, g);
5325 gimple_seq_add_stmt (seq, gimple_build_label (header));
5326 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5327 gimple_seq_add_stmt (seq, g);
5328 gimple_seq_add_stmt (seq, gimple_build_label (end));
5332 /* The copyin sequence is not to be executed by the main thread, since
5333 that would result in self-copies. Perhaps not visible to scalars,
5334 but it certainly is to C++ operator=. */
5335 if (copyin_seq)
5337 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5339 x = build2 (NE_EXPR, boolean_type_node, x,
5340 build_int_cst (TREE_TYPE (x), 0));
5341 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5342 gimplify_and_add (x, ilist);
5345 /* If any copyin variable is passed by reference, we must ensure the
5346 master thread doesn't modify it before it is copied over in all
5347 threads. Similarly for variables in both firstprivate and
5348 lastprivate clauses we need to ensure the lastprivate copying
5349 happens after firstprivate copying in all threads. And similarly
5350 for UDRs if initializer expression refers to omp_orig. */
5351 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5353 /* Don't add any barrier for #pragma omp simd or
5354 #pragma omp distribute. */
5355 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5356 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5357 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5360 /* If max_vf is non-zero, then we can use only a vectorization factor
5361 up to the max_vf we chose. So stick it into the safelen clause. */
5362 if (max_vf)
5364 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5365 OMP_CLAUSE_SAFELEN);
5366 if (c == NULL_TREE
5367 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5368 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5369 max_vf) == 1))
5371 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5372 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5373 max_vf);
5374 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5375 gimple_omp_for_set_clauses (ctx->stmt, c);
5381 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5382 both parallel and workshare constructs. PREDICATE may be NULL if it's
5383 always true. */
5385 static void
5386 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5387 omp_context *ctx)
5389 tree x, c, label = NULL, orig_clauses = clauses;
5390 bool par_clauses = false;
5391 tree simduid = NULL, lastlane = NULL;
5393 /* Early exit if there are no lastprivate or linear clauses. */
5394 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5395 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5396 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5397 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5398 break;
5399 if (clauses == NULL)
5401 /* If this was a workshare clause, see if it had been combined
5402 with its parallel. In that case, look for the clauses on the
5403 parallel statement itself. */
5404 if (is_parallel_ctx (ctx))
5405 return;
5407 ctx = ctx->outer;
5408 if (ctx == NULL || !is_parallel_ctx (ctx))
5409 return;
5411 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5412 OMP_CLAUSE_LASTPRIVATE);
5413 if (clauses == NULL)
5414 return;
5415 par_clauses = true;
5418 if (predicate)
5420 gcond *stmt;
5421 tree label_true, arm1, arm2;
5423 label = create_artificial_label (UNKNOWN_LOCATION);
5424 label_true = create_artificial_label (UNKNOWN_LOCATION);
5425 arm1 = TREE_OPERAND (predicate, 0);
5426 arm2 = TREE_OPERAND (predicate, 1);
5427 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5428 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5429 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5430 label_true, label);
5431 gimple_seq_add_stmt (stmt_list, stmt);
5432 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5435 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5436 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5438 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5439 if (simduid)
5440 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5443 for (c = clauses; c ;)
5445 tree var, new_var;
5446 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5448 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5449 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5450 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5452 var = OMP_CLAUSE_DECL (c);
5453 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5454 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5455 && is_taskloop_ctx (ctx))
5457 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5458 new_var = lookup_decl (var, ctx->outer);
5460 else
5462 new_var = lookup_decl (var, ctx);
5463 /* Avoid uninitialized warnings for lastprivate and
5464 for linear iterators. */
5465 if (predicate
5466 && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5467 || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
5468 TREE_NO_WARNING (new_var) = 1;
5471 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5473 tree val = DECL_VALUE_EXPR (new_var);
5474 if (TREE_CODE (val) == ARRAY_REF
5475 && VAR_P (TREE_OPERAND (val, 0))
5476 && lookup_attribute ("omp simd array",
5477 DECL_ATTRIBUTES (TREE_OPERAND (val,
5478 0))))
5480 if (lastlane == NULL)
5482 lastlane = create_tmp_var (unsigned_type_node);
5483 gcall *g
5484 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5485 2, simduid,
5486 TREE_OPERAND (val, 1));
5487 gimple_call_set_lhs (g, lastlane);
5488 gimple_seq_add_stmt (stmt_list, g);
5490 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5491 TREE_OPERAND (val, 0), lastlane,
5492 NULL_TREE, NULL_TREE);
5496 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5497 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5499 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5500 gimple_seq_add_seq (stmt_list,
5501 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5502 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5504 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5505 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5507 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5508 gimple_seq_add_seq (stmt_list,
5509 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5510 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5513 x = NULL_TREE;
5514 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5515 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5517 gcc_checking_assert (is_taskloop_ctx (ctx));
5518 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5519 ctx->outer->outer);
5520 if (is_global_var (ovar))
5521 x = ovar;
5523 if (!x)
5524 x = build_outer_var_ref (var, ctx, true);
5525 if (is_reference (var))
5526 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5527 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5528 gimplify_and_add (x, stmt_list);
5530 c = OMP_CLAUSE_CHAIN (c);
5531 if (c == NULL && !par_clauses)
5533 /* If this was a workshare clause, see if it had been combined
5534 with its parallel. In that case, continue looking for the
5535 clauses also on the parallel statement itself. */
5536 if (is_parallel_ctx (ctx))
5537 break;
5539 ctx = ctx->outer;
5540 if (ctx == NULL || !is_parallel_ctx (ctx))
5541 break;
5543 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5544 OMP_CLAUSE_LASTPRIVATE);
5545 par_clauses = true;
5549 if (label)
5550 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5553 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5554 (which might be a placeholder). INNER is true if this is an inner
5555 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5556 join markers. Generate the before-loop forking sequence in
5557 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5558 general form of these sequences is
5560 GOACC_REDUCTION_SETUP
5561 GOACC_FORK
5562 GOACC_REDUCTION_INIT
5564 GOACC_REDUCTION_FINI
5565 GOACC_JOIN
5566 GOACC_REDUCTION_TEARDOWN. */
5568 static void
5569 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5570 gcall *fork, gcall *join, gimple_seq *fork_seq,
5571 gimple_seq *join_seq, omp_context *ctx)
5573 gimple_seq before_fork = NULL;
5574 gimple_seq after_fork = NULL;
5575 gimple_seq before_join = NULL;
5576 gimple_seq after_join = NULL;
5577 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5578 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5579 unsigned offset = 0;
5581 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5582 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5584 tree orig = OMP_CLAUSE_DECL (c);
5585 tree var = maybe_lookup_decl (orig, ctx);
5586 tree ref_to_res = NULL_TREE;
5587 tree incoming, outgoing, v1, v2, v3;
5588 bool is_private = false;
5590 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5591 if (rcode == MINUS_EXPR)
5592 rcode = PLUS_EXPR;
5593 else if (rcode == TRUTH_ANDIF_EXPR)
5594 rcode = BIT_AND_EXPR;
5595 else if (rcode == TRUTH_ORIF_EXPR)
5596 rcode = BIT_IOR_EXPR;
5597 tree op = build_int_cst (unsigned_type_node, rcode);
5599 if (!var)
5600 var = orig;
5602 incoming = outgoing = var;
5604 if (!inner)
5606 /* See if an outer construct also reduces this variable. */
5607 omp_context *outer = ctx;
5609 while (omp_context *probe = outer->outer)
5611 enum gimple_code type = gimple_code (probe->stmt);
5612 tree cls;
5614 switch (type)
5616 case GIMPLE_OMP_FOR:
5617 cls = gimple_omp_for_clauses (probe->stmt);
5618 break;
5620 case GIMPLE_OMP_TARGET:
5621 if (gimple_omp_target_kind (probe->stmt)
5622 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5623 goto do_lookup;
5625 cls = gimple_omp_target_clauses (probe->stmt);
5626 break;
5628 default:
5629 goto do_lookup;
5632 outer = probe;
5633 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5634 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5635 && orig == OMP_CLAUSE_DECL (cls))
5637 incoming = outgoing = lookup_decl (orig, probe);
5638 goto has_outer_reduction;
5640 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5641 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5642 && orig == OMP_CLAUSE_DECL (cls))
5644 is_private = true;
5645 goto do_lookup;
5649 do_lookup:
5650 /* This is the outermost construct with this reduction,
5651 see if there's a mapping for it. */
5652 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5653 && maybe_lookup_field (orig, outer) && !is_private)
5655 ref_to_res = build_receiver_ref (orig, false, outer);
5656 if (is_reference (orig))
5657 ref_to_res = build_simple_mem_ref (ref_to_res);
5659 tree type = TREE_TYPE (var);
5660 if (POINTER_TYPE_P (type))
5661 type = TREE_TYPE (type);
5663 outgoing = var;
5664 incoming = omp_reduction_init_op (loc, rcode, type);
5666 else
5668 /* Try to look at enclosing contexts for reduction var,
5669 use original if no mapping found. */
5670 tree t = NULL_TREE;
5671 omp_context *c = ctx->outer;
5672 while (c && !t)
5674 t = maybe_lookup_decl (orig, c);
5675 c = c->outer;
5677 incoming = outgoing = (t ? t : orig);
5680 has_outer_reduction:;
5683 if (!ref_to_res)
5684 ref_to_res = integer_zero_node;
5686 if (is_reference (orig))
5688 tree type = TREE_TYPE (var);
5689 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5691 if (!inner)
5693 tree x = create_tmp_var (TREE_TYPE (type), id);
5694 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5697 v1 = create_tmp_var (type, id);
5698 v2 = create_tmp_var (type, id);
5699 v3 = create_tmp_var (type, id);
5701 gimplify_assign (v1, var, fork_seq);
5702 gimplify_assign (v2, var, fork_seq);
5703 gimplify_assign (v3, var, fork_seq);
5705 var = build_simple_mem_ref (var);
5706 v1 = build_simple_mem_ref (v1);
5707 v2 = build_simple_mem_ref (v2);
5708 v3 = build_simple_mem_ref (v3);
5709 outgoing = build_simple_mem_ref (outgoing);
5711 if (!TREE_CONSTANT (incoming))
5712 incoming = build_simple_mem_ref (incoming);
5714 else
5715 v1 = v2 = v3 = var;
5717 /* Determine position in reduction buffer, which may be used
5718 by target. */
5719 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5720 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5721 offset = (offset + align - 1) & ~(align - 1);
5722 tree off = build_int_cst (sizetype, offset);
5723 offset += GET_MODE_SIZE (mode);
5725 if (!init_code)
5727 init_code = build_int_cst (integer_type_node,
5728 IFN_GOACC_REDUCTION_INIT);
5729 fini_code = build_int_cst (integer_type_node,
5730 IFN_GOACC_REDUCTION_FINI);
5731 setup_code = build_int_cst (integer_type_node,
5732 IFN_GOACC_REDUCTION_SETUP);
5733 teardown_code = build_int_cst (integer_type_node,
5734 IFN_GOACC_REDUCTION_TEARDOWN);
5737 tree setup_call
5738 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5739 TREE_TYPE (var), 6, setup_code,
5740 unshare_expr (ref_to_res),
5741 incoming, level, op, off);
5742 tree init_call
5743 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5744 TREE_TYPE (var), 6, init_code,
5745 unshare_expr (ref_to_res),
5746 v1, level, op, off);
5747 tree fini_call
5748 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5749 TREE_TYPE (var), 6, fini_code,
5750 unshare_expr (ref_to_res),
5751 v2, level, op, off);
5752 tree teardown_call
5753 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5754 TREE_TYPE (var), 6, teardown_code,
5755 ref_to_res, v3, level, op, off);
5757 gimplify_assign (v1, setup_call, &before_fork);
5758 gimplify_assign (v2, init_call, &after_fork);
5759 gimplify_assign (v3, fini_call, &before_join);
5760 gimplify_assign (outgoing, teardown_call, &after_join);
5763 /* Now stitch things together. */
5764 gimple_seq_add_seq (fork_seq, before_fork);
5765 if (fork)
5766 gimple_seq_add_stmt (fork_seq, fork);
5767 gimple_seq_add_seq (fork_seq, after_fork);
5769 gimple_seq_add_seq (join_seq, before_join);
5770 if (join)
5771 gimple_seq_add_stmt (join_seq, join);
5772 gimple_seq_add_seq (join_seq, after_join);
5775 /* Generate code to implement the REDUCTION clauses. */
5777 static void
5778 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5780 gimple_seq sub_seq = NULL;
5781 gimple *stmt;
5782 tree x, c;
5783 int count = 0;
5785 /* OpenACC loop reductions are handled elsewhere. */
5786 if (is_gimple_omp_oacc (ctx->stmt))
5787 return;
5789 /* SIMD reductions are handled in lower_rec_input_clauses. */
5790 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5791 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5792 return;
5794 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5795 update in that case, otherwise use a lock. */
5796 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5797 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5799 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5800 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5802 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5803 count = -1;
5804 break;
5806 count++;
5809 if (count == 0)
5810 return;
5812 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5814 tree var, ref, new_var, orig_var;
5815 enum tree_code code;
5816 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5818 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5819 continue;
5821 orig_var = var = OMP_CLAUSE_DECL (c);
5822 if (TREE_CODE (var) == MEM_REF)
5824 var = TREE_OPERAND (var, 0);
5825 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5826 var = TREE_OPERAND (var, 0);
5827 if (TREE_CODE (var) == INDIRECT_REF
5828 || TREE_CODE (var) == ADDR_EXPR)
5829 var = TREE_OPERAND (var, 0);
5830 orig_var = var;
5831 if (is_variable_sized (var))
5833 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5834 var = DECL_VALUE_EXPR (var);
5835 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5836 var = TREE_OPERAND (var, 0);
5837 gcc_assert (DECL_P (var));
5840 new_var = lookup_decl (var, ctx);
5841 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5842 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5843 ref = build_outer_var_ref (var, ctx);
5844 code = OMP_CLAUSE_REDUCTION_CODE (c);
5846 /* reduction(-:var) sums up the partial results, so it acts
5847 identically to reduction(+:var). */
5848 if (code == MINUS_EXPR)
5849 code = PLUS_EXPR;
5851 if (count == 1)
5853 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5855 addr = save_expr (addr);
5856 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5857 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5858 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5859 gimplify_and_add (x, stmt_seqp);
5860 return;
5862 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5864 tree d = OMP_CLAUSE_DECL (c);
5865 tree type = TREE_TYPE (d);
5866 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5867 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5868 tree ptype = build_pointer_type (TREE_TYPE (type));
5869 tree bias = TREE_OPERAND (d, 1);
5870 d = TREE_OPERAND (d, 0);
5871 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5873 tree b = TREE_OPERAND (d, 1);
5874 b = maybe_lookup_decl (b, ctx);
5875 if (b == NULL)
5877 b = TREE_OPERAND (d, 1);
5878 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5880 if (integer_zerop (bias))
5881 bias = b;
5882 else
5884 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5885 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5886 TREE_TYPE (b), b, bias);
5888 d = TREE_OPERAND (d, 0);
5890 /* For ref build_outer_var_ref already performs this, so
5891 only new_var needs a dereference. */
5892 if (TREE_CODE (d) == INDIRECT_REF)
5894 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5895 gcc_assert (is_reference (var) && var == orig_var);
5897 else if (TREE_CODE (d) == ADDR_EXPR)
5899 if (orig_var == var)
5901 new_var = build_fold_addr_expr (new_var);
5902 ref = build_fold_addr_expr (ref);
5905 else
5907 gcc_assert (orig_var == var);
5908 if (is_reference (var))
5909 ref = build_fold_addr_expr (ref);
5911 if (DECL_P (v))
5913 tree t = maybe_lookup_decl (v, ctx);
5914 if (t)
5915 v = t;
5916 else
5917 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5918 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5920 if (!integer_zerop (bias))
5922 bias = fold_convert_loc (clause_loc, sizetype, bias);
5923 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5924 TREE_TYPE (new_var), new_var,
5925 unshare_expr (bias));
5926 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5927 TREE_TYPE (ref), ref, bias);
5929 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5930 ref = fold_convert_loc (clause_loc, ptype, ref);
5931 tree m = create_tmp_var (ptype, NULL);
5932 gimplify_assign (m, new_var, stmt_seqp);
5933 new_var = m;
5934 m = create_tmp_var (ptype, NULL);
5935 gimplify_assign (m, ref, stmt_seqp);
5936 ref = m;
5937 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5938 tree body = create_artificial_label (UNKNOWN_LOCATION);
5939 tree end = create_artificial_label (UNKNOWN_LOCATION);
5940 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5941 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5942 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5943 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5945 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5946 tree decl_placeholder
5947 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5948 SET_DECL_VALUE_EXPR (placeholder, out);
5949 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5950 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5951 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5952 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5953 gimple_seq_add_seq (&sub_seq,
5954 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5955 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5956 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5957 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5959 else
5961 x = build2 (code, TREE_TYPE (out), out, priv);
5962 out = unshare_expr (out);
5963 gimplify_assign (out, x, &sub_seq);
5965 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5966 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5967 gimple_seq_add_stmt (&sub_seq, g);
5968 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5969 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5970 gimple_seq_add_stmt (&sub_seq, g);
5971 g = gimple_build_assign (i, PLUS_EXPR, i,
5972 build_int_cst (TREE_TYPE (i), 1));
5973 gimple_seq_add_stmt (&sub_seq, g);
5974 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5975 gimple_seq_add_stmt (&sub_seq, g);
5976 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5978 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5980 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5982 if (is_reference (var)
5983 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5984 TREE_TYPE (ref)))
5985 ref = build_fold_addr_expr_loc (clause_loc, ref);
5986 SET_DECL_VALUE_EXPR (placeholder, ref);
5987 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5988 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5989 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5990 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5991 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5993 else
5995 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5996 ref = build_outer_var_ref (var, ctx);
5997 gimplify_assign (ref, x, &sub_seq);
6001 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
6003 gimple_seq_add_stmt (stmt_seqp, stmt);
6005 gimple_seq_add_seq (stmt_seqp, sub_seq);
6007 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
6009 gimple_seq_add_stmt (stmt_seqp, stmt);
6013 /* Generate code to implement the COPYPRIVATE clauses. */
6015 static void
6016 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6017 omp_context *ctx)
6019 tree c;
6021 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6023 tree var, new_var, ref, x;
6024 bool by_ref;
6025 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6027 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6028 continue;
6030 var = OMP_CLAUSE_DECL (c);
6031 by_ref = use_pointer_for_field (var, NULL);
6033 ref = build_sender_ref (var, ctx);
6034 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6035 if (by_ref)
6037 x = build_fold_addr_expr_loc (clause_loc, new_var);
6038 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6040 gimplify_assign (ref, x, slist);
6042 ref = build_receiver_ref (var, false, ctx);
6043 if (by_ref)
6045 ref = fold_convert_loc (clause_loc,
6046 build_pointer_type (TREE_TYPE (new_var)),
6047 ref);
6048 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6050 if (is_reference (var))
6052 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6053 ref = build_simple_mem_ref_loc (clause_loc, ref);
6054 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6056 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6057 gimplify_and_add (x, rlist);
6062 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6063 and REDUCTION from the sender (aka parent) side. */
6065 static void
6066 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6067 omp_context *ctx)
6069 tree c, t;
6070 int ignored_looptemp = 0;
6071 bool is_taskloop = false;
6073 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6074 by GOMP_taskloop. */
6075 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6077 ignored_looptemp = 2;
6078 is_taskloop = true;
6081 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6083 tree val, ref, x, var;
6084 bool by_ref, do_in = false, do_out = false;
6085 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6087 switch (OMP_CLAUSE_CODE (c))
6089 case OMP_CLAUSE_PRIVATE:
6090 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6091 break;
6092 continue;
6093 case OMP_CLAUSE_FIRSTPRIVATE:
6094 case OMP_CLAUSE_COPYIN:
6095 case OMP_CLAUSE_LASTPRIVATE:
6096 case OMP_CLAUSE_REDUCTION:
6097 break;
6098 case OMP_CLAUSE_SHARED:
6099 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6100 break;
6101 continue;
6102 case OMP_CLAUSE__LOOPTEMP_:
6103 if (ignored_looptemp)
6105 ignored_looptemp--;
6106 continue;
6108 break;
6109 default:
6110 continue;
6113 val = OMP_CLAUSE_DECL (c);
6114 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6115 && TREE_CODE (val) == MEM_REF)
6117 val = TREE_OPERAND (val, 0);
6118 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6119 val = TREE_OPERAND (val, 0);
6120 if (TREE_CODE (val) == INDIRECT_REF
6121 || TREE_CODE (val) == ADDR_EXPR)
6122 val = TREE_OPERAND (val, 0);
6123 if (is_variable_sized (val))
6124 continue;
6127 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6128 outer taskloop region. */
6129 omp_context *ctx_for_o = ctx;
6130 if (is_taskloop
6131 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6132 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6133 ctx_for_o = ctx->outer;
6135 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6137 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6138 && is_global_var (var))
6139 continue;
6141 t = omp_member_access_dummy_var (var);
6142 if (t)
6144 var = DECL_VALUE_EXPR (var);
6145 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6146 if (o != t)
6147 var = unshare_and_remap (var, t, o);
6148 else
6149 var = unshare_expr (var);
6152 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6154 /* Handle taskloop firstprivate/lastprivate, where the
6155 lastprivate on GIMPLE_OMP_TASK is represented as
6156 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6157 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6158 x = omp_build_component_ref (ctx->sender_decl, f);
6159 if (use_pointer_for_field (val, ctx))
6160 var = build_fold_addr_expr (var);
6161 gimplify_assign (x, var, ilist);
6162 DECL_ABSTRACT_ORIGIN (f) = NULL;
6163 continue;
6166 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6167 || val == OMP_CLAUSE_DECL (c))
6168 && is_variable_sized (val))
6169 continue;
6170 by_ref = use_pointer_for_field (val, NULL);
6172 switch (OMP_CLAUSE_CODE (c))
6174 case OMP_CLAUSE_FIRSTPRIVATE:
6175 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6176 && !by_ref
6177 && is_task_ctx (ctx))
6178 TREE_NO_WARNING (var) = 1;
6179 do_in = true;
6180 break;
6182 case OMP_CLAUSE_PRIVATE:
6183 case OMP_CLAUSE_COPYIN:
6184 case OMP_CLAUSE__LOOPTEMP_:
6185 do_in = true;
6186 break;
6188 case OMP_CLAUSE_LASTPRIVATE:
6189 if (by_ref || is_reference (val))
6191 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6192 continue;
6193 do_in = true;
6195 else
6197 do_out = true;
6198 if (lang_hooks.decls.omp_private_outer_ref (val))
6199 do_in = true;
6201 break;
6203 case OMP_CLAUSE_REDUCTION:
6204 do_in = true;
6205 if (val == OMP_CLAUSE_DECL (c))
6206 do_out = !(by_ref || is_reference (val));
6207 else
6208 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6209 break;
6211 default:
6212 gcc_unreachable ();
6215 if (do_in)
6217 ref = build_sender_ref (val, ctx);
6218 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6219 gimplify_assign (ref, x, ilist);
6220 if (is_task_ctx (ctx))
6221 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6224 if (do_out)
6226 ref = build_sender_ref (val, ctx);
6227 gimplify_assign (var, ref, olist);
6232 /* Generate code to implement SHARED from the sender (aka parent)
6233 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6234 list things that got automatically shared. */
6236 static void
6237 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6239 tree var, ovar, nvar, t, f, x, record_type;
6241 if (ctx->record_type == NULL)
6242 return;
6244 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6245 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6247 ovar = DECL_ABSTRACT_ORIGIN (f);
6248 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6249 continue;
6251 nvar = maybe_lookup_decl (ovar, ctx);
6252 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6253 continue;
6255 /* If CTX is a nested parallel directive. Find the immediately
6256 enclosing parallel or workshare construct that contains a
6257 mapping for OVAR. */
6258 var = lookup_decl_in_outer_ctx (ovar, ctx);
6260 t = omp_member_access_dummy_var (var);
6261 if (t)
6263 var = DECL_VALUE_EXPR (var);
6264 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6265 if (o != t)
6266 var = unshare_and_remap (var, t, o);
6267 else
6268 var = unshare_expr (var);
6271 if (use_pointer_for_field (ovar, ctx))
6273 x = build_sender_ref (ovar, ctx);
6274 var = build_fold_addr_expr (var);
6275 gimplify_assign (x, var, ilist);
6277 else
6279 x = build_sender_ref (ovar, ctx);
6280 gimplify_assign (x, var, ilist);
6282 if (!TREE_READONLY (var)
6283 /* We don't need to receive a new reference to a result
6284 or parm decl. In fact we may not store to it as we will
6285 invalidate any pending RSO and generate wrong gimple
6286 during inlining. */
6287 && !((TREE_CODE (var) == RESULT_DECL
6288 || TREE_CODE (var) == PARM_DECL)
6289 && DECL_BY_REFERENCE (var)))
6291 x = build_sender_ref (ovar, ctx);
6292 gimplify_assign (var, x, olist);
6298 /* Emit an OpenACC head marker call, encapulating the partitioning and
6299 other information that must be processed by the target compiler.
6300 Return the maximum number of dimensions the associated loop might
6301 be partitioned over. */
6303 static unsigned
6304 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6305 gimple_seq *seq, omp_context *ctx)
6307 unsigned levels = 0;
6308 unsigned tag = 0;
6309 tree gang_static = NULL_TREE;
6310 auto_vec<tree, 5> args;
6312 args.quick_push (build_int_cst
6313 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6314 args.quick_push (ddvar);
6315 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6317 switch (OMP_CLAUSE_CODE (c))
6319 case OMP_CLAUSE_GANG:
6320 tag |= OLF_DIM_GANG;
6321 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6322 /* static:* is represented by -1, and we can ignore it, as
6323 scheduling is always static. */
6324 if (gang_static && integer_minus_onep (gang_static))
6325 gang_static = NULL_TREE;
6326 levels++;
6327 break;
6329 case OMP_CLAUSE_WORKER:
6330 tag |= OLF_DIM_WORKER;
6331 levels++;
6332 break;
6334 case OMP_CLAUSE_VECTOR:
6335 tag |= OLF_DIM_VECTOR;
6336 levels++;
6337 break;
6339 case OMP_CLAUSE_SEQ:
6340 tag |= OLF_SEQ;
6341 break;
6343 case OMP_CLAUSE_AUTO:
6344 tag |= OLF_AUTO;
6345 break;
6347 case OMP_CLAUSE_INDEPENDENT:
6348 tag |= OLF_INDEPENDENT;
6349 break;
6351 default:
6352 continue;
6356 if (gang_static)
6358 if (DECL_P (gang_static))
6359 gang_static = build_outer_var_ref (gang_static, ctx);
6360 tag |= OLF_GANG_STATIC;
6363 /* In a parallel region, loops are implicitly INDEPENDENT. */
6364 omp_context *tgt = enclosing_target_ctx (ctx);
6365 if (!tgt || is_oacc_parallel (tgt))
6366 tag |= OLF_INDEPENDENT;
6368 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6369 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6370 | OLF_SEQ)))
6371 tag |= OLF_AUTO;
6373 /* Ensure at least one level. */
6374 if (!levels)
6375 levels++;
6377 args.quick_push (build_int_cst (integer_type_node, levels));
6378 args.quick_push (build_int_cst (integer_type_node, tag));
6379 if (gang_static)
6380 args.quick_push (gang_static);
6382 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6383 gimple_set_location (call, loc);
6384 gimple_set_lhs (call, ddvar);
6385 gimple_seq_add_stmt (seq, call);
6387 return levels;
6390 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6391 partitioning level of the enclosed region. */
6393 static void
6394 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6395 tree tofollow, gimple_seq *seq)
6397 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6398 : IFN_UNIQUE_OACC_TAIL_MARK);
6399 tree marker = build_int_cst (integer_type_node, marker_kind);
6400 int nargs = 2 + (tofollow != NULL_TREE);
6401 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6402 marker, ddvar, tofollow);
6403 gimple_set_location (call, loc);
6404 gimple_set_lhs (call, ddvar);
6405 gimple_seq_add_stmt (seq, call);
6408 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6409 the loop clauses, from which we extract reductions. Initialize
6410 HEAD and TAIL. */
6412 static void
6413 lower_oacc_head_tail (location_t loc, tree clauses,
6414 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6416 bool inner = false;
6417 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6418 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6420 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6421 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6422 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6424 gcc_assert (count);
6425 for (unsigned done = 1; count; count--, done++)
6427 gimple_seq fork_seq = NULL;
6428 gimple_seq join_seq = NULL;
6430 tree place = build_int_cst (integer_type_node, -1);
6431 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6432 fork_kind, ddvar, place);
6433 gimple_set_location (fork, loc);
6434 gimple_set_lhs (fork, ddvar);
6436 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6437 join_kind, ddvar, place);
6438 gimple_set_location (join, loc);
6439 gimple_set_lhs (join, ddvar);
6441 /* Mark the beginning of this level sequence. */
6442 if (inner)
6443 lower_oacc_loop_marker (loc, ddvar, true,
6444 build_int_cst (integer_type_node, count),
6445 &fork_seq);
6446 lower_oacc_loop_marker (loc, ddvar, false,
6447 build_int_cst (integer_type_node, done),
6448 &join_seq);
6450 lower_oacc_reductions (loc, clauses, place, inner,
6451 fork, join, &fork_seq, &join_seq, ctx);
6453 /* Append this level to head. */
6454 gimple_seq_add_seq (head, fork_seq);
6455 /* Prepend it to tail. */
6456 gimple_seq_add_seq (&join_seq, *tail);
6457 *tail = join_seq;
6459 inner = true;
6462 /* Mark the end of the sequence. */
6463 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6464 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6467 /* A convenience function to build an empty GIMPLE_COND with just the
6468 condition. */
6470 static gcond *
6471 gimple_build_cond_empty (tree cond)
6473 enum tree_code pred_code;
6474 tree lhs, rhs;
6476 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6477 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6480 /* Return true if a parallel REGION is within a declare target function or
6481 within a target region and is not a part of a gridified target. */
6483 static bool
6484 parallel_needs_hsa_kernel_p (struct omp_region *region)
6486 bool indirect = false;
6487 for (region = region->outer; region; region = region->outer)
6489 if (region->type == GIMPLE_OMP_PARALLEL)
6490 indirect = true;
6491 else if (region->type == GIMPLE_OMP_TARGET)
6493 gomp_target *tgt_stmt
6494 = as_a <gomp_target *> (last_stmt (region->entry));
6496 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6497 OMP_CLAUSE__GRIDDIM_))
6498 return indirect;
6499 else
6500 return true;
6504 if (lookup_attribute ("omp declare target",
6505 DECL_ATTRIBUTES (current_function_decl)))
6506 return true;
6508 return false;
6511 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6512 bool = false);
6514 /* Build the function calls to GOMP_parallel_start etc to actually
6515 generate the parallel operation. REGION is the parallel region
6516 being expanded. BB is the block where to insert the code. WS_ARGS
6517 will be set if this is a call to a combined parallel+workshare
6518 construct, it contains the list of additional arguments needed by
6519 the workshare construct. */
6521 static void
6522 expand_parallel_call (struct omp_region *region, basic_block bb,
6523 gomp_parallel *entry_stmt,
6524 vec<tree, va_gc> *ws_args)
6526 tree t, t1, t2, val, cond, c, clauses, flags;
6527 gimple_stmt_iterator gsi;
6528 gimple *stmt;
6529 enum built_in_function start_ix;
6530 int start_ix2;
6531 location_t clause_loc;
6532 vec<tree, va_gc> *args;
6534 clauses = gimple_omp_parallel_clauses (entry_stmt);
6536 /* Determine what flavor of GOMP_parallel we will be
6537 emitting. */
6538 start_ix = BUILT_IN_GOMP_PARALLEL;
6539 if (is_combined_parallel (region))
6541 switch (region->inner->type)
6543 case GIMPLE_OMP_FOR:
6544 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6545 switch (region->inner->sched_kind)
6547 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6548 start_ix2 = 3;
6549 break;
6550 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6551 case OMP_CLAUSE_SCHEDULE_GUIDED:
6552 if (region->inner->sched_modifiers
6553 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6555 start_ix2 = 3 + region->inner->sched_kind;
6556 break;
6558 /* FALLTHRU */
6559 default:
6560 start_ix2 = region->inner->sched_kind;
6561 break;
6563 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6564 start_ix = (enum built_in_function) start_ix2;
6565 break;
6566 case GIMPLE_OMP_SECTIONS:
6567 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6568 break;
6569 default:
6570 gcc_unreachable ();
6574 /* By default, the value of NUM_THREADS is zero (selected at run time)
6575 and there is no conditional. */
6576 cond = NULL_TREE;
6577 val = build_int_cst (unsigned_type_node, 0);
6578 flags = build_int_cst (unsigned_type_node, 0);
6580 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6581 if (c)
6582 cond = OMP_CLAUSE_IF_EXPR (c);
6584 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6585 if (c)
6587 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6588 clause_loc = OMP_CLAUSE_LOCATION (c);
6590 else
6591 clause_loc = gimple_location (entry_stmt);
6593 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6594 if (c)
6595 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6597 /* Ensure 'val' is of the correct type. */
6598 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6600 /* If we found the clause 'if (cond)', build either
6601 (cond != 0) or (cond ? val : 1u). */
6602 if (cond)
6604 cond = gimple_boolify (cond);
6606 if (integer_zerop (val))
6607 val = fold_build2_loc (clause_loc,
6608 EQ_EXPR, unsigned_type_node, cond,
6609 build_int_cst (TREE_TYPE (cond), 0));
6610 else
6612 basic_block cond_bb, then_bb, else_bb;
6613 edge e, e_then, e_else;
6614 tree tmp_then, tmp_else, tmp_join, tmp_var;
6616 tmp_var = create_tmp_var (TREE_TYPE (val));
6617 if (gimple_in_ssa_p (cfun))
6619 tmp_then = make_ssa_name (tmp_var);
6620 tmp_else = make_ssa_name (tmp_var);
6621 tmp_join = make_ssa_name (tmp_var);
6623 else
6625 tmp_then = tmp_var;
6626 tmp_else = tmp_var;
6627 tmp_join = tmp_var;
6630 e = split_block_after_labels (bb);
6631 cond_bb = e->src;
6632 bb = e->dest;
6633 remove_edge (e);
6635 then_bb = create_empty_bb (cond_bb);
6636 else_bb = create_empty_bb (then_bb);
6637 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6638 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6640 stmt = gimple_build_cond_empty (cond);
6641 gsi = gsi_start_bb (cond_bb);
6642 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6644 gsi = gsi_start_bb (then_bb);
6645 expand_omp_build_assign (&gsi, tmp_then, val, true);
6647 gsi = gsi_start_bb (else_bb);
6648 expand_omp_build_assign (&gsi, tmp_else,
6649 build_int_cst (unsigned_type_node, 1),
6650 true);
6652 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6653 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6654 add_bb_to_loop (then_bb, cond_bb->loop_father);
6655 add_bb_to_loop (else_bb, cond_bb->loop_father);
6656 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6657 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6659 if (gimple_in_ssa_p (cfun))
6661 gphi *phi = create_phi_node (tmp_join, bb);
6662 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6663 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6666 val = tmp_join;
6669 gsi = gsi_start_bb (bb);
6670 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6671 false, GSI_CONTINUE_LINKING);
6674 gsi = gsi_last_bb (bb);
6675 t = gimple_omp_parallel_data_arg (entry_stmt);
6676 if (t == NULL)
6677 t1 = null_pointer_node;
6678 else
6679 t1 = build_fold_addr_expr (t);
6680 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6681 t2 = build_fold_addr_expr (child_fndecl);
6683 vec_alloc (args, 4 + vec_safe_length (ws_args));
6684 args->quick_push (t2);
6685 args->quick_push (t1);
6686 args->quick_push (val);
6687 if (ws_args)
6688 args->splice (*ws_args);
6689 args->quick_push (flags);
6691 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6692 builtin_decl_explicit (start_ix), args);
6694 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6695 false, GSI_CONTINUE_LINKING);
6697 if (hsa_gen_requested_p ()
6698 && parallel_needs_hsa_kernel_p (region))
6700 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6701 hsa_register_kernel (child_cnode);
6705 /* Insert a function call whose name is FUNC_NAME with the information from
6706 ENTRY_STMT into the basic_block BB. */
6708 static void
6709 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6710 vec <tree, va_gc> *ws_args)
6712 tree t, t1, t2;
6713 gimple_stmt_iterator gsi;
6714 vec <tree, va_gc> *args;
6716 gcc_assert (vec_safe_length (ws_args) == 2);
6717 tree func_name = (*ws_args)[0];
6718 tree grain = (*ws_args)[1];
6720 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6721 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6722 gcc_assert (count != NULL_TREE);
6723 count = OMP_CLAUSE_OPERAND (count, 0);
6725 gsi = gsi_last_bb (bb);
6726 t = gimple_omp_parallel_data_arg (entry_stmt);
6727 if (t == NULL)
6728 t1 = null_pointer_node;
6729 else
6730 t1 = build_fold_addr_expr (t);
6731 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6733 vec_alloc (args, 4);
6734 args->quick_push (t2);
6735 args->quick_push (t1);
6736 args->quick_push (count);
6737 args->quick_push (grain);
6738 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6740 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6741 GSI_CONTINUE_LINKING);
6744 /* Build the function call to GOMP_task to actually
6745 generate the task operation. BB is the block where to insert the code. */
6747 static void
6748 expand_task_call (struct omp_region *region, basic_block bb,
6749 gomp_task *entry_stmt)
6751 tree t1, t2, t3;
6752 gimple_stmt_iterator gsi;
6753 location_t loc = gimple_location (entry_stmt);
6755 tree clauses = gimple_omp_task_clauses (entry_stmt);
6757 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6758 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6759 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6760 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6761 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6762 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6764 unsigned int iflags
6765 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6766 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6767 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6769 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6770 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6771 tree num_tasks = NULL_TREE;
6772 bool ull = false;
6773 if (taskloop_p)
6775 gimple *g = last_stmt (region->outer->entry);
6776 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6777 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6778 struct omp_for_data fd;
6779 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6780 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6781 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6782 OMP_CLAUSE__LOOPTEMP_);
6783 startvar = OMP_CLAUSE_DECL (startvar);
6784 endvar = OMP_CLAUSE_DECL (endvar);
6785 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6786 if (fd.loop.cond_code == LT_EXPR)
6787 iflags |= GOMP_TASK_FLAG_UP;
6788 tree tclauses = gimple_omp_for_clauses (g);
6789 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6790 if (num_tasks)
6791 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6792 else
6794 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6795 if (num_tasks)
6797 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6798 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6800 else
6801 num_tasks = integer_zero_node;
6803 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6804 if (ifc == NULL_TREE)
6805 iflags |= GOMP_TASK_FLAG_IF;
6806 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6807 iflags |= GOMP_TASK_FLAG_NOGROUP;
6808 ull = fd.iter_type == long_long_unsigned_type_node;
6810 else if (priority)
6811 iflags |= GOMP_TASK_FLAG_PRIORITY;
6813 tree flags = build_int_cst (unsigned_type_node, iflags);
6815 tree cond = boolean_true_node;
6816 if (ifc)
6818 if (taskloop_p)
6820 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6821 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6822 build_int_cst (unsigned_type_node,
6823 GOMP_TASK_FLAG_IF),
6824 build_int_cst (unsigned_type_node, 0));
6825 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6826 flags, t);
6828 else
6829 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6832 if (finalc)
6834 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6835 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6836 build_int_cst (unsigned_type_node,
6837 GOMP_TASK_FLAG_FINAL),
6838 build_int_cst (unsigned_type_node, 0));
6839 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6841 if (depend)
6842 depend = OMP_CLAUSE_DECL (depend);
6843 else
6844 depend = build_int_cst (ptr_type_node, 0);
6845 if (priority)
6846 priority = fold_convert (integer_type_node,
6847 OMP_CLAUSE_PRIORITY_EXPR (priority));
6848 else
6849 priority = integer_zero_node;
6851 gsi = gsi_last_bb (bb);
6852 tree t = gimple_omp_task_data_arg (entry_stmt);
6853 if (t == NULL)
6854 t2 = null_pointer_node;
6855 else
6856 t2 = build_fold_addr_expr_loc (loc, t);
6857 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6858 t = gimple_omp_task_copy_fn (entry_stmt);
6859 if (t == NULL)
6860 t3 = null_pointer_node;
6861 else
6862 t3 = build_fold_addr_expr_loc (loc, t);
6864 if (taskloop_p)
6865 t = build_call_expr (ull
6866 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6867 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6868 11, t1, t2, t3,
6869 gimple_omp_task_arg_size (entry_stmt),
6870 gimple_omp_task_arg_align (entry_stmt), flags,
6871 num_tasks, priority, startvar, endvar, step);
6872 else
6873 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6874 9, t1, t2, t3,
6875 gimple_omp_task_arg_size (entry_stmt),
6876 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6877 depend, priority);
6879 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6880 false, GSI_CONTINUE_LINKING);
6884 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6885 catch handler and return it. This prevents programs from violating the
6886 structured block semantics with throws. */
6888 static gimple_seq
6889 maybe_catch_exception (gimple_seq body)
6891 gimple *g;
6892 tree decl;
6894 if (!flag_exceptions)
6895 return body;
6897 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6898 decl = lang_hooks.eh_protect_cleanup_actions ();
6899 else
6900 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6902 g = gimple_build_eh_must_not_throw (decl);
6903 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6904 GIMPLE_TRY_CATCH);
6906 return gimple_seq_alloc_with_stmt (g);
6909 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6911 static tree
6912 vec2chain (vec<tree, va_gc> *v)
6914 tree chain = NULL_TREE, t;
6915 unsigned ix;
6917 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6919 DECL_CHAIN (t) = chain;
6920 chain = t;
6923 return chain;
6927 /* Remove barriers in REGION->EXIT's block. Note that this is only
6928 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6929 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6930 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6931 removed. */
6933 static void
6934 remove_exit_barrier (struct omp_region *region)
6936 gimple_stmt_iterator gsi;
6937 basic_block exit_bb;
6938 edge_iterator ei;
6939 edge e;
6940 gimple *stmt;
6941 int any_addressable_vars = -1;
6943 exit_bb = region->exit;
6945 /* If the parallel region doesn't return, we don't have REGION->EXIT
6946 block at all. */
6947 if (! exit_bb)
6948 return;
6950 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6951 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6952 statements that can appear in between are extremely limited -- no
6953 memory operations at all. Here, we allow nothing at all, so the
6954 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6955 gsi = gsi_last_bb (exit_bb);
6956 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6957 gsi_prev (&gsi);
6958 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6959 return;
6961 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6963 gsi = gsi_last_bb (e->src);
6964 if (gsi_end_p (gsi))
6965 continue;
6966 stmt = gsi_stmt (gsi);
6967 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6968 && !gimple_omp_return_nowait_p (stmt))
6970 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6971 in many cases. If there could be tasks queued, the barrier
6972 might be needed to let the tasks run before some local
6973 variable of the parallel that the task uses as shared
6974 runs out of scope. The task can be spawned either
6975 from within current function (this would be easy to check)
6976 or from some function it calls and gets passed an address
6977 of such a variable. */
6978 if (any_addressable_vars < 0)
6980 gomp_parallel *parallel_stmt
6981 = as_a <gomp_parallel *> (last_stmt (region->entry));
6982 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6983 tree local_decls, block, decl;
6984 unsigned ix;
6986 any_addressable_vars = 0;
6987 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6988 if (TREE_ADDRESSABLE (decl))
6990 any_addressable_vars = 1;
6991 break;
6993 for (block = gimple_block (stmt);
6994 !any_addressable_vars
6995 && block
6996 && TREE_CODE (block) == BLOCK;
6997 block = BLOCK_SUPERCONTEXT (block))
6999 for (local_decls = BLOCK_VARS (block);
7000 local_decls;
7001 local_decls = DECL_CHAIN (local_decls))
7002 if (TREE_ADDRESSABLE (local_decls))
7004 any_addressable_vars = 1;
7005 break;
7007 if (block == gimple_block (parallel_stmt))
7008 break;
7011 if (!any_addressable_vars)
7012 gimple_omp_return_set_nowait (stmt);
7017 static void
7018 remove_exit_barriers (struct omp_region *region)
7020 if (region->type == GIMPLE_OMP_PARALLEL)
7021 remove_exit_barrier (region);
7023 if (region->inner)
7025 region = region->inner;
7026 remove_exit_barriers (region);
7027 while (region->next)
7029 region = region->next;
7030 remove_exit_barriers (region);
7035 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7036 calls. These can't be declared as const functions, but
7037 within one parallel body they are constant, so they can be
7038 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7039 which are declared const. Similarly for task body, except
7040 that in untied task omp_get_thread_num () can change at any task
7041 scheduling point. */
7043 static void
7044 optimize_omp_library_calls (gimple *entry_stmt)
7046 basic_block bb;
7047 gimple_stmt_iterator gsi;
7048 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7049 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7050 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7051 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7052 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7053 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7054 OMP_CLAUSE_UNTIED) != NULL);
7056 FOR_EACH_BB_FN (bb, cfun)
7057 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7059 gimple *call = gsi_stmt (gsi);
7060 tree decl;
7062 if (is_gimple_call (call)
7063 && (decl = gimple_call_fndecl (call))
7064 && DECL_EXTERNAL (decl)
7065 && TREE_PUBLIC (decl)
7066 && DECL_INITIAL (decl) == NULL)
7068 tree built_in;
7070 if (DECL_NAME (decl) == thr_num_id)
7072 /* In #pragma omp task untied omp_get_thread_num () can change
7073 during the execution of the task region. */
7074 if (untied_task)
7075 continue;
7076 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7078 else if (DECL_NAME (decl) == num_thr_id)
7079 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7080 else
7081 continue;
7083 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7084 || gimple_call_num_args (call) != 0)
7085 continue;
7087 if (flag_exceptions && !TREE_NOTHROW (decl))
7088 continue;
7090 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7091 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7092 TREE_TYPE (TREE_TYPE (built_in))))
7093 continue;
7095 gimple_call_set_fndecl (call, built_in);
7100 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7101 regimplified. */
7103 static tree
7104 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7106 tree t = *tp;
7108 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7109 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
7110 return t;
7112 if (TREE_CODE (t) == ADDR_EXPR)
7113 recompute_tree_invariant_for_addr_expr (t);
7115 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7116 return NULL_TREE;
7119 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7121 static void
7122 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7123 bool after)
7125 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7126 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7127 !after, after ? GSI_CONTINUE_LINKING
7128 : GSI_SAME_STMT);
7129 gimple *stmt = gimple_build_assign (to, from);
7130 if (after)
7131 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7132 else
7133 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7134 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7135 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7137 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7138 gimple_regimplify_operands (stmt, &gsi);
7142 /* Expand the OpenMP parallel or task directive starting at REGION. */
7144 static void
7145 expand_omp_taskreg (struct omp_region *region)
7147 basic_block entry_bb, exit_bb, new_bb;
7148 struct function *child_cfun;
7149 tree child_fn, block, t;
7150 gimple_stmt_iterator gsi;
7151 gimple *entry_stmt, *stmt;
7152 edge e;
7153 vec<tree, va_gc> *ws_args;
7155 entry_stmt = last_stmt (region->entry);
7156 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7157 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7159 entry_bb = region->entry;
7160 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7161 exit_bb = region->cont;
7162 else
7163 exit_bb = region->exit;
7165 bool is_cilk_for
7166 = (flag_cilkplus
7167 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7168 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7169 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7171 if (is_cilk_for)
7172 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7173 and the inner statement contains the name of the built-in function
7174 and grain. */
7175 ws_args = region->inner->ws_args;
7176 else if (is_combined_parallel (region))
7177 ws_args = region->ws_args;
7178 else
7179 ws_args = NULL;
7181 if (child_cfun->cfg)
7183 /* Due to inlining, it may happen that we have already outlined
7184 the region, in which case all we need to do is make the
7185 sub-graph unreachable and emit the parallel call. */
7186 edge entry_succ_e, exit_succ_e;
7188 entry_succ_e = single_succ_edge (entry_bb);
7190 gsi = gsi_last_bb (entry_bb);
7191 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7192 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7193 gsi_remove (&gsi, true);
7195 new_bb = entry_bb;
7196 if (exit_bb)
7198 exit_succ_e = single_succ_edge (exit_bb);
7199 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7201 remove_edge_and_dominated_blocks (entry_succ_e);
7203 else
7205 unsigned srcidx, dstidx, num;
7207 /* If the parallel region needs data sent from the parent
7208 function, then the very first statement (except possible
7209 tree profile counter updates) of the parallel body
7210 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7211 &.OMP_DATA_O is passed as an argument to the child function,
7212 we need to replace it with the argument as seen by the child
7213 function.
7215 In most cases, this will end up being the identity assignment
7216 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7217 a function call that has been inlined, the original PARM_DECL
7218 .OMP_DATA_I may have been converted into a different local
7219 variable. In which case, we need to keep the assignment. */
7220 if (gimple_omp_taskreg_data_arg (entry_stmt))
7222 basic_block entry_succ_bb
7223 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7224 : FALLTHRU_EDGE (entry_bb)->dest;
7225 tree arg;
7226 gimple *parcopy_stmt = NULL;
7228 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7230 gimple *stmt;
7232 gcc_assert (!gsi_end_p (gsi));
7233 stmt = gsi_stmt (gsi);
7234 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7235 continue;
7237 if (gimple_num_ops (stmt) == 2)
7239 tree arg = gimple_assign_rhs1 (stmt);
7241 /* We're ignore the subcode because we're
7242 effectively doing a STRIP_NOPS. */
7244 if (TREE_CODE (arg) == ADDR_EXPR
7245 && TREE_OPERAND (arg, 0)
7246 == gimple_omp_taskreg_data_arg (entry_stmt))
7248 parcopy_stmt = stmt;
7249 break;
7254 gcc_assert (parcopy_stmt != NULL);
7255 arg = DECL_ARGUMENTS (child_fn);
7257 if (!gimple_in_ssa_p (cfun))
7259 if (gimple_assign_lhs (parcopy_stmt) == arg)
7260 gsi_remove (&gsi, true);
7261 else
7263 /* ?? Is setting the subcode really necessary ?? */
7264 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7265 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7268 else
7270 tree lhs = gimple_assign_lhs (parcopy_stmt);
7271 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7272 /* We'd like to set the rhs to the default def in the child_fn,
7273 but it's too early to create ssa names in the child_fn.
7274 Instead, we set the rhs to the parm. In
7275 move_sese_region_to_fn, we introduce a default def for the
7276 parm, map the parm to it's default def, and once we encounter
7277 this stmt, replace the parm with the default def. */
7278 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7279 update_stmt (parcopy_stmt);
7283 /* Declare local variables needed in CHILD_CFUN. */
7284 block = DECL_INITIAL (child_fn);
7285 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7286 /* The gimplifier could record temporaries in parallel/task block
7287 rather than in containing function's local_decls chain,
7288 which would mean cgraph missed finalizing them. Do it now. */
7289 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7290 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
7291 varpool_node::finalize_decl (t);
7292 DECL_SAVED_TREE (child_fn) = NULL;
7293 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7294 gimple_set_body (child_fn, NULL);
7295 TREE_USED (block) = 1;
7297 /* Reset DECL_CONTEXT on function arguments. */
7298 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7299 DECL_CONTEXT (t) = child_fn;
7301 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7302 so that it can be moved to the child function. */
7303 gsi = gsi_last_bb (entry_bb);
7304 stmt = gsi_stmt (gsi);
7305 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7306 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7307 e = split_block (entry_bb, stmt);
7308 gsi_remove (&gsi, true);
7309 entry_bb = e->dest;
7310 edge e2 = NULL;
7311 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7312 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7313 else
7315 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7316 gcc_assert (e2->dest == region->exit);
7317 remove_edge (BRANCH_EDGE (entry_bb));
7318 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7319 gsi = gsi_last_bb (region->exit);
7320 gcc_assert (!gsi_end_p (gsi)
7321 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7322 gsi_remove (&gsi, true);
7325 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7326 if (exit_bb)
7328 gsi = gsi_last_bb (exit_bb);
7329 gcc_assert (!gsi_end_p (gsi)
7330 && (gimple_code (gsi_stmt (gsi))
7331 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7332 stmt = gimple_build_return (NULL);
7333 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7334 gsi_remove (&gsi, true);
7337 /* Move the parallel region into CHILD_CFUN. */
7339 if (gimple_in_ssa_p (cfun))
7341 init_tree_ssa (child_cfun);
7342 init_ssa_operands (child_cfun);
7343 child_cfun->gimple_df->in_ssa_p = true;
7344 block = NULL_TREE;
7346 else
7347 block = gimple_block (entry_stmt);
7349 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7350 if (exit_bb)
7351 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7352 if (e2)
7354 basic_block dest_bb = e2->dest;
7355 if (!exit_bb)
7356 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7357 remove_edge (e2);
7358 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7360 /* When the OMP expansion process cannot guarantee an up-to-date
7361 loop tree arrange for the child function to fixup loops. */
7362 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7363 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7365 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7366 num = vec_safe_length (child_cfun->local_decls);
7367 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7369 t = (*child_cfun->local_decls)[srcidx];
7370 if (DECL_CONTEXT (t) == cfun->decl)
7371 continue;
7372 if (srcidx != dstidx)
7373 (*child_cfun->local_decls)[dstidx] = t;
7374 dstidx++;
7376 if (dstidx != num)
7377 vec_safe_truncate (child_cfun->local_decls, dstidx);
7379 /* Inform the callgraph about the new function. */
7380 child_cfun->curr_properties = cfun->curr_properties;
7381 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7382 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7383 cgraph_node *node = cgraph_node::get_create (child_fn);
7384 node->parallelized_function = 1;
7385 cgraph_node::add_new_function (child_fn, true);
7387 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7388 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7390 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7391 fixed in a following pass. */
7392 push_cfun (child_cfun);
7393 if (need_asm)
7394 assign_assembler_name_if_neeeded (child_fn);
7396 if (optimize)
7397 optimize_omp_library_calls (entry_stmt);
7398 cgraph_edge::rebuild_edges ();
7400 /* Some EH regions might become dead, see PR34608. If
7401 pass_cleanup_cfg isn't the first pass to happen with the
7402 new child, these dead EH edges might cause problems.
7403 Clean them up now. */
7404 if (flag_exceptions)
7406 basic_block bb;
7407 bool changed = false;
7409 FOR_EACH_BB_FN (bb, cfun)
7410 changed |= gimple_purge_dead_eh_edges (bb);
7411 if (changed)
7412 cleanup_tree_cfg ();
7414 if (gimple_in_ssa_p (cfun))
7415 update_ssa (TODO_update_ssa);
7416 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7417 verify_loop_structure ();
7418 pop_cfun ();
7420 if (dump_file && !gimple_in_ssa_p (cfun))
7422 omp_any_child_fn_dumped = true;
7423 dump_function_header (dump_file, child_fn, dump_flags);
7424 dump_function_to_file (child_fn, dump_file, dump_flags);
7428 /* Emit a library call to launch the children threads. */
7429 if (is_cilk_for)
7430 expand_cilk_for_call (new_bb,
7431 as_a <gomp_parallel *> (entry_stmt), ws_args);
7432 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7433 expand_parallel_call (region, new_bb,
7434 as_a <gomp_parallel *> (entry_stmt), ws_args);
7435 else
7436 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7437 if (gimple_in_ssa_p (cfun))
7438 update_ssa (TODO_update_ssa_only_virtuals);
7441 /* Information about members of an OpenACC collapsed loop nest. */
7443 struct oacc_collapse
7445 tree base; /* Base value. */
7446 tree iters; /* Number of steps. */
7447 tree step; /* step size. */
7450 /* Helper for expand_oacc_for. Determine collapsed loop information.
7451 Fill in COUNTS array. Emit any initialization code before GSI.
7452 Return the calculated outer loop bound of BOUND_TYPE. */
7454 static tree
7455 expand_oacc_collapse_init (const struct omp_for_data *fd,
7456 gimple_stmt_iterator *gsi,
7457 oacc_collapse *counts, tree bound_type)
7459 tree total = build_int_cst (bound_type, 1);
7460 int ix;
7462 gcc_assert (integer_onep (fd->loop.step));
7463 gcc_assert (integer_zerop (fd->loop.n1));
7465 for (ix = 0; ix != fd->collapse; ix++)
7467 const omp_for_data_loop *loop = &fd->loops[ix];
7469 tree iter_type = TREE_TYPE (loop->v);
7470 tree diff_type = iter_type;
7471 tree plus_type = iter_type;
7473 gcc_assert (loop->cond_code == fd->loop.cond_code);
7475 if (POINTER_TYPE_P (iter_type))
7476 plus_type = sizetype;
7477 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7478 diff_type = signed_type_for (diff_type);
7480 tree b = loop->n1;
7481 tree e = loop->n2;
7482 tree s = loop->step;
7483 bool up = loop->cond_code == LT_EXPR;
7484 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7485 bool negating;
7486 tree expr;
7488 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7489 true, GSI_SAME_STMT);
7490 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7491 true, GSI_SAME_STMT);
7493 /* Convert the step, avoiding possible unsigned->signed overflow. */
7494 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7495 if (negating)
7496 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7497 s = fold_convert (diff_type, s);
7498 if (negating)
7499 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7500 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7501 true, GSI_SAME_STMT);
7503 /* Determine the range, avoiding possible unsigned->signed overflow. */
7504 negating = !up && TYPE_UNSIGNED (iter_type);
7505 expr = fold_build2 (MINUS_EXPR, plus_type,
7506 fold_convert (plus_type, negating ? b : e),
7507 fold_convert (plus_type, negating ? e : b));
7508 expr = fold_convert (diff_type, expr);
7509 if (negating)
7510 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7511 tree range = force_gimple_operand_gsi
7512 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7514 /* Determine number of iterations. */
7515 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7516 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7517 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7519 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7520 true, GSI_SAME_STMT);
7522 counts[ix].base = b;
7523 counts[ix].iters = iters;
7524 counts[ix].step = s;
7526 total = fold_build2 (MULT_EXPR, bound_type, total,
7527 fold_convert (bound_type, iters));
7530 return total;
7533 /* Emit initializers for collapsed loop members. IVAR is the outer
7534 loop iteration variable, from which collapsed loop iteration values
7535 are calculated. COUNTS array has been initialized by
7536 expand_oacc_collapse_inits. */
7538 static void
7539 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7540 gimple_stmt_iterator *gsi,
7541 const oacc_collapse *counts, tree ivar)
7543 tree ivar_type = TREE_TYPE (ivar);
7545 /* The most rapidly changing iteration variable is the innermost
7546 one. */
7547 for (int ix = fd->collapse; ix--;)
7549 const omp_for_data_loop *loop = &fd->loops[ix];
7550 const oacc_collapse *collapse = &counts[ix];
7551 tree iter_type = TREE_TYPE (loop->v);
7552 tree diff_type = TREE_TYPE (collapse->step);
7553 tree plus_type = iter_type;
7554 enum tree_code plus_code = PLUS_EXPR;
7555 tree expr;
7557 if (POINTER_TYPE_P (iter_type))
7559 plus_code = POINTER_PLUS_EXPR;
7560 plus_type = sizetype;
7563 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7564 fold_convert (ivar_type, collapse->iters));
7565 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7566 collapse->step);
7567 expr = fold_build2 (plus_code, iter_type, collapse->base,
7568 fold_convert (plus_type, expr));
7569 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7570 true, GSI_SAME_STMT);
7571 gassign *ass = gimple_build_assign (loop->v, expr);
7572 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7574 if (ix)
7576 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7577 fold_convert (ivar_type, collapse->iters));
7578 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7579 true, GSI_SAME_STMT);
7585 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7586 of the combined collapse > 1 loop constructs, generate code like:
7587 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7588 if (cond3 is <)
7589 adj = STEP3 - 1;
7590 else
7591 adj = STEP3 + 1;
7592 count3 = (adj + N32 - N31) / STEP3;
7593 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7594 if (cond2 is <)
7595 adj = STEP2 - 1;
7596 else
7597 adj = STEP2 + 1;
7598 count2 = (adj + N22 - N21) / STEP2;
7599 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7600 if (cond1 is <)
7601 adj = STEP1 - 1;
7602 else
7603 adj = STEP1 + 1;
7604 count1 = (adj + N12 - N11) / STEP1;
7605 count = count1 * count2 * count3;
7606 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7607 count = 0;
7608 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7609 of the combined loop constructs, just initialize COUNTS array
7610 from the _looptemp_ clauses. */
7612 /* NOTE: It *could* be better to moosh all of the BBs together,
7613 creating one larger BB with all the computation and the unexpected
7614 jump at the end. I.e.
7616 bool zero3, zero2, zero1, zero;
7618 zero3 = N32 c3 N31;
7619 count3 = (N32 - N31) /[cl] STEP3;
7620 zero2 = N22 c2 N21;
7621 count2 = (N22 - N21) /[cl] STEP2;
7622 zero1 = N12 c1 N11;
7623 count1 = (N12 - N11) /[cl] STEP1;
7624 zero = zero3 || zero2 || zero1;
7625 count = count1 * count2 * count3;
7626 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7628 After all, we expect the zero=false, and thus we expect to have to
7629 evaluate all of the comparison expressions, so short-circuiting
7630 oughtn't be a win. Since the condition isn't protecting a
7631 denominator, we're not concerned about divide-by-zero, so we can
7632 fully evaluate count even if a numerator turned out to be wrong.
7634 It seems like putting this all together would create much better
7635 scheduling opportunities, and less pressure on the chip's branch
7636 predictor. */
7638 static void
7639 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7640 basic_block &entry_bb, tree *counts,
7641 basic_block &zero_iter1_bb, int &first_zero_iter1,
7642 basic_block &zero_iter2_bb, int &first_zero_iter2,
7643 basic_block &l2_dom_bb)
7645 tree t, type = TREE_TYPE (fd->loop.v);
7646 edge e, ne;
7647 int i;
7649 /* Collapsed loops need work for expansion into SSA form. */
7650 gcc_assert (!gimple_in_ssa_p (cfun));
7652 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7653 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7655 gcc_assert (fd->ordered == 0);
7656 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7657 isn't supposed to be handled, as the inner loop doesn't
7658 use it. */
7659 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7660 OMP_CLAUSE__LOOPTEMP_);
7661 gcc_assert (innerc);
7662 for (i = 0; i < fd->collapse; i++)
7664 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7665 OMP_CLAUSE__LOOPTEMP_);
7666 gcc_assert (innerc);
7667 if (i)
7668 counts[i] = OMP_CLAUSE_DECL (innerc);
7669 else
7670 counts[0] = NULL_TREE;
7672 return;
7675 for (i = fd->collapse; i < fd->ordered; i++)
7677 tree itype = TREE_TYPE (fd->loops[i].v);
7678 counts[i] = NULL_TREE;
7679 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7680 fold_convert (itype, fd->loops[i].n1),
7681 fold_convert (itype, fd->loops[i].n2));
7682 if (t && integer_zerop (t))
7684 for (i = fd->collapse; i < fd->ordered; i++)
7685 counts[i] = build_int_cst (type, 0);
7686 break;
7689 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7691 tree itype = TREE_TYPE (fd->loops[i].v);
7693 if (i >= fd->collapse && counts[i])
7694 continue;
7695 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7696 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7697 fold_convert (itype, fd->loops[i].n1),
7698 fold_convert (itype, fd->loops[i].n2)))
7699 == NULL_TREE || !integer_onep (t)))
7701 gcond *cond_stmt;
7702 tree n1, n2;
7703 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7704 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7705 true, GSI_SAME_STMT);
7706 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7707 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7708 true, GSI_SAME_STMT);
7709 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7710 NULL_TREE, NULL_TREE);
7711 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7712 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7713 expand_omp_regimplify_p, NULL, NULL)
7714 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7715 expand_omp_regimplify_p, NULL, NULL))
7717 *gsi = gsi_for_stmt (cond_stmt);
7718 gimple_regimplify_operands (cond_stmt, gsi);
7720 e = split_block (entry_bb, cond_stmt);
7721 basic_block &zero_iter_bb
7722 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7723 int &first_zero_iter
7724 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7725 if (zero_iter_bb == NULL)
7727 gassign *assign_stmt;
7728 first_zero_iter = i;
7729 zero_iter_bb = create_empty_bb (entry_bb);
7730 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7731 *gsi = gsi_after_labels (zero_iter_bb);
7732 if (i < fd->collapse)
7733 assign_stmt = gimple_build_assign (fd->loop.n2,
7734 build_zero_cst (type));
7735 else
7737 counts[i] = create_tmp_reg (type, ".count");
7738 assign_stmt
7739 = gimple_build_assign (counts[i], build_zero_cst (type));
7741 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7742 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7743 entry_bb);
7745 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7746 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7747 e->flags = EDGE_TRUE_VALUE;
7748 e->probability = REG_BR_PROB_BASE - ne->probability;
7749 if (l2_dom_bb == NULL)
7750 l2_dom_bb = entry_bb;
7751 entry_bb = e->dest;
7752 *gsi = gsi_last_bb (entry_bb);
7755 if (POINTER_TYPE_P (itype))
7756 itype = signed_type_for (itype);
7757 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7758 ? -1 : 1));
7759 t = fold_build2 (PLUS_EXPR, itype,
7760 fold_convert (itype, fd->loops[i].step), t);
7761 t = fold_build2 (PLUS_EXPR, itype, t,
7762 fold_convert (itype, fd->loops[i].n2));
7763 t = fold_build2 (MINUS_EXPR, itype, t,
7764 fold_convert (itype, fd->loops[i].n1));
7765 /* ?? We could probably use CEIL_DIV_EXPR instead of
7766 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7767 generate the same code in the end because generically we
7768 don't know that the values involved must be negative for
7769 GT?? */
7770 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7771 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7772 fold_build1 (NEGATE_EXPR, itype, t),
7773 fold_build1 (NEGATE_EXPR, itype,
7774 fold_convert (itype,
7775 fd->loops[i].step)));
7776 else
7777 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7778 fold_convert (itype, fd->loops[i].step));
7779 t = fold_convert (type, t);
7780 if (TREE_CODE (t) == INTEGER_CST)
7781 counts[i] = t;
7782 else
7784 if (i < fd->collapse || i != first_zero_iter2)
7785 counts[i] = create_tmp_reg (type, ".count");
7786 expand_omp_build_assign (gsi, counts[i], t);
7788 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7790 if (i == 0)
7791 t = counts[0];
7792 else
7793 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7794 expand_omp_build_assign (gsi, fd->loop.n2, t);
7800 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7801 T = V;
7802 V3 = N31 + (T % count3) * STEP3;
7803 T = T / count3;
7804 V2 = N21 + (T % count2) * STEP2;
7805 T = T / count2;
7806 V1 = N11 + T * STEP1;
7807 if this loop doesn't have an inner loop construct combined with it.
7808 If it does have an inner loop construct combined with it and the
7809 iteration count isn't known constant, store values from counts array
7810 into its _looptemp_ temporaries instead. */
7812 static void
7813 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7814 tree *counts, gimple *inner_stmt, tree startvar)
7816 int i;
7817 if (gimple_omp_for_combined_p (fd->for_stmt))
7819 /* If fd->loop.n2 is constant, then no propagation of the counts
7820 is needed, they are constant. */
7821 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7822 return;
7824 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7825 ? gimple_omp_taskreg_clauses (inner_stmt)
7826 : gimple_omp_for_clauses (inner_stmt);
7827 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7828 isn't supposed to be handled, as the inner loop doesn't
7829 use it. */
7830 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7831 gcc_assert (innerc);
7832 for (i = 0; i < fd->collapse; i++)
7834 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7835 OMP_CLAUSE__LOOPTEMP_);
7836 gcc_assert (innerc);
7837 if (i)
7839 tree tem = OMP_CLAUSE_DECL (innerc);
7840 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7841 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7842 false, GSI_CONTINUE_LINKING);
7843 gassign *stmt = gimple_build_assign (tem, t);
7844 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7847 return;
7850 tree type = TREE_TYPE (fd->loop.v);
7851 tree tem = create_tmp_reg (type, ".tem");
7852 gassign *stmt = gimple_build_assign (tem, startvar);
7853 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7855 for (i = fd->collapse - 1; i >= 0; i--)
7857 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7858 itype = vtype;
7859 if (POINTER_TYPE_P (vtype))
7860 itype = signed_type_for (vtype);
7861 if (i != 0)
7862 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7863 else
7864 t = tem;
7865 t = fold_convert (itype, t);
7866 t = fold_build2 (MULT_EXPR, itype, t,
7867 fold_convert (itype, fd->loops[i].step));
7868 if (POINTER_TYPE_P (vtype))
7869 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7870 else
7871 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7872 t = force_gimple_operand_gsi (gsi, t,
7873 DECL_P (fd->loops[i].v)
7874 && TREE_ADDRESSABLE (fd->loops[i].v),
7875 NULL_TREE, false,
7876 GSI_CONTINUE_LINKING);
7877 stmt = gimple_build_assign (fd->loops[i].v, t);
7878 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7879 if (i != 0)
7881 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7882 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7883 false, GSI_CONTINUE_LINKING);
7884 stmt = gimple_build_assign (tem, t);
7885 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7891 /* Helper function for expand_omp_for_*. Generate code like:
7892 L10:
7893 V3 += STEP3;
7894 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7895 L11:
7896 V3 = N31;
7897 V2 += STEP2;
7898 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7899 L12:
7900 V2 = N21;
7901 V1 += STEP1;
7902 goto BODY_BB; */
7904 static basic_block
7905 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7906 basic_block body_bb)
7908 basic_block last_bb, bb, collapse_bb = NULL;
7909 int i;
7910 gimple_stmt_iterator gsi;
7911 edge e;
7912 tree t;
7913 gimple *stmt;
7915 last_bb = cont_bb;
7916 for (i = fd->collapse - 1; i >= 0; i--)
7918 tree vtype = TREE_TYPE (fd->loops[i].v);
7920 bb = create_empty_bb (last_bb);
7921 add_bb_to_loop (bb, last_bb->loop_father);
7922 gsi = gsi_start_bb (bb);
7924 if (i < fd->collapse - 1)
7926 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7927 e->probability = REG_BR_PROB_BASE / 8;
7929 t = fd->loops[i + 1].n1;
7930 t = force_gimple_operand_gsi (&gsi, t,
7931 DECL_P (fd->loops[i + 1].v)
7932 && TREE_ADDRESSABLE (fd->loops[i
7933 + 1].v),
7934 NULL_TREE, false,
7935 GSI_CONTINUE_LINKING);
7936 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7937 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7939 else
7940 collapse_bb = bb;
7942 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7944 if (POINTER_TYPE_P (vtype))
7945 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7946 else
7947 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7948 t = force_gimple_operand_gsi (&gsi, t,
7949 DECL_P (fd->loops[i].v)
7950 && TREE_ADDRESSABLE (fd->loops[i].v),
7951 NULL_TREE, false, GSI_CONTINUE_LINKING);
7952 stmt = gimple_build_assign (fd->loops[i].v, t);
7953 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7955 if (i > 0)
7957 t = fd->loops[i].n2;
7958 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7959 false, GSI_CONTINUE_LINKING);
7960 tree v = fd->loops[i].v;
7961 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7962 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7963 false, GSI_CONTINUE_LINKING);
7964 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7965 stmt = gimple_build_cond_empty (t);
7966 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7967 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7968 e->probability = REG_BR_PROB_BASE * 7 / 8;
7970 else
7971 make_edge (bb, body_bb, EDGE_FALLTHRU);
7972 last_bb = bb;
7975 return collapse_bb;
7979 /* Expand #pragma omp ordered depend(source). */
7981 static void
7982 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7983 tree *counts, location_t loc)
7985 enum built_in_function source_ix
7986 = fd->iter_type == long_integer_type_node
7987 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7988 gimple *g
7989 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7990 build_fold_addr_expr (counts[fd->ordered]));
7991 gimple_set_location (g, loc);
7992 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7995 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7997 static void
7998 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7999 tree *counts, tree c, location_t loc)
8001 auto_vec<tree, 10> args;
8002 enum built_in_function sink_ix
8003 = fd->iter_type == long_integer_type_node
8004 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
8005 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
8006 int i;
8007 gimple_stmt_iterator gsi2 = *gsi;
8008 bool warned_step = false;
8010 for (i = 0; i < fd->ordered; i++)
8012 off = TREE_PURPOSE (deps);
8013 if (!integer_zerop (off))
8015 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8016 || fd->loops[i].cond_code == GT_EXPR);
8017 bool forward = fd->loops[i].cond_code == LT_EXPR;
8018 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8019 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8020 "lexically later iteration");
8021 break;
8023 deps = TREE_CHAIN (deps);
8025 /* If all offsets corresponding to the collapsed loops are zero,
8026 this depend clause can be ignored. FIXME: but there is still a
8027 flush needed. We need to emit one __sync_synchronize () for it
8028 though (perhaps conditionally)? Solve this together with the
8029 conservative dependence folding optimization.
8030 if (i >= fd->collapse)
8031 return; */
8033 deps = OMP_CLAUSE_DECL (c);
8034 gsi_prev (&gsi2);
8035 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8036 edge e2 = split_block_after_labels (e1->dest);
8038 *gsi = gsi_after_labels (e1->dest);
8039 for (i = 0; i < fd->ordered; i++)
8041 tree itype = TREE_TYPE (fd->loops[i].v);
8042 if (POINTER_TYPE_P (itype))
8043 itype = sizetype;
8044 if (i)
8045 deps = TREE_CHAIN (deps);
8046 off = TREE_PURPOSE (deps);
8047 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8049 if (integer_zerop (off))
8050 t = boolean_true_node;
8051 else
8053 tree a;
8054 tree co = fold_convert_loc (loc, itype, off);
8055 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8057 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8058 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8059 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8060 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8061 co);
8063 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8064 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8065 fd->loops[i].v, co);
8066 else
8067 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8068 fd->loops[i].v, co);
8069 if (fd->loops[i].cond_code == LT_EXPR)
8071 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8072 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8073 fd->loops[i].n1);
8074 else
8075 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8076 fd->loops[i].n2);
8078 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8079 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8080 fd->loops[i].n2);
8081 else
8082 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8083 fd->loops[i].n1);
8085 if (cond)
8086 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8087 else
8088 cond = t;
8090 off = fold_convert_loc (loc, itype, off);
8092 if (fd->loops[i].cond_code == LT_EXPR
8093 ? !integer_onep (fd->loops[i].step)
8094 : !integer_minus_onep (fd->loops[i].step))
8096 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8097 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8098 fold_build1_loc (loc, NEGATE_EXPR, itype,
8099 s));
8100 else
8101 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8102 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8103 build_int_cst (itype, 0));
8104 if (integer_zerop (t) && !warned_step)
8106 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8107 "in the iteration space");
8108 warned_step = true;
8110 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8111 cond, t);
8114 if (i <= fd->collapse - 1 && fd->collapse > 1)
8115 t = fd->loop.v;
8116 else if (counts[i])
8117 t = counts[i];
8118 else
8120 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8121 fd->loops[i].v, fd->loops[i].n1);
8122 t = fold_convert_loc (loc, fd->iter_type, t);
8124 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8125 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8126 fold_build1_loc (loc, NEGATE_EXPR, itype,
8127 s));
8128 else
8129 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8130 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8131 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8132 off = fold_convert_loc (loc, fd->iter_type, off);
8133 if (i <= fd->collapse - 1 && fd->collapse > 1)
8135 if (i)
8136 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8137 off);
8138 if (i < fd->collapse - 1)
8140 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8141 counts[i]);
8142 continue;
8145 off = unshare_expr (off);
8146 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8147 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8148 true, GSI_SAME_STMT);
8149 args.safe_push (t);
8151 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8152 gimple_set_location (g, loc);
8153 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8155 *gsi = gsi_last_bb (e1->src);
8156 cond = unshare_expr (cond);
8157 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8158 GSI_CONTINUE_LINKING);
8159 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8160 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8161 e3->probability = REG_BR_PROB_BASE / 8;
8162 e1->probability = REG_BR_PROB_BASE - e3->probability;
8163 e1->flags = EDGE_TRUE_VALUE;
8164 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8166 *gsi = gsi_after_labels (e2->dest);
8169 /* Expand all #pragma omp ordered depend(source) and
8170 #pragma omp ordered depend(sink:...) constructs in the current
8171 #pragma omp for ordered(n) region. */
8173 static void
8174 expand_omp_ordered_source_sink (struct omp_region *region,
8175 struct omp_for_data *fd, tree *counts,
8176 basic_block cont_bb)
8178 struct omp_region *inner;
8179 int i;
8180 for (i = fd->collapse - 1; i < fd->ordered; i++)
8181 if (i == fd->collapse - 1 && fd->collapse > 1)
8182 counts[i] = NULL_TREE;
8183 else if (i >= fd->collapse && !cont_bb)
8184 counts[i] = build_zero_cst (fd->iter_type);
8185 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8186 && integer_onep (fd->loops[i].step))
8187 counts[i] = NULL_TREE;
8188 else
8189 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8190 tree atype
8191 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8192 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8193 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8195 for (inner = region->inner; inner; inner = inner->next)
8196 if (inner->type == GIMPLE_OMP_ORDERED)
8198 gomp_ordered *ord_stmt = inner->ord_stmt;
8199 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8200 location_t loc = gimple_location (ord_stmt);
8201 tree c;
8202 for (c = gimple_omp_ordered_clauses (ord_stmt);
8203 c; c = OMP_CLAUSE_CHAIN (c))
8204 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8205 break;
8206 if (c)
8207 expand_omp_ordered_source (&gsi, fd, counts, loc);
8208 for (c = gimple_omp_ordered_clauses (ord_stmt);
8209 c; c = OMP_CLAUSE_CHAIN (c))
8210 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8211 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8212 gsi_remove (&gsi, true);
8216 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8217 collapsed. */
8219 static basic_block
8220 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8221 basic_block cont_bb, basic_block body_bb,
8222 bool ordered_lastprivate)
8224 if (fd->ordered == fd->collapse)
8225 return cont_bb;
8227 if (!cont_bb)
8229 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8230 for (int i = fd->collapse; i < fd->ordered; i++)
8232 tree type = TREE_TYPE (fd->loops[i].v);
8233 tree n1 = fold_convert (type, fd->loops[i].n1);
8234 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8235 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8236 size_int (i - fd->collapse + 1),
8237 NULL_TREE, NULL_TREE);
8238 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8240 return NULL;
8243 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8245 tree t, type = TREE_TYPE (fd->loops[i].v);
8246 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8247 expand_omp_build_assign (&gsi, fd->loops[i].v,
8248 fold_convert (type, fd->loops[i].n1));
8249 if (counts[i])
8250 expand_omp_build_assign (&gsi, counts[i],
8251 build_zero_cst (fd->iter_type));
8252 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8253 size_int (i - fd->collapse + 1),
8254 NULL_TREE, NULL_TREE);
8255 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8256 if (!gsi_end_p (gsi))
8257 gsi_prev (&gsi);
8258 else
8259 gsi = gsi_last_bb (body_bb);
8260 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8261 basic_block new_body = e1->dest;
8262 if (body_bb == cont_bb)
8263 cont_bb = new_body;
8264 edge e2 = NULL;
8265 basic_block new_header;
8266 if (EDGE_COUNT (cont_bb->preds) > 0)
8268 gsi = gsi_last_bb (cont_bb);
8269 if (POINTER_TYPE_P (type))
8270 t = fold_build_pointer_plus (fd->loops[i].v,
8271 fold_convert (sizetype,
8272 fd->loops[i].step));
8273 else
8274 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8275 fold_convert (type, fd->loops[i].step));
8276 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8277 if (counts[i])
8279 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8280 build_int_cst (fd->iter_type, 1));
8281 expand_omp_build_assign (&gsi, counts[i], t);
8282 t = counts[i];
8284 else
8286 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8287 fd->loops[i].v, fd->loops[i].n1);
8288 t = fold_convert (fd->iter_type, t);
8289 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8290 true, GSI_SAME_STMT);
8292 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8293 size_int (i - fd->collapse + 1),
8294 NULL_TREE, NULL_TREE);
8295 expand_omp_build_assign (&gsi, aref, t);
8296 gsi_prev (&gsi);
8297 e2 = split_block (cont_bb, gsi_stmt (gsi));
8298 new_header = e2->dest;
8300 else
8301 new_header = cont_bb;
8302 gsi = gsi_after_labels (new_header);
8303 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8304 true, GSI_SAME_STMT);
8305 tree n2
8306 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8307 true, NULL_TREE, true, GSI_SAME_STMT);
8308 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8309 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8310 edge e3 = split_block (new_header, gsi_stmt (gsi));
8311 cont_bb = e3->dest;
8312 remove_edge (e1);
8313 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8314 e3->flags = EDGE_FALSE_VALUE;
8315 e3->probability = REG_BR_PROB_BASE / 8;
8316 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8317 e1->probability = REG_BR_PROB_BASE - e3->probability;
8319 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8320 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8322 if (e2)
8324 struct loop *loop = alloc_loop ();
8325 loop->header = new_header;
8326 loop->latch = e2->src;
8327 add_loop (loop, body_bb->loop_father);
8331 /* If there are any lastprivate clauses and it is possible some loops
8332 might have zero iterations, ensure all the decls are initialized,
8333 otherwise we could crash evaluating C++ class iterators with lastprivate
8334 clauses. */
8335 bool need_inits = false;
8336 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8337 if (need_inits)
8339 tree type = TREE_TYPE (fd->loops[i].v);
8340 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8341 expand_omp_build_assign (&gsi, fd->loops[i].v,
8342 fold_convert (type, fd->loops[i].n1));
8344 else
8346 tree type = TREE_TYPE (fd->loops[i].v);
8347 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8348 boolean_type_node,
8349 fold_convert (type, fd->loops[i].n1),
8350 fold_convert (type, fd->loops[i].n2));
8351 if (!integer_onep (this_cond))
8352 need_inits = true;
8355 return cont_bb;
8359 /* A subroutine of expand_omp_for. Generate code for a parallel
8360 loop with any schedule. Given parameters:
8362 for (V = N1; V cond N2; V += STEP) BODY;
8364 where COND is "<" or ">", we generate pseudocode
8366 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8367 if (more) goto L0; else goto L3;
8369 V = istart0;
8370 iend = iend0;
8372 BODY;
8373 V += STEP;
8374 if (V cond iend) goto L1; else goto L2;
8376 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8379 If this is a combined omp parallel loop, instead of the call to
8380 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8381 If this is gimple_omp_for_combined_p loop, then instead of assigning
8382 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8383 inner GIMPLE_OMP_FOR and V += STEP; and
8384 if (V cond iend) goto L1; else goto L2; are removed.
8386 For collapsed loops, given parameters:
8387 collapse(3)
8388 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8389 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8390 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8391 BODY;
8393 we generate pseudocode
8395 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8396 if (cond3 is <)
8397 adj = STEP3 - 1;
8398 else
8399 adj = STEP3 + 1;
8400 count3 = (adj + N32 - N31) / STEP3;
8401 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8402 if (cond2 is <)
8403 adj = STEP2 - 1;
8404 else
8405 adj = STEP2 + 1;
8406 count2 = (adj + N22 - N21) / STEP2;
8407 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8408 if (cond1 is <)
8409 adj = STEP1 - 1;
8410 else
8411 adj = STEP1 + 1;
8412 count1 = (adj + N12 - N11) / STEP1;
8413 count = count1 * count2 * count3;
8414 goto Z1;
8416 count = 0;
8418 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8419 if (more) goto L0; else goto L3;
8421 V = istart0;
8422 T = V;
8423 V3 = N31 + (T % count3) * STEP3;
8424 T = T / count3;
8425 V2 = N21 + (T % count2) * STEP2;
8426 T = T / count2;
8427 V1 = N11 + T * STEP1;
8428 iend = iend0;
8430 BODY;
8431 V += 1;
8432 if (V < iend) goto L10; else goto L2;
8433 L10:
8434 V3 += STEP3;
8435 if (V3 cond3 N32) goto L1; else goto L11;
8436 L11:
8437 V3 = N31;
8438 V2 += STEP2;
8439 if (V2 cond2 N22) goto L1; else goto L12;
8440 L12:
8441 V2 = N21;
8442 V1 += STEP1;
8443 goto L1;
8445 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8450 static void
8451 expand_omp_for_generic (struct omp_region *region,
8452 struct omp_for_data *fd,
8453 enum built_in_function start_fn,
8454 enum built_in_function next_fn,
8455 gimple *inner_stmt)
8457 tree type, istart0, iend0, iend;
8458 tree t, vmain, vback, bias = NULL_TREE;
8459 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8460 basic_block l2_bb = NULL, l3_bb = NULL;
8461 gimple_stmt_iterator gsi;
8462 gassign *assign_stmt;
8463 bool in_combined_parallel = is_combined_parallel (region);
8464 bool broken_loop = region->cont == NULL;
8465 edge e, ne;
8466 tree *counts = NULL;
8467 int i;
8468 bool ordered_lastprivate = false;
8470 gcc_assert (!broken_loop || !in_combined_parallel);
8471 gcc_assert (fd->iter_type == long_integer_type_node
8472 || !in_combined_parallel);
8474 entry_bb = region->entry;
8475 cont_bb = region->cont;
8476 collapse_bb = NULL;
8477 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8478 gcc_assert (broken_loop
8479 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8480 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8481 l1_bb = single_succ (l0_bb);
8482 if (!broken_loop)
8484 l2_bb = create_empty_bb (cont_bb);
8485 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8486 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8487 == l1_bb));
8488 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8490 else
8491 l2_bb = NULL;
8492 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8493 exit_bb = region->exit;
8495 gsi = gsi_last_bb (entry_bb);
8497 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8498 if (fd->ordered
8499 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8500 OMP_CLAUSE_LASTPRIVATE))
8501 ordered_lastprivate = false;
8502 if (fd->collapse > 1 || fd->ordered)
8504 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8505 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8507 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8508 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8509 zero_iter1_bb, first_zero_iter1,
8510 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8512 if (zero_iter1_bb)
8514 /* Some counts[i] vars might be uninitialized if
8515 some loop has zero iterations. But the body shouldn't
8516 be executed in that case, so just avoid uninit warnings. */
8517 for (i = first_zero_iter1;
8518 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8519 if (SSA_VAR_P (counts[i]))
8520 TREE_NO_WARNING (counts[i]) = 1;
8521 gsi_prev (&gsi);
8522 e = split_block (entry_bb, gsi_stmt (gsi));
8523 entry_bb = e->dest;
8524 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8525 gsi = gsi_last_bb (entry_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8527 get_immediate_dominator (CDI_DOMINATORS,
8528 zero_iter1_bb));
8530 if (zero_iter2_bb)
8532 /* Some counts[i] vars might be uninitialized if
8533 some loop has zero iterations. But the body shouldn't
8534 be executed in that case, so just avoid uninit warnings. */
8535 for (i = first_zero_iter2; i < fd->ordered; i++)
8536 if (SSA_VAR_P (counts[i]))
8537 TREE_NO_WARNING (counts[i]) = 1;
8538 if (zero_iter1_bb)
8539 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8540 else
8542 gsi_prev (&gsi);
8543 e = split_block (entry_bb, gsi_stmt (gsi));
8544 entry_bb = e->dest;
8545 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8546 gsi = gsi_last_bb (entry_bb);
8547 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8548 get_immediate_dominator
8549 (CDI_DOMINATORS, zero_iter2_bb));
8552 if (fd->collapse == 1)
8554 counts[0] = fd->loop.n2;
8555 fd->loop = fd->loops[0];
8559 type = TREE_TYPE (fd->loop.v);
8560 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8561 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8562 TREE_ADDRESSABLE (istart0) = 1;
8563 TREE_ADDRESSABLE (iend0) = 1;
8565 /* See if we need to bias by LLONG_MIN. */
8566 if (fd->iter_type == long_long_unsigned_type_node
8567 && TREE_CODE (type) == INTEGER_TYPE
8568 && !TYPE_UNSIGNED (type)
8569 && fd->ordered == 0)
8571 tree n1, n2;
8573 if (fd->loop.cond_code == LT_EXPR)
8575 n1 = fd->loop.n1;
8576 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8578 else
8580 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8581 n2 = fd->loop.n1;
8583 if (TREE_CODE (n1) != INTEGER_CST
8584 || TREE_CODE (n2) != INTEGER_CST
8585 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8586 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8589 gimple_stmt_iterator gsif = gsi;
8590 gsi_prev (&gsif);
8592 tree arr = NULL_TREE;
8593 if (in_combined_parallel)
8595 gcc_assert (fd->ordered == 0);
8596 /* In a combined parallel loop, emit a call to
8597 GOMP_loop_foo_next. */
8598 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8599 build_fold_addr_expr (istart0),
8600 build_fold_addr_expr (iend0));
8602 else
8604 tree t0, t1, t2, t3, t4;
8605 /* If this is not a combined parallel loop, emit a call to
8606 GOMP_loop_foo_start in ENTRY_BB. */
8607 t4 = build_fold_addr_expr (iend0);
8608 t3 = build_fold_addr_expr (istart0);
8609 if (fd->ordered)
8611 t0 = build_int_cst (unsigned_type_node,
8612 fd->ordered - fd->collapse + 1);
8613 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8614 fd->ordered
8615 - fd->collapse + 1),
8616 ".omp_counts");
8617 DECL_NAMELESS (arr) = 1;
8618 TREE_ADDRESSABLE (arr) = 1;
8619 TREE_STATIC (arr) = 1;
8620 vec<constructor_elt, va_gc> *v;
8621 vec_alloc (v, fd->ordered - fd->collapse + 1);
8622 int idx;
8624 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8626 tree c;
8627 if (idx == 0 && fd->collapse > 1)
8628 c = fd->loop.n2;
8629 else
8630 c = counts[idx + fd->collapse - 1];
8631 tree purpose = size_int (idx);
8632 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8633 if (TREE_CODE (c) != INTEGER_CST)
8634 TREE_STATIC (arr) = 0;
8637 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8638 if (!TREE_STATIC (arr))
8639 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8640 void_type_node, arr),
8641 true, NULL_TREE, true, GSI_SAME_STMT);
8642 t1 = build_fold_addr_expr (arr);
8643 t2 = NULL_TREE;
8645 else
8647 t2 = fold_convert (fd->iter_type, fd->loop.step);
8648 t1 = fd->loop.n2;
8649 t0 = fd->loop.n1;
8650 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8652 tree innerc
8653 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8654 OMP_CLAUSE__LOOPTEMP_);
8655 gcc_assert (innerc);
8656 t0 = OMP_CLAUSE_DECL (innerc);
8657 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8658 OMP_CLAUSE__LOOPTEMP_);
8659 gcc_assert (innerc);
8660 t1 = OMP_CLAUSE_DECL (innerc);
8662 if (POINTER_TYPE_P (TREE_TYPE (t0))
8663 && TYPE_PRECISION (TREE_TYPE (t0))
8664 != TYPE_PRECISION (fd->iter_type))
8666 /* Avoid casting pointers to integer of a different size. */
8667 tree itype = signed_type_for (type);
8668 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8669 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8671 else
8673 t1 = fold_convert (fd->iter_type, t1);
8674 t0 = fold_convert (fd->iter_type, t0);
8676 if (bias)
8678 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8679 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8682 if (fd->iter_type == long_integer_type_node || fd->ordered)
8684 if (fd->chunk_size)
8686 t = fold_convert (fd->iter_type, fd->chunk_size);
8687 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8688 if (fd->ordered)
8689 t = build_call_expr (builtin_decl_explicit (start_fn),
8690 5, t0, t1, t, t3, t4);
8691 else
8692 t = build_call_expr (builtin_decl_explicit (start_fn),
8693 6, t0, t1, t2, t, t3, t4);
8695 else if (fd->ordered)
8696 t = build_call_expr (builtin_decl_explicit (start_fn),
8697 4, t0, t1, t3, t4);
8698 else
8699 t = build_call_expr (builtin_decl_explicit (start_fn),
8700 5, t0, t1, t2, t3, t4);
8702 else
8704 tree t5;
8705 tree c_bool_type;
8706 tree bfn_decl;
8708 /* The GOMP_loop_ull_*start functions have additional boolean
8709 argument, true for < loops and false for > loops.
8710 In Fortran, the C bool type can be different from
8711 boolean_type_node. */
8712 bfn_decl = builtin_decl_explicit (start_fn);
8713 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8714 t5 = build_int_cst (c_bool_type,
8715 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8716 if (fd->chunk_size)
8718 tree bfn_decl = builtin_decl_explicit (start_fn);
8719 t = fold_convert (fd->iter_type, fd->chunk_size);
8720 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8721 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8723 else
8724 t = build_call_expr (builtin_decl_explicit (start_fn),
8725 6, t5, t0, t1, t2, t3, t4);
8728 if (TREE_TYPE (t) != boolean_type_node)
8729 t = fold_build2 (NE_EXPR, boolean_type_node,
8730 t, build_int_cst (TREE_TYPE (t), 0));
8731 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8732 true, GSI_SAME_STMT);
8733 if (arr && !TREE_STATIC (arr))
8735 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8736 TREE_THIS_VOLATILE (clobber) = 1;
8737 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8738 GSI_SAME_STMT);
8740 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8742 /* Remove the GIMPLE_OMP_FOR statement. */
8743 gsi_remove (&gsi, true);
8745 if (gsi_end_p (gsif))
8746 gsif = gsi_after_labels (gsi_bb (gsif));
8747 gsi_next (&gsif);
8749 /* Iteration setup for sequential loop goes in L0_BB. */
8750 tree startvar = fd->loop.v;
8751 tree endvar = NULL_TREE;
8753 if (gimple_omp_for_combined_p (fd->for_stmt))
8755 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8756 && gimple_omp_for_kind (inner_stmt)
8757 == GF_OMP_FOR_KIND_SIMD);
8758 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8759 OMP_CLAUSE__LOOPTEMP_);
8760 gcc_assert (innerc);
8761 startvar = OMP_CLAUSE_DECL (innerc);
8762 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8763 OMP_CLAUSE__LOOPTEMP_);
8764 gcc_assert (innerc);
8765 endvar = OMP_CLAUSE_DECL (innerc);
8768 gsi = gsi_start_bb (l0_bb);
8769 t = istart0;
8770 if (fd->ordered && fd->collapse == 1)
8771 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8772 fold_convert (fd->iter_type, fd->loop.step));
8773 else if (bias)
8774 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8775 if (fd->ordered && fd->collapse == 1)
8777 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8778 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8779 fd->loop.n1, fold_convert (sizetype, t));
8780 else
8782 t = fold_convert (TREE_TYPE (startvar), t);
8783 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8784 fd->loop.n1, t);
8787 else
8789 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8790 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8791 t = fold_convert (TREE_TYPE (startvar), t);
8793 t = force_gimple_operand_gsi (&gsi, t,
8794 DECL_P (startvar)
8795 && TREE_ADDRESSABLE (startvar),
8796 NULL_TREE, false, GSI_CONTINUE_LINKING);
8797 assign_stmt = gimple_build_assign (startvar, t);
8798 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8800 t = iend0;
8801 if (fd->ordered && fd->collapse == 1)
8802 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8803 fold_convert (fd->iter_type, fd->loop.step));
8804 else if (bias)
8805 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8806 if (fd->ordered && fd->collapse == 1)
8808 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8809 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8810 fd->loop.n1, fold_convert (sizetype, t));
8811 else
8813 t = fold_convert (TREE_TYPE (startvar), t);
8814 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8815 fd->loop.n1, t);
8818 else
8820 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8821 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8822 t = fold_convert (TREE_TYPE (startvar), t);
8824 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8825 false, GSI_CONTINUE_LINKING);
8826 if (endvar)
8828 assign_stmt = gimple_build_assign (endvar, iend);
8829 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8830 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8831 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8832 else
8833 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8834 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8836 /* Handle linear clause adjustments. */
8837 tree itercnt = NULL_TREE;
8838 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8839 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8840 c; c = OMP_CLAUSE_CHAIN (c))
8841 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8842 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8844 tree d = OMP_CLAUSE_DECL (c);
8845 bool is_ref = is_reference (d);
8846 tree t = d, a, dest;
8847 if (is_ref)
8848 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8849 tree type = TREE_TYPE (t);
8850 if (POINTER_TYPE_P (type))
8851 type = sizetype;
8852 dest = unshare_expr (t);
8853 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8854 expand_omp_build_assign (&gsif, v, t);
8855 if (itercnt == NULL_TREE)
8857 itercnt = startvar;
8858 tree n1 = fd->loop.n1;
8859 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8861 itercnt
8862 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8863 itercnt);
8864 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8866 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8867 itercnt, n1);
8868 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8869 itercnt, fd->loop.step);
8870 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8871 NULL_TREE, false,
8872 GSI_CONTINUE_LINKING);
8874 a = fold_build2 (MULT_EXPR, type,
8875 fold_convert (type, itercnt),
8876 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8877 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8878 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8879 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8880 false, GSI_CONTINUE_LINKING);
8881 assign_stmt = gimple_build_assign (dest, t);
8882 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8884 if (fd->collapse > 1)
8885 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8887 if (fd->ordered)
8889 /* Until now, counts array contained number of iterations or
8890 variable containing it for ith loop. From now on, we need
8891 those counts only for collapsed loops, and only for the 2nd
8892 till the last collapsed one. Move those one element earlier,
8893 we'll use counts[fd->collapse - 1] for the first source/sink
8894 iteration counter and so on and counts[fd->ordered]
8895 as the array holding the current counter values for
8896 depend(source). */
8897 if (fd->collapse > 1)
8898 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8899 if (broken_loop)
8901 int i;
8902 for (i = fd->collapse; i < fd->ordered; i++)
8904 tree type = TREE_TYPE (fd->loops[i].v);
8905 tree this_cond
8906 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8907 fold_convert (type, fd->loops[i].n1),
8908 fold_convert (type, fd->loops[i].n2));
8909 if (!integer_onep (this_cond))
8910 break;
8912 if (i < fd->ordered)
8914 cont_bb
8915 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8916 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8917 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8918 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8919 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8920 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8921 make_edge (cont_bb, l1_bb, 0);
8922 l2_bb = create_empty_bb (cont_bb);
8923 broken_loop = false;
8926 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8927 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8928 ordered_lastprivate);
8929 if (counts[fd->collapse - 1])
8931 gcc_assert (fd->collapse == 1);
8932 gsi = gsi_last_bb (l0_bb);
8933 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8934 istart0, true);
8935 gsi = gsi_last_bb (cont_bb);
8936 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8937 build_int_cst (fd->iter_type, 1));
8938 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8939 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8940 size_zero_node, NULL_TREE, NULL_TREE);
8941 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8942 t = counts[fd->collapse - 1];
8944 else if (fd->collapse > 1)
8945 t = fd->loop.v;
8946 else
8948 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8949 fd->loops[0].v, fd->loops[0].n1);
8950 t = fold_convert (fd->iter_type, t);
8952 gsi = gsi_last_bb (l0_bb);
8953 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8954 size_zero_node, NULL_TREE, NULL_TREE);
8955 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8956 false, GSI_CONTINUE_LINKING);
8957 expand_omp_build_assign (&gsi, aref, t, true);
8960 if (!broken_loop)
8962 /* Code to control the increment and predicate for the sequential
8963 loop goes in the CONT_BB. */
8964 gsi = gsi_last_bb (cont_bb);
8965 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8966 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8967 vmain = gimple_omp_continue_control_use (cont_stmt);
8968 vback = gimple_omp_continue_control_def (cont_stmt);
8970 if (!gimple_omp_for_combined_p (fd->for_stmt))
8972 if (POINTER_TYPE_P (type))
8973 t = fold_build_pointer_plus (vmain, fd->loop.step);
8974 else
8975 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8976 t = force_gimple_operand_gsi (&gsi, t,
8977 DECL_P (vback)
8978 && TREE_ADDRESSABLE (vback),
8979 NULL_TREE, true, GSI_SAME_STMT);
8980 assign_stmt = gimple_build_assign (vback, t);
8981 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8983 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8985 if (fd->collapse > 1)
8986 t = fd->loop.v;
8987 else
8989 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8990 fd->loops[0].v, fd->loops[0].n1);
8991 t = fold_convert (fd->iter_type, t);
8993 tree aref = build4 (ARRAY_REF, fd->iter_type,
8994 counts[fd->ordered], size_zero_node,
8995 NULL_TREE, NULL_TREE);
8996 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8997 true, GSI_SAME_STMT);
8998 expand_omp_build_assign (&gsi, aref, t);
9001 t = build2 (fd->loop.cond_code, boolean_type_node,
9002 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
9003 iend);
9004 gcond *cond_stmt = gimple_build_cond_empty (t);
9005 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9008 /* Remove GIMPLE_OMP_CONTINUE. */
9009 gsi_remove (&gsi, true);
9011 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9012 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9014 /* Emit code to get the next parallel iteration in L2_BB. */
9015 gsi = gsi_start_bb (l2_bb);
9017 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9018 build_fold_addr_expr (istart0),
9019 build_fold_addr_expr (iend0));
9020 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9021 false, GSI_CONTINUE_LINKING);
9022 if (TREE_TYPE (t) != boolean_type_node)
9023 t = fold_build2 (NE_EXPR, boolean_type_node,
9024 t, build_int_cst (TREE_TYPE (t), 0));
9025 gcond *cond_stmt = gimple_build_cond_empty (t);
9026 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9029 /* Add the loop cleanup function. */
9030 gsi = gsi_last_bb (exit_bb);
9031 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9032 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9033 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9034 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9035 else
9036 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9037 gcall *call_stmt = gimple_build_call (t, 0);
9038 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9039 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9040 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9041 if (fd->ordered)
9043 tree arr = counts[fd->ordered];
9044 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9045 TREE_THIS_VOLATILE (clobber) = 1;
9046 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9047 GSI_SAME_STMT);
9049 gsi_remove (&gsi, true);
9051 /* Connect the new blocks. */
9052 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9053 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9055 if (!broken_loop)
9057 gimple_seq phis;
9059 e = find_edge (cont_bb, l3_bb);
9060 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9062 phis = phi_nodes (l3_bb);
9063 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9065 gimple *phi = gsi_stmt (gsi);
9066 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9067 PHI_ARG_DEF_FROM_EDGE (phi, e));
9069 remove_edge (e);
9071 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9072 e = find_edge (cont_bb, l1_bb);
9073 if (e == NULL)
9075 e = BRANCH_EDGE (cont_bb);
9076 gcc_assert (single_succ (e->dest) == l1_bb);
9078 if (gimple_omp_for_combined_p (fd->for_stmt))
9080 remove_edge (e);
9081 e = NULL;
9083 else if (fd->collapse > 1)
9085 remove_edge (e);
9086 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9088 else
9089 e->flags = EDGE_TRUE_VALUE;
9090 if (e)
9092 e->probability = REG_BR_PROB_BASE * 7 / 8;
9093 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9095 else
9097 e = find_edge (cont_bb, l2_bb);
9098 e->flags = EDGE_FALLTHRU;
9100 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9102 if (gimple_in_ssa_p (cfun))
9104 /* Add phis to the outer loop that connect to the phis in the inner,
9105 original loop, and move the loop entry value of the inner phi to
9106 the loop entry value of the outer phi. */
9107 gphi_iterator psi;
9108 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9110 source_location locus;
9111 gphi *nphi;
9112 gphi *exit_phi = psi.phi ();
9114 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9115 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9117 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9118 edge latch_to_l1 = find_edge (latch, l1_bb);
9119 gphi *inner_phi
9120 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9122 tree t = gimple_phi_result (exit_phi);
9123 tree new_res = copy_ssa_name (t, NULL);
9124 nphi = create_phi_node (new_res, l0_bb);
9126 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9127 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9128 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9129 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9130 add_phi_arg (nphi, t, entry_to_l0, locus);
9132 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9133 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9135 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9139 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9140 recompute_dominator (CDI_DOMINATORS, l2_bb));
9141 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9142 recompute_dominator (CDI_DOMINATORS, l3_bb));
9143 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9144 recompute_dominator (CDI_DOMINATORS, l0_bb));
9145 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9146 recompute_dominator (CDI_DOMINATORS, l1_bb));
9148 /* We enter expand_omp_for_generic with a loop. This original loop may
9149 have its own loop struct, or it may be part of an outer loop struct
9150 (which may be the fake loop). */
9151 struct loop *outer_loop = entry_bb->loop_father;
9152 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9154 add_bb_to_loop (l2_bb, outer_loop);
9156 /* We've added a new loop around the original loop. Allocate the
9157 corresponding loop struct. */
9158 struct loop *new_loop = alloc_loop ();
9159 new_loop->header = l0_bb;
9160 new_loop->latch = l2_bb;
9161 add_loop (new_loop, outer_loop);
9163 /* Allocate a loop structure for the original loop unless we already
9164 had one. */
9165 if (!orig_loop_has_loop_struct
9166 && !gimple_omp_for_combined_p (fd->for_stmt))
9168 struct loop *orig_loop = alloc_loop ();
9169 orig_loop->header = l1_bb;
9170 /* The loop may have multiple latches. */
9171 add_loop (orig_loop, new_loop);
9177 /* A subroutine of expand_omp_for. Generate code for a parallel
9178 loop with static schedule and no specified chunk size. Given
9179 parameters:
9181 for (V = N1; V cond N2; V += STEP) BODY;
9183 where COND is "<" or ">", we generate pseudocode
9185 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9186 if (cond is <)
9187 adj = STEP - 1;
9188 else
9189 adj = STEP + 1;
9190 if ((__typeof (V)) -1 > 0 && cond is >)
9191 n = -(adj + N2 - N1) / -STEP;
9192 else
9193 n = (adj + N2 - N1) / STEP;
9194 q = n / nthreads;
9195 tt = n % nthreads;
9196 if (threadid < tt) goto L3; else goto L4;
9198 tt = 0;
9199 q = q + 1;
9201 s0 = q * threadid + tt;
9202 e0 = s0 + q;
9203 V = s0 * STEP + N1;
9204 if (s0 >= e0) goto L2; else goto L0;
9206 e = e0 * STEP + N1;
9208 BODY;
9209 V += STEP;
9210 if (V cond e) goto L1;
9214 static void
9215 expand_omp_for_static_nochunk (struct omp_region *region,
9216 struct omp_for_data *fd,
9217 gimple *inner_stmt)
9219 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9220 tree type, itype, vmain, vback;
9221 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9222 basic_block body_bb, cont_bb, collapse_bb = NULL;
9223 basic_block fin_bb;
9224 gimple_stmt_iterator gsi;
9225 edge ep;
9226 bool broken_loop = region->cont == NULL;
9227 tree *counts = NULL;
9228 tree n1, n2, step;
9230 itype = type = TREE_TYPE (fd->loop.v);
9231 if (POINTER_TYPE_P (type))
9232 itype = signed_type_for (type);
9234 entry_bb = region->entry;
9235 cont_bb = region->cont;
9236 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9237 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9238 gcc_assert (broken_loop
9239 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9240 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9241 body_bb = single_succ (seq_start_bb);
9242 if (!broken_loop)
9244 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9245 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9246 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9248 exit_bb = region->exit;
9250 /* Iteration space partitioning goes in ENTRY_BB. */
9251 gsi = gsi_last_bb (entry_bb);
9252 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9254 if (fd->collapse > 1)
9256 int first_zero_iter = -1, dummy = -1;
9257 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9259 counts = XALLOCAVEC (tree, fd->collapse);
9260 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9261 fin_bb, first_zero_iter,
9262 dummy_bb, dummy, l2_dom_bb);
9263 t = NULL_TREE;
9265 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9266 t = integer_one_node;
9267 else
9268 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9269 fold_convert (type, fd->loop.n1),
9270 fold_convert (type, fd->loop.n2));
9271 if (fd->collapse == 1
9272 && TYPE_UNSIGNED (type)
9273 && (t == NULL_TREE || !integer_onep (t)))
9275 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9276 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9277 true, GSI_SAME_STMT);
9278 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9279 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9280 true, GSI_SAME_STMT);
9281 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9282 NULL_TREE, NULL_TREE);
9283 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9284 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9285 expand_omp_regimplify_p, NULL, NULL)
9286 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9287 expand_omp_regimplify_p, NULL, NULL))
9289 gsi = gsi_for_stmt (cond_stmt);
9290 gimple_regimplify_operands (cond_stmt, &gsi);
9292 ep = split_block (entry_bb, cond_stmt);
9293 ep->flags = EDGE_TRUE_VALUE;
9294 entry_bb = ep->dest;
9295 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9296 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9297 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9298 if (gimple_in_ssa_p (cfun))
9300 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9301 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9302 !gsi_end_p (gpi); gsi_next (&gpi))
9304 gphi *phi = gpi.phi ();
9305 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9306 ep, UNKNOWN_LOCATION);
9309 gsi = gsi_last_bb (entry_bb);
9312 switch (gimple_omp_for_kind (fd->for_stmt))
9314 case GF_OMP_FOR_KIND_FOR:
9315 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9316 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9317 break;
9318 case GF_OMP_FOR_KIND_DISTRIBUTE:
9319 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9320 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9321 break;
9322 default:
9323 gcc_unreachable ();
9325 nthreads = build_call_expr (nthreads, 0);
9326 nthreads = fold_convert (itype, nthreads);
9327 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9328 true, GSI_SAME_STMT);
9329 threadid = build_call_expr (threadid, 0);
9330 threadid = fold_convert (itype, threadid);
9331 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9332 true, GSI_SAME_STMT);
9334 n1 = fd->loop.n1;
9335 n2 = fd->loop.n2;
9336 step = fd->loop.step;
9337 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9339 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9340 OMP_CLAUSE__LOOPTEMP_);
9341 gcc_assert (innerc);
9342 n1 = OMP_CLAUSE_DECL (innerc);
9343 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9344 OMP_CLAUSE__LOOPTEMP_);
9345 gcc_assert (innerc);
9346 n2 = OMP_CLAUSE_DECL (innerc);
9348 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9349 true, NULL_TREE, true, GSI_SAME_STMT);
9350 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9351 true, NULL_TREE, true, GSI_SAME_STMT);
9352 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9353 true, NULL_TREE, true, GSI_SAME_STMT);
9355 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9356 t = fold_build2 (PLUS_EXPR, itype, step, t);
9357 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9358 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9359 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9360 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9361 fold_build1 (NEGATE_EXPR, itype, t),
9362 fold_build1 (NEGATE_EXPR, itype, step));
9363 else
9364 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9365 t = fold_convert (itype, t);
9366 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9368 q = create_tmp_reg (itype, "q");
9369 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9370 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9371 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9373 tt = create_tmp_reg (itype, "tt");
9374 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9375 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9376 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9378 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9379 gcond *cond_stmt = gimple_build_cond_empty (t);
9380 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9382 second_bb = split_block (entry_bb, cond_stmt)->dest;
9383 gsi = gsi_last_bb (second_bb);
9384 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9386 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9387 GSI_SAME_STMT);
9388 gassign *assign_stmt
9389 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9390 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9392 third_bb = split_block (second_bb, assign_stmt)->dest;
9393 gsi = gsi_last_bb (third_bb);
9394 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9396 t = build2 (MULT_EXPR, itype, q, threadid);
9397 t = build2 (PLUS_EXPR, itype, t, tt);
9398 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9400 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9401 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9403 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9404 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9406 /* Remove the GIMPLE_OMP_FOR statement. */
9407 gsi_remove (&gsi, true);
9409 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9410 gsi = gsi_start_bb (seq_start_bb);
9412 tree startvar = fd->loop.v;
9413 tree endvar = NULL_TREE;
9415 if (gimple_omp_for_combined_p (fd->for_stmt))
9417 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9418 ? gimple_omp_parallel_clauses (inner_stmt)
9419 : gimple_omp_for_clauses (inner_stmt);
9420 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9421 gcc_assert (innerc);
9422 startvar = OMP_CLAUSE_DECL (innerc);
9423 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9424 OMP_CLAUSE__LOOPTEMP_);
9425 gcc_assert (innerc);
9426 endvar = OMP_CLAUSE_DECL (innerc);
9427 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9428 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9430 int i;
9431 for (i = 1; i < fd->collapse; i++)
9433 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9434 OMP_CLAUSE__LOOPTEMP_);
9435 gcc_assert (innerc);
9437 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9438 OMP_CLAUSE__LOOPTEMP_);
9439 if (innerc)
9441 /* If needed (distribute parallel for with lastprivate),
9442 propagate down the total number of iterations. */
9443 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9444 fd->loop.n2);
9445 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9446 GSI_CONTINUE_LINKING);
9447 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9448 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9452 t = fold_convert (itype, s0);
9453 t = fold_build2 (MULT_EXPR, itype, t, step);
9454 if (POINTER_TYPE_P (type))
9455 t = fold_build_pointer_plus (n1, t);
9456 else
9457 t = fold_build2 (PLUS_EXPR, type, t, n1);
9458 t = fold_convert (TREE_TYPE (startvar), t);
9459 t = force_gimple_operand_gsi (&gsi, t,
9460 DECL_P (startvar)
9461 && TREE_ADDRESSABLE (startvar),
9462 NULL_TREE, false, GSI_CONTINUE_LINKING);
9463 assign_stmt = gimple_build_assign (startvar, t);
9464 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9466 t = fold_convert (itype, e0);
9467 t = fold_build2 (MULT_EXPR, itype, t, step);
9468 if (POINTER_TYPE_P (type))
9469 t = fold_build_pointer_plus (n1, t);
9470 else
9471 t = fold_build2 (PLUS_EXPR, type, t, n1);
9472 t = fold_convert (TREE_TYPE (startvar), t);
9473 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9474 false, GSI_CONTINUE_LINKING);
9475 if (endvar)
9477 assign_stmt = gimple_build_assign (endvar, e);
9478 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9479 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9480 assign_stmt = gimple_build_assign (fd->loop.v, e);
9481 else
9482 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9483 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9485 /* Handle linear clause adjustments. */
9486 tree itercnt = NULL_TREE;
9487 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9488 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9489 c; c = OMP_CLAUSE_CHAIN (c))
9490 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9491 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9493 tree d = OMP_CLAUSE_DECL (c);
9494 bool is_ref = is_reference (d);
9495 tree t = d, a, dest;
9496 if (is_ref)
9497 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9498 if (itercnt == NULL_TREE)
9500 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9502 itercnt = fold_build2 (MINUS_EXPR, itype,
9503 fold_convert (itype, n1),
9504 fold_convert (itype, fd->loop.n1));
9505 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9506 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9507 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9508 NULL_TREE, false,
9509 GSI_CONTINUE_LINKING);
9511 else
9512 itercnt = s0;
9514 tree type = TREE_TYPE (t);
9515 if (POINTER_TYPE_P (type))
9516 type = sizetype;
9517 a = fold_build2 (MULT_EXPR, type,
9518 fold_convert (type, itercnt),
9519 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9520 dest = unshare_expr (t);
9521 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9522 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9523 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9524 false, GSI_CONTINUE_LINKING);
9525 assign_stmt = gimple_build_assign (dest, t);
9526 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9528 if (fd->collapse > 1)
9529 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9531 if (!broken_loop)
9533 /* The code controlling the sequential loop replaces the
9534 GIMPLE_OMP_CONTINUE. */
9535 gsi = gsi_last_bb (cont_bb);
9536 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9537 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9538 vmain = gimple_omp_continue_control_use (cont_stmt);
9539 vback = gimple_omp_continue_control_def (cont_stmt);
9541 if (!gimple_omp_for_combined_p (fd->for_stmt))
9543 if (POINTER_TYPE_P (type))
9544 t = fold_build_pointer_plus (vmain, step);
9545 else
9546 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9547 t = force_gimple_operand_gsi (&gsi, t,
9548 DECL_P (vback)
9549 && TREE_ADDRESSABLE (vback),
9550 NULL_TREE, true, GSI_SAME_STMT);
9551 assign_stmt = gimple_build_assign (vback, t);
9552 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9554 t = build2 (fd->loop.cond_code, boolean_type_node,
9555 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9556 ? t : vback, e);
9557 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9560 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9561 gsi_remove (&gsi, true);
9563 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9564 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9567 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9568 gsi = gsi_last_bb (exit_bb);
9569 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9571 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9572 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9574 gsi_remove (&gsi, true);
9576 /* Connect all the blocks. */
9577 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9578 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9579 ep = find_edge (entry_bb, second_bb);
9580 ep->flags = EDGE_TRUE_VALUE;
9581 ep->probability = REG_BR_PROB_BASE / 4;
9582 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9583 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9585 if (!broken_loop)
9587 ep = find_edge (cont_bb, body_bb);
9588 if (ep == NULL)
9590 ep = BRANCH_EDGE (cont_bb);
9591 gcc_assert (single_succ (ep->dest) == body_bb);
9593 if (gimple_omp_for_combined_p (fd->for_stmt))
9595 remove_edge (ep);
9596 ep = NULL;
9598 else if (fd->collapse > 1)
9600 remove_edge (ep);
9601 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9603 else
9604 ep->flags = EDGE_TRUE_VALUE;
9605 find_edge (cont_bb, fin_bb)->flags
9606 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9609 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9610 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9611 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9613 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9614 recompute_dominator (CDI_DOMINATORS, body_bb));
9615 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9616 recompute_dominator (CDI_DOMINATORS, fin_bb));
9618 struct loop *loop = body_bb->loop_father;
9619 if (loop != entry_bb->loop_father)
9621 gcc_assert (loop->header == body_bb);
9622 gcc_assert (broken_loop
9623 || loop->latch == region->cont
9624 || single_pred (loop->latch) == region->cont);
9625 return;
9628 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9630 loop = alloc_loop ();
9631 loop->header = body_bb;
9632 if (collapse_bb == NULL)
9633 loop->latch = cont_bb;
9634 add_loop (loop, body_bb->loop_father);
9638 /* Return phi in E->DEST with ARG on edge E. */
9640 static gphi *
9641 find_phi_with_arg_on_edge (tree arg, edge e)
9643 basic_block bb = e->dest;
9645 for (gphi_iterator gpi = gsi_start_phis (bb);
9646 !gsi_end_p (gpi);
9647 gsi_next (&gpi))
9649 gphi *phi = gpi.phi ();
9650 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9651 return phi;
9654 return NULL;
9657 /* A subroutine of expand_omp_for. Generate code for a parallel
9658 loop with static schedule and a specified chunk size. Given
9659 parameters:
9661 for (V = N1; V cond N2; V += STEP) BODY;
9663 where COND is "<" or ">", we generate pseudocode
9665 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9666 if (cond is <)
9667 adj = STEP - 1;
9668 else
9669 adj = STEP + 1;
9670 if ((__typeof (V)) -1 > 0 && cond is >)
9671 n = -(adj + N2 - N1) / -STEP;
9672 else
9673 n = (adj + N2 - N1) / STEP;
9674 trip = 0;
9675 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9676 here so that V is defined
9677 if the loop is not entered
9679 s0 = (trip * nthreads + threadid) * CHUNK;
9680 e0 = min(s0 + CHUNK, n);
9681 if (s0 < n) goto L1; else goto L4;
9683 V = s0 * STEP + N1;
9684 e = e0 * STEP + N1;
9686 BODY;
9687 V += STEP;
9688 if (V cond e) goto L2; else goto L3;
9690 trip += 1;
9691 goto L0;
9695 static void
9696 expand_omp_for_static_chunk (struct omp_region *region,
9697 struct omp_for_data *fd, gimple *inner_stmt)
9699 tree n, s0, e0, e, t;
9700 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9701 tree type, itype, vmain, vback, vextra;
9702 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9703 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9704 gimple_stmt_iterator gsi;
9705 edge se;
9706 bool broken_loop = region->cont == NULL;
9707 tree *counts = NULL;
9708 tree n1, n2, step;
9710 itype = type = TREE_TYPE (fd->loop.v);
9711 if (POINTER_TYPE_P (type))
9712 itype = signed_type_for (type);
9714 entry_bb = region->entry;
9715 se = split_block (entry_bb, last_stmt (entry_bb));
9716 entry_bb = se->src;
9717 iter_part_bb = se->dest;
9718 cont_bb = region->cont;
9719 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9720 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9721 gcc_assert (broken_loop
9722 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9723 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9724 body_bb = single_succ (seq_start_bb);
9725 if (!broken_loop)
9727 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9728 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9729 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9730 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9732 exit_bb = region->exit;
9734 /* Trip and adjustment setup goes in ENTRY_BB. */
9735 gsi = gsi_last_bb (entry_bb);
9736 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9738 if (fd->collapse > 1)
9740 int first_zero_iter = -1, dummy = -1;
9741 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9743 counts = XALLOCAVEC (tree, fd->collapse);
9744 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9745 fin_bb, first_zero_iter,
9746 dummy_bb, dummy, l2_dom_bb);
9747 t = NULL_TREE;
9749 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9750 t = integer_one_node;
9751 else
9752 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9753 fold_convert (type, fd->loop.n1),
9754 fold_convert (type, fd->loop.n2));
9755 if (fd->collapse == 1
9756 && TYPE_UNSIGNED (type)
9757 && (t == NULL_TREE || !integer_onep (t)))
9759 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9760 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9761 true, GSI_SAME_STMT);
9762 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9763 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9764 true, GSI_SAME_STMT);
9765 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9766 NULL_TREE, NULL_TREE);
9767 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9768 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9769 expand_omp_regimplify_p, NULL, NULL)
9770 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9771 expand_omp_regimplify_p, NULL, NULL))
9773 gsi = gsi_for_stmt (cond_stmt);
9774 gimple_regimplify_operands (cond_stmt, &gsi);
9776 se = split_block (entry_bb, cond_stmt);
9777 se->flags = EDGE_TRUE_VALUE;
9778 entry_bb = se->dest;
9779 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9780 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9781 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9782 if (gimple_in_ssa_p (cfun))
9784 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9785 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9786 !gsi_end_p (gpi); gsi_next (&gpi))
9788 gphi *phi = gpi.phi ();
9789 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9790 se, UNKNOWN_LOCATION);
9793 gsi = gsi_last_bb (entry_bb);
9796 switch (gimple_omp_for_kind (fd->for_stmt))
9798 case GF_OMP_FOR_KIND_FOR:
9799 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9800 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9801 break;
9802 case GF_OMP_FOR_KIND_DISTRIBUTE:
9803 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9804 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9805 break;
9806 default:
9807 gcc_unreachable ();
9809 nthreads = build_call_expr (nthreads, 0);
9810 nthreads = fold_convert (itype, nthreads);
9811 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9812 true, GSI_SAME_STMT);
9813 threadid = build_call_expr (threadid, 0);
9814 threadid = fold_convert (itype, threadid);
9815 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9816 true, GSI_SAME_STMT);
9818 n1 = fd->loop.n1;
9819 n2 = fd->loop.n2;
9820 step = fd->loop.step;
9821 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9823 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9824 OMP_CLAUSE__LOOPTEMP_);
9825 gcc_assert (innerc);
9826 n1 = OMP_CLAUSE_DECL (innerc);
9827 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9828 OMP_CLAUSE__LOOPTEMP_);
9829 gcc_assert (innerc);
9830 n2 = OMP_CLAUSE_DECL (innerc);
9832 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9833 true, NULL_TREE, true, GSI_SAME_STMT);
9834 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9835 true, NULL_TREE, true, GSI_SAME_STMT);
9836 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9837 true, NULL_TREE, true, GSI_SAME_STMT);
9838 tree chunk_size = fold_convert (itype, fd->chunk_size);
9839 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9840 chunk_size
9841 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9842 GSI_SAME_STMT);
9844 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9845 t = fold_build2 (PLUS_EXPR, itype, step, t);
9846 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9847 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9848 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9849 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9850 fold_build1 (NEGATE_EXPR, itype, t),
9851 fold_build1 (NEGATE_EXPR, itype, step));
9852 else
9853 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9854 t = fold_convert (itype, t);
9855 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9856 true, GSI_SAME_STMT);
9858 trip_var = create_tmp_reg (itype, ".trip");
9859 if (gimple_in_ssa_p (cfun))
9861 trip_init = make_ssa_name (trip_var);
9862 trip_main = make_ssa_name (trip_var);
9863 trip_back = make_ssa_name (trip_var);
9865 else
9867 trip_init = trip_var;
9868 trip_main = trip_var;
9869 trip_back = trip_var;
9872 gassign *assign_stmt
9873 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9874 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9876 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9877 t = fold_build2 (MULT_EXPR, itype, t, step);
9878 if (POINTER_TYPE_P (type))
9879 t = fold_build_pointer_plus (n1, t);
9880 else
9881 t = fold_build2 (PLUS_EXPR, type, t, n1);
9882 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9883 true, GSI_SAME_STMT);
9885 /* Remove the GIMPLE_OMP_FOR. */
9886 gsi_remove (&gsi, true);
9888 gimple_stmt_iterator gsif = gsi;
9890 /* Iteration space partitioning goes in ITER_PART_BB. */
9891 gsi = gsi_last_bb (iter_part_bb);
9893 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9894 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9895 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9896 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9897 false, GSI_CONTINUE_LINKING);
9899 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9900 t = fold_build2 (MIN_EXPR, itype, t, n);
9901 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9902 false, GSI_CONTINUE_LINKING);
9904 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9905 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9907 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9908 gsi = gsi_start_bb (seq_start_bb);
9910 tree startvar = fd->loop.v;
9911 tree endvar = NULL_TREE;
9913 if (gimple_omp_for_combined_p (fd->for_stmt))
9915 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9916 ? gimple_omp_parallel_clauses (inner_stmt)
9917 : gimple_omp_for_clauses (inner_stmt);
9918 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9919 gcc_assert (innerc);
9920 startvar = OMP_CLAUSE_DECL (innerc);
9921 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9922 OMP_CLAUSE__LOOPTEMP_);
9923 gcc_assert (innerc);
9924 endvar = OMP_CLAUSE_DECL (innerc);
9925 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9926 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9928 int i;
9929 for (i = 1; i < fd->collapse; i++)
9931 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9932 OMP_CLAUSE__LOOPTEMP_);
9933 gcc_assert (innerc);
9935 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9936 OMP_CLAUSE__LOOPTEMP_);
9937 if (innerc)
9939 /* If needed (distribute parallel for with lastprivate),
9940 propagate down the total number of iterations. */
9941 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9942 fd->loop.n2);
9943 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9944 GSI_CONTINUE_LINKING);
9945 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9946 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9951 t = fold_convert (itype, s0);
9952 t = fold_build2 (MULT_EXPR, itype, t, step);
9953 if (POINTER_TYPE_P (type))
9954 t = fold_build_pointer_plus (n1, t);
9955 else
9956 t = fold_build2 (PLUS_EXPR, type, t, n1);
9957 t = fold_convert (TREE_TYPE (startvar), t);
9958 t = force_gimple_operand_gsi (&gsi, t,
9959 DECL_P (startvar)
9960 && TREE_ADDRESSABLE (startvar),
9961 NULL_TREE, false, GSI_CONTINUE_LINKING);
9962 assign_stmt = gimple_build_assign (startvar, t);
9963 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965 t = fold_convert (itype, e0);
9966 t = fold_build2 (MULT_EXPR, itype, t, step);
9967 if (POINTER_TYPE_P (type))
9968 t = fold_build_pointer_plus (n1, t);
9969 else
9970 t = fold_build2 (PLUS_EXPR, type, t, n1);
9971 t = fold_convert (TREE_TYPE (startvar), t);
9972 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9973 false, GSI_CONTINUE_LINKING);
9974 if (endvar)
9976 assign_stmt = gimple_build_assign (endvar, e);
9977 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9978 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9979 assign_stmt = gimple_build_assign (fd->loop.v, e);
9980 else
9981 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9982 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9984 /* Handle linear clause adjustments. */
9985 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9986 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9987 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9988 c; c = OMP_CLAUSE_CHAIN (c))
9989 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9990 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9992 tree d = OMP_CLAUSE_DECL (c);
9993 bool is_ref = is_reference (d);
9994 tree t = d, a, dest;
9995 if (is_ref)
9996 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9997 tree type = TREE_TYPE (t);
9998 if (POINTER_TYPE_P (type))
9999 type = sizetype;
10000 dest = unshare_expr (t);
10001 tree v = create_tmp_var (TREE_TYPE (t), NULL);
10002 expand_omp_build_assign (&gsif, v, t);
10003 if (itercnt == NULL_TREE)
10005 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10007 itercntbias
10008 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
10009 fold_convert (itype, fd->loop.n1));
10010 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
10011 itercntbias, step);
10012 itercntbias
10013 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10014 NULL_TREE, true,
10015 GSI_SAME_STMT);
10016 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10017 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10018 NULL_TREE, false,
10019 GSI_CONTINUE_LINKING);
10021 else
10022 itercnt = s0;
10024 a = fold_build2 (MULT_EXPR, type,
10025 fold_convert (type, itercnt),
10026 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10027 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10028 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10029 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10030 false, GSI_CONTINUE_LINKING);
10031 assign_stmt = gimple_build_assign (dest, t);
10032 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10034 if (fd->collapse > 1)
10035 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10037 if (!broken_loop)
10039 /* The code controlling the sequential loop goes in CONT_BB,
10040 replacing the GIMPLE_OMP_CONTINUE. */
10041 gsi = gsi_last_bb (cont_bb);
10042 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10043 vmain = gimple_omp_continue_control_use (cont_stmt);
10044 vback = gimple_omp_continue_control_def (cont_stmt);
10046 if (!gimple_omp_for_combined_p (fd->for_stmt))
10048 if (POINTER_TYPE_P (type))
10049 t = fold_build_pointer_plus (vmain, step);
10050 else
10051 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10052 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10053 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10054 true, GSI_SAME_STMT);
10055 assign_stmt = gimple_build_assign (vback, t);
10056 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10058 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10059 t = build2 (EQ_EXPR, boolean_type_node,
10060 build_int_cst (itype, 0),
10061 build_int_cst (itype, 1));
10062 else
10063 t = build2 (fd->loop.cond_code, boolean_type_node,
10064 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10065 ? t : vback, e);
10066 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10069 /* Remove GIMPLE_OMP_CONTINUE. */
10070 gsi_remove (&gsi, true);
10072 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10073 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10075 /* Trip update code goes into TRIP_UPDATE_BB. */
10076 gsi = gsi_start_bb (trip_update_bb);
10078 t = build_int_cst (itype, 1);
10079 t = build2 (PLUS_EXPR, itype, trip_main, t);
10080 assign_stmt = gimple_build_assign (trip_back, t);
10081 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10084 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10085 gsi = gsi_last_bb (exit_bb);
10086 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10088 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10089 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10091 gsi_remove (&gsi, true);
10093 /* Connect the new blocks. */
10094 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10095 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10097 if (!broken_loop)
10099 se = find_edge (cont_bb, body_bb);
10100 if (se == NULL)
10102 se = BRANCH_EDGE (cont_bb);
10103 gcc_assert (single_succ (se->dest) == body_bb);
10105 if (gimple_omp_for_combined_p (fd->for_stmt))
10107 remove_edge (se);
10108 se = NULL;
10110 else if (fd->collapse > 1)
10112 remove_edge (se);
10113 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10115 else
10116 se->flags = EDGE_TRUE_VALUE;
10117 find_edge (cont_bb, trip_update_bb)->flags
10118 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10120 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10123 if (gimple_in_ssa_p (cfun))
10125 gphi_iterator psi;
10126 gphi *phi;
10127 edge re, ene;
10128 edge_var_map *vm;
10129 size_t i;
10131 gcc_assert (fd->collapse == 1 && !broken_loop);
10133 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10134 remove arguments of the phi nodes in fin_bb. We need to create
10135 appropriate phi nodes in iter_part_bb instead. */
10136 se = find_edge (iter_part_bb, fin_bb);
10137 re = single_succ_edge (trip_update_bb);
10138 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10139 ene = single_succ_edge (entry_bb);
10141 psi = gsi_start_phis (fin_bb);
10142 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10143 gsi_next (&psi), ++i)
10145 gphi *nphi;
10146 source_location locus;
10148 phi = psi.phi ();
10149 t = gimple_phi_result (phi);
10150 gcc_assert (t == redirect_edge_var_map_result (vm));
10152 if (!single_pred_p (fin_bb))
10153 t = copy_ssa_name (t, phi);
10155 nphi = create_phi_node (t, iter_part_bb);
10157 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10158 locus = gimple_phi_arg_location_from_edge (phi, se);
10160 /* A special case -- fd->loop.v is not yet computed in
10161 iter_part_bb, we need to use vextra instead. */
10162 if (t == fd->loop.v)
10163 t = vextra;
10164 add_phi_arg (nphi, t, ene, locus);
10165 locus = redirect_edge_var_map_location (vm);
10166 tree back_arg = redirect_edge_var_map_def (vm);
10167 add_phi_arg (nphi, back_arg, re, locus);
10168 edge ce = find_edge (cont_bb, body_bb);
10169 if (ce == NULL)
10171 ce = BRANCH_EDGE (cont_bb);
10172 gcc_assert (single_succ (ce->dest) == body_bb);
10173 ce = single_succ_edge (ce->dest);
10175 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10176 gcc_assert (inner_loop_phi != NULL);
10177 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10178 find_edge (seq_start_bb, body_bb), locus);
10180 if (!single_pred_p (fin_bb))
10181 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10183 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10184 redirect_edge_var_map_clear (re);
10185 if (single_pred_p (fin_bb))
10186 while (1)
10188 psi = gsi_start_phis (fin_bb);
10189 if (gsi_end_p (psi))
10190 break;
10191 remove_phi_node (&psi, false);
10194 /* Make phi node for trip. */
10195 phi = create_phi_node (trip_main, iter_part_bb);
10196 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10197 UNKNOWN_LOCATION);
10198 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10199 UNKNOWN_LOCATION);
10202 if (!broken_loop)
10203 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10204 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10205 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10206 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10207 recompute_dominator (CDI_DOMINATORS, fin_bb));
10208 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10209 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10210 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10211 recompute_dominator (CDI_DOMINATORS, body_bb));
10213 if (!broken_loop)
10215 struct loop *loop = body_bb->loop_father;
10216 struct loop *trip_loop = alloc_loop ();
10217 trip_loop->header = iter_part_bb;
10218 trip_loop->latch = trip_update_bb;
10219 add_loop (trip_loop, iter_part_bb->loop_father);
10221 if (loop != entry_bb->loop_father)
10223 gcc_assert (loop->header == body_bb);
10224 gcc_assert (loop->latch == region->cont
10225 || single_pred (loop->latch) == region->cont);
10226 trip_loop->inner = loop;
10227 return;
10230 if (!gimple_omp_for_combined_p (fd->for_stmt))
10232 loop = alloc_loop ();
10233 loop->header = body_bb;
10234 if (collapse_bb == NULL)
10235 loop->latch = cont_bb;
10236 add_loop (loop, trip_loop);
10241 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10242 Given parameters:
10243 for (V = N1; V cond N2; V += STEP) BODY;
10245 where COND is "<" or ">" or "!=", we generate pseudocode
10247 for (ind_var = low; ind_var < high; ind_var++)
10249 V = n1 + (ind_var * STEP)
10251 <BODY>
10254 In the above pseudocode, low and high are function parameters of the
10255 child function. In the function below, we are inserting a temp.
10256 variable that will be making a call to two OMP functions that will not be
10257 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10258 with _Cilk_for). These functions are replaced with low and high
10259 by the function that handles taskreg. */
10262 static void
10263 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10265 bool broken_loop = region->cont == NULL;
10266 basic_block entry_bb = region->entry;
10267 basic_block cont_bb = region->cont;
10269 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10270 gcc_assert (broken_loop
10271 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10272 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10273 basic_block l1_bb, l2_bb;
10275 if (!broken_loop)
10277 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10278 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10279 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10280 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10282 else
10284 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10285 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10286 l2_bb = single_succ (l1_bb);
10288 basic_block exit_bb = region->exit;
10289 basic_block l2_dom_bb = NULL;
10291 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10293 /* Below statements until the "tree high_val = ..." are pseudo statements
10294 used to pass information to be used by expand_omp_taskreg.
10295 low_val and high_val will be replaced by the __low and __high
10296 parameter from the child function.
10298 The call_exprs part is a place-holder, it is mainly used
10299 to distinctly identify to the top-level part that this is
10300 where we should put low and high (reasoning given in header
10301 comment). */
10303 tree child_fndecl
10304 = gimple_omp_parallel_child_fn (
10305 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10306 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10307 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10309 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10310 high_val = t;
10311 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10312 low_val = t;
10314 gcc_assert (low_val && high_val);
10316 tree type = TREE_TYPE (low_val);
10317 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10318 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10320 /* Not needed in SSA form right now. */
10321 gcc_assert (!gimple_in_ssa_p (cfun));
10322 if (l2_dom_bb == NULL)
10323 l2_dom_bb = l1_bb;
10325 tree n1 = low_val;
10326 tree n2 = high_val;
10328 gimple *stmt = gimple_build_assign (ind_var, n1);
10330 /* Replace the GIMPLE_OMP_FOR statement. */
10331 gsi_replace (&gsi, stmt, true);
10333 if (!broken_loop)
10335 /* Code to control the increment goes in the CONT_BB. */
10336 gsi = gsi_last_bb (cont_bb);
10337 stmt = gsi_stmt (gsi);
10338 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10339 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10340 build_one_cst (type));
10342 /* Replace GIMPLE_OMP_CONTINUE. */
10343 gsi_replace (&gsi, stmt, true);
10346 /* Emit the condition in L1_BB. */
10347 gsi = gsi_after_labels (l1_bb);
10348 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10349 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10350 fd->loop.step);
10351 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10352 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10353 fd->loop.n1, fold_convert (sizetype, t));
10354 else
10355 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10356 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10357 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10358 expand_omp_build_assign (&gsi, fd->loop.v, t);
10360 /* The condition is always '<' since the runtime will fill in the low
10361 and high values. */
10362 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10363 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10365 /* Remove GIMPLE_OMP_RETURN. */
10366 gsi = gsi_last_bb (exit_bb);
10367 gsi_remove (&gsi, true);
10369 /* Connect the new blocks. */
10370 remove_edge (FALLTHRU_EDGE (entry_bb));
10372 edge e, ne;
10373 if (!broken_loop)
10375 remove_edge (BRANCH_EDGE (entry_bb));
10376 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10378 e = BRANCH_EDGE (l1_bb);
10379 ne = FALLTHRU_EDGE (l1_bb);
10380 e->flags = EDGE_TRUE_VALUE;
10382 else
10384 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10386 ne = single_succ_edge (l1_bb);
10387 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10390 ne->flags = EDGE_FALSE_VALUE;
10391 e->probability = REG_BR_PROB_BASE * 7 / 8;
10392 ne->probability = REG_BR_PROB_BASE / 8;
10394 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10395 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10396 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10398 if (!broken_loop)
10400 struct loop *loop = alloc_loop ();
10401 loop->header = l1_bb;
10402 loop->latch = cont_bb;
10403 add_loop (loop, l1_bb->loop_father);
10404 loop->safelen = INT_MAX;
10407 /* Pick the correct library function based on the precision of the
10408 induction variable type. */
10409 tree lib_fun = NULL_TREE;
10410 if (TYPE_PRECISION (type) == 32)
10411 lib_fun = cilk_for_32_fndecl;
10412 else if (TYPE_PRECISION (type) == 64)
10413 lib_fun = cilk_for_64_fndecl;
10414 else
10415 gcc_unreachable ();
10417 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10419 /* WS_ARGS contains the library function flavor to call:
10420 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10421 user-defined grain value. If the user does not define one, then zero
10422 is passed in by the parser. */
10423 vec_alloc (region->ws_args, 2);
10424 region->ws_args->quick_push (lib_fun);
10425 region->ws_args->quick_push (fd->chunk_size);
10428 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10429 loop. Given parameters:
10431 for (V = N1; V cond N2; V += STEP) BODY;
10433 where COND is "<" or ">", we generate pseudocode
10435 V = N1;
10436 goto L1;
10438 BODY;
10439 V += STEP;
10441 if (V cond N2) goto L0; else goto L2;
10444 For collapsed loops, given parameters:
10445 collapse(3)
10446 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10447 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10448 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10449 BODY;
10451 we generate pseudocode
10453 if (cond3 is <)
10454 adj = STEP3 - 1;
10455 else
10456 adj = STEP3 + 1;
10457 count3 = (adj + N32 - N31) / STEP3;
10458 if (cond2 is <)
10459 adj = STEP2 - 1;
10460 else
10461 adj = STEP2 + 1;
10462 count2 = (adj + N22 - N21) / STEP2;
10463 if (cond1 is <)
10464 adj = STEP1 - 1;
10465 else
10466 adj = STEP1 + 1;
10467 count1 = (adj + N12 - N11) / STEP1;
10468 count = count1 * count2 * count3;
10469 V = 0;
10470 V1 = N11;
10471 V2 = N21;
10472 V3 = N31;
10473 goto L1;
10475 BODY;
10476 V += 1;
10477 V3 += STEP3;
10478 V2 += (V3 cond3 N32) ? 0 : STEP2;
10479 V3 = (V3 cond3 N32) ? V3 : N31;
10480 V1 += (V2 cond2 N22) ? 0 : STEP1;
10481 V2 = (V2 cond2 N22) ? V2 : N21;
10483 if (V < count) goto L0; else goto L2;
10488 static void
10489 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10491 tree type, t;
10492 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10493 gimple_stmt_iterator gsi;
10494 gimple *stmt;
10495 gcond *cond_stmt;
10496 bool broken_loop = region->cont == NULL;
10497 edge e, ne;
10498 tree *counts = NULL;
10499 int i;
10500 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10501 OMP_CLAUSE_SAFELEN);
10502 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10503 OMP_CLAUSE__SIMDUID_);
10504 tree n1, n2;
10506 type = TREE_TYPE (fd->loop.v);
10507 entry_bb = region->entry;
10508 cont_bb = region->cont;
10509 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10510 gcc_assert (broken_loop
10511 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10512 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10513 if (!broken_loop)
10515 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10516 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10517 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10518 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10520 else
10522 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10523 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10524 l2_bb = single_succ (l1_bb);
10526 exit_bb = region->exit;
10527 l2_dom_bb = NULL;
10529 gsi = gsi_last_bb (entry_bb);
10531 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10532 /* Not needed in SSA form right now. */
10533 gcc_assert (!gimple_in_ssa_p (cfun));
10534 if (fd->collapse > 1)
10536 int first_zero_iter = -1, dummy = -1;
10537 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10539 counts = XALLOCAVEC (tree, fd->collapse);
10540 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10541 zero_iter_bb, first_zero_iter,
10542 dummy_bb, dummy, l2_dom_bb);
10544 if (l2_dom_bb == NULL)
10545 l2_dom_bb = l1_bb;
10547 n1 = fd->loop.n1;
10548 n2 = fd->loop.n2;
10549 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10551 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10552 OMP_CLAUSE__LOOPTEMP_);
10553 gcc_assert (innerc);
10554 n1 = OMP_CLAUSE_DECL (innerc);
10555 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10556 OMP_CLAUSE__LOOPTEMP_);
10557 gcc_assert (innerc);
10558 n2 = OMP_CLAUSE_DECL (innerc);
10559 expand_omp_build_assign (&gsi, fd->loop.v,
10560 fold_convert (type, n1));
10561 if (fd->collapse > 1)
10563 gsi_prev (&gsi);
10564 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10565 gsi_next (&gsi);
10568 else
10570 expand_omp_build_assign (&gsi, fd->loop.v,
10571 fold_convert (type, fd->loop.n1));
10572 if (fd->collapse > 1)
10573 for (i = 0; i < fd->collapse; i++)
10575 tree itype = TREE_TYPE (fd->loops[i].v);
10576 if (POINTER_TYPE_P (itype))
10577 itype = signed_type_for (itype);
10578 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10579 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10583 /* Remove the GIMPLE_OMP_FOR statement. */
10584 gsi_remove (&gsi, true);
10586 if (!broken_loop)
10588 /* Code to control the increment goes in the CONT_BB. */
10589 gsi = gsi_last_bb (cont_bb);
10590 stmt = gsi_stmt (gsi);
10591 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10593 if (POINTER_TYPE_P (type))
10594 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10595 else
10596 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10597 expand_omp_build_assign (&gsi, fd->loop.v, t);
10599 if (fd->collapse > 1)
10601 i = fd->collapse - 1;
10602 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10604 t = fold_convert (sizetype, fd->loops[i].step);
10605 t = fold_build_pointer_plus (fd->loops[i].v, t);
10607 else
10609 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10610 fd->loops[i].step);
10611 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10612 fd->loops[i].v, t);
10614 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10616 for (i = fd->collapse - 1; i > 0; i--)
10618 tree itype = TREE_TYPE (fd->loops[i].v);
10619 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10620 if (POINTER_TYPE_P (itype2))
10621 itype2 = signed_type_for (itype2);
10622 t = build3 (COND_EXPR, itype2,
10623 build2 (fd->loops[i].cond_code, boolean_type_node,
10624 fd->loops[i].v,
10625 fold_convert (itype, fd->loops[i].n2)),
10626 build_int_cst (itype2, 0),
10627 fold_convert (itype2, fd->loops[i - 1].step));
10628 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10629 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10630 else
10631 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10632 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10634 t = build3 (COND_EXPR, itype,
10635 build2 (fd->loops[i].cond_code, boolean_type_node,
10636 fd->loops[i].v,
10637 fold_convert (itype, fd->loops[i].n2)),
10638 fd->loops[i].v,
10639 fold_convert (itype, fd->loops[i].n1));
10640 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10644 /* Remove GIMPLE_OMP_CONTINUE. */
10645 gsi_remove (&gsi, true);
10648 /* Emit the condition in L1_BB. */
10649 gsi = gsi_start_bb (l1_bb);
10651 t = fold_convert (type, n2);
10652 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10653 false, GSI_CONTINUE_LINKING);
10654 tree v = fd->loop.v;
10655 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10656 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10657 false, GSI_CONTINUE_LINKING);
10658 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10659 cond_stmt = gimple_build_cond_empty (t);
10660 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10661 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10662 NULL, NULL)
10663 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10664 NULL, NULL))
10666 gsi = gsi_for_stmt (cond_stmt);
10667 gimple_regimplify_operands (cond_stmt, &gsi);
10670 /* Remove GIMPLE_OMP_RETURN. */
10671 gsi = gsi_last_bb (exit_bb);
10672 gsi_remove (&gsi, true);
10674 /* Connect the new blocks. */
10675 remove_edge (FALLTHRU_EDGE (entry_bb));
10677 if (!broken_loop)
10679 remove_edge (BRANCH_EDGE (entry_bb));
10680 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10682 e = BRANCH_EDGE (l1_bb);
10683 ne = FALLTHRU_EDGE (l1_bb);
10684 e->flags = EDGE_TRUE_VALUE;
10686 else
10688 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10690 ne = single_succ_edge (l1_bb);
10691 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10694 ne->flags = EDGE_FALSE_VALUE;
10695 e->probability = REG_BR_PROB_BASE * 7 / 8;
10696 ne->probability = REG_BR_PROB_BASE / 8;
10698 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10699 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10700 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10702 if (!broken_loop)
10704 struct loop *loop = alloc_loop ();
10705 loop->header = l1_bb;
10706 loop->latch = cont_bb;
10707 add_loop (loop, l1_bb->loop_father);
10708 if (safelen == NULL_TREE)
10709 loop->safelen = INT_MAX;
10710 else
10712 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10713 if (TREE_CODE (safelen) != INTEGER_CST)
10714 loop->safelen = 0;
10715 else if (!tree_fits_uhwi_p (safelen)
10716 || tree_to_uhwi (safelen) > INT_MAX)
10717 loop->safelen = INT_MAX;
10718 else
10719 loop->safelen = tree_to_uhwi (safelen);
10720 if (loop->safelen == 1)
10721 loop->safelen = 0;
10723 if (simduid)
10725 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10726 cfun->has_simduid_loops = true;
10728 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10729 the loop. */
10730 if ((flag_tree_loop_vectorize
10731 || (!global_options_set.x_flag_tree_loop_vectorize
10732 && !global_options_set.x_flag_tree_vectorize))
10733 && flag_tree_loop_optimize
10734 && loop->safelen > 1)
10736 loop->force_vectorize = true;
10737 cfun->has_force_vectorize_loops = true;
10740 else if (simduid)
10741 cfun->has_simduid_loops = true;
10744 /* Taskloop construct is represented after gimplification with
10745 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10746 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10747 which should just compute all the needed loop temporaries
10748 for GIMPLE_OMP_TASK. */
10750 static void
10751 expand_omp_taskloop_for_outer (struct omp_region *region,
10752 struct omp_for_data *fd,
10753 gimple *inner_stmt)
10755 tree type, bias = NULL_TREE;
10756 basic_block entry_bb, cont_bb, exit_bb;
10757 gimple_stmt_iterator gsi;
10758 gassign *assign_stmt;
10759 tree *counts = NULL;
10760 int i;
10762 gcc_assert (inner_stmt);
10763 gcc_assert (region->cont);
10764 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10765 && gimple_omp_task_taskloop_p (inner_stmt));
10766 type = TREE_TYPE (fd->loop.v);
10768 /* See if we need to bias by LLONG_MIN. */
10769 if (fd->iter_type == long_long_unsigned_type_node
10770 && TREE_CODE (type) == INTEGER_TYPE
10771 && !TYPE_UNSIGNED (type))
10773 tree n1, n2;
10775 if (fd->loop.cond_code == LT_EXPR)
10777 n1 = fd->loop.n1;
10778 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10780 else
10782 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10783 n2 = fd->loop.n1;
10785 if (TREE_CODE (n1) != INTEGER_CST
10786 || TREE_CODE (n2) != INTEGER_CST
10787 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10788 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10791 entry_bb = region->entry;
10792 cont_bb = region->cont;
10793 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10794 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10795 exit_bb = region->exit;
10797 gsi = gsi_last_bb (entry_bb);
10798 gimple *for_stmt = gsi_stmt (gsi);
10799 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10800 if (fd->collapse > 1)
10802 int first_zero_iter = -1, dummy = -1;
10803 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10805 counts = XALLOCAVEC (tree, fd->collapse);
10806 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10807 zero_iter_bb, first_zero_iter,
10808 dummy_bb, dummy, l2_dom_bb);
10810 if (zero_iter_bb)
10812 /* Some counts[i] vars might be uninitialized if
10813 some loop has zero iterations. But the body shouldn't
10814 be executed in that case, so just avoid uninit warnings. */
10815 for (i = first_zero_iter; i < fd->collapse; i++)
10816 if (SSA_VAR_P (counts[i]))
10817 TREE_NO_WARNING (counts[i]) = 1;
10818 gsi_prev (&gsi);
10819 edge e = split_block (entry_bb, gsi_stmt (gsi));
10820 entry_bb = e->dest;
10821 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10822 gsi = gsi_last_bb (entry_bb);
10823 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10824 get_immediate_dominator (CDI_DOMINATORS,
10825 zero_iter_bb));
10829 tree t0, t1;
10830 t1 = fd->loop.n2;
10831 t0 = fd->loop.n1;
10832 if (POINTER_TYPE_P (TREE_TYPE (t0))
10833 && TYPE_PRECISION (TREE_TYPE (t0))
10834 != TYPE_PRECISION (fd->iter_type))
10836 /* Avoid casting pointers to integer of a different size. */
10837 tree itype = signed_type_for (type);
10838 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10839 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10841 else
10843 t1 = fold_convert (fd->iter_type, t1);
10844 t0 = fold_convert (fd->iter_type, t0);
10846 if (bias)
10848 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10849 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10852 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10853 OMP_CLAUSE__LOOPTEMP_);
10854 gcc_assert (innerc);
10855 tree startvar = OMP_CLAUSE_DECL (innerc);
10856 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10857 gcc_assert (innerc);
10858 tree endvar = OMP_CLAUSE_DECL (innerc);
10859 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10861 gcc_assert (innerc);
10862 for (i = 1; i < fd->collapse; i++)
10864 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10865 OMP_CLAUSE__LOOPTEMP_);
10866 gcc_assert (innerc);
10868 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10869 OMP_CLAUSE__LOOPTEMP_);
10870 if (innerc)
10872 /* If needed (inner taskloop has lastprivate clause), propagate
10873 down the total number of iterations. */
10874 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10875 NULL_TREE, false,
10876 GSI_CONTINUE_LINKING);
10877 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10878 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10882 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10883 GSI_CONTINUE_LINKING);
10884 assign_stmt = gimple_build_assign (startvar, t0);
10885 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10887 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10888 GSI_CONTINUE_LINKING);
10889 assign_stmt = gimple_build_assign (endvar, t1);
10890 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10891 if (fd->collapse > 1)
10892 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10894 /* Remove the GIMPLE_OMP_FOR statement. */
10895 gsi = gsi_for_stmt (for_stmt);
10896 gsi_remove (&gsi, true);
10898 gsi = gsi_last_bb (cont_bb);
10899 gsi_remove (&gsi, true);
10901 gsi = gsi_last_bb (exit_bb);
10902 gsi_remove (&gsi, true);
10904 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10905 remove_edge (BRANCH_EDGE (entry_bb));
10906 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10907 remove_edge (BRANCH_EDGE (cont_bb));
10908 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10909 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10910 recompute_dominator (CDI_DOMINATORS, region->entry));
10913 /* Taskloop construct is represented after gimplification with
10914 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10915 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10916 GOMP_taskloop{,_ull} function arranges for each task to be given just
10917 a single range of iterations. */
10919 static void
10920 expand_omp_taskloop_for_inner (struct omp_region *region,
10921 struct omp_for_data *fd,
10922 gimple *inner_stmt)
10924 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10925 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10926 basic_block fin_bb;
10927 gimple_stmt_iterator gsi;
10928 edge ep;
10929 bool broken_loop = region->cont == NULL;
10930 tree *counts = NULL;
10931 tree n1, n2, step;
10933 itype = type = TREE_TYPE (fd->loop.v);
10934 if (POINTER_TYPE_P (type))
10935 itype = signed_type_for (type);
10937 /* See if we need to bias by LLONG_MIN. */
10938 if (fd->iter_type == long_long_unsigned_type_node
10939 && TREE_CODE (type) == INTEGER_TYPE
10940 && !TYPE_UNSIGNED (type))
10942 tree n1, n2;
10944 if (fd->loop.cond_code == LT_EXPR)
10946 n1 = fd->loop.n1;
10947 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10949 else
10951 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10952 n2 = fd->loop.n1;
10954 if (TREE_CODE (n1) != INTEGER_CST
10955 || TREE_CODE (n2) != INTEGER_CST
10956 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10957 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10960 entry_bb = region->entry;
10961 cont_bb = region->cont;
10962 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10963 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10964 gcc_assert (broken_loop
10965 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10966 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10967 if (!broken_loop)
10969 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10970 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10972 exit_bb = region->exit;
10974 /* Iteration space partitioning goes in ENTRY_BB. */
10975 gsi = gsi_last_bb (entry_bb);
10976 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10978 if (fd->collapse > 1)
10980 int first_zero_iter = -1, dummy = -1;
10981 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10983 counts = XALLOCAVEC (tree, fd->collapse);
10984 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10985 fin_bb, first_zero_iter,
10986 dummy_bb, dummy, l2_dom_bb);
10987 t = NULL_TREE;
10989 else
10990 t = integer_one_node;
10992 step = fd->loop.step;
10993 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10994 OMP_CLAUSE__LOOPTEMP_);
10995 gcc_assert (innerc);
10996 n1 = OMP_CLAUSE_DECL (innerc);
10997 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10998 gcc_assert (innerc);
10999 n2 = OMP_CLAUSE_DECL (innerc);
11000 if (bias)
11002 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
11003 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
11005 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
11006 true, NULL_TREE, true, GSI_SAME_STMT);
11007 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
11008 true, NULL_TREE, true, GSI_SAME_STMT);
11009 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
11010 true, NULL_TREE, true, GSI_SAME_STMT);
11012 tree startvar = fd->loop.v;
11013 tree endvar = NULL_TREE;
11015 if (gimple_omp_for_combined_p (fd->for_stmt))
11017 tree clauses = gimple_omp_for_clauses (inner_stmt);
11018 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11019 gcc_assert (innerc);
11020 startvar = OMP_CLAUSE_DECL (innerc);
11021 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11022 OMP_CLAUSE__LOOPTEMP_);
11023 gcc_assert (innerc);
11024 endvar = OMP_CLAUSE_DECL (innerc);
11026 t = fold_convert (TREE_TYPE (startvar), n1);
11027 t = force_gimple_operand_gsi (&gsi, t,
11028 DECL_P (startvar)
11029 && TREE_ADDRESSABLE (startvar),
11030 NULL_TREE, false, GSI_CONTINUE_LINKING);
11031 gimple *assign_stmt = gimple_build_assign (startvar, t);
11032 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11034 t = fold_convert (TREE_TYPE (startvar), n2);
11035 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11036 false, GSI_CONTINUE_LINKING);
11037 if (endvar)
11039 assign_stmt = gimple_build_assign (endvar, e);
11040 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11041 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11042 assign_stmt = gimple_build_assign (fd->loop.v, e);
11043 else
11044 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11045 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11047 if (fd->collapse > 1)
11048 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11050 if (!broken_loop)
11052 /* The code controlling the sequential loop replaces the
11053 GIMPLE_OMP_CONTINUE. */
11054 gsi = gsi_last_bb (cont_bb);
11055 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11056 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11057 vmain = gimple_omp_continue_control_use (cont_stmt);
11058 vback = gimple_omp_continue_control_def (cont_stmt);
11060 if (!gimple_omp_for_combined_p (fd->for_stmt))
11062 if (POINTER_TYPE_P (type))
11063 t = fold_build_pointer_plus (vmain, step);
11064 else
11065 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11066 t = force_gimple_operand_gsi (&gsi, t,
11067 DECL_P (vback)
11068 && TREE_ADDRESSABLE (vback),
11069 NULL_TREE, true, GSI_SAME_STMT);
11070 assign_stmt = gimple_build_assign (vback, t);
11071 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11073 t = build2 (fd->loop.cond_code, boolean_type_node,
11074 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11075 ? t : vback, e);
11076 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11079 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11080 gsi_remove (&gsi, true);
11082 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11083 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11086 /* Remove the GIMPLE_OMP_FOR statement. */
11087 gsi = gsi_for_stmt (fd->for_stmt);
11088 gsi_remove (&gsi, true);
11090 /* Remove the GIMPLE_OMP_RETURN statement. */
11091 gsi = gsi_last_bb (exit_bb);
11092 gsi_remove (&gsi, true);
11094 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11095 if (!broken_loop)
11096 remove_edge (BRANCH_EDGE (entry_bb));
11097 else
11099 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11100 region->outer->cont = NULL;
11103 /* Connect all the blocks. */
11104 if (!broken_loop)
11106 ep = find_edge (cont_bb, body_bb);
11107 if (gimple_omp_for_combined_p (fd->for_stmt))
11109 remove_edge (ep);
11110 ep = NULL;
11112 else if (fd->collapse > 1)
11114 remove_edge (ep);
11115 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11117 else
11118 ep->flags = EDGE_TRUE_VALUE;
11119 find_edge (cont_bb, fin_bb)->flags
11120 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11123 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11124 recompute_dominator (CDI_DOMINATORS, body_bb));
11125 if (!broken_loop)
11126 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11127 recompute_dominator (CDI_DOMINATORS, fin_bb));
11129 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11131 struct loop *loop = alloc_loop ();
11132 loop->header = body_bb;
11133 if (collapse_bb == NULL)
11134 loop->latch = cont_bb;
11135 add_loop (loop, body_bb->loop_father);
11139 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11140 partitioned loop. The lowering here is abstracted, in that the
11141 loop parameters are passed through internal functions, which are
11142 further lowered by oacc_device_lower, once we get to the target
11143 compiler. The loop is of the form:
11145 for (V = B; V LTGT E; V += S) {BODY}
11147 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11148 (constant 0 for no chunking) and we will have a GWV partitioning
11149 mask, specifying dimensions over which the loop is to be
11150 partitioned (see note below). We generate code that looks like:
11152 <entry_bb> [incoming FALL->body, BRANCH->exit]
11153 typedef signedintify (typeof (V)) T; // underlying signed integral type
11154 T range = E - B;
11155 T chunk_no = 0;
11156 T DIR = LTGT == '<' ? +1 : -1;
11157 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11158 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11160 <head_bb> [created by splitting end of entry_bb]
11161 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11162 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11163 if (!(offset LTGT bound)) goto bottom_bb;
11165 <body_bb> [incoming]
11166 V = B + offset;
11167 {BODY}
11169 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11170 offset += step;
11171 if (offset LTGT bound) goto body_bb; [*]
11173 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11174 chunk_no++;
11175 if (chunk < chunk_max) goto head_bb;
11177 <exit_bb> [incoming]
11178 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11180 [*] Needed if V live at end of loop
11182 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11183 transition, and will be specified by a more general mechanism shortly.
11186 static void
11187 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11189 tree v = fd->loop.v;
11190 enum tree_code cond_code = fd->loop.cond_code;
11191 enum tree_code plus_code = PLUS_EXPR;
11193 tree chunk_size = integer_minus_one_node;
11194 tree gwv = integer_zero_node;
11195 tree iter_type = TREE_TYPE (v);
11196 tree diff_type = iter_type;
11197 tree plus_type = iter_type;
11198 struct oacc_collapse *counts = NULL;
11200 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11201 == GF_OMP_FOR_KIND_OACC_LOOP);
11202 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11203 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11205 if (POINTER_TYPE_P (iter_type))
11207 plus_code = POINTER_PLUS_EXPR;
11208 plus_type = sizetype;
11210 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11211 diff_type = signed_type_for (diff_type);
11213 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11214 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11215 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11216 basic_block bottom_bb = NULL;
11218 /* entry_bb has two sucessors; the branch edge is to the exit
11219 block, fallthrough edge to body. */
11220 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11221 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11223 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11224 body_bb, or to a block whose only successor is the body_bb. Its
11225 fallthrough successor is the final block (same as the branch
11226 successor of the entry_bb). */
11227 if (cont_bb)
11229 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11230 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11232 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11233 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11235 else
11236 gcc_assert (!gimple_in_ssa_p (cfun));
11238 /* The exit block only has entry_bb and cont_bb as predecessors. */
11239 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11241 tree chunk_no;
11242 tree chunk_max = NULL_TREE;
11243 tree bound, offset;
11244 tree step = create_tmp_var (diff_type, ".step");
11245 bool up = cond_code == LT_EXPR;
11246 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11247 bool chunking = !gimple_in_ssa_p (cfun);;
11248 bool negating;
11250 /* SSA instances. */
11251 tree offset_incr = NULL_TREE;
11252 tree offset_init = NULL_TREE;
11254 gimple_stmt_iterator gsi;
11255 gassign *ass;
11256 gcall *call;
11257 gimple *stmt;
11258 tree expr;
11259 location_t loc;
11260 edge split, be, fte;
11262 /* Split the end of entry_bb to create head_bb. */
11263 split = split_block (entry_bb, last_stmt (entry_bb));
11264 basic_block head_bb = split->dest;
11265 entry_bb = split->src;
11267 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11268 gsi = gsi_last_bb (entry_bb);
11269 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11270 loc = gimple_location (for_stmt);
11272 if (gimple_in_ssa_p (cfun))
11274 offset_init = gimple_omp_for_index (for_stmt, 0);
11275 gcc_assert (integer_zerop (fd->loop.n1));
11276 /* The SSA parallelizer does gang parallelism. */
11277 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11280 if (fd->collapse > 1)
11282 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11283 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11284 TREE_TYPE (fd->loop.n2));
11286 if (SSA_VAR_P (fd->loop.n2))
11288 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11289 true, GSI_SAME_STMT);
11290 ass = gimple_build_assign (fd->loop.n2, total);
11291 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11296 tree b = fd->loop.n1;
11297 tree e = fd->loop.n2;
11298 tree s = fd->loop.step;
11300 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11301 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11303 /* Convert the step, avoiding possible unsigned->signed overflow. */
11304 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11305 if (negating)
11306 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11307 s = fold_convert (diff_type, s);
11308 if (negating)
11309 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11310 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11312 if (!chunking)
11313 chunk_size = integer_zero_node;
11314 expr = fold_convert (diff_type, chunk_size);
11315 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11316 NULL_TREE, true, GSI_SAME_STMT);
11317 /* Determine the range, avoiding possible unsigned->signed overflow. */
11318 negating = !up && TYPE_UNSIGNED (iter_type);
11319 expr = fold_build2 (MINUS_EXPR, plus_type,
11320 fold_convert (plus_type, negating ? b : e),
11321 fold_convert (plus_type, negating ? e : b));
11322 expr = fold_convert (diff_type, expr);
11323 if (negating)
11324 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11325 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11326 NULL_TREE, true, GSI_SAME_STMT);
11328 chunk_no = build_int_cst (diff_type, 0);
11329 if (chunking)
11331 gcc_assert (!gimple_in_ssa_p (cfun));
11333 expr = chunk_no;
11334 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11335 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11337 ass = gimple_build_assign (chunk_no, expr);
11338 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11340 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11341 build_int_cst (integer_type_node,
11342 IFN_GOACC_LOOP_CHUNKS),
11343 dir, range, s, chunk_size, gwv);
11344 gimple_call_set_lhs (call, chunk_max);
11345 gimple_set_location (call, loc);
11346 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11348 else
11349 chunk_size = chunk_no;
11351 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11352 build_int_cst (integer_type_node,
11353 IFN_GOACC_LOOP_STEP),
11354 dir, range, s, chunk_size, gwv);
11355 gimple_call_set_lhs (call, step);
11356 gimple_set_location (call, loc);
11357 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11359 /* Remove the GIMPLE_OMP_FOR. */
11360 gsi_remove (&gsi, true);
11362 /* Fixup edges from head_bb */
11363 be = BRANCH_EDGE (head_bb);
11364 fte = FALLTHRU_EDGE (head_bb);
11365 be->flags |= EDGE_FALSE_VALUE;
11366 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11368 basic_block body_bb = fte->dest;
11370 if (gimple_in_ssa_p (cfun))
11372 gsi = gsi_last_bb (cont_bb);
11373 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11375 offset = gimple_omp_continue_control_use (cont_stmt);
11376 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11378 else
11380 offset = create_tmp_var (diff_type, ".offset");
11381 offset_init = offset_incr = offset;
11383 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11385 /* Loop offset & bound go into head_bb. */
11386 gsi = gsi_start_bb (head_bb);
11388 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11389 build_int_cst (integer_type_node,
11390 IFN_GOACC_LOOP_OFFSET),
11391 dir, range, s,
11392 chunk_size, gwv, chunk_no);
11393 gimple_call_set_lhs (call, offset_init);
11394 gimple_set_location (call, loc);
11395 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11397 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11398 build_int_cst (integer_type_node,
11399 IFN_GOACC_LOOP_BOUND),
11400 dir, range, s,
11401 chunk_size, gwv, offset_init);
11402 gimple_call_set_lhs (call, bound);
11403 gimple_set_location (call, loc);
11404 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11406 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11407 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11408 GSI_CONTINUE_LINKING);
11410 /* V assignment goes into body_bb. */
11411 if (!gimple_in_ssa_p (cfun))
11413 gsi = gsi_start_bb (body_bb);
11415 expr = build2 (plus_code, iter_type, b,
11416 fold_convert (plus_type, offset));
11417 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11418 true, GSI_SAME_STMT);
11419 ass = gimple_build_assign (v, expr);
11420 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11421 if (fd->collapse > 1)
11422 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11425 /* Loop increment goes into cont_bb. If this is not a loop, we
11426 will have spawned threads as if it was, and each one will
11427 execute one iteration. The specification is not explicit about
11428 whether such constructs are ill-formed or not, and they can
11429 occur, especially when noreturn routines are involved. */
11430 if (cont_bb)
11432 gsi = gsi_last_bb (cont_bb);
11433 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11434 loc = gimple_location (cont_stmt);
11436 /* Increment offset. */
11437 if (gimple_in_ssa_p (cfun))
11438 expr= build2 (plus_code, iter_type, offset,
11439 fold_convert (plus_type, step));
11440 else
11441 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11442 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11443 true, GSI_SAME_STMT);
11444 ass = gimple_build_assign (offset_incr, expr);
11445 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11446 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11447 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11449 /* Remove the GIMPLE_OMP_CONTINUE. */
11450 gsi_remove (&gsi, true);
11452 /* Fixup edges from cont_bb */
11453 be = BRANCH_EDGE (cont_bb);
11454 fte = FALLTHRU_EDGE (cont_bb);
11455 be->flags |= EDGE_TRUE_VALUE;
11456 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11458 if (chunking)
11460 /* Split the beginning of exit_bb to make bottom_bb. We
11461 need to insert a nop at the start, because splitting is
11462 after a stmt, not before. */
11463 gsi = gsi_start_bb (exit_bb);
11464 stmt = gimple_build_nop ();
11465 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11466 split = split_block (exit_bb, stmt);
11467 bottom_bb = split->src;
11468 exit_bb = split->dest;
11469 gsi = gsi_last_bb (bottom_bb);
11471 /* Chunk increment and test goes into bottom_bb. */
11472 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11473 build_int_cst (diff_type, 1));
11474 ass = gimple_build_assign (chunk_no, expr);
11475 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11477 /* Chunk test at end of bottom_bb. */
11478 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11479 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11480 GSI_CONTINUE_LINKING);
11482 /* Fixup edges from bottom_bb. */
11483 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11484 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11488 gsi = gsi_last_bb (exit_bb);
11489 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11490 loc = gimple_location (gsi_stmt (gsi));
11492 if (!gimple_in_ssa_p (cfun))
11494 /* Insert the final value of V, in case it is live. This is the
11495 value for the only thread that survives past the join. */
11496 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11497 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11498 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11499 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11500 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11501 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11502 true, GSI_SAME_STMT);
11503 ass = gimple_build_assign (v, expr);
11504 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11507 /* Remove the OMP_RETURN. */
11508 gsi_remove (&gsi, true);
11510 if (cont_bb)
11512 /* We now have one or two nested loops. Update the loop
11513 structures. */
11514 struct loop *parent = entry_bb->loop_father;
11515 struct loop *body = body_bb->loop_father;
11517 if (chunking)
11519 struct loop *chunk_loop = alloc_loop ();
11520 chunk_loop->header = head_bb;
11521 chunk_loop->latch = bottom_bb;
11522 add_loop (chunk_loop, parent);
11523 parent = chunk_loop;
11525 else if (parent != body)
11527 gcc_assert (body->header == body_bb);
11528 gcc_assert (body->latch == cont_bb
11529 || single_pred (body->latch) == cont_bb);
11530 parent = NULL;
11533 if (parent)
11535 struct loop *body_loop = alloc_loop ();
11536 body_loop->header = body_bb;
11537 body_loop->latch = cont_bb;
11538 add_loop (body_loop, parent);
11543 /* Expand the OMP loop defined by REGION. */
11545 static void
11546 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11548 struct omp_for_data fd;
11549 struct omp_for_data_loop *loops;
11551 loops
11552 = (struct omp_for_data_loop *)
11553 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11554 * sizeof (struct omp_for_data_loop));
11555 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11556 &fd, loops);
11557 region->sched_kind = fd.sched_kind;
11558 region->sched_modifiers = fd.sched_modifiers;
11560 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11561 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11562 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11563 if (region->cont)
11565 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11566 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11567 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11569 else
11570 /* If there isn't a continue then this is a degerate case where
11571 the introduction of abnormal edges during lowering will prevent
11572 original loops from being detected. Fix that up. */
11573 loops_state_set (LOOPS_NEED_FIXUP);
11575 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11576 expand_omp_simd (region, &fd);
11577 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11578 expand_cilk_for (region, &fd);
11579 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11581 gcc_assert (!inner_stmt);
11582 expand_oacc_for (region, &fd);
11584 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11586 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11587 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11588 else
11589 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11591 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11592 && !fd.have_ordered)
11594 if (fd.chunk_size == NULL)
11595 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11596 else
11597 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11599 else
11601 int fn_index, start_ix, next_ix;
11603 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11604 == GF_OMP_FOR_KIND_FOR);
11605 if (fd.chunk_size == NULL
11606 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11607 fd.chunk_size = integer_zero_node;
11608 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11609 switch (fd.sched_kind)
11611 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11612 fn_index = 3;
11613 break;
11614 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11615 case OMP_CLAUSE_SCHEDULE_GUIDED:
11616 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11617 && !fd.ordered
11618 && !fd.have_ordered)
11620 fn_index = 3 + fd.sched_kind;
11621 break;
11623 /* FALLTHRU */
11624 default:
11625 fn_index = fd.sched_kind;
11626 break;
11628 if (!fd.ordered)
11629 fn_index += fd.have_ordered * 6;
11630 if (fd.ordered)
11631 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11632 else
11633 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11634 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11635 if (fd.iter_type == long_long_unsigned_type_node)
11637 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11638 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11639 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11640 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11642 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11643 (enum built_in_function) next_ix, inner_stmt);
11646 if (gimple_in_ssa_p (cfun))
11647 update_ssa (TODO_update_ssa_only_virtuals);
11651 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11653 v = GOMP_sections_start (n);
11655 switch (v)
11657 case 0:
11658 goto L2;
11659 case 1:
11660 section 1;
11661 goto L1;
11662 case 2:
11664 case n:
11666 default:
11667 abort ();
11670 v = GOMP_sections_next ();
11671 goto L0;
11673 reduction;
11675 If this is a combined parallel sections, replace the call to
11676 GOMP_sections_start with call to GOMP_sections_next. */
11678 static void
11679 expand_omp_sections (struct omp_region *region)
11681 tree t, u, vin = NULL, vmain, vnext, l2;
11682 unsigned len;
11683 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11684 gimple_stmt_iterator si, switch_si;
11685 gomp_sections *sections_stmt;
11686 gimple *stmt;
11687 gomp_continue *cont;
11688 edge_iterator ei;
11689 edge e;
11690 struct omp_region *inner;
11691 unsigned i, casei;
11692 bool exit_reachable = region->cont != NULL;
11694 gcc_assert (region->exit != NULL);
11695 entry_bb = region->entry;
11696 l0_bb = single_succ (entry_bb);
11697 l1_bb = region->cont;
11698 l2_bb = region->exit;
11699 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11700 l2 = gimple_block_label (l2_bb);
11701 else
11703 /* This can happen if there are reductions. */
11704 len = EDGE_COUNT (l0_bb->succs);
11705 gcc_assert (len > 0);
11706 e = EDGE_SUCC (l0_bb, len - 1);
11707 si = gsi_last_bb (e->dest);
11708 l2 = NULL_TREE;
11709 if (gsi_end_p (si)
11710 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11711 l2 = gimple_block_label (e->dest);
11712 else
11713 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11715 si = gsi_last_bb (e->dest);
11716 if (gsi_end_p (si)
11717 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11719 l2 = gimple_block_label (e->dest);
11720 break;
11724 if (exit_reachable)
11725 default_bb = create_empty_bb (l1_bb->prev_bb);
11726 else
11727 default_bb = create_empty_bb (l0_bb);
11729 /* We will build a switch() with enough cases for all the
11730 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11731 and a default case to abort if something goes wrong. */
11732 len = EDGE_COUNT (l0_bb->succs);
11734 /* Use vec::quick_push on label_vec throughout, since we know the size
11735 in advance. */
11736 auto_vec<tree> label_vec (len);
11738 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11739 GIMPLE_OMP_SECTIONS statement. */
11740 si = gsi_last_bb (entry_bb);
11741 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11742 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11743 vin = gimple_omp_sections_control (sections_stmt);
11744 if (!is_combined_parallel (region))
11746 /* If we are not inside a combined parallel+sections region,
11747 call GOMP_sections_start. */
11748 t = build_int_cst (unsigned_type_node, len - 1);
11749 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11750 stmt = gimple_build_call (u, 1, t);
11752 else
11754 /* Otherwise, call GOMP_sections_next. */
11755 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11756 stmt = gimple_build_call (u, 0);
11758 gimple_call_set_lhs (stmt, vin);
11759 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11760 gsi_remove (&si, true);
11762 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11763 L0_BB. */
11764 switch_si = gsi_last_bb (l0_bb);
11765 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11766 if (exit_reachable)
11768 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11769 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11770 vmain = gimple_omp_continue_control_use (cont);
11771 vnext = gimple_omp_continue_control_def (cont);
11773 else
11775 vmain = vin;
11776 vnext = NULL_TREE;
11779 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11780 label_vec.quick_push (t);
11781 i = 1;
11783 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11784 for (inner = region->inner, casei = 1;
11785 inner;
11786 inner = inner->next, i++, casei++)
11788 basic_block s_entry_bb, s_exit_bb;
11790 /* Skip optional reduction region. */
11791 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11793 --i;
11794 --casei;
11795 continue;
11798 s_entry_bb = inner->entry;
11799 s_exit_bb = inner->exit;
11801 t = gimple_block_label (s_entry_bb);
11802 u = build_int_cst (unsigned_type_node, casei);
11803 u = build_case_label (u, NULL, t);
11804 label_vec.quick_push (u);
11806 si = gsi_last_bb (s_entry_bb);
11807 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11808 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11809 gsi_remove (&si, true);
11810 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11812 if (s_exit_bb == NULL)
11813 continue;
11815 si = gsi_last_bb (s_exit_bb);
11816 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11817 gsi_remove (&si, true);
11819 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11822 /* Error handling code goes in DEFAULT_BB. */
11823 t = gimple_block_label (default_bb);
11824 u = build_case_label (NULL, NULL, t);
11825 make_edge (l0_bb, default_bb, 0);
11826 add_bb_to_loop (default_bb, current_loops->tree_root);
11828 stmt = gimple_build_switch (vmain, u, label_vec);
11829 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11830 gsi_remove (&switch_si, true);
11832 si = gsi_start_bb (default_bb);
11833 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11834 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11836 if (exit_reachable)
11838 tree bfn_decl;
11840 /* Code to get the next section goes in L1_BB. */
11841 si = gsi_last_bb (l1_bb);
11842 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11844 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11845 stmt = gimple_build_call (bfn_decl, 0);
11846 gimple_call_set_lhs (stmt, vnext);
11847 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11848 gsi_remove (&si, true);
11850 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11853 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11854 si = gsi_last_bb (l2_bb);
11855 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11856 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11857 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11858 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11859 else
11860 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11861 stmt = gimple_build_call (t, 0);
11862 if (gimple_omp_return_lhs (gsi_stmt (si)))
11863 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11864 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11865 gsi_remove (&si, true);
11867 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11871 /* Expand code for an OpenMP single directive. We've already expanded
11872 much of the code, here we simply place the GOMP_barrier call. */
11874 static void
11875 expand_omp_single (struct omp_region *region)
11877 basic_block entry_bb, exit_bb;
11878 gimple_stmt_iterator si;
11880 entry_bb = region->entry;
11881 exit_bb = region->exit;
11883 si = gsi_last_bb (entry_bb);
11884 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11885 gsi_remove (&si, true);
11886 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11888 si = gsi_last_bb (exit_bb);
11889 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11891 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11892 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11894 gsi_remove (&si, true);
11895 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11899 /* Generic expansion for OpenMP synchronization directives: master,
11900 ordered and critical. All we need to do here is remove the entry
11901 and exit markers for REGION. */
11903 static void
11904 expand_omp_synch (struct omp_region *region)
11906 basic_block entry_bb, exit_bb;
11907 gimple_stmt_iterator si;
11909 entry_bb = region->entry;
11910 exit_bb = region->exit;
11912 si = gsi_last_bb (entry_bb);
11913 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11914 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11915 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11916 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11917 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11918 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11919 gsi_remove (&si, true);
11920 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11922 if (exit_bb)
11924 si = gsi_last_bb (exit_bb);
11925 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11926 gsi_remove (&si, true);
11927 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11931 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11932 operation as a normal volatile load. */
11934 static bool
11935 expand_omp_atomic_load (basic_block load_bb, tree addr,
11936 tree loaded_val, int index)
11938 enum built_in_function tmpbase;
11939 gimple_stmt_iterator gsi;
11940 basic_block store_bb;
11941 location_t loc;
11942 gimple *stmt;
11943 tree decl, call, type, itype;
11945 gsi = gsi_last_bb (load_bb);
11946 stmt = gsi_stmt (gsi);
11947 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11948 loc = gimple_location (stmt);
11950 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11951 is smaller than word size, then expand_atomic_load assumes that the load
11952 is atomic. We could avoid the builtin entirely in this case. */
11954 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11955 decl = builtin_decl_explicit (tmpbase);
11956 if (decl == NULL_TREE)
11957 return false;
11959 type = TREE_TYPE (loaded_val);
11960 itype = TREE_TYPE (TREE_TYPE (decl));
11962 call = build_call_expr_loc (loc, decl, 2, addr,
11963 build_int_cst (NULL,
11964 gimple_omp_atomic_seq_cst_p (stmt)
11965 ? MEMMODEL_SEQ_CST
11966 : MEMMODEL_RELAXED));
11967 if (!useless_type_conversion_p (type, itype))
11968 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11969 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11971 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11972 gsi_remove (&gsi, true);
11974 store_bb = single_succ (load_bb);
11975 gsi = gsi_last_bb (store_bb);
11976 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11977 gsi_remove (&gsi, true);
11979 if (gimple_in_ssa_p (cfun))
11980 update_ssa (TODO_update_ssa_no_phi);
11982 return true;
11985 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11986 operation as a normal volatile store. */
11988 static bool
11989 expand_omp_atomic_store (basic_block load_bb, tree addr,
11990 tree loaded_val, tree stored_val, int index)
11992 enum built_in_function tmpbase;
11993 gimple_stmt_iterator gsi;
11994 basic_block store_bb = single_succ (load_bb);
11995 location_t loc;
11996 gimple *stmt;
11997 tree decl, call, type, itype;
11998 machine_mode imode;
11999 bool exchange;
12001 gsi = gsi_last_bb (load_bb);
12002 stmt = gsi_stmt (gsi);
12003 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
12005 /* If the load value is needed, then this isn't a store but an exchange. */
12006 exchange = gimple_omp_atomic_need_value_p (stmt);
12008 gsi = gsi_last_bb (store_bb);
12009 stmt = gsi_stmt (gsi);
12010 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
12011 loc = gimple_location (stmt);
12013 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12014 is smaller than word size, then expand_atomic_store assumes that the store
12015 is atomic. We could avoid the builtin entirely in this case. */
12017 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12018 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12019 decl = builtin_decl_explicit (tmpbase);
12020 if (decl == NULL_TREE)
12021 return false;
12023 type = TREE_TYPE (stored_val);
12025 /* Dig out the type of the function's second argument. */
12026 itype = TREE_TYPE (decl);
12027 itype = TYPE_ARG_TYPES (itype);
12028 itype = TREE_CHAIN (itype);
12029 itype = TREE_VALUE (itype);
12030 imode = TYPE_MODE (itype);
12032 if (exchange && !can_atomic_exchange_p (imode, true))
12033 return false;
12035 if (!useless_type_conversion_p (itype, type))
12036 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12037 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12038 build_int_cst (NULL,
12039 gimple_omp_atomic_seq_cst_p (stmt)
12040 ? MEMMODEL_SEQ_CST
12041 : MEMMODEL_RELAXED));
12042 if (exchange)
12044 if (!useless_type_conversion_p (type, itype))
12045 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12046 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12049 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12050 gsi_remove (&gsi, true);
12052 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12053 gsi = gsi_last_bb (load_bb);
12054 gsi_remove (&gsi, true);
12056 if (gimple_in_ssa_p (cfun))
12057 update_ssa (TODO_update_ssa_no_phi);
12059 return true;
12062 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12063 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12064 size of the data type, and thus usable to find the index of the builtin
12065 decl. Returns false if the expression is not of the proper form. */
12067 static bool
12068 expand_omp_atomic_fetch_op (basic_block load_bb,
12069 tree addr, tree loaded_val,
12070 tree stored_val, int index)
12072 enum built_in_function oldbase, newbase, tmpbase;
12073 tree decl, itype, call;
12074 tree lhs, rhs;
12075 basic_block store_bb = single_succ (load_bb);
12076 gimple_stmt_iterator gsi;
12077 gimple *stmt;
12078 location_t loc;
12079 enum tree_code code;
12080 bool need_old, need_new;
12081 machine_mode imode;
12082 bool seq_cst;
12084 /* We expect to find the following sequences:
12086 load_bb:
12087 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12089 store_bb:
12090 val = tmp OP something; (or: something OP tmp)
12091 GIMPLE_OMP_STORE (val)
12093 ???FIXME: Allow a more flexible sequence.
12094 Perhaps use data flow to pick the statements.
12098 gsi = gsi_after_labels (store_bb);
12099 stmt = gsi_stmt (gsi);
12100 loc = gimple_location (stmt);
12101 if (!is_gimple_assign (stmt))
12102 return false;
12103 gsi_next (&gsi);
12104 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12105 return false;
12106 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12107 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12108 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12109 gcc_checking_assert (!need_old || !need_new);
12111 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12112 return false;
12114 /* Check for one of the supported fetch-op operations. */
12115 code = gimple_assign_rhs_code (stmt);
12116 switch (code)
12118 case PLUS_EXPR:
12119 case POINTER_PLUS_EXPR:
12120 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12121 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12122 break;
12123 case MINUS_EXPR:
12124 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12125 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12126 break;
12127 case BIT_AND_EXPR:
12128 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12129 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12130 break;
12131 case BIT_IOR_EXPR:
12132 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12133 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12134 break;
12135 case BIT_XOR_EXPR:
12136 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12137 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12138 break;
12139 default:
12140 return false;
12143 /* Make sure the expression is of the proper form. */
12144 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12145 rhs = gimple_assign_rhs2 (stmt);
12146 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12147 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12148 rhs = gimple_assign_rhs1 (stmt);
12149 else
12150 return false;
12152 tmpbase = ((enum built_in_function)
12153 ((need_new ? newbase : oldbase) + index + 1));
12154 decl = builtin_decl_explicit (tmpbase);
12155 if (decl == NULL_TREE)
12156 return false;
12157 itype = TREE_TYPE (TREE_TYPE (decl));
12158 imode = TYPE_MODE (itype);
12160 /* We could test all of the various optabs involved, but the fact of the
12161 matter is that (with the exception of i486 vs i586 and xadd) all targets
12162 that support any atomic operaton optab also implements compare-and-swap.
12163 Let optabs.c take care of expanding any compare-and-swap loop. */
12164 if (!can_compare_and_swap_p (imode, true))
12165 return false;
12167 gsi = gsi_last_bb (load_bb);
12168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12170 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12171 It only requires that the operation happen atomically. Thus we can
12172 use the RELAXED memory model. */
12173 call = build_call_expr_loc (loc, decl, 3, addr,
12174 fold_convert_loc (loc, itype, rhs),
12175 build_int_cst (NULL,
12176 seq_cst ? MEMMODEL_SEQ_CST
12177 : MEMMODEL_RELAXED));
12179 if (need_old || need_new)
12181 lhs = need_old ? loaded_val : stored_val;
12182 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12183 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12185 else
12186 call = fold_convert_loc (loc, void_type_node, call);
12187 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12188 gsi_remove (&gsi, true);
12190 gsi = gsi_last_bb (store_bb);
12191 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12192 gsi_remove (&gsi, true);
12193 gsi = gsi_last_bb (store_bb);
12194 stmt = gsi_stmt (gsi);
12195 gsi_remove (&gsi, true);
12197 if (gimple_in_ssa_p (cfun))
12199 release_defs (stmt);
12200 update_ssa (TODO_update_ssa_no_phi);
12203 return true;
12206 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12208 oldval = *addr;
12209 repeat:
12210 newval = rhs; // with oldval replacing *addr in rhs
12211 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12212 if (oldval != newval)
12213 goto repeat;
12215 INDEX is log2 of the size of the data type, and thus usable to find the
12216 index of the builtin decl. */
12218 static bool
12219 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12220 tree addr, tree loaded_val, tree stored_val,
12221 int index)
12223 tree loadedi, storedi, initial, new_storedi, old_vali;
12224 tree type, itype, cmpxchg, iaddr;
12225 gimple_stmt_iterator si;
12226 basic_block loop_header = single_succ (load_bb);
12227 gimple *phi, *stmt;
12228 edge e;
12229 enum built_in_function fncode;
12231 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12232 order to use the RELAXED memory model effectively. */
12233 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12234 + index + 1);
12235 cmpxchg = builtin_decl_explicit (fncode);
12236 if (cmpxchg == NULL_TREE)
12237 return false;
12238 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12239 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12241 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12242 return false;
12244 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12245 si = gsi_last_bb (load_bb);
12246 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12248 /* For floating-point values, we'll need to view-convert them to integers
12249 so that we can perform the atomic compare and swap. Simplify the
12250 following code by always setting up the "i"ntegral variables. */
12251 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12253 tree iaddr_val;
12255 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12256 true));
12257 iaddr_val
12258 = force_gimple_operand_gsi (&si,
12259 fold_convert (TREE_TYPE (iaddr), addr),
12260 false, NULL_TREE, true, GSI_SAME_STMT);
12261 stmt = gimple_build_assign (iaddr, iaddr_val);
12262 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12263 loadedi = create_tmp_var (itype);
12264 if (gimple_in_ssa_p (cfun))
12265 loadedi = make_ssa_name (loadedi);
12267 else
12269 iaddr = addr;
12270 loadedi = loaded_val;
12273 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12274 tree loaddecl = builtin_decl_explicit (fncode);
12275 if (loaddecl)
12276 initial
12277 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12278 build_call_expr (loaddecl, 2, iaddr,
12279 build_int_cst (NULL_TREE,
12280 MEMMODEL_RELAXED)));
12281 else
12282 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12283 build_int_cst (TREE_TYPE (iaddr), 0));
12285 initial
12286 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12287 GSI_SAME_STMT);
12289 /* Move the value to the LOADEDI temporary. */
12290 if (gimple_in_ssa_p (cfun))
12292 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12293 phi = create_phi_node (loadedi, loop_header);
12294 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12295 initial);
12297 else
12298 gsi_insert_before (&si,
12299 gimple_build_assign (loadedi, initial),
12300 GSI_SAME_STMT);
12301 if (loadedi != loaded_val)
12303 gimple_stmt_iterator gsi2;
12304 tree x;
12306 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12307 gsi2 = gsi_start_bb (loop_header);
12308 if (gimple_in_ssa_p (cfun))
12310 gassign *stmt;
12311 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12312 true, GSI_SAME_STMT);
12313 stmt = gimple_build_assign (loaded_val, x);
12314 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12316 else
12318 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12319 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12320 true, GSI_SAME_STMT);
12323 gsi_remove (&si, true);
12325 si = gsi_last_bb (store_bb);
12326 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12328 if (iaddr == addr)
12329 storedi = stored_val;
12330 else
12331 storedi =
12332 force_gimple_operand_gsi (&si,
12333 build1 (VIEW_CONVERT_EXPR, itype,
12334 stored_val), true, NULL_TREE, true,
12335 GSI_SAME_STMT);
12337 /* Build the compare&swap statement. */
12338 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12339 new_storedi = force_gimple_operand_gsi (&si,
12340 fold_convert (TREE_TYPE (loadedi),
12341 new_storedi),
12342 true, NULL_TREE,
12343 true, GSI_SAME_STMT);
12345 if (gimple_in_ssa_p (cfun))
12346 old_vali = loadedi;
12347 else
12349 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12350 stmt = gimple_build_assign (old_vali, loadedi);
12351 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12353 stmt = gimple_build_assign (loadedi, new_storedi);
12354 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12357 /* Note that we always perform the comparison as an integer, even for
12358 floating point. This allows the atomic operation to properly
12359 succeed even with NaNs and -0.0. */
12360 stmt = gimple_build_cond_empty
12361 (build2 (NE_EXPR, boolean_type_node,
12362 new_storedi, old_vali));
12363 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12365 /* Update cfg. */
12366 e = single_succ_edge (store_bb);
12367 e->flags &= ~EDGE_FALLTHRU;
12368 e->flags |= EDGE_FALSE_VALUE;
12370 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12372 /* Copy the new value to loadedi (we already did that before the condition
12373 if we are not in SSA). */
12374 if (gimple_in_ssa_p (cfun))
12376 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12377 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12380 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12381 gsi_remove (&si, true);
12383 struct loop *loop = alloc_loop ();
12384 loop->header = loop_header;
12385 loop->latch = store_bb;
12386 add_loop (loop, loop_header->loop_father);
12388 if (gimple_in_ssa_p (cfun))
12389 update_ssa (TODO_update_ssa_no_phi);
12391 return true;
12394 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12396 GOMP_atomic_start ();
12397 *addr = rhs;
12398 GOMP_atomic_end ();
12400 The result is not globally atomic, but works so long as all parallel
12401 references are within #pragma omp atomic directives. According to
12402 responses received from omp@openmp.org, appears to be within spec.
12403 Which makes sense, since that's how several other compilers handle
12404 this situation as well.
12405 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12406 expanding. STORED_VAL is the operand of the matching
12407 GIMPLE_OMP_ATOMIC_STORE.
12409 We replace
12410 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12411 loaded_val = *addr;
12413 and replace
12414 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12415 *addr = stored_val;
12418 static bool
12419 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12420 tree addr, tree loaded_val, tree stored_val)
12422 gimple_stmt_iterator si;
12423 gassign *stmt;
12424 tree t;
12426 si = gsi_last_bb (load_bb);
12427 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12429 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12430 t = build_call_expr (t, 0);
12431 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12433 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12434 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12435 gsi_remove (&si, true);
12437 si = gsi_last_bb (store_bb);
12438 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12440 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12441 stored_val);
12442 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12444 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12445 t = build_call_expr (t, 0);
12446 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12447 gsi_remove (&si, true);
12449 if (gimple_in_ssa_p (cfun))
12450 update_ssa (TODO_update_ssa_no_phi);
12451 return true;
12454 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12455 using expand_omp_atomic_fetch_op. If it failed, we try to
12456 call expand_omp_atomic_pipeline, and if it fails too, the
12457 ultimate fallback is wrapping the operation in a mutex
12458 (expand_omp_atomic_mutex). REGION is the atomic region built
12459 by build_omp_regions_1(). */
12461 static void
12462 expand_omp_atomic (struct omp_region *region)
12464 basic_block load_bb = region->entry, store_bb = region->exit;
12465 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12466 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12467 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12468 tree addr = gimple_omp_atomic_load_rhs (load);
12469 tree stored_val = gimple_omp_atomic_store_val (store);
12470 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12471 HOST_WIDE_INT index;
12473 /* Make sure the type is one of the supported sizes. */
12474 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12475 index = exact_log2 (index);
12476 if (index >= 0 && index <= 4)
12478 unsigned int align = TYPE_ALIGN_UNIT (type);
12480 /* __sync builtins require strict data alignment. */
12481 if (exact_log2 (align) >= index)
12483 /* Atomic load. */
12484 if (loaded_val == stored_val
12485 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12486 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12487 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12488 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12489 return;
12491 /* Atomic store. */
12492 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12493 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12494 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12495 && store_bb == single_succ (load_bb)
12496 && first_stmt (store_bb) == store
12497 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12498 stored_val, index))
12499 return;
12501 /* When possible, use specialized atomic update functions. */
12502 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12503 && store_bb == single_succ (load_bb)
12504 && expand_omp_atomic_fetch_op (load_bb, addr,
12505 loaded_val, stored_val, index))
12506 return;
12508 /* If we don't have specialized __sync builtins, try and implement
12509 as a compare and swap loop. */
12510 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12511 loaded_val, stored_val, index))
12512 return;
12516 /* The ultimate fallback is wrapping the operation in a mutex. */
12517 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12521 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12522 macro on gomp-constants.h. We do not check for overflow. */
12524 static tree
12525 oacc_launch_pack (unsigned code, tree device, unsigned op)
12527 tree res;
12529 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12530 if (device)
12532 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12533 device, build_int_cst (unsigned_type_node,
12534 GOMP_LAUNCH_DEVICE_SHIFT));
12535 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12537 return res;
12540 /* Look for compute grid dimension clauses and convert to an attribute
12541 attached to FN. This permits the target-side code to (a) massage
12542 the dimensions, (b) emit that data and (c) optimize. Non-constant
12543 dimensions are pushed onto ARGS.
12545 The attribute value is a TREE_LIST. A set of dimensions is
12546 represented as a list of INTEGER_CST. Those that are runtime
12547 exprs are represented as an INTEGER_CST of zero.
12549 TOOO. Normally the attribute will just contain a single such list. If
12550 however it contains a list of lists, this will represent the use of
12551 device_type. Each member of the outer list is an assoc list of
12552 dimensions, keyed by the device type. The first entry will be the
12553 default. Well, that's the plan. */
12555 #define OACC_FN_ATTRIB "oacc function"
12557 /* Replace any existing oacc fn attribute with updated dimensions. */
12559 void
12560 replace_oacc_fn_attrib (tree fn, tree dims)
12562 tree ident = get_identifier (OACC_FN_ATTRIB);
12563 tree attribs = DECL_ATTRIBUTES (fn);
12565 /* If we happen to be present as the first attrib, drop it. */
12566 if (attribs && TREE_PURPOSE (attribs) == ident)
12567 attribs = TREE_CHAIN (attribs);
12568 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12571 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12572 function attribute. Push any that are non-constant onto the ARGS
12573 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12574 true, if these are for a kernels region offload function. */
12576 void
12577 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12579 /* Must match GOMP_DIM ordering. */
12580 static const omp_clause_code ids[]
12581 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12582 OMP_CLAUSE_VECTOR_LENGTH };
12583 unsigned ix;
12584 tree dims[GOMP_DIM_MAX];
12585 tree attr = NULL_TREE;
12586 unsigned non_const = 0;
12588 for (ix = GOMP_DIM_MAX; ix--;)
12590 tree clause = find_omp_clause (clauses, ids[ix]);
12591 tree dim = NULL_TREE;
12593 if (clause)
12594 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12595 dims[ix] = dim;
12596 if (dim && TREE_CODE (dim) != INTEGER_CST)
12598 dim = integer_zero_node;
12599 non_const |= GOMP_DIM_MASK (ix);
12601 attr = tree_cons (NULL_TREE, dim, attr);
12602 /* Note kernelness with TREE_PUBLIC. */
12603 if (is_kernel)
12604 TREE_PUBLIC (attr) = 1;
12607 replace_oacc_fn_attrib (fn, attr);
12609 if (non_const)
12611 /* Push a dynamic argument set. */
12612 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12613 NULL_TREE, non_const));
12614 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12615 if (non_const & GOMP_DIM_MASK (ix))
12616 args->safe_push (dims[ix]);
12620 /* Process the routine's dimension clauess to generate an attribute
12621 value. Issue diagnostics as appropriate. We default to SEQ
12622 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12623 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12624 can have a loop partitioned on it. non-zero indicates
12625 yes, zero indicates no. By construction once a non-zero has been
12626 reached, further inner dimensions must also be non-zero. We set
12627 TREE_VALUE to zero for the dimensions that may be partitioned and
12628 1 for the other ones -- if a loop is (erroneously) spawned at
12629 an outer level, we don't want to try and partition it. */
12631 tree
12632 build_oacc_routine_dims (tree clauses)
12634 /* Must match GOMP_DIM ordering. */
12635 static const omp_clause_code ids[] =
12636 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12637 int ix;
12638 int level = -1;
12640 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12641 for (ix = GOMP_DIM_MAX + 1; ix--;)
12642 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12644 if (level >= 0)
12645 error_at (OMP_CLAUSE_LOCATION (clauses),
12646 "multiple loop axes specified for routine");
12647 level = ix;
12648 break;
12651 /* Default to SEQ. */
12652 if (level < 0)
12653 level = GOMP_DIM_MAX;
12655 tree dims = NULL_TREE;
12657 for (ix = GOMP_DIM_MAX; ix--;)
12658 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12659 build_int_cst (integer_type_node, ix < level), dims);
12661 return dims;
12664 /* Retrieve the oacc function attrib and return it. Non-oacc
12665 functions will return NULL. */
12667 tree
12668 get_oacc_fn_attrib (tree fn)
12670 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12673 /* Return true if this oacc fn attrib is for a kernels offload
12674 region. We use the TREE_PUBLIC flag of each dimension -- only
12675 need to check the first one. */
12677 bool
12678 oacc_fn_attrib_kernels_p (tree attr)
12680 return TREE_PUBLIC (TREE_VALUE (attr));
12683 /* Return level at which oacc routine may spawn a partitioned loop, or
12684 -1 if it is not a routine (i.e. is an offload fn). */
12686 static int
12687 oacc_fn_attrib_level (tree attr)
12689 tree pos = TREE_VALUE (attr);
12691 if (!TREE_PURPOSE (pos))
12692 return -1;
12694 int ix = 0;
12695 for (ix = 0; ix != GOMP_DIM_MAX;
12696 ix++, pos = TREE_CHAIN (pos))
12697 if (!integer_zerop (TREE_PURPOSE (pos)))
12698 break;
12700 return ix;
12703 /* Extract an oacc execution dimension from FN. FN must be an
12704 offloaded function or routine that has already had its execution
12705 dimensions lowered to the target-specific values. */
12708 get_oacc_fn_dim_size (tree fn, int axis)
12710 tree attrs = get_oacc_fn_attrib (fn);
12712 gcc_assert (axis < GOMP_DIM_MAX);
12714 tree dims = TREE_VALUE (attrs);
12715 while (axis--)
12716 dims = TREE_CHAIN (dims);
12718 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12720 return size;
12723 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12724 IFN_GOACC_DIM_SIZE call. */
12727 get_oacc_ifn_dim_arg (const gimple *stmt)
12729 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12730 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12731 tree arg = gimple_call_arg (stmt, 0);
12732 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12734 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12735 return (int) axis;
12738 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12739 at REGION_EXIT. */
12741 static void
12742 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12743 basic_block region_exit)
12745 struct loop *outer = region_entry->loop_father;
12746 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12748 /* Don't parallelize the kernels region if it contains more than one outer
12749 loop. */
12750 unsigned int nr_outer_loops = 0;
12751 struct loop *single_outer = NULL;
12752 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12754 gcc_assert (loop_outer (loop) == outer);
12756 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12757 continue;
12759 if (region_exit != NULL
12760 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12761 continue;
12763 nr_outer_loops++;
12764 single_outer = loop;
12766 if (nr_outer_loops != 1)
12767 return;
12769 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12770 if (loop->next)
12771 return;
12773 /* Mark the loops in the region. */
12774 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12775 loop->in_oacc_kernels_region = true;
12778 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12780 struct GTY(()) grid_launch_attributes_trees
12782 tree kernel_dim_array_type;
12783 tree kernel_lattrs_dimnum_decl;
12784 tree kernel_lattrs_grid_decl;
12785 tree kernel_lattrs_group_decl;
12786 tree kernel_launch_attributes_type;
12789 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12791 /* Create types used to pass kernel launch attributes to target. */
12793 static void
12794 grid_create_kernel_launch_attr_types (void)
12796 if (grid_attr_trees)
12797 return;
12798 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12800 tree dim_arr_index_type
12801 = build_index_type (build_int_cst (integer_type_node, 2));
12802 grid_attr_trees->kernel_dim_array_type
12803 = build_array_type (uint32_type_node, dim_arr_index_type);
12805 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12806 grid_attr_trees->kernel_lattrs_dimnum_decl
12807 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12808 uint32_type_node);
12809 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12811 grid_attr_trees->kernel_lattrs_grid_decl
12812 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12813 grid_attr_trees->kernel_dim_array_type);
12814 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12815 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12816 grid_attr_trees->kernel_lattrs_group_decl
12817 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12818 grid_attr_trees->kernel_dim_array_type);
12819 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12820 = grid_attr_trees->kernel_lattrs_grid_decl;
12821 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12822 "__gomp_kernel_launch_attributes",
12823 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12826 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12827 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12828 of type uint32_type_node. */
12830 static void
12831 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12832 tree fld_decl, int index, tree value)
12834 tree ref = build4 (ARRAY_REF, uint32_type_node,
12835 build3 (COMPONENT_REF,
12836 grid_attr_trees->kernel_dim_array_type,
12837 range_var, fld_decl, NULL_TREE),
12838 build_int_cst (integer_type_node, index),
12839 NULL_TREE, NULL_TREE);
12840 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12843 /* Return a tree representation of a pointer to a structure with grid and
12844 work-group size information. Statements filling that information will be
12845 inserted before GSI, TGT_STMT is the target statement which has the
12846 necessary information in it. */
12848 static tree
12849 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12850 gomp_target *tgt_stmt)
12852 grid_create_kernel_launch_attr_types ();
12853 tree u32_one = build_one_cst (uint32_type_node);
12854 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12855 "__kernel_launch_attrs");
12857 unsigned max_dim = 0;
12858 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12859 clause;
12860 clause = OMP_CLAUSE_CHAIN (clause))
12862 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12863 continue;
12865 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12866 max_dim = MAX (dim, max_dim);
12868 grid_insert_store_range_dim (gsi, lattrs,
12869 grid_attr_trees->kernel_lattrs_grid_decl,
12870 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12871 grid_insert_store_range_dim (gsi, lattrs,
12872 grid_attr_trees->kernel_lattrs_group_decl,
12873 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12876 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12877 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12878 /* At this moment we cannot gridify a loop with a collapse clause. */
12879 /* TODO: Adjust when we support bigger collapse. */
12880 gcc_assert (max_dim == 0);
12881 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12882 TREE_ADDRESSABLE (lattrs) = 1;
12883 return build_fold_addr_expr (lattrs);
12886 /* Build target argument identifier from the DEVICE identifier, value
12887 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12889 static tree
12890 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12892 tree t = build_int_cst (integer_type_node, device);
12893 if (subseqent_param)
12894 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12895 build_int_cst (integer_type_node,
12896 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12897 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12898 build_int_cst (integer_type_node, id));
12899 return t;
12902 /* Like above but return it in type that can be directly stored as an element
12903 of the argument array. */
12905 static tree
12906 get_target_argument_identifier (int device, bool subseqent_param, int id)
12908 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12909 return fold_convert (ptr_type_node, t);
12912 /* Return a target argument consisting of DEVICE identifier, value identifier
12913 ID, and the actual VALUE. */
12915 static tree
12916 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12917 tree value)
12919 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12920 fold_convert (integer_type_node, value),
12921 build_int_cst (unsigned_type_node,
12922 GOMP_TARGET_ARG_VALUE_SHIFT));
12923 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12924 get_target_argument_identifier_1 (device, false, id));
12925 t = fold_convert (ptr_type_node, t);
12926 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12929 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12930 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12931 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12932 arguments. */
12934 static void
12935 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12936 int id, tree value, vec <tree> *args)
12938 if (tree_fits_shwi_p (value)
12939 && tree_to_shwi (value) > -(1 << 15)
12940 && tree_to_shwi (value) < (1 << 15))
12941 args->quick_push (get_target_argument_value (gsi, device, id, value));
12942 else
12944 args->quick_push (get_target_argument_identifier (device, true, id));
12945 value = fold_convert (ptr_type_node, value);
12946 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12947 GSI_SAME_STMT);
12948 args->quick_push (value);
12952 /* Create an array of arguments that is then passed to GOMP_target. */
12954 static tree
12955 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12957 auto_vec <tree, 6> args;
12958 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12959 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12960 if (c)
12961 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12962 else
12963 t = integer_minus_one_node;
12964 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12965 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12967 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12968 if (c)
12969 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12970 else
12971 t = integer_minus_one_node;
12972 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12973 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12974 &args);
12976 /* Add HSA-specific grid sizes, if available. */
12977 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12978 OMP_CLAUSE__GRIDDIM_))
12980 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12981 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12982 args.quick_push (t);
12983 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12986 /* Produce more, perhaps device specific, arguments here. */
12988 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12989 args.length () + 1),
12990 ".omp_target_args");
12991 for (unsigned i = 0; i < args.length (); i++)
12993 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12994 build_int_cst (integer_type_node, i),
12995 NULL_TREE, NULL_TREE);
12996 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12997 GSI_SAME_STMT);
12999 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
13000 build_int_cst (integer_type_node, args.length ()),
13001 NULL_TREE, NULL_TREE);
13002 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
13003 GSI_SAME_STMT);
13004 TREE_ADDRESSABLE (argarray) = 1;
13005 return build_fold_addr_expr (argarray);
13008 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
13010 static void
13011 expand_omp_target (struct omp_region *region)
13013 basic_block entry_bb, exit_bb, new_bb;
13014 struct function *child_cfun;
13015 tree child_fn, block, t;
13016 gimple_stmt_iterator gsi;
13017 gomp_target *entry_stmt;
13018 gimple *stmt;
13019 edge e;
13020 bool offloaded, data_region;
13022 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13023 new_bb = region->entry;
13025 offloaded = is_gimple_omp_offloaded (entry_stmt);
13026 switch (gimple_omp_target_kind (entry_stmt))
13028 case GF_OMP_TARGET_KIND_REGION:
13029 case GF_OMP_TARGET_KIND_UPDATE:
13030 case GF_OMP_TARGET_KIND_ENTER_DATA:
13031 case GF_OMP_TARGET_KIND_EXIT_DATA:
13032 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13033 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13034 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13035 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13036 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13037 data_region = false;
13038 break;
13039 case GF_OMP_TARGET_KIND_DATA:
13040 case GF_OMP_TARGET_KIND_OACC_DATA:
13041 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13042 data_region = true;
13043 break;
13044 default:
13045 gcc_unreachable ();
13048 child_fn = NULL_TREE;
13049 child_cfun = NULL;
13050 if (offloaded)
13052 child_fn = gimple_omp_target_child_fn (entry_stmt);
13053 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13056 /* Supported by expand_omp_taskreg, but not here. */
13057 if (child_cfun != NULL)
13058 gcc_checking_assert (!child_cfun->cfg);
13059 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13061 entry_bb = region->entry;
13062 exit_bb = region->exit;
13064 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13065 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13067 if (offloaded)
13069 unsigned srcidx, dstidx, num;
13071 /* If the offloading region needs data sent from the parent
13072 function, then the very first statement (except possible
13073 tree profile counter updates) of the offloading body
13074 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13075 &.OMP_DATA_O is passed as an argument to the child function,
13076 we need to replace it with the argument as seen by the child
13077 function.
13079 In most cases, this will end up being the identity assignment
13080 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13081 a function call that has been inlined, the original PARM_DECL
13082 .OMP_DATA_I may have been converted into a different local
13083 variable. In which case, we need to keep the assignment. */
13084 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13085 if (data_arg)
13087 basic_block entry_succ_bb = single_succ (entry_bb);
13088 gimple_stmt_iterator gsi;
13089 tree arg;
13090 gimple *tgtcopy_stmt = NULL;
13091 tree sender = TREE_VEC_ELT (data_arg, 0);
13093 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13095 gcc_assert (!gsi_end_p (gsi));
13096 stmt = gsi_stmt (gsi);
13097 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13098 continue;
13100 if (gimple_num_ops (stmt) == 2)
13102 tree arg = gimple_assign_rhs1 (stmt);
13104 /* We're ignoring the subcode because we're
13105 effectively doing a STRIP_NOPS. */
13107 if (TREE_CODE (arg) == ADDR_EXPR
13108 && TREE_OPERAND (arg, 0) == sender)
13110 tgtcopy_stmt = stmt;
13111 break;
13116 gcc_assert (tgtcopy_stmt != NULL);
13117 arg = DECL_ARGUMENTS (child_fn);
13119 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13120 gsi_remove (&gsi, true);
13123 /* Declare local variables needed in CHILD_CFUN. */
13124 block = DECL_INITIAL (child_fn);
13125 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13126 /* The gimplifier could record temporaries in the offloading block
13127 rather than in containing function's local_decls chain,
13128 which would mean cgraph missed finalizing them. Do it now. */
13129 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13130 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
13131 varpool_node::finalize_decl (t);
13132 DECL_SAVED_TREE (child_fn) = NULL;
13133 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13134 gimple_set_body (child_fn, NULL);
13135 TREE_USED (block) = 1;
13137 /* Reset DECL_CONTEXT on function arguments. */
13138 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13139 DECL_CONTEXT (t) = child_fn;
13141 /* Split ENTRY_BB at GIMPLE_*,
13142 so that it can be moved to the child function. */
13143 gsi = gsi_last_bb (entry_bb);
13144 stmt = gsi_stmt (gsi);
13145 gcc_assert (stmt
13146 && gimple_code (stmt) == gimple_code (entry_stmt));
13147 e = split_block (entry_bb, stmt);
13148 gsi_remove (&gsi, true);
13149 entry_bb = e->dest;
13150 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13152 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13153 if (exit_bb)
13155 gsi = gsi_last_bb (exit_bb);
13156 gcc_assert (!gsi_end_p (gsi)
13157 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13158 stmt = gimple_build_return (NULL);
13159 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13160 gsi_remove (&gsi, true);
13163 /* Move the offloading region into CHILD_CFUN. */
13165 block = gimple_block (entry_stmt);
13167 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13168 if (exit_bb)
13169 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13170 /* When the OMP expansion process cannot guarantee an up-to-date
13171 loop tree arrange for the child function to fixup loops. */
13172 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13173 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13175 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13176 num = vec_safe_length (child_cfun->local_decls);
13177 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13179 t = (*child_cfun->local_decls)[srcidx];
13180 if (DECL_CONTEXT (t) == cfun->decl)
13181 continue;
13182 if (srcidx != dstidx)
13183 (*child_cfun->local_decls)[dstidx] = t;
13184 dstidx++;
13186 if (dstidx != num)
13187 vec_safe_truncate (child_cfun->local_decls, dstidx);
13189 /* Inform the callgraph about the new function. */
13190 child_cfun->curr_properties = cfun->curr_properties;
13191 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13192 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13193 cgraph_node *node = cgraph_node::get_create (child_fn);
13194 node->parallelized_function = 1;
13195 cgraph_node::add_new_function (child_fn, true);
13197 /* Add the new function to the offload table. */
13198 if (ENABLE_OFFLOADING)
13199 vec_safe_push (offload_funcs, child_fn);
13201 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13202 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13204 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13205 fixed in a following pass. */
13206 push_cfun (child_cfun);
13207 if (need_asm)
13208 assign_assembler_name_if_neeeded (child_fn);
13209 cgraph_edge::rebuild_edges ();
13211 /* Some EH regions might become dead, see PR34608. If
13212 pass_cleanup_cfg isn't the first pass to happen with the
13213 new child, these dead EH edges might cause problems.
13214 Clean them up now. */
13215 if (flag_exceptions)
13217 basic_block bb;
13218 bool changed = false;
13220 FOR_EACH_BB_FN (bb, cfun)
13221 changed |= gimple_purge_dead_eh_edges (bb);
13222 if (changed)
13223 cleanup_tree_cfg ();
13225 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13226 verify_loop_structure ();
13227 pop_cfun ();
13229 if (dump_file && !gimple_in_ssa_p (cfun))
13231 omp_any_child_fn_dumped = true;
13232 dump_function_header (dump_file, child_fn, dump_flags);
13233 dump_function_to_file (child_fn, dump_file, dump_flags);
13237 /* Emit a library call to launch the offloading region, or do data
13238 transfers. */
13239 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13240 enum built_in_function start_ix;
13241 location_t clause_loc;
13242 unsigned int flags_i = 0;
13243 bool oacc_kernels_p = false;
13245 switch (gimple_omp_target_kind (entry_stmt))
13247 case GF_OMP_TARGET_KIND_REGION:
13248 start_ix = BUILT_IN_GOMP_TARGET;
13249 break;
13250 case GF_OMP_TARGET_KIND_DATA:
13251 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13252 break;
13253 case GF_OMP_TARGET_KIND_UPDATE:
13254 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13255 break;
13256 case GF_OMP_TARGET_KIND_ENTER_DATA:
13257 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13258 break;
13259 case GF_OMP_TARGET_KIND_EXIT_DATA:
13260 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13261 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13262 break;
13263 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13264 oacc_kernels_p = true;
13265 /* FALLTHROUGH */
13266 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13267 start_ix = BUILT_IN_GOACC_PARALLEL;
13268 break;
13269 case GF_OMP_TARGET_KIND_OACC_DATA:
13270 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13271 start_ix = BUILT_IN_GOACC_DATA_START;
13272 break;
13273 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13274 start_ix = BUILT_IN_GOACC_UPDATE;
13275 break;
13276 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13277 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13278 break;
13279 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13280 start_ix = BUILT_IN_GOACC_DECLARE;
13281 break;
13282 default:
13283 gcc_unreachable ();
13286 clauses = gimple_omp_target_clauses (entry_stmt);
13288 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13289 library choose) and there is no conditional. */
13290 cond = NULL_TREE;
13291 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13293 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13294 if (c)
13295 cond = OMP_CLAUSE_IF_EXPR (c);
13297 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13298 if (c)
13300 /* Even if we pass it to all library function calls, it is currently only
13301 defined/used for the OpenMP target ones. */
13302 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13303 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13304 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13305 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13307 device = OMP_CLAUSE_DEVICE_ID (c);
13308 clause_loc = OMP_CLAUSE_LOCATION (c);
13310 else
13311 clause_loc = gimple_location (entry_stmt);
13313 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13314 if (c)
13315 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13317 /* Ensure 'device' is of the correct type. */
13318 device = fold_convert_loc (clause_loc, integer_type_node, device);
13320 /* If we found the clause 'if (cond)', build
13321 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13322 if (cond)
13324 cond = gimple_boolify (cond);
13326 basic_block cond_bb, then_bb, else_bb;
13327 edge e;
13328 tree tmp_var;
13330 tmp_var = create_tmp_var (TREE_TYPE (device));
13331 if (offloaded)
13332 e = split_block_after_labels (new_bb);
13333 else
13335 gsi = gsi_last_bb (new_bb);
13336 gsi_prev (&gsi);
13337 e = split_block (new_bb, gsi_stmt (gsi));
13339 cond_bb = e->src;
13340 new_bb = e->dest;
13341 remove_edge (e);
13343 then_bb = create_empty_bb (cond_bb);
13344 else_bb = create_empty_bb (then_bb);
13345 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13346 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13348 stmt = gimple_build_cond_empty (cond);
13349 gsi = gsi_last_bb (cond_bb);
13350 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13352 gsi = gsi_start_bb (then_bb);
13353 stmt = gimple_build_assign (tmp_var, device);
13354 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13356 gsi = gsi_start_bb (else_bb);
13357 stmt = gimple_build_assign (tmp_var,
13358 build_int_cst (integer_type_node,
13359 GOMP_DEVICE_HOST_FALLBACK));
13360 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13362 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13363 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13364 add_bb_to_loop (then_bb, cond_bb->loop_father);
13365 add_bb_to_loop (else_bb, cond_bb->loop_father);
13366 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13367 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13369 device = tmp_var;
13370 gsi = gsi_last_bb (new_bb);
13372 else
13374 gsi = gsi_last_bb (new_bb);
13375 device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
13376 true, GSI_SAME_STMT);
13379 t = gimple_omp_target_data_arg (entry_stmt);
13380 if (t == NULL)
13382 t1 = size_zero_node;
13383 t2 = build_zero_cst (ptr_type_node);
13384 t3 = t2;
13385 t4 = t2;
13387 else
13389 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13390 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13391 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13392 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13393 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13396 gimple *g;
13397 bool tagging = false;
13398 /* The maximum number used by any start_ix, without varargs. */
13399 auto_vec<tree, 11> args;
13400 args.quick_push (device);
13401 if (offloaded)
13402 args.quick_push (build_fold_addr_expr (child_fn));
13403 args.quick_push (t1);
13404 args.quick_push (t2);
13405 args.quick_push (t3);
13406 args.quick_push (t4);
13407 switch (start_ix)
13409 case BUILT_IN_GOACC_DATA_START:
13410 case BUILT_IN_GOACC_DECLARE:
13411 case BUILT_IN_GOMP_TARGET_DATA:
13412 break;
13413 case BUILT_IN_GOMP_TARGET:
13414 case BUILT_IN_GOMP_TARGET_UPDATE:
13415 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13416 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13417 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13418 if (c)
13419 depend = OMP_CLAUSE_DECL (c);
13420 else
13421 depend = build_int_cst (ptr_type_node, 0);
13422 args.quick_push (depend);
13423 if (start_ix == BUILT_IN_GOMP_TARGET)
13424 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13425 break;
13426 case BUILT_IN_GOACC_PARALLEL:
13428 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13429 tagging = true;
13431 /* FALLTHRU */
13432 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13433 case BUILT_IN_GOACC_UPDATE:
13435 tree t_async = NULL_TREE;
13437 /* If present, use the value specified by the respective
13438 clause, making sure that is of the correct type. */
13439 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13440 if (c)
13441 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13442 integer_type_node,
13443 OMP_CLAUSE_ASYNC_EXPR (c));
13444 else if (!tagging)
13445 /* Default values for t_async. */
13446 t_async = fold_convert_loc (gimple_location (entry_stmt),
13447 integer_type_node,
13448 build_int_cst (integer_type_node,
13449 GOMP_ASYNC_SYNC));
13450 if (tagging && t_async)
13452 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13454 if (TREE_CODE (t_async) == INTEGER_CST)
13456 /* See if we can pack the async arg in to the tag's
13457 operand. */
13458 i_async = TREE_INT_CST_LOW (t_async);
13459 if (i_async < GOMP_LAUNCH_OP_MAX)
13460 t_async = NULL_TREE;
13461 else
13462 i_async = GOMP_LAUNCH_OP_MAX;
13464 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13465 i_async));
13467 if (t_async)
13468 args.safe_push (t_async);
13470 /* Save the argument index, and ... */
13471 unsigned t_wait_idx = args.length ();
13472 unsigned num_waits = 0;
13473 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13474 if (!tagging || c)
13475 /* ... push a placeholder. */
13476 args.safe_push (integer_zero_node);
13478 for (; c; c = OMP_CLAUSE_CHAIN (c))
13479 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13481 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13482 integer_type_node,
13483 OMP_CLAUSE_WAIT_EXPR (c)));
13484 num_waits++;
13487 if (!tagging || num_waits)
13489 tree len;
13491 /* Now that we know the number, update the placeholder. */
13492 if (tagging)
13493 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13494 else
13495 len = build_int_cst (integer_type_node, num_waits);
13496 len = fold_convert_loc (gimple_location (entry_stmt),
13497 unsigned_type_node, len);
13498 args[t_wait_idx] = len;
13501 break;
13502 default:
13503 gcc_unreachable ();
13505 if (tagging)
13506 /* Push terminal marker - zero. */
13507 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13509 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13510 gimple_set_location (g, gimple_location (entry_stmt));
13511 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13512 if (!offloaded)
13514 g = gsi_stmt (gsi);
13515 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13516 gsi_remove (&gsi, true);
13518 if (data_region && region->exit)
13520 gsi = gsi_last_bb (region->exit);
13521 g = gsi_stmt (gsi);
13522 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13523 gsi_remove (&gsi, true);
13527 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13528 variable derived from the thread number. */
13530 static void
13531 grid_expand_omp_for_loop (struct omp_region *kfor)
13533 tree t, threadid;
13534 tree type, itype;
13535 gimple_stmt_iterator gsi;
13536 tree n1, step;
13537 struct omp_for_data fd;
13539 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13540 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13541 == GF_OMP_FOR_KIND_GRID_LOOP);
13542 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13544 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13545 gcc_assert (kfor->cont);
13546 extract_omp_for_data (for_stmt, &fd, NULL);
13548 itype = type = TREE_TYPE (fd.loop.v);
13549 if (POINTER_TYPE_P (type))
13550 itype = signed_type_for (type);
13552 gsi = gsi_start_bb (body_bb);
13554 n1 = fd.loop.n1;
13555 step = fd.loop.step;
13556 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13557 true, NULL_TREE, true, GSI_SAME_STMT);
13558 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13559 true, NULL_TREE, true, GSI_SAME_STMT);
13560 threadid = build_call_expr (builtin_decl_explicit
13561 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13562 threadid = fold_convert (itype, threadid);
13563 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13564 true, GSI_SAME_STMT);
13566 tree startvar = fd.loop.v;
13567 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13568 if (POINTER_TYPE_P (type))
13569 t = fold_build_pointer_plus (n1, t);
13570 else
13571 t = fold_build2 (PLUS_EXPR, type, t, n1);
13572 t = fold_convert (type, t);
13573 t = force_gimple_operand_gsi (&gsi, t,
13574 DECL_P (startvar)
13575 && TREE_ADDRESSABLE (startvar),
13576 NULL_TREE, true, GSI_SAME_STMT);
13577 gassign *assign_stmt = gimple_build_assign (startvar, t);
13578 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13580 /* Remove the omp for statement */
13581 gsi = gsi_last_bb (kfor->entry);
13582 gsi_remove (&gsi, true);
13584 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13585 gsi = gsi_last_bb (kfor->cont);
13586 gcc_assert (!gsi_end_p (gsi)
13587 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13588 gsi_remove (&gsi, true);
13590 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13591 gsi = gsi_last_bb (kfor->exit);
13592 gcc_assert (!gsi_end_p (gsi)
13593 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13594 gsi_remove (&gsi, true);
13596 /* Fixup the much simpler CFG. */
13597 remove_edge (find_edge (kfor->cont, body_bb));
13599 if (kfor->cont != body_bb)
13600 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13601 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13604 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13605 argument_decls. */
13607 struct grid_arg_decl_map
13609 tree old_arg;
13610 tree new_arg;
13613 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13614 pertaining to kernel function. */
13616 static tree
13617 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13619 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13620 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13621 tree t = *tp;
13623 if (t == adm->old_arg)
13624 *tp = adm->new_arg;
13625 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13626 return NULL_TREE;
13629 static void expand_omp (struct omp_region *region);
13631 /* If TARGET region contains a kernel body for loop, remove its region from the
13632 TARGET and expand it in GPGPU kernel fashion. */
13634 static void
13635 grid_expand_target_grid_body (struct omp_region *target)
13637 if (!hsa_gen_requested_p ())
13638 return;
13640 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13641 struct omp_region **pp;
13643 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13644 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13645 break;
13647 struct omp_region *gpukernel = *pp;
13649 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13650 if (!gpukernel)
13652 /* HSA cannot handle OACC stuff. */
13653 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13654 return;
13655 gcc_checking_assert (orig_child_fndecl);
13656 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13657 OMP_CLAUSE__GRIDDIM_));
13658 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13660 hsa_register_kernel (n);
13661 return;
13664 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13665 OMP_CLAUSE__GRIDDIM_));
13666 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13667 *pp = gpukernel->next;
13668 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13669 if ((*pp)->type == GIMPLE_OMP_FOR)
13670 break;
13672 struct omp_region *kfor = *pp;
13673 gcc_assert (kfor);
13674 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13675 == GF_OMP_FOR_KIND_GRID_LOOP);
13676 *pp = kfor->next;
13677 if (kfor->inner)
13678 expand_omp (kfor->inner);
13679 if (gpukernel->inner)
13680 expand_omp (gpukernel->inner);
13682 tree kern_fndecl = copy_node (orig_child_fndecl);
13683 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13684 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13685 tree tgtblock = gimple_block (tgt_stmt);
13686 tree fniniblock = make_node (BLOCK);
13687 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13688 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13689 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13690 BLOCK_SUPERCONTEXT (fniniblock) = kern_fndecl;
13691 DECL_INITIAL (kern_fndecl) = fniniblock;
13692 push_struct_function (kern_fndecl);
13693 cfun->function_end_locus = gimple_location (tgt_stmt);
13694 init_tree_ssa (cfun);
13695 pop_cfun ();
13697 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13698 gcc_assert (!DECL_CHAIN (old_parm_decl));
13699 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13700 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13701 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13702 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13703 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13704 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13705 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13706 kern_cfun->curr_properties = cfun->curr_properties;
13708 remove_edge (BRANCH_EDGE (kfor->entry));
13709 grid_expand_omp_for_loop (kfor);
13711 /* Remove the omp for statement */
13712 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13713 gsi_remove (&gsi, true);
13714 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13715 return. */
13716 gsi = gsi_last_bb (gpukernel->exit);
13717 gcc_assert (!gsi_end_p (gsi)
13718 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13719 gimple *ret_stmt = gimple_build_return (NULL);
13720 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13721 gsi_remove (&gsi, true);
13723 /* Statements in the first BB in the target construct have been produced by
13724 target lowering and must be copied inside the GPUKERNEL, with the two
13725 exceptions of the first OMP statement and the OMP_DATA assignment
13726 statement. */
13727 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13728 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13729 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13730 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13731 !gsi_end_p (tsi); gsi_next (&tsi))
13733 gimple *stmt = gsi_stmt (tsi);
13734 if (is_gimple_omp (stmt))
13735 break;
13736 if (sender
13737 && is_gimple_assign (stmt)
13738 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13739 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13740 continue;
13741 gimple *copy = gimple_copy (stmt);
13742 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13743 gimple_set_block (copy, fniniblock);
13746 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13747 gpukernel->exit, inside_block);
13749 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13750 kcn->mark_force_output ();
13751 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13753 hsa_register_kernel (kcn, orig_child);
13755 cgraph_node::add_new_function (kern_fndecl, true);
13756 push_cfun (kern_cfun);
13757 cgraph_edge::rebuild_edges ();
13759 /* Re-map any mention of the PARM_DECL of the original function to the
13760 PARM_DECL of the new one.
13762 TODO: It would be great if lowering produced references into the GPU
13763 kernel decl straight away and we did not have to do this. */
13764 struct grid_arg_decl_map adm;
13765 adm.old_arg = old_parm_decl;
13766 adm.new_arg = new_parm_decl;
13767 basic_block bb;
13768 FOR_EACH_BB_FN (bb, kern_cfun)
13770 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13772 gimple *stmt = gsi_stmt (gsi);
13773 struct walk_stmt_info wi;
13774 memset (&wi, 0, sizeof (wi));
13775 wi.info = &adm;
13776 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13779 pop_cfun ();
13781 return;
13784 /* Expand the parallel region tree rooted at REGION. Expansion
13785 proceeds in depth-first order. Innermost regions are expanded
13786 first. This way, parallel regions that require a new function to
13787 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13788 internal dependencies in their body. */
13790 static void
13791 expand_omp (struct omp_region *region)
13793 omp_any_child_fn_dumped = false;
13794 while (region)
13796 location_t saved_location;
13797 gimple *inner_stmt = NULL;
13799 /* First, determine whether this is a combined parallel+workshare
13800 region. */
13801 if (region->type == GIMPLE_OMP_PARALLEL)
13802 determine_parallel_type (region);
13803 else if (region->type == GIMPLE_OMP_TARGET)
13804 grid_expand_target_grid_body (region);
13806 if (region->type == GIMPLE_OMP_FOR
13807 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13808 inner_stmt = last_stmt (region->inner->entry);
13810 if (region->inner)
13811 expand_omp (region->inner);
13813 saved_location = input_location;
13814 if (gimple_has_location (last_stmt (region->entry)))
13815 input_location = gimple_location (last_stmt (region->entry));
13817 switch (region->type)
13819 case GIMPLE_OMP_PARALLEL:
13820 case GIMPLE_OMP_TASK:
13821 expand_omp_taskreg (region);
13822 break;
13824 case GIMPLE_OMP_FOR:
13825 expand_omp_for (region, inner_stmt);
13826 break;
13828 case GIMPLE_OMP_SECTIONS:
13829 expand_omp_sections (region);
13830 break;
13832 case GIMPLE_OMP_SECTION:
13833 /* Individual omp sections are handled together with their
13834 parent GIMPLE_OMP_SECTIONS region. */
13835 break;
13837 case GIMPLE_OMP_SINGLE:
13838 expand_omp_single (region);
13839 break;
13841 case GIMPLE_OMP_ORDERED:
13843 gomp_ordered *ord_stmt
13844 = as_a <gomp_ordered *> (last_stmt (region->entry));
13845 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13846 OMP_CLAUSE_DEPEND))
13848 /* We'll expand these when expanding corresponding
13849 worksharing region with ordered(n) clause. */
13850 gcc_assert (region->outer
13851 && region->outer->type == GIMPLE_OMP_FOR);
13852 region->ord_stmt = ord_stmt;
13853 break;
13856 /* FALLTHRU */
13857 case GIMPLE_OMP_MASTER:
13858 case GIMPLE_OMP_TASKGROUP:
13859 case GIMPLE_OMP_CRITICAL:
13860 case GIMPLE_OMP_TEAMS:
13861 expand_omp_synch (region);
13862 break;
13864 case GIMPLE_OMP_ATOMIC_LOAD:
13865 expand_omp_atomic (region);
13866 break;
13868 case GIMPLE_OMP_TARGET:
13869 expand_omp_target (region);
13870 break;
13872 default:
13873 gcc_unreachable ();
13876 input_location = saved_location;
13877 region = region->next;
13879 if (omp_any_child_fn_dumped)
13881 if (dump_file)
13882 dump_function_header (dump_file, current_function_decl, dump_flags);
13883 omp_any_child_fn_dumped = false;
13888 /* Helper for build_omp_regions. Scan the dominator tree starting at
13889 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13890 true, the function ends once a single tree is built (otherwise, whole
13891 forest of OMP constructs may be built). */
13893 static void
13894 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13895 bool single_tree)
13897 gimple_stmt_iterator gsi;
13898 gimple *stmt;
13899 basic_block son;
13901 gsi = gsi_last_bb (bb);
13902 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13904 struct omp_region *region;
13905 enum gimple_code code;
13907 stmt = gsi_stmt (gsi);
13908 code = gimple_code (stmt);
13909 if (code == GIMPLE_OMP_RETURN)
13911 /* STMT is the return point out of region PARENT. Mark it
13912 as the exit point and make PARENT the immediately
13913 enclosing region. */
13914 gcc_assert (parent);
13915 region = parent;
13916 region->exit = bb;
13917 parent = parent->outer;
13919 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13921 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13922 GIMPLE_OMP_RETURN, but matches with
13923 GIMPLE_OMP_ATOMIC_LOAD. */
13924 gcc_assert (parent);
13925 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13926 region = parent;
13927 region->exit = bb;
13928 parent = parent->outer;
13930 else if (code == GIMPLE_OMP_CONTINUE)
13932 gcc_assert (parent);
13933 parent->cont = bb;
13935 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13937 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13938 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13940 else
13942 region = new_omp_region (bb, code, parent);
13943 /* Otherwise... */
13944 if (code == GIMPLE_OMP_TARGET)
13946 switch (gimple_omp_target_kind (stmt))
13948 case GF_OMP_TARGET_KIND_REGION:
13949 case GF_OMP_TARGET_KIND_DATA:
13950 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13951 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13952 case GF_OMP_TARGET_KIND_OACC_DATA:
13953 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13954 break;
13955 case GF_OMP_TARGET_KIND_UPDATE:
13956 case GF_OMP_TARGET_KIND_ENTER_DATA:
13957 case GF_OMP_TARGET_KIND_EXIT_DATA:
13958 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13959 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13960 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13961 /* ..., other than for those stand-alone directives... */
13962 region = NULL;
13963 break;
13964 default:
13965 gcc_unreachable ();
13968 else if (code == GIMPLE_OMP_ORDERED
13969 && find_omp_clause (gimple_omp_ordered_clauses
13970 (as_a <gomp_ordered *> (stmt)),
13971 OMP_CLAUSE_DEPEND))
13972 /* #pragma omp ordered depend is also just a stand-alone
13973 directive. */
13974 region = NULL;
13975 /* ..., this directive becomes the parent for a new region. */
13976 if (region)
13977 parent = region;
13981 if (single_tree && !parent)
13982 return;
13984 for (son = first_dom_son (CDI_DOMINATORS, bb);
13985 son;
13986 son = next_dom_son (CDI_DOMINATORS, son))
13987 build_omp_regions_1 (son, parent, single_tree);
13990 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13991 root_omp_region. */
13993 static void
13994 build_omp_regions_root (basic_block root)
13996 gcc_assert (root_omp_region == NULL);
13997 build_omp_regions_1 (root, NULL, true);
13998 gcc_assert (root_omp_region != NULL);
14001 /* Expands omp construct (and its subconstructs) starting in HEAD. */
14003 void
14004 omp_expand_local (basic_block head)
14006 build_omp_regions_root (head);
14007 if (dump_file && (dump_flags & TDF_DETAILS))
14009 fprintf (dump_file, "\nOMP region tree\n\n");
14010 dump_omp_region (dump_file, root_omp_region, 0);
14011 fprintf (dump_file, "\n");
14014 remove_exit_barriers (root_omp_region);
14015 expand_omp (root_omp_region);
14017 free_omp_regions ();
14020 /* Scan the CFG and build a tree of OMP regions. Return the root of
14021 the OMP region tree. */
14023 static void
14024 build_omp_regions (void)
14026 gcc_assert (root_omp_region == NULL);
14027 calculate_dominance_info (CDI_DOMINATORS);
14028 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14031 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14033 static unsigned int
14034 execute_expand_omp (void)
14036 build_omp_regions ();
14038 if (!root_omp_region)
14039 return 0;
14041 if (dump_file)
14043 fprintf (dump_file, "\nOMP region tree\n\n");
14044 dump_omp_region (dump_file, root_omp_region, 0);
14045 fprintf (dump_file, "\n");
14048 remove_exit_barriers (root_omp_region);
14050 expand_omp (root_omp_region);
14052 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14053 verify_loop_structure ();
14054 cleanup_tree_cfg ();
14056 free_omp_regions ();
14058 return 0;
14061 /* OMP expansion -- the default pass, run before creation of SSA form. */
14063 namespace {
14065 const pass_data pass_data_expand_omp =
14067 GIMPLE_PASS, /* type */
14068 "ompexp", /* name */
14069 OPTGROUP_NONE, /* optinfo_flags */
14070 TV_NONE, /* tv_id */
14071 PROP_gimple_any, /* properties_required */
14072 PROP_gimple_eomp, /* properties_provided */
14073 0, /* properties_destroyed */
14074 0, /* todo_flags_start */
14075 0, /* todo_flags_finish */
14078 class pass_expand_omp : public gimple_opt_pass
14080 public:
14081 pass_expand_omp (gcc::context *ctxt)
14082 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14085 /* opt_pass methods: */
14086 virtual unsigned int execute (function *)
14088 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14089 || flag_openmp_simd != 0)
14090 && !seen_error ());
14092 /* This pass always runs, to provide PROP_gimple_eomp.
14093 But often, there is nothing to do. */
14094 if (!gate)
14095 return 0;
14097 return execute_expand_omp ();
14100 }; // class pass_expand_omp
14102 } // anon namespace
14104 gimple_opt_pass *
14105 make_pass_expand_omp (gcc::context *ctxt)
14107 return new pass_expand_omp (ctxt);
14110 namespace {
14112 const pass_data pass_data_expand_omp_ssa =
14114 GIMPLE_PASS, /* type */
14115 "ompexpssa", /* name */
14116 OPTGROUP_NONE, /* optinfo_flags */
14117 TV_NONE, /* tv_id */
14118 PROP_cfg | PROP_ssa, /* properties_required */
14119 PROP_gimple_eomp, /* properties_provided */
14120 0, /* properties_destroyed */
14121 0, /* todo_flags_start */
14122 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14125 class pass_expand_omp_ssa : public gimple_opt_pass
14127 public:
14128 pass_expand_omp_ssa (gcc::context *ctxt)
14129 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14132 /* opt_pass methods: */
14133 virtual bool gate (function *fun)
14135 return !(fun->curr_properties & PROP_gimple_eomp);
14137 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14138 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14140 }; // class pass_expand_omp_ssa
14142 } // anon namespace
14144 gimple_opt_pass *
14145 make_pass_expand_omp_ssa (gcc::context *ctxt)
14147 return new pass_expand_omp_ssa (ctxt);
14150 /* Routines to lower OMP directives into OMP-GIMPLE. */
14152 /* If ctx is a worksharing context inside of a cancellable parallel
14153 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14154 and conditional branch to parallel's cancel_label to handle
14155 cancellation in the implicit barrier. */
14157 static void
14158 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14160 gimple *omp_return = gimple_seq_last_stmt (*body);
14161 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14162 if (gimple_omp_return_nowait_p (omp_return))
14163 return;
14164 if (ctx->outer
14165 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14166 && ctx->outer->cancellable)
14168 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14169 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14170 tree lhs = create_tmp_var (c_bool_type);
14171 gimple_omp_return_set_lhs (omp_return, lhs);
14172 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14173 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14174 fold_convert (c_bool_type,
14175 boolean_false_node),
14176 ctx->outer->cancel_label, fallthru_label);
14177 gimple_seq_add_stmt (body, g);
14178 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14182 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14183 CTX is the enclosing OMP context for the current statement. */
14185 static void
14186 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14188 tree block, control;
14189 gimple_stmt_iterator tgsi;
14190 gomp_sections *stmt;
14191 gimple *t;
14192 gbind *new_stmt, *bind;
14193 gimple_seq ilist, dlist, olist, new_body;
14195 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14197 push_gimplify_context ();
14199 dlist = NULL;
14200 ilist = NULL;
14201 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14202 &ilist, &dlist, ctx, NULL);
14204 new_body = gimple_omp_body (stmt);
14205 gimple_omp_set_body (stmt, NULL);
14206 tgsi = gsi_start (new_body);
14207 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14209 omp_context *sctx;
14210 gimple *sec_start;
14212 sec_start = gsi_stmt (tgsi);
14213 sctx = maybe_lookup_ctx (sec_start);
14214 gcc_assert (sctx);
14216 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14217 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14218 GSI_CONTINUE_LINKING);
14219 gimple_omp_set_body (sec_start, NULL);
14221 if (gsi_one_before_end_p (tgsi))
14223 gimple_seq l = NULL;
14224 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14225 &l, ctx);
14226 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14227 gimple_omp_section_set_last (sec_start);
14230 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14231 GSI_CONTINUE_LINKING);
14234 block = make_node (BLOCK);
14235 bind = gimple_build_bind (NULL, new_body, block);
14237 olist = NULL;
14238 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14240 block = make_node (BLOCK);
14241 new_stmt = gimple_build_bind (NULL, NULL, block);
14242 gsi_replace (gsi_p, new_stmt, true);
14244 pop_gimplify_context (new_stmt);
14245 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14246 BLOCK_VARS (block) = gimple_bind_vars (bind);
14247 if (BLOCK_VARS (block))
14248 TREE_USED (block) = 1;
14250 new_body = NULL;
14251 gimple_seq_add_seq (&new_body, ilist);
14252 gimple_seq_add_stmt (&new_body, stmt);
14253 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14254 gimple_seq_add_stmt (&new_body, bind);
14256 control = create_tmp_var (unsigned_type_node, ".section");
14257 t = gimple_build_omp_continue (control, control);
14258 gimple_omp_sections_set_control (stmt, control);
14259 gimple_seq_add_stmt (&new_body, t);
14261 gimple_seq_add_seq (&new_body, olist);
14262 if (ctx->cancellable)
14263 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14264 gimple_seq_add_seq (&new_body, dlist);
14266 new_body = maybe_catch_exception (new_body);
14268 t = gimple_build_omp_return
14269 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14270 OMP_CLAUSE_NOWAIT));
14271 gimple_seq_add_stmt (&new_body, t);
14272 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14274 gimple_bind_set_body (new_stmt, new_body);
14278 /* A subroutine of lower_omp_single. Expand the simple form of
14279 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14281 if (GOMP_single_start ())
14282 BODY;
14283 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14285 FIXME. It may be better to delay expanding the logic of this until
14286 pass_expand_omp. The expanded logic may make the job more difficult
14287 to a synchronization analysis pass. */
14289 static void
14290 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14292 location_t loc = gimple_location (single_stmt);
14293 tree tlabel = create_artificial_label (loc);
14294 tree flabel = create_artificial_label (loc);
14295 gimple *call, *cond;
14296 tree lhs, decl;
14298 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14299 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14300 call = gimple_build_call (decl, 0);
14301 gimple_call_set_lhs (call, lhs);
14302 gimple_seq_add_stmt (pre_p, call);
14304 cond = gimple_build_cond (EQ_EXPR, lhs,
14305 fold_convert_loc (loc, TREE_TYPE (lhs),
14306 boolean_true_node),
14307 tlabel, flabel);
14308 gimple_seq_add_stmt (pre_p, cond);
14309 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14310 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14311 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14315 /* A subroutine of lower_omp_single. Expand the simple form of
14316 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14318 #pragma omp single copyprivate (a, b, c)
14320 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14323 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14325 BODY;
14326 copyout.a = a;
14327 copyout.b = b;
14328 copyout.c = c;
14329 GOMP_single_copy_end (&copyout);
14331 else
14333 a = copyout_p->a;
14334 b = copyout_p->b;
14335 c = copyout_p->c;
14337 GOMP_barrier ();
14340 FIXME. It may be better to delay expanding the logic of this until
14341 pass_expand_omp. The expanded logic may make the job more difficult
14342 to a synchronization analysis pass. */
14344 static void
14345 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14346 omp_context *ctx)
14348 tree ptr_type, t, l0, l1, l2, bfn_decl;
14349 gimple_seq copyin_seq;
14350 location_t loc = gimple_location (single_stmt);
14352 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14354 ptr_type = build_pointer_type (ctx->record_type);
14355 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14357 l0 = create_artificial_label (loc);
14358 l1 = create_artificial_label (loc);
14359 l2 = create_artificial_label (loc);
14361 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14362 t = build_call_expr_loc (loc, bfn_decl, 0);
14363 t = fold_convert_loc (loc, ptr_type, t);
14364 gimplify_assign (ctx->receiver_decl, t, pre_p);
14366 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14367 build_int_cst (ptr_type, 0));
14368 t = build3 (COND_EXPR, void_type_node, t,
14369 build_and_jump (&l0), build_and_jump (&l1));
14370 gimplify_and_add (t, pre_p);
14372 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14374 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14376 copyin_seq = NULL;
14377 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14378 &copyin_seq, ctx);
14380 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14381 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14382 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14383 gimplify_and_add (t, pre_p);
14385 t = build_and_jump (&l2);
14386 gimplify_and_add (t, pre_p);
14388 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14390 gimple_seq_add_seq (pre_p, copyin_seq);
14392 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14396 /* Expand code for an OpenMP single directive. */
14398 static void
14399 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14401 tree block;
14402 gimple *t;
14403 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14404 gbind *bind;
14405 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14407 push_gimplify_context ();
14409 block = make_node (BLOCK);
14410 bind = gimple_build_bind (NULL, NULL, block);
14411 gsi_replace (gsi_p, bind, true);
14412 bind_body = NULL;
14413 dlist = NULL;
14414 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14415 &bind_body, &dlist, ctx, NULL);
14416 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14418 gimple_seq_add_stmt (&bind_body, single_stmt);
14420 if (ctx->record_type)
14421 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14422 else
14423 lower_omp_single_simple (single_stmt, &bind_body);
14425 gimple_omp_set_body (single_stmt, NULL);
14427 gimple_seq_add_seq (&bind_body, dlist);
14429 bind_body = maybe_catch_exception (bind_body);
14431 t = gimple_build_omp_return
14432 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14433 OMP_CLAUSE_NOWAIT));
14434 gimple_seq_add_stmt (&bind_body_tail, t);
14435 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14436 if (ctx->record_type)
14438 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14439 tree clobber = build_constructor (ctx->record_type, NULL);
14440 TREE_THIS_VOLATILE (clobber) = 1;
14441 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14442 clobber), GSI_SAME_STMT);
14444 gimple_seq_add_seq (&bind_body, bind_body_tail);
14445 gimple_bind_set_body (bind, bind_body);
14447 pop_gimplify_context (bind);
14449 gimple_bind_append_vars (bind, ctx->block_vars);
14450 BLOCK_VARS (block) = ctx->block_vars;
14451 if (BLOCK_VARS (block))
14452 TREE_USED (block) = 1;
14456 /* Expand code for an OpenMP master directive. */
14458 static void
14459 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14461 tree block, lab = NULL, x, bfn_decl;
14462 gimple *stmt = gsi_stmt (*gsi_p);
14463 gbind *bind;
14464 location_t loc = gimple_location (stmt);
14465 gimple_seq tseq;
14467 push_gimplify_context ();
14469 block = make_node (BLOCK);
14470 bind = gimple_build_bind (NULL, NULL, block);
14471 gsi_replace (gsi_p, bind, true);
14472 gimple_bind_add_stmt (bind, stmt);
14474 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14475 x = build_call_expr_loc (loc, bfn_decl, 0);
14476 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14477 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14478 tseq = NULL;
14479 gimplify_and_add (x, &tseq);
14480 gimple_bind_add_seq (bind, tseq);
14482 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14483 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14484 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14485 gimple_omp_set_body (stmt, NULL);
14487 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14489 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14491 pop_gimplify_context (bind);
14493 gimple_bind_append_vars (bind, ctx->block_vars);
14494 BLOCK_VARS (block) = ctx->block_vars;
14498 /* Expand code for an OpenMP taskgroup directive. */
14500 static void
14501 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14503 gimple *stmt = gsi_stmt (*gsi_p);
14504 gcall *x;
14505 gbind *bind;
14506 tree block = make_node (BLOCK);
14508 bind = gimple_build_bind (NULL, NULL, block);
14509 gsi_replace (gsi_p, bind, true);
14510 gimple_bind_add_stmt (bind, stmt);
14512 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14514 gimple_bind_add_stmt (bind, x);
14516 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14517 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14518 gimple_omp_set_body (stmt, NULL);
14520 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14522 gimple_bind_append_vars (bind, ctx->block_vars);
14523 BLOCK_VARS (block) = ctx->block_vars;
14527 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14529 static void
14530 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14531 omp_context *ctx)
14533 struct omp_for_data fd;
14534 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14535 return;
14537 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14538 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14539 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14540 if (!fd.ordered)
14541 return;
14543 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14544 tree c = gimple_omp_ordered_clauses (ord_stmt);
14545 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14546 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14548 /* Merge depend clauses from multiple adjacent
14549 #pragma omp ordered depend(sink:...) constructs
14550 into one #pragma omp ordered depend(sink:...), so that
14551 we can optimize them together. */
14552 gimple_stmt_iterator gsi = *gsi_p;
14553 gsi_next (&gsi);
14554 while (!gsi_end_p (gsi))
14556 gimple *stmt = gsi_stmt (gsi);
14557 if (is_gimple_debug (stmt)
14558 || gimple_code (stmt) == GIMPLE_NOP)
14560 gsi_next (&gsi);
14561 continue;
14563 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14564 break;
14565 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14566 c = gimple_omp_ordered_clauses (ord_stmt2);
14567 if (c == NULL_TREE
14568 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14569 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14570 break;
14571 while (*list_p)
14572 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14573 *list_p = c;
14574 gsi_remove (&gsi, true);
14578 /* Canonicalize sink dependence clauses into one folded clause if
14579 possible.
14581 The basic algorithm is to create a sink vector whose first
14582 element is the GCD of all the first elements, and whose remaining
14583 elements are the minimum of the subsequent columns.
14585 We ignore dependence vectors whose first element is zero because
14586 such dependencies are known to be executed by the same thread.
14588 We take into account the direction of the loop, so a minimum
14589 becomes a maximum if the loop is iterating forwards. We also
14590 ignore sink clauses where the loop direction is unknown, or where
14591 the offsets are clearly invalid because they are not a multiple
14592 of the loop increment.
14594 For example:
14596 #pragma omp for ordered(2)
14597 for (i=0; i < N; ++i)
14598 for (j=0; j < M; ++j)
14600 #pragma omp ordered \
14601 depend(sink:i-8,j-2) \
14602 depend(sink:i,j-1) \ // Completely ignored because i+0.
14603 depend(sink:i-4,j-3) \
14604 depend(sink:i-6,j-4)
14605 #pragma omp ordered depend(source)
14608 Folded clause is:
14610 depend(sink:-gcd(8,4,6),-min(2,3,4))
14611 -or-
14612 depend(sink:-2,-2)
14615 /* FIXME: Computing GCD's where the first element is zero is
14616 non-trivial in the presence of collapsed loops. Do this later. */
14617 if (fd.collapse > 1)
14618 return;
14620 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14621 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14622 tree folded_dep = NULL_TREE;
14623 /* TRUE if the first dimension's offset is negative. */
14624 bool neg_offset_p = false;
14626 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14627 unsigned int i;
14628 while ((c = *list_p) != NULL)
14630 bool remove = false;
14632 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14633 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14634 goto next_ordered_clause;
14636 tree vec;
14637 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14638 vec && TREE_CODE (vec) == TREE_LIST;
14639 vec = TREE_CHAIN (vec), ++i)
14641 gcc_assert (i < len);
14643 /* extract_omp_for_data has canonicalized the condition. */
14644 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14645 || fd.loops[i].cond_code == GT_EXPR);
14646 bool forward = fd.loops[i].cond_code == LT_EXPR;
14647 bool maybe_lexically_later = true;
14649 /* While the committee makes up its mind, bail if we have any
14650 non-constant steps. */
14651 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14652 goto lower_omp_ordered_ret;
14654 tree itype = TREE_TYPE (TREE_VALUE (vec));
14655 if (POINTER_TYPE_P (itype))
14656 itype = sizetype;
14657 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14658 TYPE_PRECISION (itype),
14659 TYPE_SIGN (itype));
14661 /* Ignore invalid offsets that are not multiples of the step. */
14662 if (!wi::multiple_of_p
14663 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14664 UNSIGNED))
14666 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14667 "ignoring sink clause with offset that is not "
14668 "a multiple of the loop step");
14669 remove = true;
14670 goto next_ordered_clause;
14673 /* Calculate the first dimension. The first dimension of
14674 the folded dependency vector is the GCD of the first
14675 elements, while ignoring any first elements whose offset
14676 is 0. */
14677 if (i == 0)
14679 /* Ignore dependence vectors whose first dimension is 0. */
14680 if (offset == 0)
14682 remove = true;
14683 goto next_ordered_clause;
14685 else
14687 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14689 error_at (OMP_CLAUSE_LOCATION (c),
14690 "first offset must be in opposite direction "
14691 "of loop iterations");
14692 goto lower_omp_ordered_ret;
14694 if (forward)
14695 offset = -offset;
14696 neg_offset_p = forward;
14697 /* Initialize the first time around. */
14698 if (folded_dep == NULL_TREE)
14700 folded_dep = c;
14701 folded_deps[0] = offset;
14703 else
14704 folded_deps[0] = wi::gcd (folded_deps[0],
14705 offset, UNSIGNED);
14708 /* Calculate minimum for the remaining dimensions. */
14709 else
14711 folded_deps[len + i - 1] = offset;
14712 if (folded_dep == c)
14713 folded_deps[i] = offset;
14714 else if (maybe_lexically_later
14715 && !wi::eq_p (folded_deps[i], offset))
14717 if (forward ^ wi::gts_p (folded_deps[i], offset))
14719 unsigned int j;
14720 folded_dep = c;
14721 for (j = 1; j <= i; j++)
14722 folded_deps[j] = folded_deps[len + j - 1];
14724 else
14725 maybe_lexically_later = false;
14729 gcc_assert (i == len);
14731 remove = true;
14733 next_ordered_clause:
14734 if (remove)
14735 *list_p = OMP_CLAUSE_CHAIN (c);
14736 else
14737 list_p = &OMP_CLAUSE_CHAIN (c);
14740 if (folded_dep)
14742 if (neg_offset_p)
14743 folded_deps[0] = -folded_deps[0];
14745 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14746 if (POINTER_TYPE_P (itype))
14747 itype = sizetype;
14749 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14750 = wide_int_to_tree (itype, folded_deps[0]);
14751 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14752 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14755 lower_omp_ordered_ret:
14757 /* Ordered without clauses is #pragma omp threads, while we want
14758 a nop instead if we remove all clauses. */
14759 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14760 gsi_replace (gsi_p, gimple_build_nop (), true);
14764 /* Expand code for an OpenMP ordered directive. */
14766 static void
14767 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14769 tree block;
14770 gimple *stmt = gsi_stmt (*gsi_p);
14771 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14772 gcall *x;
14773 gbind *bind;
14774 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14775 OMP_CLAUSE_SIMD);
14776 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14777 OMP_CLAUSE_THREADS);
14779 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14780 OMP_CLAUSE_DEPEND))
14782 /* FIXME: This is needs to be moved to the expansion to verify various
14783 conditions only testable on cfg with dominators computed, and also
14784 all the depend clauses to be merged still might need to be available
14785 for the runtime checks. */
14786 if (0)
14787 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14788 return;
14791 push_gimplify_context ();
14793 block = make_node (BLOCK);
14794 bind = gimple_build_bind (NULL, NULL, block);
14795 gsi_replace (gsi_p, bind, true);
14796 gimple_bind_add_stmt (bind, stmt);
14798 if (simd)
14800 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14801 build_int_cst (NULL_TREE, threads));
14802 cfun->has_simduid_loops = true;
14804 else
14805 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14807 gimple_bind_add_stmt (bind, x);
14809 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14810 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14811 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14812 gimple_omp_set_body (stmt, NULL);
14814 if (simd)
14815 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14816 build_int_cst (NULL_TREE, threads));
14817 else
14818 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14820 gimple_bind_add_stmt (bind, x);
14822 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14824 pop_gimplify_context (bind);
14826 gimple_bind_append_vars (bind, ctx->block_vars);
14827 BLOCK_VARS (block) = gimple_bind_vars (bind);
14831 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14832 substitution of a couple of function calls. But in the NAMED case,
14833 requires that languages coordinate a symbol name. It is therefore
14834 best put here in common code. */
14836 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14838 static void
14839 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14841 tree block;
14842 tree name, lock, unlock;
14843 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14844 gbind *bind;
14845 location_t loc = gimple_location (stmt);
14846 gimple_seq tbody;
14848 name = gimple_omp_critical_name (stmt);
14849 if (name)
14851 tree decl;
14853 if (!critical_name_mutexes)
14854 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14856 tree *n = critical_name_mutexes->get (name);
14857 if (n == NULL)
14859 char *new_str;
14861 decl = create_tmp_var_raw (ptr_type_node);
14863 new_str = ACONCAT ((".gomp_critical_user_",
14864 IDENTIFIER_POINTER (name), NULL));
14865 DECL_NAME (decl) = get_identifier (new_str);
14866 TREE_PUBLIC (decl) = 1;
14867 TREE_STATIC (decl) = 1;
14868 DECL_COMMON (decl) = 1;
14869 DECL_ARTIFICIAL (decl) = 1;
14870 DECL_IGNORED_P (decl) = 1;
14872 varpool_node::finalize_decl (decl);
14874 critical_name_mutexes->put (name, decl);
14876 else
14877 decl = *n;
14879 /* If '#pragma omp critical' is inside offloaded region or
14880 inside function marked as offloadable, the symbol must be
14881 marked as offloadable too. */
14882 omp_context *octx;
14883 if (cgraph_node::get (current_function_decl)->offloadable)
14884 varpool_node::get_create (decl)->offloadable = 1;
14885 else
14886 for (octx = ctx->outer; octx; octx = octx->outer)
14887 if (is_gimple_omp_offloaded (octx->stmt))
14889 varpool_node::get_create (decl)->offloadable = 1;
14890 break;
14893 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14894 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14896 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14897 unlock = build_call_expr_loc (loc, unlock, 1,
14898 build_fold_addr_expr_loc (loc, decl));
14900 else
14902 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14903 lock = build_call_expr_loc (loc, lock, 0);
14905 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14906 unlock = build_call_expr_loc (loc, unlock, 0);
14909 push_gimplify_context ();
14911 block = make_node (BLOCK);
14912 bind = gimple_build_bind (NULL, NULL, block);
14913 gsi_replace (gsi_p, bind, true);
14914 gimple_bind_add_stmt (bind, stmt);
14916 tbody = gimple_bind_body (bind);
14917 gimplify_and_add (lock, &tbody);
14918 gimple_bind_set_body (bind, tbody);
14920 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14921 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14922 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14923 gimple_omp_set_body (stmt, NULL);
14925 tbody = gimple_bind_body (bind);
14926 gimplify_and_add (unlock, &tbody);
14927 gimple_bind_set_body (bind, tbody);
14929 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14931 pop_gimplify_context (bind);
14932 gimple_bind_append_vars (bind, ctx->block_vars);
14933 BLOCK_VARS (block) = gimple_bind_vars (bind);
14937 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14938 for a lastprivate clause. Given a loop control predicate of (V
14939 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14940 is appended to *DLIST, iterator initialization is appended to
14941 *BODY_P. */
14943 static void
14944 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14945 gimple_seq *dlist, struct omp_context *ctx)
14947 tree clauses, cond, vinit;
14948 enum tree_code cond_code;
14949 gimple_seq stmts;
14951 cond_code = fd->loop.cond_code;
14952 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14954 /* When possible, use a strict equality expression. This can let VRP
14955 type optimizations deduce the value and remove a copy. */
14956 if (tree_fits_shwi_p (fd->loop.step))
14958 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14959 if (step == 1 || step == -1)
14960 cond_code = EQ_EXPR;
14963 tree n2 = fd->loop.n2;
14964 if (fd->collapse > 1
14965 && TREE_CODE (n2) != INTEGER_CST
14966 && gimple_omp_for_combined_into_p (fd->for_stmt))
14968 struct omp_context *taskreg_ctx = NULL;
14969 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14971 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14972 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14973 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14975 if (gimple_omp_for_combined_into_p (gfor))
14977 gcc_assert (ctx->outer->outer
14978 && is_parallel_ctx (ctx->outer->outer));
14979 taskreg_ctx = ctx->outer->outer;
14981 else
14983 struct omp_for_data outer_fd;
14984 extract_omp_for_data (gfor, &outer_fd, NULL);
14985 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14988 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14989 taskreg_ctx = ctx->outer->outer;
14991 else if (is_taskreg_ctx (ctx->outer))
14992 taskreg_ctx = ctx->outer;
14993 if (taskreg_ctx)
14995 int i;
14996 tree innerc
14997 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14998 OMP_CLAUSE__LOOPTEMP_);
14999 gcc_assert (innerc);
15000 for (i = 0; i < fd->collapse; i++)
15002 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15003 OMP_CLAUSE__LOOPTEMP_);
15004 gcc_assert (innerc);
15006 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15007 OMP_CLAUSE__LOOPTEMP_);
15008 if (innerc)
15009 n2 = fold_convert (TREE_TYPE (n2),
15010 lookup_decl (OMP_CLAUSE_DECL (innerc),
15011 taskreg_ctx));
15014 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
15016 clauses = gimple_omp_for_clauses (fd->for_stmt);
15017 stmts = NULL;
15018 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15019 if (!gimple_seq_empty_p (stmts))
15021 gimple_seq_add_seq (&stmts, *dlist);
15022 *dlist = stmts;
15024 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15025 vinit = fd->loop.n1;
15026 if (cond_code == EQ_EXPR
15027 && tree_fits_shwi_p (fd->loop.n2)
15028 && ! integer_zerop (fd->loop.n2))
15029 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15030 else
15031 vinit = unshare_expr (vinit);
15033 /* Initialize the iterator variable, so that threads that don't execute
15034 any iterations don't execute the lastprivate clauses by accident. */
15035 gimplify_assign (fd->loop.v, vinit, body_p);
15040 /* Lower code for an OMP loop directive. */
15042 static void
15043 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15045 tree *rhs_p, block;
15046 struct omp_for_data fd, *fdp = NULL;
15047 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15048 gbind *new_stmt;
15049 gimple_seq omp_for_body, body, dlist;
15050 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15051 size_t i;
15053 push_gimplify_context ();
15055 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15057 block = make_node (BLOCK);
15058 new_stmt = gimple_build_bind (NULL, NULL, block);
15059 /* Replace at gsi right away, so that 'stmt' is no member
15060 of a sequence anymore as we're going to add to a different
15061 one below. */
15062 gsi_replace (gsi_p, new_stmt, true);
15064 /* Move declaration of temporaries in the loop body before we make
15065 it go away. */
15066 omp_for_body = gimple_omp_body (stmt);
15067 if (!gimple_seq_empty_p (omp_for_body)
15068 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15070 gbind *inner_bind
15071 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15072 tree vars = gimple_bind_vars (inner_bind);
15073 gimple_bind_append_vars (new_stmt, vars);
15074 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15075 keep them on the inner_bind and it's block. */
15076 gimple_bind_set_vars (inner_bind, NULL_TREE);
15077 if (gimple_bind_block (inner_bind))
15078 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15081 if (gimple_omp_for_combined_into_p (stmt))
15083 extract_omp_for_data (stmt, &fd, NULL);
15084 fdp = &fd;
15086 /* We need two temporaries with fd.loop.v type (istart/iend)
15087 and then (fd.collapse - 1) temporaries with the same
15088 type for count2 ... countN-1 vars if not constant. */
15089 size_t count = 2;
15090 tree type = fd.iter_type;
15091 if (fd.collapse > 1
15092 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15093 count += fd.collapse - 1;
15094 bool taskreg_for
15095 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15096 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15097 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15098 tree clauses = *pc;
15099 if (taskreg_for)
15100 outerc
15101 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15102 OMP_CLAUSE__LOOPTEMP_);
15103 for (i = 0; i < count; i++)
15105 tree temp;
15106 if (taskreg_for)
15108 gcc_assert (outerc);
15109 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15110 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15111 OMP_CLAUSE__LOOPTEMP_);
15113 else
15115 temp = create_tmp_var (type);
15116 insert_decl_map (&ctx->outer->cb, temp, temp);
15118 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15119 OMP_CLAUSE_DECL (*pc) = temp;
15120 pc = &OMP_CLAUSE_CHAIN (*pc);
15122 *pc = clauses;
15125 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15126 dlist = NULL;
15127 body = NULL;
15128 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15129 fdp);
15130 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15132 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15134 /* Lower the header expressions. At this point, we can assume that
15135 the header is of the form:
15137 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15139 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15140 using the .omp_data_s mapping, if needed. */
15141 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15143 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15144 if (!is_gimple_min_invariant (*rhs_p))
15145 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15147 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15148 if (!is_gimple_min_invariant (*rhs_p))
15149 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15151 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15152 if (!is_gimple_min_invariant (*rhs_p))
15153 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15156 /* Once lowered, extract the bounds and clauses. */
15157 extract_omp_for_data (stmt, &fd, NULL);
15159 if (is_gimple_omp_oacc (ctx->stmt)
15160 && !ctx_in_oacc_kernels_region (ctx))
15161 lower_oacc_head_tail (gimple_location (stmt),
15162 gimple_omp_for_clauses (stmt),
15163 &oacc_head, &oacc_tail, ctx);
15165 /* Add OpenACC partitioning and reduction markers just before the loop */
15166 if (oacc_head)
15167 gimple_seq_add_seq (&body, oacc_head);
15169 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15171 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15172 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15173 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15174 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15176 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15177 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15178 OMP_CLAUSE_LINEAR_STEP (c)
15179 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15180 ctx);
15183 if (!gimple_omp_for_grid_phony (stmt))
15184 gimple_seq_add_stmt (&body, stmt);
15185 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15187 if (!gimple_omp_for_grid_phony (stmt))
15188 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15189 fd.loop.v));
15191 /* After the loop, add exit clauses. */
15192 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15194 if (ctx->cancellable)
15195 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15197 gimple_seq_add_seq (&body, dlist);
15199 body = maybe_catch_exception (body);
15201 if (!gimple_omp_for_grid_phony (stmt))
15203 /* Region exit marker goes at the end of the loop body. */
15204 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15205 maybe_add_implicit_barrier_cancel (ctx, &body);
15208 /* Add OpenACC joining and reduction markers just after the loop. */
15209 if (oacc_tail)
15210 gimple_seq_add_seq (&body, oacc_tail);
15212 pop_gimplify_context (new_stmt);
15214 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15215 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15216 if (BLOCK_VARS (block))
15217 TREE_USED (block) = 1;
15219 gimple_bind_set_body (new_stmt, body);
15220 gimple_omp_set_body (stmt, NULL);
15221 gimple_omp_for_set_pre_body (stmt, NULL);
15224 /* Callback for walk_stmts. Check if the current statement only contains
15225 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15227 static tree
15228 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15229 bool *handled_ops_p,
15230 struct walk_stmt_info *wi)
15232 int *info = (int *) wi->info;
15233 gimple *stmt = gsi_stmt (*gsi_p);
15235 *handled_ops_p = true;
15236 switch (gimple_code (stmt))
15238 WALK_SUBSTMTS;
15240 case GIMPLE_OMP_FOR:
15241 case GIMPLE_OMP_SECTIONS:
15242 *info = *info == 0 ? 1 : -1;
15243 break;
15244 default:
15245 *info = -1;
15246 break;
15248 return NULL;
15251 struct omp_taskcopy_context
15253 /* This field must be at the beginning, as we do "inheritance": Some
15254 callback functions for tree-inline.c (e.g., omp_copy_decl)
15255 receive a copy_body_data pointer that is up-casted to an
15256 omp_context pointer. */
15257 copy_body_data cb;
15258 omp_context *ctx;
15261 static tree
15262 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15264 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15266 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15267 return create_tmp_var (TREE_TYPE (var));
15269 return var;
15272 static tree
15273 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15275 tree name, new_fields = NULL, type, f;
15277 type = lang_hooks.types.make_type (RECORD_TYPE);
15278 name = DECL_NAME (TYPE_NAME (orig_type));
15279 name = build_decl (gimple_location (tcctx->ctx->stmt),
15280 TYPE_DECL, name, type);
15281 TYPE_NAME (type) = name;
15283 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15285 tree new_f = copy_node (f);
15286 DECL_CONTEXT (new_f) = type;
15287 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15288 TREE_CHAIN (new_f) = new_fields;
15289 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15290 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15291 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15292 &tcctx->cb, NULL);
15293 new_fields = new_f;
15294 tcctx->cb.decl_map->put (f, new_f);
15296 TYPE_FIELDS (type) = nreverse (new_fields);
15297 layout_type (type);
15298 return type;
15301 /* Create task copyfn. */
15303 static void
15304 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15306 struct function *child_cfun;
15307 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15308 tree record_type, srecord_type, bind, list;
15309 bool record_needs_remap = false, srecord_needs_remap = false;
15310 splay_tree_node n;
15311 struct omp_taskcopy_context tcctx;
15312 location_t loc = gimple_location (task_stmt);
15314 child_fn = gimple_omp_task_copy_fn (task_stmt);
15315 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15316 gcc_assert (child_cfun->cfg == NULL);
15317 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15319 /* Reset DECL_CONTEXT on function arguments. */
15320 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15321 DECL_CONTEXT (t) = child_fn;
15323 /* Populate the function. */
15324 push_gimplify_context ();
15325 push_cfun (child_cfun);
15327 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15328 TREE_SIDE_EFFECTS (bind) = 1;
15329 list = NULL;
15330 DECL_SAVED_TREE (child_fn) = bind;
15331 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15333 /* Remap src and dst argument types if needed. */
15334 record_type = ctx->record_type;
15335 srecord_type = ctx->srecord_type;
15336 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15337 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15339 record_needs_remap = true;
15340 break;
15342 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15343 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15345 srecord_needs_remap = true;
15346 break;
15349 if (record_needs_remap || srecord_needs_remap)
15351 memset (&tcctx, '\0', sizeof (tcctx));
15352 tcctx.cb.src_fn = ctx->cb.src_fn;
15353 tcctx.cb.dst_fn = child_fn;
15354 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15355 gcc_checking_assert (tcctx.cb.src_node);
15356 tcctx.cb.dst_node = tcctx.cb.src_node;
15357 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15358 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15359 tcctx.cb.eh_lp_nr = 0;
15360 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15361 tcctx.cb.decl_map = new hash_map<tree, tree>;
15362 tcctx.ctx = ctx;
15364 if (record_needs_remap)
15365 record_type = task_copyfn_remap_type (&tcctx, record_type);
15366 if (srecord_needs_remap)
15367 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15369 else
15370 tcctx.cb.decl_map = NULL;
15372 arg = DECL_ARGUMENTS (child_fn);
15373 TREE_TYPE (arg) = build_pointer_type (record_type);
15374 sarg = DECL_CHAIN (arg);
15375 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15377 /* First pass: initialize temporaries used in record_type and srecord_type
15378 sizes and field offsets. */
15379 if (tcctx.cb.decl_map)
15380 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15381 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15383 tree *p;
15385 decl = OMP_CLAUSE_DECL (c);
15386 p = tcctx.cb.decl_map->get (decl);
15387 if (p == NULL)
15388 continue;
15389 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15390 sf = (tree) n->value;
15391 sf = *tcctx.cb.decl_map->get (sf);
15392 src = build_simple_mem_ref_loc (loc, sarg);
15393 src = omp_build_component_ref (src, sf);
15394 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15395 append_to_statement_list (t, &list);
15398 /* Second pass: copy shared var pointers and copy construct non-VLA
15399 firstprivate vars. */
15400 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15401 switch (OMP_CLAUSE_CODE (c))
15403 splay_tree_key key;
15404 case OMP_CLAUSE_SHARED:
15405 decl = OMP_CLAUSE_DECL (c);
15406 key = (splay_tree_key) decl;
15407 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15408 key = (splay_tree_key) &DECL_UID (decl);
15409 n = splay_tree_lookup (ctx->field_map, key);
15410 if (n == NULL)
15411 break;
15412 f = (tree) n->value;
15413 if (tcctx.cb.decl_map)
15414 f = *tcctx.cb.decl_map->get (f);
15415 n = splay_tree_lookup (ctx->sfield_map, key);
15416 sf = (tree) n->value;
15417 if (tcctx.cb.decl_map)
15418 sf = *tcctx.cb.decl_map->get (sf);
15419 src = build_simple_mem_ref_loc (loc, sarg);
15420 src = omp_build_component_ref (src, sf);
15421 dst = build_simple_mem_ref_loc (loc, arg);
15422 dst = omp_build_component_ref (dst, f);
15423 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15424 append_to_statement_list (t, &list);
15425 break;
15426 case OMP_CLAUSE_FIRSTPRIVATE:
15427 decl = OMP_CLAUSE_DECL (c);
15428 if (is_variable_sized (decl))
15429 break;
15430 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15431 if (n == NULL)
15432 break;
15433 f = (tree) n->value;
15434 if (tcctx.cb.decl_map)
15435 f = *tcctx.cb.decl_map->get (f);
15436 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15437 if (n != NULL)
15439 sf = (tree) n->value;
15440 if (tcctx.cb.decl_map)
15441 sf = *tcctx.cb.decl_map->get (sf);
15442 src = build_simple_mem_ref_loc (loc, sarg);
15443 src = omp_build_component_ref (src, sf);
15444 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15445 src = build_simple_mem_ref_loc (loc, src);
15447 else
15448 src = decl;
15449 dst = build_simple_mem_ref_loc (loc, arg);
15450 dst = omp_build_component_ref (dst, f);
15451 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15452 append_to_statement_list (t, &list);
15453 break;
15454 case OMP_CLAUSE_PRIVATE:
15455 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15456 break;
15457 decl = OMP_CLAUSE_DECL (c);
15458 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15459 f = (tree) n->value;
15460 if (tcctx.cb.decl_map)
15461 f = *tcctx.cb.decl_map->get (f);
15462 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15463 if (n != NULL)
15465 sf = (tree) n->value;
15466 if (tcctx.cb.decl_map)
15467 sf = *tcctx.cb.decl_map->get (sf);
15468 src = build_simple_mem_ref_loc (loc, sarg);
15469 src = omp_build_component_ref (src, sf);
15470 if (use_pointer_for_field (decl, NULL))
15471 src = build_simple_mem_ref_loc (loc, src);
15473 else
15474 src = decl;
15475 dst = build_simple_mem_ref_loc (loc, arg);
15476 dst = omp_build_component_ref (dst, f);
15477 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15478 append_to_statement_list (t, &list);
15479 break;
15480 default:
15481 break;
15484 /* Last pass: handle VLA firstprivates. */
15485 if (tcctx.cb.decl_map)
15486 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15487 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15489 tree ind, ptr, df;
15491 decl = OMP_CLAUSE_DECL (c);
15492 if (!is_variable_sized (decl))
15493 continue;
15494 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15495 if (n == NULL)
15496 continue;
15497 f = (tree) n->value;
15498 f = *tcctx.cb.decl_map->get (f);
15499 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15500 ind = DECL_VALUE_EXPR (decl);
15501 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15502 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15503 n = splay_tree_lookup (ctx->sfield_map,
15504 (splay_tree_key) TREE_OPERAND (ind, 0));
15505 sf = (tree) n->value;
15506 sf = *tcctx.cb.decl_map->get (sf);
15507 src = build_simple_mem_ref_loc (loc, sarg);
15508 src = omp_build_component_ref (src, sf);
15509 src = build_simple_mem_ref_loc (loc, src);
15510 dst = build_simple_mem_ref_loc (loc, arg);
15511 dst = omp_build_component_ref (dst, f);
15512 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15513 append_to_statement_list (t, &list);
15514 n = splay_tree_lookup (ctx->field_map,
15515 (splay_tree_key) TREE_OPERAND (ind, 0));
15516 df = (tree) n->value;
15517 df = *tcctx.cb.decl_map->get (df);
15518 ptr = build_simple_mem_ref_loc (loc, arg);
15519 ptr = omp_build_component_ref (ptr, df);
15520 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15521 build_fold_addr_expr_loc (loc, dst));
15522 append_to_statement_list (t, &list);
15525 t = build1 (RETURN_EXPR, void_type_node, NULL);
15526 append_to_statement_list (t, &list);
15528 if (tcctx.cb.decl_map)
15529 delete tcctx.cb.decl_map;
15530 pop_gimplify_context (NULL);
15531 BIND_EXPR_BODY (bind) = list;
15532 pop_cfun ();
15535 static void
15536 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15538 tree c, clauses;
15539 gimple *g;
15540 size_t n_in = 0, n_out = 0, idx = 2, i;
15542 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15543 gcc_assert (clauses);
15544 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15545 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15546 switch (OMP_CLAUSE_DEPEND_KIND (c))
15548 case OMP_CLAUSE_DEPEND_IN:
15549 n_in++;
15550 break;
15551 case OMP_CLAUSE_DEPEND_OUT:
15552 case OMP_CLAUSE_DEPEND_INOUT:
15553 n_out++;
15554 break;
15555 case OMP_CLAUSE_DEPEND_SOURCE:
15556 case OMP_CLAUSE_DEPEND_SINK:
15557 /* FALLTHRU */
15558 default:
15559 gcc_unreachable ();
15561 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15562 tree array = create_tmp_var (type);
15563 TREE_ADDRESSABLE (array) = 1;
15564 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15565 NULL_TREE);
15566 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15567 gimple_seq_add_stmt (iseq, g);
15568 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15569 NULL_TREE);
15570 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15571 gimple_seq_add_stmt (iseq, g);
15572 for (i = 0; i < 2; i++)
15574 if ((i ? n_in : n_out) == 0)
15575 continue;
15576 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15578 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15580 tree t = OMP_CLAUSE_DECL (c);
15581 t = fold_convert (ptr_type_node, t);
15582 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15583 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15584 NULL_TREE, NULL_TREE);
15585 g = gimple_build_assign (r, t);
15586 gimple_seq_add_stmt (iseq, g);
15589 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15590 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15591 OMP_CLAUSE_CHAIN (c) = *pclauses;
15592 *pclauses = c;
15593 tree clobber = build_constructor (type, NULL);
15594 TREE_THIS_VOLATILE (clobber) = 1;
15595 g = gimple_build_assign (array, clobber);
15596 gimple_seq_add_stmt (oseq, g);
15599 /* Lower the OpenMP parallel or task directive in the current statement
15600 in GSI_P. CTX holds context information for the directive. */
15602 static void
15603 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15605 tree clauses;
15606 tree child_fn, t;
15607 gimple *stmt = gsi_stmt (*gsi_p);
15608 gbind *par_bind, *bind, *dep_bind = NULL;
15609 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15610 location_t loc = gimple_location (stmt);
15612 clauses = gimple_omp_taskreg_clauses (stmt);
15613 par_bind
15614 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15615 par_body = gimple_bind_body (par_bind);
15616 child_fn = ctx->cb.dst_fn;
15617 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15618 && !gimple_omp_parallel_combined_p (stmt))
15620 struct walk_stmt_info wi;
15621 int ws_num = 0;
15623 memset (&wi, 0, sizeof (wi));
15624 wi.info = &ws_num;
15625 wi.val_only = true;
15626 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15627 if (ws_num == 1)
15628 gimple_omp_parallel_set_combined_p (stmt, true);
15630 gimple_seq dep_ilist = NULL;
15631 gimple_seq dep_olist = NULL;
15632 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15633 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15635 push_gimplify_context ();
15636 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15637 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15638 &dep_ilist, &dep_olist);
15641 if (ctx->srecord_type)
15642 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15644 push_gimplify_context ();
15646 par_olist = NULL;
15647 par_ilist = NULL;
15648 par_rlist = NULL;
15649 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15650 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15651 if (phony_construct && ctx->record_type)
15653 gcc_checking_assert (!ctx->receiver_decl);
15654 ctx->receiver_decl = create_tmp_var
15655 (build_reference_type (ctx->record_type), ".omp_rec");
15657 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15658 lower_omp (&par_body, ctx);
15659 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15660 lower_reduction_clauses (clauses, &par_rlist, ctx);
15662 /* Declare all the variables created by mapping and the variables
15663 declared in the scope of the parallel body. */
15664 record_vars_into (ctx->block_vars, child_fn);
15665 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15667 if (ctx->record_type)
15669 ctx->sender_decl
15670 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15671 : ctx->record_type, ".omp_data_o");
15672 DECL_NAMELESS (ctx->sender_decl) = 1;
15673 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15674 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15677 olist = NULL;
15678 ilist = NULL;
15679 lower_send_clauses (clauses, &ilist, &olist, ctx);
15680 lower_send_shared_vars (&ilist, &olist, ctx);
15682 if (ctx->record_type)
15684 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15685 TREE_THIS_VOLATILE (clobber) = 1;
15686 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15687 clobber));
15690 /* Once all the expansions are done, sequence all the different
15691 fragments inside gimple_omp_body. */
15693 new_body = NULL;
15695 if (ctx->record_type)
15697 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15698 /* fixup_child_record_type might have changed receiver_decl's type. */
15699 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15700 gimple_seq_add_stmt (&new_body,
15701 gimple_build_assign (ctx->receiver_decl, t));
15704 gimple_seq_add_seq (&new_body, par_ilist);
15705 gimple_seq_add_seq (&new_body, par_body);
15706 gimple_seq_add_seq (&new_body, par_rlist);
15707 if (ctx->cancellable)
15708 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15709 gimple_seq_add_seq (&new_body, par_olist);
15710 new_body = maybe_catch_exception (new_body);
15711 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15712 gimple_seq_add_stmt (&new_body,
15713 gimple_build_omp_continue (integer_zero_node,
15714 integer_zero_node));
15715 if (!phony_construct)
15717 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15718 gimple_omp_set_body (stmt, new_body);
15721 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15722 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15723 gimple_bind_add_seq (bind, ilist);
15724 if (!phony_construct)
15725 gimple_bind_add_stmt (bind, stmt);
15726 else
15727 gimple_bind_add_seq (bind, new_body);
15728 gimple_bind_add_seq (bind, olist);
15730 pop_gimplify_context (NULL);
15732 if (dep_bind)
15734 gimple_bind_add_seq (dep_bind, dep_ilist);
15735 gimple_bind_add_stmt (dep_bind, bind);
15736 gimple_bind_add_seq (dep_bind, dep_olist);
15737 pop_gimplify_context (dep_bind);
15741 /* Lower the GIMPLE_OMP_TARGET in the current statement
15742 in GSI_P. CTX holds context information for the directive. */
15744 static void
15745 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15747 tree clauses;
15748 tree child_fn, t, c;
15749 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15750 gbind *tgt_bind, *bind, *dep_bind = NULL;
15751 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15752 location_t loc = gimple_location (stmt);
15753 bool offloaded, data_region;
15754 unsigned int map_cnt = 0;
15756 offloaded = is_gimple_omp_offloaded (stmt);
15757 switch (gimple_omp_target_kind (stmt))
15759 case GF_OMP_TARGET_KIND_REGION:
15760 case GF_OMP_TARGET_KIND_UPDATE:
15761 case GF_OMP_TARGET_KIND_ENTER_DATA:
15762 case GF_OMP_TARGET_KIND_EXIT_DATA:
15763 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15764 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15765 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15766 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15767 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15768 data_region = false;
15769 break;
15770 case GF_OMP_TARGET_KIND_DATA:
15771 case GF_OMP_TARGET_KIND_OACC_DATA:
15772 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15773 data_region = true;
15774 break;
15775 default:
15776 gcc_unreachable ();
15779 clauses = gimple_omp_target_clauses (stmt);
15781 gimple_seq dep_ilist = NULL;
15782 gimple_seq dep_olist = NULL;
15783 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15785 push_gimplify_context ();
15786 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15787 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15788 &dep_ilist, &dep_olist);
15791 tgt_bind = NULL;
15792 tgt_body = NULL;
15793 if (offloaded)
15795 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15796 tgt_body = gimple_bind_body (tgt_bind);
15798 else if (data_region)
15799 tgt_body = gimple_omp_body (stmt);
15800 child_fn = ctx->cb.dst_fn;
15802 push_gimplify_context ();
15803 fplist = NULL;
15805 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15806 switch (OMP_CLAUSE_CODE (c))
15808 tree var, x;
15810 default:
15811 break;
15812 case OMP_CLAUSE_MAP:
15813 #if CHECKING_P
15814 /* First check what we're prepared to handle in the following. */
15815 switch (OMP_CLAUSE_MAP_KIND (c))
15817 case GOMP_MAP_ALLOC:
15818 case GOMP_MAP_TO:
15819 case GOMP_MAP_FROM:
15820 case GOMP_MAP_TOFROM:
15821 case GOMP_MAP_POINTER:
15822 case GOMP_MAP_TO_PSET:
15823 case GOMP_MAP_DELETE:
15824 case GOMP_MAP_RELEASE:
15825 case GOMP_MAP_ALWAYS_TO:
15826 case GOMP_MAP_ALWAYS_FROM:
15827 case GOMP_MAP_ALWAYS_TOFROM:
15828 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15829 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15830 case GOMP_MAP_STRUCT:
15831 case GOMP_MAP_ALWAYS_POINTER:
15832 break;
15833 case GOMP_MAP_FORCE_ALLOC:
15834 case GOMP_MAP_FORCE_TO:
15835 case GOMP_MAP_FORCE_FROM:
15836 case GOMP_MAP_FORCE_TOFROM:
15837 case GOMP_MAP_FORCE_PRESENT:
15838 case GOMP_MAP_FORCE_DEVICEPTR:
15839 case GOMP_MAP_DEVICE_RESIDENT:
15840 case GOMP_MAP_LINK:
15841 gcc_assert (is_gimple_omp_oacc (stmt));
15842 break;
15843 default:
15844 gcc_unreachable ();
15846 #endif
15847 /* FALLTHRU */
15848 case OMP_CLAUSE_TO:
15849 case OMP_CLAUSE_FROM:
15850 oacc_firstprivate:
15851 var = OMP_CLAUSE_DECL (c);
15852 if (!DECL_P (var))
15854 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15855 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15856 && (OMP_CLAUSE_MAP_KIND (c)
15857 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15858 map_cnt++;
15859 continue;
15862 if (DECL_SIZE (var)
15863 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15865 tree var2 = DECL_VALUE_EXPR (var);
15866 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15867 var2 = TREE_OPERAND (var2, 0);
15868 gcc_assert (DECL_P (var2));
15869 var = var2;
15872 if (offloaded
15873 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15874 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15875 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15877 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15879 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15880 && varpool_node::get_create (var)->offloadable)
15881 continue;
15883 tree type = build_pointer_type (TREE_TYPE (var));
15884 tree new_var = lookup_decl (var, ctx);
15885 x = create_tmp_var_raw (type, get_name (new_var));
15886 gimple_add_tmp_var (x);
15887 x = build_simple_mem_ref (x);
15888 SET_DECL_VALUE_EXPR (new_var, x);
15889 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15891 continue;
15894 if (!maybe_lookup_field (var, ctx))
15895 continue;
15897 /* Don't remap oacc parallel reduction variables, because the
15898 intermediate result must be local to each gang. */
15899 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15900 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15902 x = build_receiver_ref (var, true, ctx);
15903 tree new_var = lookup_decl (var, ctx);
15905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15906 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15907 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15908 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15909 x = build_simple_mem_ref (x);
15910 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15912 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15913 if (is_reference (new_var))
15915 /* Create a local object to hold the instance
15916 value. */
15917 tree type = TREE_TYPE (TREE_TYPE (new_var));
15918 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15919 tree inst = create_tmp_var (type, id);
15920 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15921 x = build_fold_addr_expr (inst);
15923 gimplify_assign (new_var, x, &fplist);
15925 else if (DECL_P (new_var))
15927 SET_DECL_VALUE_EXPR (new_var, x);
15928 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15930 else
15931 gcc_unreachable ();
15933 map_cnt++;
15934 break;
15936 case OMP_CLAUSE_FIRSTPRIVATE:
15937 if (is_oacc_parallel (ctx))
15938 goto oacc_firstprivate;
15939 map_cnt++;
15940 var = OMP_CLAUSE_DECL (c);
15941 if (!is_reference (var)
15942 && !is_gimple_reg_type (TREE_TYPE (var)))
15944 tree new_var = lookup_decl (var, ctx);
15945 if (is_variable_sized (var))
15947 tree pvar = DECL_VALUE_EXPR (var);
15948 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15949 pvar = TREE_OPERAND (pvar, 0);
15950 gcc_assert (DECL_P (pvar));
15951 tree new_pvar = lookup_decl (pvar, ctx);
15952 x = build_fold_indirect_ref (new_pvar);
15953 TREE_THIS_NOTRAP (x) = 1;
15955 else
15956 x = build_receiver_ref (var, true, ctx);
15957 SET_DECL_VALUE_EXPR (new_var, x);
15958 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15960 break;
15962 case OMP_CLAUSE_PRIVATE:
15963 if (is_gimple_omp_oacc (ctx->stmt))
15964 break;
15965 var = OMP_CLAUSE_DECL (c);
15966 if (is_variable_sized (var))
15968 tree new_var = lookup_decl (var, ctx);
15969 tree pvar = DECL_VALUE_EXPR (var);
15970 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15971 pvar = TREE_OPERAND (pvar, 0);
15972 gcc_assert (DECL_P (pvar));
15973 tree new_pvar = lookup_decl (pvar, ctx);
15974 x = build_fold_indirect_ref (new_pvar);
15975 TREE_THIS_NOTRAP (x) = 1;
15976 SET_DECL_VALUE_EXPR (new_var, x);
15977 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15979 break;
15981 case OMP_CLAUSE_USE_DEVICE_PTR:
15982 case OMP_CLAUSE_IS_DEVICE_PTR:
15983 var = OMP_CLAUSE_DECL (c);
15984 map_cnt++;
15985 if (is_variable_sized (var))
15987 tree new_var = lookup_decl (var, ctx);
15988 tree pvar = DECL_VALUE_EXPR (var);
15989 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15990 pvar = TREE_OPERAND (pvar, 0);
15991 gcc_assert (DECL_P (pvar));
15992 tree new_pvar = lookup_decl (pvar, ctx);
15993 x = build_fold_indirect_ref (new_pvar);
15994 TREE_THIS_NOTRAP (x) = 1;
15995 SET_DECL_VALUE_EXPR (new_var, x);
15996 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15998 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16000 tree new_var = lookup_decl (var, ctx);
16001 tree type = build_pointer_type (TREE_TYPE (var));
16002 x = create_tmp_var_raw (type, get_name (new_var));
16003 gimple_add_tmp_var (x);
16004 x = build_simple_mem_ref (x);
16005 SET_DECL_VALUE_EXPR (new_var, x);
16006 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16008 else
16010 tree new_var = lookup_decl (var, ctx);
16011 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
16012 gimple_add_tmp_var (x);
16013 SET_DECL_VALUE_EXPR (new_var, x);
16014 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16016 break;
16019 if (offloaded)
16021 target_nesting_level++;
16022 lower_omp (&tgt_body, ctx);
16023 target_nesting_level--;
16025 else if (data_region)
16026 lower_omp (&tgt_body, ctx);
16028 if (offloaded)
16030 /* Declare all the variables created by mapping and the variables
16031 declared in the scope of the target body. */
16032 record_vars_into (ctx->block_vars, child_fn);
16033 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16036 olist = NULL;
16037 ilist = NULL;
16038 if (ctx->record_type)
16040 ctx->sender_decl
16041 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16042 DECL_NAMELESS (ctx->sender_decl) = 1;
16043 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16044 t = make_tree_vec (3);
16045 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16046 TREE_VEC_ELT (t, 1)
16047 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16048 ".omp_data_sizes");
16049 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16050 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16051 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16052 tree tkind_type = short_unsigned_type_node;
16053 int talign_shift = 8;
16054 TREE_VEC_ELT (t, 2)
16055 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16056 ".omp_data_kinds");
16057 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16058 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16059 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16060 gimple_omp_target_set_data_arg (stmt, t);
16062 vec<constructor_elt, va_gc> *vsize;
16063 vec<constructor_elt, va_gc> *vkind;
16064 vec_alloc (vsize, map_cnt);
16065 vec_alloc (vkind, map_cnt);
16066 unsigned int map_idx = 0;
16068 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16069 switch (OMP_CLAUSE_CODE (c))
16071 tree ovar, nc, s, purpose, var, x, type;
16072 unsigned int talign;
16074 default:
16075 break;
16077 case OMP_CLAUSE_MAP:
16078 case OMP_CLAUSE_TO:
16079 case OMP_CLAUSE_FROM:
16080 oacc_firstprivate_map:
16081 nc = c;
16082 ovar = OMP_CLAUSE_DECL (c);
16083 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16084 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16085 || (OMP_CLAUSE_MAP_KIND (c)
16086 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16087 break;
16088 if (!DECL_P (ovar))
16090 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16091 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16093 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16094 == get_base_address (ovar));
16095 nc = OMP_CLAUSE_CHAIN (c);
16096 ovar = OMP_CLAUSE_DECL (nc);
16098 else
16100 tree x = build_sender_ref (ovar, ctx);
16101 tree v
16102 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16103 gimplify_assign (x, v, &ilist);
16104 nc = NULL_TREE;
16107 else
16109 if (DECL_SIZE (ovar)
16110 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16112 tree ovar2 = DECL_VALUE_EXPR (ovar);
16113 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16114 ovar2 = TREE_OPERAND (ovar2, 0);
16115 gcc_assert (DECL_P (ovar2));
16116 ovar = ovar2;
16118 if (!maybe_lookup_field (ovar, ctx))
16119 continue;
16122 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16123 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16124 talign = DECL_ALIGN_UNIT (ovar);
16125 if (nc)
16127 var = lookup_decl_in_outer_ctx (ovar, ctx);
16128 x = build_sender_ref (ovar, ctx);
16130 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16131 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16132 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16133 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16135 gcc_assert (offloaded);
16136 tree avar
16137 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16138 mark_addressable (avar);
16139 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16140 talign = DECL_ALIGN_UNIT (avar);
16141 avar = build_fold_addr_expr (avar);
16142 gimplify_assign (x, avar, &ilist);
16144 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16146 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16147 if (!is_reference (var))
16149 if (is_gimple_reg (var)
16150 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16151 TREE_NO_WARNING (var) = 1;
16152 var = build_fold_addr_expr (var);
16154 else
16155 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16156 gimplify_assign (x, var, &ilist);
16158 else if (is_gimple_reg (var))
16160 gcc_assert (offloaded);
16161 tree avar = create_tmp_var (TREE_TYPE (var));
16162 mark_addressable (avar);
16163 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16164 if (GOMP_MAP_COPY_TO_P (map_kind)
16165 || map_kind == GOMP_MAP_POINTER
16166 || map_kind == GOMP_MAP_TO_PSET
16167 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16169 /* If we need to initialize a temporary
16170 with VAR because it is not addressable, and
16171 the variable hasn't been initialized yet, then
16172 we'll get a warning for the store to avar.
16173 Don't warn in that case, the mapping might
16174 be implicit. */
16175 TREE_NO_WARNING (var) = 1;
16176 gimplify_assign (avar, var, &ilist);
16178 avar = build_fold_addr_expr (avar);
16179 gimplify_assign (x, avar, &ilist);
16180 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16181 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16182 && !TYPE_READONLY (TREE_TYPE (var)))
16184 x = unshare_expr (x);
16185 x = build_simple_mem_ref (x);
16186 gimplify_assign (var, x, &olist);
16189 else
16191 var = build_fold_addr_expr (var);
16192 gimplify_assign (x, var, &ilist);
16195 s = NULL_TREE;
16196 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16198 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16199 s = TREE_TYPE (ovar);
16200 if (TREE_CODE (s) == REFERENCE_TYPE)
16201 s = TREE_TYPE (s);
16202 s = TYPE_SIZE_UNIT (s);
16204 else
16205 s = OMP_CLAUSE_SIZE (c);
16206 if (s == NULL_TREE)
16207 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16208 s = fold_convert (size_type_node, s);
16209 purpose = size_int (map_idx++);
16210 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16211 if (TREE_CODE (s) != INTEGER_CST)
16212 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16214 unsigned HOST_WIDE_INT tkind, tkind_zero;
16215 switch (OMP_CLAUSE_CODE (c))
16217 case OMP_CLAUSE_MAP:
16218 tkind = OMP_CLAUSE_MAP_KIND (c);
16219 tkind_zero = tkind;
16220 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16221 switch (tkind)
16223 case GOMP_MAP_ALLOC:
16224 case GOMP_MAP_TO:
16225 case GOMP_MAP_FROM:
16226 case GOMP_MAP_TOFROM:
16227 case GOMP_MAP_ALWAYS_TO:
16228 case GOMP_MAP_ALWAYS_FROM:
16229 case GOMP_MAP_ALWAYS_TOFROM:
16230 case GOMP_MAP_RELEASE:
16231 case GOMP_MAP_FORCE_TO:
16232 case GOMP_MAP_FORCE_FROM:
16233 case GOMP_MAP_FORCE_TOFROM:
16234 case GOMP_MAP_FORCE_PRESENT:
16235 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16236 break;
16237 case GOMP_MAP_DELETE:
16238 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16239 default:
16240 break;
16242 if (tkind_zero != tkind)
16244 if (integer_zerop (s))
16245 tkind = tkind_zero;
16246 else if (integer_nonzerop (s))
16247 tkind_zero = tkind;
16249 break;
16250 case OMP_CLAUSE_FIRSTPRIVATE:
16251 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16252 tkind = GOMP_MAP_TO;
16253 tkind_zero = tkind;
16254 break;
16255 case OMP_CLAUSE_TO:
16256 tkind = GOMP_MAP_TO;
16257 tkind_zero = tkind;
16258 break;
16259 case OMP_CLAUSE_FROM:
16260 tkind = GOMP_MAP_FROM;
16261 tkind_zero = tkind;
16262 break;
16263 default:
16264 gcc_unreachable ();
16266 gcc_checking_assert (tkind
16267 < (HOST_WIDE_INT_C (1U) << talign_shift));
16268 gcc_checking_assert (tkind_zero
16269 < (HOST_WIDE_INT_C (1U) << talign_shift));
16270 talign = ceil_log2 (talign);
16271 tkind |= talign << talign_shift;
16272 tkind_zero |= talign << talign_shift;
16273 gcc_checking_assert (tkind
16274 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16275 gcc_checking_assert (tkind_zero
16276 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16277 if (tkind == tkind_zero)
16278 x = build_int_cstu (tkind_type, tkind);
16279 else
16281 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16282 x = build3 (COND_EXPR, tkind_type,
16283 fold_build2 (EQ_EXPR, boolean_type_node,
16284 unshare_expr (s), size_zero_node),
16285 build_int_cstu (tkind_type, tkind_zero),
16286 build_int_cstu (tkind_type, tkind));
16288 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16289 if (nc && nc != c)
16290 c = nc;
16291 break;
16293 case OMP_CLAUSE_FIRSTPRIVATE:
16294 if (is_oacc_parallel (ctx))
16295 goto oacc_firstprivate_map;
16296 ovar = OMP_CLAUSE_DECL (c);
16297 if (is_reference (ovar))
16298 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16299 else
16300 talign = DECL_ALIGN_UNIT (ovar);
16301 var = lookup_decl_in_outer_ctx (ovar, ctx);
16302 x = build_sender_ref (ovar, ctx);
16303 tkind = GOMP_MAP_FIRSTPRIVATE;
16304 type = TREE_TYPE (ovar);
16305 if (is_reference (ovar))
16306 type = TREE_TYPE (type);
16307 if ((INTEGRAL_TYPE_P (type)
16308 && TYPE_PRECISION (type) <= POINTER_SIZE)
16309 || TREE_CODE (type) == POINTER_TYPE)
16311 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16312 tree t = var;
16313 if (is_reference (var))
16314 t = build_simple_mem_ref (var);
16315 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16316 TREE_NO_WARNING (var) = 1;
16317 if (TREE_CODE (type) != POINTER_TYPE)
16318 t = fold_convert (pointer_sized_int_node, t);
16319 t = fold_convert (TREE_TYPE (x), t);
16320 gimplify_assign (x, t, &ilist);
16322 else if (is_reference (var))
16323 gimplify_assign (x, var, &ilist);
16324 else if (is_gimple_reg (var))
16326 tree avar = create_tmp_var (TREE_TYPE (var));
16327 mark_addressable (avar);
16328 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16329 TREE_NO_WARNING (var) = 1;
16330 gimplify_assign (avar, var, &ilist);
16331 avar = build_fold_addr_expr (avar);
16332 gimplify_assign (x, avar, &ilist);
16334 else
16336 var = build_fold_addr_expr (var);
16337 gimplify_assign (x, var, &ilist);
16339 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16340 s = size_int (0);
16341 else if (is_reference (var))
16342 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16343 else
16344 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16345 s = fold_convert (size_type_node, s);
16346 purpose = size_int (map_idx++);
16347 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16348 if (TREE_CODE (s) != INTEGER_CST)
16349 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16351 gcc_checking_assert (tkind
16352 < (HOST_WIDE_INT_C (1U) << talign_shift));
16353 talign = ceil_log2 (talign);
16354 tkind |= talign << talign_shift;
16355 gcc_checking_assert (tkind
16356 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16357 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16358 build_int_cstu (tkind_type, tkind));
16359 break;
16361 case OMP_CLAUSE_USE_DEVICE_PTR:
16362 case OMP_CLAUSE_IS_DEVICE_PTR:
16363 ovar = OMP_CLAUSE_DECL (c);
16364 var = lookup_decl_in_outer_ctx (ovar, ctx);
16365 x = build_sender_ref (ovar, ctx);
16366 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16367 tkind = GOMP_MAP_USE_DEVICE_PTR;
16368 else
16369 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16370 type = TREE_TYPE (ovar);
16371 if (TREE_CODE (type) == ARRAY_TYPE)
16372 var = build_fold_addr_expr (var);
16373 else
16375 if (is_reference (ovar))
16377 type = TREE_TYPE (type);
16378 if (TREE_CODE (type) != ARRAY_TYPE)
16379 var = build_simple_mem_ref (var);
16380 var = fold_convert (TREE_TYPE (x), var);
16383 gimplify_assign (x, var, &ilist);
16384 s = size_int (0);
16385 purpose = size_int (map_idx++);
16386 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16387 gcc_checking_assert (tkind
16388 < (HOST_WIDE_INT_C (1U) << talign_shift));
16389 gcc_checking_assert (tkind
16390 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16391 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16392 build_int_cstu (tkind_type, tkind));
16393 break;
16396 gcc_assert (map_idx == map_cnt);
16398 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16399 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16400 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16401 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16402 for (int i = 1; i <= 2; i++)
16403 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16405 gimple_seq initlist = NULL;
16406 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16407 TREE_VEC_ELT (t, i)),
16408 &initlist, true, NULL_TREE);
16409 gimple_seq_add_seq (&ilist, initlist);
16411 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16412 NULL);
16413 TREE_THIS_VOLATILE (clobber) = 1;
16414 gimple_seq_add_stmt (&olist,
16415 gimple_build_assign (TREE_VEC_ELT (t, i),
16416 clobber));
16419 tree clobber = build_constructor (ctx->record_type, NULL);
16420 TREE_THIS_VOLATILE (clobber) = 1;
16421 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16422 clobber));
16425 /* Once all the expansions are done, sequence all the different
16426 fragments inside gimple_omp_body. */
16428 new_body = NULL;
16430 if (offloaded
16431 && ctx->record_type)
16433 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16434 /* fixup_child_record_type might have changed receiver_decl's type. */
16435 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16436 gimple_seq_add_stmt (&new_body,
16437 gimple_build_assign (ctx->receiver_decl, t));
16439 gimple_seq_add_seq (&new_body, fplist);
16441 if (offloaded || data_region)
16443 tree prev = NULL_TREE;
16444 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16445 switch (OMP_CLAUSE_CODE (c))
16447 tree var, x;
16448 default:
16449 break;
16450 case OMP_CLAUSE_FIRSTPRIVATE:
16451 if (is_gimple_omp_oacc (ctx->stmt))
16452 break;
16453 var = OMP_CLAUSE_DECL (c);
16454 if (is_reference (var)
16455 || is_gimple_reg_type (TREE_TYPE (var)))
16457 tree new_var = lookup_decl (var, ctx);
16458 tree type;
16459 type = TREE_TYPE (var);
16460 if (is_reference (var))
16461 type = TREE_TYPE (type);
16462 if ((INTEGRAL_TYPE_P (type)
16463 && TYPE_PRECISION (type) <= POINTER_SIZE)
16464 || TREE_CODE (type) == POINTER_TYPE)
16466 x = build_receiver_ref (var, false, ctx);
16467 if (TREE_CODE (type) != POINTER_TYPE)
16468 x = fold_convert (pointer_sized_int_node, x);
16469 x = fold_convert (type, x);
16470 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16471 fb_rvalue);
16472 if (is_reference (var))
16474 tree v = create_tmp_var_raw (type, get_name (var));
16475 gimple_add_tmp_var (v);
16476 TREE_ADDRESSABLE (v) = 1;
16477 gimple_seq_add_stmt (&new_body,
16478 gimple_build_assign (v, x));
16479 x = build_fold_addr_expr (v);
16481 gimple_seq_add_stmt (&new_body,
16482 gimple_build_assign (new_var, x));
16484 else
16486 x = build_receiver_ref (var, !is_reference (var), ctx);
16487 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16488 fb_rvalue);
16489 gimple_seq_add_stmt (&new_body,
16490 gimple_build_assign (new_var, x));
16493 else if (is_variable_sized (var))
16495 tree pvar = DECL_VALUE_EXPR (var);
16496 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16497 pvar = TREE_OPERAND (pvar, 0);
16498 gcc_assert (DECL_P (pvar));
16499 tree new_var = lookup_decl (pvar, ctx);
16500 x = build_receiver_ref (var, false, ctx);
16501 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16502 gimple_seq_add_stmt (&new_body,
16503 gimple_build_assign (new_var, x));
16505 break;
16506 case OMP_CLAUSE_PRIVATE:
16507 if (is_gimple_omp_oacc (ctx->stmt))
16508 break;
16509 var = OMP_CLAUSE_DECL (c);
16510 if (is_reference (var))
16512 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16513 tree new_var = lookup_decl (var, ctx);
16514 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16515 if (TREE_CONSTANT (x))
16517 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16518 get_name (var));
16519 gimple_add_tmp_var (x);
16520 TREE_ADDRESSABLE (x) = 1;
16521 x = build_fold_addr_expr_loc (clause_loc, x);
16523 else
16524 break;
16526 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16527 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16528 gimple_seq_add_stmt (&new_body,
16529 gimple_build_assign (new_var, x));
16531 break;
16532 case OMP_CLAUSE_USE_DEVICE_PTR:
16533 case OMP_CLAUSE_IS_DEVICE_PTR:
16534 var = OMP_CLAUSE_DECL (c);
16535 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16536 x = build_sender_ref (var, ctx);
16537 else
16538 x = build_receiver_ref (var, false, ctx);
16539 if (is_variable_sized (var))
16541 tree pvar = DECL_VALUE_EXPR (var);
16542 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16543 pvar = TREE_OPERAND (pvar, 0);
16544 gcc_assert (DECL_P (pvar));
16545 tree new_var = lookup_decl (pvar, ctx);
16546 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16547 gimple_seq_add_stmt (&new_body,
16548 gimple_build_assign (new_var, x));
16550 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16552 tree new_var = lookup_decl (var, ctx);
16553 new_var = DECL_VALUE_EXPR (new_var);
16554 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16555 new_var = TREE_OPERAND (new_var, 0);
16556 gcc_assert (DECL_P (new_var));
16557 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16558 gimple_seq_add_stmt (&new_body,
16559 gimple_build_assign (new_var, x));
16561 else
16563 tree type = TREE_TYPE (var);
16564 tree new_var = lookup_decl (var, ctx);
16565 if (is_reference (var))
16567 type = TREE_TYPE (type);
16568 if (TREE_CODE (type) != ARRAY_TYPE)
16570 tree v = create_tmp_var_raw (type, get_name (var));
16571 gimple_add_tmp_var (v);
16572 TREE_ADDRESSABLE (v) = 1;
16573 x = fold_convert (type, x);
16574 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16575 fb_rvalue);
16576 gimple_seq_add_stmt (&new_body,
16577 gimple_build_assign (v, x));
16578 x = build_fold_addr_expr (v);
16581 new_var = DECL_VALUE_EXPR (new_var);
16582 x = fold_convert (TREE_TYPE (new_var), x);
16583 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16584 gimple_seq_add_stmt (&new_body,
16585 gimple_build_assign (new_var, x));
16587 break;
16589 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16590 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16591 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16592 or references to VLAs. */
16593 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16594 switch (OMP_CLAUSE_CODE (c))
16596 tree var;
16597 default:
16598 break;
16599 case OMP_CLAUSE_MAP:
16600 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16601 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16603 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16604 HOST_WIDE_INT offset = 0;
16605 gcc_assert (prev);
16606 var = OMP_CLAUSE_DECL (c);
16607 if (DECL_P (var)
16608 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16609 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16610 ctx))
16611 && varpool_node::get_create (var)->offloadable)
16612 break;
16613 if (TREE_CODE (var) == INDIRECT_REF
16614 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16615 var = TREE_OPERAND (var, 0);
16616 if (TREE_CODE (var) == COMPONENT_REF)
16618 var = get_addr_base_and_unit_offset (var, &offset);
16619 gcc_assert (var != NULL_TREE && DECL_P (var));
16621 else if (DECL_SIZE (var)
16622 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16624 tree var2 = DECL_VALUE_EXPR (var);
16625 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16626 var2 = TREE_OPERAND (var2, 0);
16627 gcc_assert (DECL_P (var2));
16628 var = var2;
16630 tree new_var = lookup_decl (var, ctx), x;
16631 tree type = TREE_TYPE (new_var);
16632 bool is_ref;
16633 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16634 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16635 == COMPONENT_REF))
16637 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16638 is_ref = true;
16639 new_var = build2 (MEM_REF, type,
16640 build_fold_addr_expr (new_var),
16641 build_int_cst (build_pointer_type (type),
16642 offset));
16644 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16646 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16647 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16648 new_var = build2 (MEM_REF, type,
16649 build_fold_addr_expr (new_var),
16650 build_int_cst (build_pointer_type (type),
16651 offset));
16653 else
16654 is_ref = is_reference (var);
16655 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16656 is_ref = false;
16657 bool ref_to_array = false;
16658 if (is_ref)
16660 type = TREE_TYPE (type);
16661 if (TREE_CODE (type) == ARRAY_TYPE)
16663 type = build_pointer_type (type);
16664 ref_to_array = true;
16667 else if (TREE_CODE (type) == ARRAY_TYPE)
16669 tree decl2 = DECL_VALUE_EXPR (new_var);
16670 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16671 decl2 = TREE_OPERAND (decl2, 0);
16672 gcc_assert (DECL_P (decl2));
16673 new_var = decl2;
16674 type = TREE_TYPE (new_var);
16676 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16677 x = fold_convert_loc (clause_loc, type, x);
16678 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16680 tree bias = OMP_CLAUSE_SIZE (c);
16681 if (DECL_P (bias))
16682 bias = lookup_decl (bias, ctx);
16683 bias = fold_convert_loc (clause_loc, sizetype, bias);
16684 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16685 bias);
16686 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16687 TREE_TYPE (x), x, bias);
16689 if (ref_to_array)
16690 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16691 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16692 if (is_ref && !ref_to_array)
16694 tree t = create_tmp_var_raw (type, get_name (var));
16695 gimple_add_tmp_var (t);
16696 TREE_ADDRESSABLE (t) = 1;
16697 gimple_seq_add_stmt (&new_body,
16698 gimple_build_assign (t, x));
16699 x = build_fold_addr_expr_loc (clause_loc, t);
16701 gimple_seq_add_stmt (&new_body,
16702 gimple_build_assign (new_var, x));
16703 prev = NULL_TREE;
16705 else if (OMP_CLAUSE_CHAIN (c)
16706 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16707 == OMP_CLAUSE_MAP
16708 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16709 == GOMP_MAP_FIRSTPRIVATE_POINTER
16710 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16711 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16712 prev = c;
16713 break;
16714 case OMP_CLAUSE_PRIVATE:
16715 var = OMP_CLAUSE_DECL (c);
16716 if (is_variable_sized (var))
16718 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16719 tree new_var = lookup_decl (var, ctx);
16720 tree pvar = DECL_VALUE_EXPR (var);
16721 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16722 pvar = TREE_OPERAND (pvar, 0);
16723 gcc_assert (DECL_P (pvar));
16724 tree new_pvar = lookup_decl (pvar, ctx);
16725 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16726 tree al = size_int (DECL_ALIGN (var));
16727 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16728 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16729 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16730 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16731 gimple_seq_add_stmt (&new_body,
16732 gimple_build_assign (new_pvar, x));
16734 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16736 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16737 tree new_var = lookup_decl (var, ctx);
16738 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16739 if (TREE_CONSTANT (x))
16740 break;
16741 else
16743 tree atmp
16744 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16745 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16746 tree al = size_int (TYPE_ALIGN (rtype));
16747 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16750 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16751 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16752 gimple_seq_add_stmt (&new_body,
16753 gimple_build_assign (new_var, x));
16755 break;
16758 gimple_seq fork_seq = NULL;
16759 gimple_seq join_seq = NULL;
16761 if (is_oacc_parallel (ctx))
16763 /* If there are reductions on the offloaded region itself, treat
16764 them as a dummy GANG loop. */
16765 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16767 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16768 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16771 gimple_seq_add_seq (&new_body, fork_seq);
16772 gimple_seq_add_seq (&new_body, tgt_body);
16773 gimple_seq_add_seq (&new_body, join_seq);
16775 if (offloaded)
16776 new_body = maybe_catch_exception (new_body);
16778 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16779 gimple_omp_set_body (stmt, new_body);
16782 bind = gimple_build_bind (NULL, NULL,
16783 tgt_bind ? gimple_bind_block (tgt_bind)
16784 : NULL_TREE);
16785 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16786 gimple_bind_add_seq (bind, ilist);
16787 gimple_bind_add_stmt (bind, stmt);
16788 gimple_bind_add_seq (bind, olist);
16790 pop_gimplify_context (NULL);
16792 if (dep_bind)
16794 gimple_bind_add_seq (dep_bind, dep_ilist);
16795 gimple_bind_add_stmt (dep_bind, bind);
16796 gimple_bind_add_seq (dep_bind, dep_olist);
16797 pop_gimplify_context (dep_bind);
16801 /* Expand code for an OpenMP teams directive. */
16803 static void
16804 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16806 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16807 push_gimplify_context ();
16809 tree block = make_node (BLOCK);
16810 gbind *bind = gimple_build_bind (NULL, NULL, block);
16811 gsi_replace (gsi_p, bind, true);
16812 gimple_seq bind_body = NULL;
16813 gimple_seq dlist = NULL;
16814 gimple_seq olist = NULL;
16816 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16817 OMP_CLAUSE_NUM_TEAMS);
16818 if (num_teams == NULL_TREE)
16819 num_teams = build_int_cst (unsigned_type_node, 0);
16820 else
16822 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16823 num_teams = fold_convert (unsigned_type_node, num_teams);
16824 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16826 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16827 OMP_CLAUSE_THREAD_LIMIT);
16828 if (thread_limit == NULL_TREE)
16829 thread_limit = build_int_cst (unsigned_type_node, 0);
16830 else
16832 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16833 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16834 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16835 fb_rvalue);
16838 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16839 &bind_body, &dlist, ctx, NULL);
16840 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16841 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16842 if (!gimple_omp_teams_grid_phony (teams_stmt))
16844 gimple_seq_add_stmt (&bind_body, teams_stmt);
16845 location_t loc = gimple_location (teams_stmt);
16846 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16847 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16848 gimple_set_location (call, loc);
16849 gimple_seq_add_stmt (&bind_body, call);
16852 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16853 gimple_omp_set_body (teams_stmt, NULL);
16854 gimple_seq_add_seq (&bind_body, olist);
16855 gimple_seq_add_seq (&bind_body, dlist);
16856 if (!gimple_omp_teams_grid_phony (teams_stmt))
16857 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16858 gimple_bind_set_body (bind, bind_body);
16860 pop_gimplify_context (bind);
16862 gimple_bind_append_vars (bind, ctx->block_vars);
16863 BLOCK_VARS (block) = ctx->block_vars;
16864 if (BLOCK_VARS (block))
16865 TREE_USED (block) = 1;
16868 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16870 static void
16871 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16873 gimple *stmt = gsi_stmt (*gsi_p);
16874 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16875 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16876 gimple_build_omp_return (false));
16880 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16881 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16882 of OMP context, but with task_shared_vars set. */
16884 static tree
16885 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16886 void *data)
16888 tree t = *tp;
16890 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16891 if (VAR_P (t) && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16892 return t;
16894 if (task_shared_vars
16895 && DECL_P (t)
16896 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16897 return t;
16899 /* If a global variable has been privatized, TREE_CONSTANT on
16900 ADDR_EXPR might be wrong. */
16901 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16902 recompute_tree_invariant_for_addr_expr (t);
16904 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16905 return NULL_TREE;
16908 /* Data to be communicated between lower_omp_regimplify_operands and
16909 lower_omp_regimplify_operands_p. */
16911 struct lower_omp_regimplify_operands_data
16913 omp_context *ctx;
16914 vec<tree> *decls;
16917 /* Helper function for lower_omp_regimplify_operands. Find
16918 omp_member_access_dummy_var vars and adjust temporarily their
16919 DECL_VALUE_EXPRs if needed. */
16921 static tree
16922 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16923 void *data)
16925 tree t = omp_member_access_dummy_var (*tp);
16926 if (t)
16928 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16929 lower_omp_regimplify_operands_data *ldata
16930 = (lower_omp_regimplify_operands_data *) wi->info;
16931 tree o = maybe_lookup_decl (t, ldata->ctx);
16932 if (o != t)
16934 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16935 ldata->decls->safe_push (*tp);
16936 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16937 SET_DECL_VALUE_EXPR (*tp, v);
16940 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16941 return NULL_TREE;
16944 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16945 of omp_member_access_dummy_var vars during regimplification. */
16947 static void
16948 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16949 gimple_stmt_iterator *gsi_p)
16951 auto_vec<tree, 10> decls;
16952 if (ctx)
16954 struct walk_stmt_info wi;
16955 memset (&wi, '\0', sizeof (wi));
16956 struct lower_omp_regimplify_operands_data data;
16957 data.ctx = ctx;
16958 data.decls = &decls;
16959 wi.info = &data;
16960 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16962 gimple_regimplify_operands (stmt, gsi_p);
16963 while (!decls.is_empty ())
16965 tree t = decls.pop ();
16966 tree v = decls.pop ();
16967 SET_DECL_VALUE_EXPR (t, v);
16971 static void
16972 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16974 gimple *stmt = gsi_stmt (*gsi_p);
16975 struct walk_stmt_info wi;
16976 gcall *call_stmt;
16978 if (gimple_has_location (stmt))
16979 input_location = gimple_location (stmt);
16981 if (task_shared_vars)
16982 memset (&wi, '\0', sizeof (wi));
16984 /* If we have issued syntax errors, avoid doing any heavy lifting.
16985 Just replace the OMP directives with a NOP to avoid
16986 confusing RTL expansion. */
16987 if (seen_error () && is_gimple_omp (stmt))
16989 gsi_replace (gsi_p, gimple_build_nop (), true);
16990 return;
16993 switch (gimple_code (stmt))
16995 case GIMPLE_COND:
16997 gcond *cond_stmt = as_a <gcond *> (stmt);
16998 if ((ctx || task_shared_vars)
16999 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
17000 lower_omp_regimplify_p,
17001 ctx ? NULL : &wi, NULL)
17002 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
17003 lower_omp_regimplify_p,
17004 ctx ? NULL : &wi, NULL)))
17005 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
17007 break;
17008 case GIMPLE_CATCH:
17009 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
17010 break;
17011 case GIMPLE_EH_FILTER:
17012 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
17013 break;
17014 case GIMPLE_TRY:
17015 lower_omp (gimple_try_eval_ptr (stmt), ctx);
17016 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
17017 break;
17018 case GIMPLE_TRANSACTION:
17019 lower_omp (gimple_transaction_body_ptr (
17020 as_a <gtransaction *> (stmt)),
17021 ctx);
17022 break;
17023 case GIMPLE_BIND:
17024 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17025 break;
17026 case GIMPLE_OMP_PARALLEL:
17027 case GIMPLE_OMP_TASK:
17028 ctx = maybe_lookup_ctx (stmt);
17029 gcc_assert (ctx);
17030 if (ctx->cancellable)
17031 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17032 lower_omp_taskreg (gsi_p, ctx);
17033 break;
17034 case GIMPLE_OMP_FOR:
17035 ctx = maybe_lookup_ctx (stmt);
17036 gcc_assert (ctx);
17037 if (ctx->cancellable)
17038 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17039 lower_omp_for (gsi_p, ctx);
17040 break;
17041 case GIMPLE_OMP_SECTIONS:
17042 ctx = maybe_lookup_ctx (stmt);
17043 gcc_assert (ctx);
17044 if (ctx->cancellable)
17045 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17046 lower_omp_sections (gsi_p, ctx);
17047 break;
17048 case GIMPLE_OMP_SINGLE:
17049 ctx = maybe_lookup_ctx (stmt);
17050 gcc_assert (ctx);
17051 lower_omp_single (gsi_p, ctx);
17052 break;
17053 case GIMPLE_OMP_MASTER:
17054 ctx = maybe_lookup_ctx (stmt);
17055 gcc_assert (ctx);
17056 lower_omp_master (gsi_p, ctx);
17057 break;
17058 case GIMPLE_OMP_TASKGROUP:
17059 ctx = maybe_lookup_ctx (stmt);
17060 gcc_assert (ctx);
17061 lower_omp_taskgroup (gsi_p, ctx);
17062 break;
17063 case GIMPLE_OMP_ORDERED:
17064 ctx = maybe_lookup_ctx (stmt);
17065 gcc_assert (ctx);
17066 lower_omp_ordered (gsi_p, ctx);
17067 break;
17068 case GIMPLE_OMP_CRITICAL:
17069 ctx = maybe_lookup_ctx (stmt);
17070 gcc_assert (ctx);
17071 lower_omp_critical (gsi_p, ctx);
17072 break;
17073 case GIMPLE_OMP_ATOMIC_LOAD:
17074 if ((ctx || task_shared_vars)
17075 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17076 as_a <gomp_atomic_load *> (stmt)),
17077 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17078 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17079 break;
17080 case GIMPLE_OMP_TARGET:
17081 ctx = maybe_lookup_ctx (stmt);
17082 gcc_assert (ctx);
17083 lower_omp_target (gsi_p, ctx);
17084 break;
17085 case GIMPLE_OMP_TEAMS:
17086 ctx = maybe_lookup_ctx (stmt);
17087 gcc_assert (ctx);
17088 lower_omp_teams (gsi_p, ctx);
17089 break;
17090 case GIMPLE_OMP_GRID_BODY:
17091 ctx = maybe_lookup_ctx (stmt);
17092 gcc_assert (ctx);
17093 lower_omp_grid_body (gsi_p, ctx);
17094 break;
17095 case GIMPLE_CALL:
17096 tree fndecl;
17097 call_stmt = as_a <gcall *> (stmt);
17098 fndecl = gimple_call_fndecl (call_stmt);
17099 if (fndecl
17100 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17101 switch (DECL_FUNCTION_CODE (fndecl))
17103 case BUILT_IN_GOMP_BARRIER:
17104 if (ctx == NULL)
17105 break;
17106 /* FALLTHRU */
17107 case BUILT_IN_GOMP_CANCEL:
17108 case BUILT_IN_GOMP_CANCELLATION_POINT:
17109 omp_context *cctx;
17110 cctx = ctx;
17111 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17112 cctx = cctx->outer;
17113 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17114 if (!cctx->cancellable)
17116 if (DECL_FUNCTION_CODE (fndecl)
17117 == BUILT_IN_GOMP_CANCELLATION_POINT)
17119 stmt = gimple_build_nop ();
17120 gsi_replace (gsi_p, stmt, false);
17122 break;
17124 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17126 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17127 gimple_call_set_fndecl (call_stmt, fndecl);
17128 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17130 tree lhs;
17131 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17132 gimple_call_set_lhs (call_stmt, lhs);
17133 tree fallthru_label;
17134 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17135 gimple *g;
17136 g = gimple_build_label (fallthru_label);
17137 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17138 g = gimple_build_cond (NE_EXPR, lhs,
17139 fold_convert (TREE_TYPE (lhs),
17140 boolean_false_node),
17141 cctx->cancel_label, fallthru_label);
17142 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17143 break;
17144 default:
17145 break;
17147 /* FALLTHRU */
17148 default:
17149 if ((ctx || task_shared_vars)
17150 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17151 ctx ? NULL : &wi))
17153 /* Just remove clobbers, this should happen only if we have
17154 "privatized" local addressable variables in SIMD regions,
17155 the clobber isn't needed in that case and gimplifying address
17156 of the ARRAY_REF into a pointer and creating MEM_REF based
17157 clobber would create worse code than we get with the clobber
17158 dropped. */
17159 if (gimple_clobber_p (stmt))
17161 gsi_replace (gsi_p, gimple_build_nop (), true);
17162 break;
17164 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17166 break;
17170 static void
17171 lower_omp (gimple_seq *body, omp_context *ctx)
17173 location_t saved_location = input_location;
17174 gimple_stmt_iterator gsi;
17175 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17176 lower_omp_1 (&gsi, ctx);
17177 /* During gimplification, we haven't folded statments inside offloading
17178 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17179 if (target_nesting_level || taskreg_nesting_level)
17180 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17181 fold_stmt (&gsi);
17182 input_location = saved_location;
17185 /* Returen true if STMT is an assignment of a register-type into a local
17186 VAR_DECL. */
17188 static bool
17189 grid_reg_assignment_to_local_var_p (gimple *stmt)
17191 gassign *assign = dyn_cast <gassign *> (stmt);
17192 if (!assign)
17193 return false;
17194 tree lhs = gimple_assign_lhs (assign);
17195 if (!VAR_P (lhs)
17196 || !is_gimple_reg_type (TREE_TYPE (lhs))
17197 || is_global_var (lhs))
17198 return false;
17199 return true;
17202 /* Return true if all statements in SEQ are assignments to local register-type
17203 variables. */
17205 static bool
17206 grid_seq_only_contains_local_assignments (gimple_seq seq)
17208 if (!seq)
17209 return true;
17211 gimple_stmt_iterator gsi;
17212 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17213 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17214 return false;
17215 return true;
17218 /* Scan statements in SEQ and call itself recursively on any bind. If during
17219 whole search only assignments to register-type local variables and one
17220 single OMP statement is encountered, return true, otherwise return false.
17221 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17222 are used for dumping a note about a failure. */
17224 static bool
17225 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17226 const char *name, gimple **ret)
17228 gimple_stmt_iterator gsi;
17229 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17231 gimple *stmt = gsi_stmt (gsi);
17233 if (grid_reg_assignment_to_local_var_p (stmt))
17234 continue;
17235 if (gbind *bind = dyn_cast <gbind *> (stmt))
17237 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17238 target_loc, name, ret))
17239 return false;
17241 else if (is_gimple_omp (stmt))
17243 if (*ret)
17245 if (dump_enabled_p ())
17246 dump_printf_loc (MSG_NOTE, target_loc,
17247 "Will not turn target construct into a simple "
17248 "GPGPU kernel because %s construct contains "
17249 "multiple OpenMP constructs\n", name);
17250 return false;
17252 *ret = stmt;
17254 else
17256 if (dump_enabled_p ())
17257 dump_printf_loc (MSG_NOTE, target_loc,
17258 "Will not turn target construct into a simple "
17259 "GPGPU kernel because %s construct contains "
17260 "a complex statement\n", name);
17261 return false;
17264 return true;
17267 /* Scan statements in SEQ and make sure that it and any binds in it contain
17268 only assignments to local register-type variables and one OMP construct. If
17269 so, return that construct, otherwise return NULL. If dumping is enabled and
17270 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17271 failure. */
17273 static gimple *
17274 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17275 const char *name)
17277 if (!seq)
17279 if (dump_enabled_p ())
17280 dump_printf_loc (MSG_NOTE, target_loc,
17281 "Will not turn target construct into a simple "
17282 "GPGPU kernel because %s construct has empty "
17283 "body\n",
17284 name);
17285 return NULL;
17288 gimple *ret = NULL;
17289 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17291 if (!ret && dump_enabled_p ())
17292 dump_printf_loc (MSG_NOTE, target_loc,
17293 "Will not turn target construct into a simple "
17294 "GPGPU kernel because %s construct does not contain"
17295 "any other OpenMP construct\n", name);
17296 return ret;
17298 else
17299 return NULL;
17302 /* Walker function looking for statements there is no point gridifying (and for
17303 noreturn function calls which we cannot do). Return non-NULL if such a
17304 function is found. */
17306 static tree
17307 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17308 bool *handled_ops_p,
17309 struct walk_stmt_info *wi)
17311 *handled_ops_p = false;
17312 gimple *stmt = gsi_stmt (*gsi);
17313 switch (gimple_code (stmt))
17315 case GIMPLE_CALL:
17316 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17318 *handled_ops_p = true;
17319 wi->info = stmt;
17320 return error_mark_node;
17322 break;
17324 /* We may reduce the following list if we find a way to implement the
17325 clauses, but now there is no point trying further. */
17326 case GIMPLE_OMP_CRITICAL:
17327 case GIMPLE_OMP_TASKGROUP:
17328 case GIMPLE_OMP_TASK:
17329 case GIMPLE_OMP_SECTION:
17330 case GIMPLE_OMP_SECTIONS:
17331 case GIMPLE_OMP_SECTIONS_SWITCH:
17332 case GIMPLE_OMP_TARGET:
17333 case GIMPLE_OMP_ORDERED:
17334 *handled_ops_p = true;
17335 wi->info = stmt;
17336 return error_mark_node;
17338 case GIMPLE_OMP_FOR:
17339 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17340 && gimple_omp_for_combined_into_p (stmt))
17342 *handled_ops_p = true;
17343 wi->info = stmt;
17344 return error_mark_node;
17346 break;
17348 default:
17349 break;
17351 return NULL;
17355 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17356 kernel, return true, otherwise return false. In the case of success, also
17357 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17358 none. */
17360 static bool
17361 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17363 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17364 return false;
17366 location_t tloc = gimple_location (target);
17367 gimple *stmt
17368 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17369 tloc, "target");
17370 if (!stmt)
17371 return false;
17372 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17373 tree group_size = NULL;
17374 if (!teams)
17376 dump_printf_loc (MSG_NOTE, tloc,
17377 "Will not turn target construct into a simple "
17378 "GPGPU kernel because it does not have a sole teams "
17379 "construct in it.\n");
17380 return false;
17383 tree clauses = gimple_omp_teams_clauses (teams);
17384 while (clauses)
17386 switch (OMP_CLAUSE_CODE (clauses))
17388 case OMP_CLAUSE_NUM_TEAMS:
17389 if (dump_enabled_p ())
17390 dump_printf_loc (MSG_NOTE, tloc,
17391 "Will not turn target construct into a "
17392 "gridified GPGPU kernel because we cannot "
17393 "handle num_teams clause of teams "
17394 "construct\n ");
17395 return false;
17397 case OMP_CLAUSE_REDUCTION:
17398 if (dump_enabled_p ())
17399 dump_printf_loc (MSG_NOTE, tloc,
17400 "Will not turn target construct into a "
17401 "gridified GPGPU kernel because a reduction "
17402 "clause is present\n ");
17403 return false;
17405 case OMP_CLAUSE_LASTPRIVATE:
17406 if (dump_enabled_p ())
17407 dump_printf_loc (MSG_NOTE, tloc,
17408 "Will not turn target construct into a "
17409 "gridified GPGPU kernel because a lastprivate "
17410 "clause is present\n ");
17411 return false;
17413 case OMP_CLAUSE_THREAD_LIMIT:
17414 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17415 break;
17417 default:
17418 break;
17420 clauses = OMP_CLAUSE_CHAIN (clauses);
17423 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17424 "teams");
17425 if (!stmt)
17426 return false;
17427 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17428 if (!dist)
17430 dump_printf_loc (MSG_NOTE, tloc,
17431 "Will not turn target construct into a simple "
17432 "GPGPU kernel because the teams construct does not have "
17433 "a sole distribute construct in it.\n");
17434 return false;
17437 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17438 if (!gimple_omp_for_combined_p (dist))
17440 if (dump_enabled_p ())
17441 dump_printf_loc (MSG_NOTE, tloc,
17442 "Will not turn target construct into a gridified GPGPU "
17443 "kernel because we cannot handle a standalone "
17444 "distribute construct\n ");
17445 return false;
17447 if (dist->collapse > 1)
17449 if (dump_enabled_p ())
17450 dump_printf_loc (MSG_NOTE, tloc,
17451 "Will not turn target construct into a gridified GPGPU "
17452 "kernel because the distribute construct contains "
17453 "collapse clause\n");
17454 return false;
17456 struct omp_for_data fd;
17457 extract_omp_for_data (dist, &fd, NULL);
17458 if (fd.chunk_size)
17460 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE, tloc,
17464 "Will not turn target construct into a "
17465 "gridified GPGPU kernel because the teams "
17466 "thread limit is different from distribute "
17467 "schedule chunk\n");
17468 return false;
17470 group_size = fd.chunk_size;
17472 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17473 "distribute");
17474 gomp_parallel *par;
17475 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17476 return false;
17478 clauses = gimple_omp_parallel_clauses (par);
17479 while (clauses)
17481 switch (OMP_CLAUSE_CODE (clauses))
17483 case OMP_CLAUSE_NUM_THREADS:
17484 if (dump_enabled_p ())
17485 dump_printf_loc (MSG_NOTE, tloc,
17486 "Will not turn target construct into a gridified"
17487 "GPGPU kernel because there is a num_threads "
17488 "clause of the parallel construct\n");
17489 return false;
17491 case OMP_CLAUSE_REDUCTION:
17492 if (dump_enabled_p ())
17493 dump_printf_loc (MSG_NOTE, tloc,
17494 "Will not turn target construct into a "
17495 "gridified GPGPU kernel because a reduction "
17496 "clause is present\n ");
17497 return false;
17499 case OMP_CLAUSE_LASTPRIVATE:
17500 if (dump_enabled_p ())
17501 dump_printf_loc (MSG_NOTE, tloc,
17502 "Will not turn target construct into a "
17503 "gridified GPGPU kernel because a lastprivate "
17504 "clause is present\n ");
17505 return false;
17507 default:
17508 break;
17510 clauses = OMP_CLAUSE_CHAIN (clauses);
17513 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17514 "parallel");
17515 gomp_for *gfor;
17516 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17517 return false;
17519 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17521 if (dump_enabled_p ())
17522 dump_printf_loc (MSG_NOTE, tloc,
17523 "Will not turn target construct into a gridified GPGPU "
17524 "kernel because the inner loop is not a simple for "
17525 "loop\n");
17526 return false;
17528 if (gfor->collapse > 1)
17530 if (dump_enabled_p ())
17531 dump_printf_loc (MSG_NOTE, tloc,
17532 "Will not turn target construct into a gridified GPGPU "
17533 "kernel because the inner loop contains collapse "
17534 "clause\n");
17535 return false;
17538 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17540 if (dump_enabled_p ())
17541 dump_printf_loc (MSG_NOTE, tloc,
17542 "Will not turn target construct into a gridified GPGPU "
17543 "kernel because the inner loop pre_body contains"
17544 "a complex instruction\n");
17545 return false;
17548 clauses = gimple_omp_for_clauses (gfor);
17549 while (clauses)
17551 switch (OMP_CLAUSE_CODE (clauses))
17553 case OMP_CLAUSE_SCHEDULE:
17554 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17556 if (dump_enabled_p ())
17557 dump_printf_loc (MSG_NOTE, tloc,
17558 "Will not turn target construct into a "
17559 "gridified GPGPU kernel because the inner "
17560 "loop has a non-automatic scheduling clause\n");
17561 return false;
17563 break;
17565 case OMP_CLAUSE_REDUCTION:
17566 if (dump_enabled_p ())
17567 dump_printf_loc (MSG_NOTE, tloc,
17568 "Will not turn target construct into a "
17569 "gridified GPGPU kernel because a reduction "
17570 "clause is present\n ");
17571 return false;
17573 case OMP_CLAUSE_LASTPRIVATE:
17574 if (dump_enabled_p ())
17575 dump_printf_loc (MSG_NOTE, tloc,
17576 "Will not turn target construct into a "
17577 "gridified GPGPU kernel because a lastprivate "
17578 "clause is present\n ");
17579 return false;
17581 default:
17582 break;
17584 clauses = OMP_CLAUSE_CHAIN (clauses);
17587 struct walk_stmt_info wi;
17588 memset (&wi, 0, sizeof (wi));
17589 if (walk_gimple_seq (gimple_omp_body (gfor),
17590 grid_find_ungridifiable_statement,
17591 NULL, &wi))
17593 gimple *bad = (gimple *) wi.info;
17594 if (dump_enabled_p ())
17596 if (is_gimple_call (bad))
17597 dump_printf_loc (MSG_NOTE, tloc,
17598 "Will not turn target construct into a gridified "
17599 " GPGPU kernel because the inner loop contains "
17600 "call to a noreturn function\n");
17601 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17602 dump_printf_loc (MSG_NOTE, tloc,
17603 "Will not turn target construct into a gridified "
17604 " GPGPU kernel because the inner loop contains "
17605 "a simd construct\n");
17606 else
17607 dump_printf_loc (MSG_NOTE, tloc,
17608 "Will not turn target construct into a gridified "
17609 "GPGPU kernel because the inner loop contains "
17610 "statement %s which cannot be transformed\n",
17611 gimple_code_name[(int) gimple_code (bad)]);
17613 return false;
17616 *group_size_p = group_size;
17617 return true;
17620 /* Operand walker, used to remap pre-body declarations according to a hash map
17621 provided in DATA. */
17623 static tree
17624 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17626 tree t = *tp;
17628 if (DECL_P (t) || TYPE_P (t))
17629 *walk_subtrees = 0;
17630 else
17631 *walk_subtrees = 1;
17633 if (VAR_P (t))
17635 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17636 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17637 tree *repl = declmap->get (t);
17638 if (repl)
17639 *tp = *repl;
17641 return NULL_TREE;
17644 /* Copy leading register-type assignments to local variables in SRC to just
17645 before DST, Creating temporaries, adjusting mapping of operands in WI and
17646 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17647 Return the first statement that does not conform to
17648 grid_reg_assignment_to_local_var_p or NULL. */
17650 static gimple *
17651 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17652 gbind *tgt_bind, struct walk_stmt_info *wi)
17654 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17655 gimple_stmt_iterator gsi;
17656 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17658 gimple *stmt = gsi_stmt (gsi);
17659 if (gbind *bind = dyn_cast <gbind *> (stmt))
17661 gimple *r = grid_copy_leading_local_assignments
17662 (gimple_bind_body (bind), dst, tgt_bind, wi);
17663 if (r)
17664 return r;
17665 else
17666 continue;
17668 if (!grid_reg_assignment_to_local_var_p (stmt))
17669 return stmt;
17670 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17671 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17672 TREE_TYPE (lhs));
17673 DECL_CONTEXT (repl) = current_function_decl;
17674 gimple_bind_append_vars (tgt_bind, repl);
17676 declmap->put (lhs, repl);
17677 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17678 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17679 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17681 return NULL;
17684 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17685 components, mark them as part of kernel and return the inner loop, and copy
17686 assignment leading to them just before DST, remapping them using WI and
17687 adding new temporaries to TGT_BIND. */
17689 static gomp_for *
17690 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17691 gbind *tgt_bind, struct walk_stmt_info *wi)
17693 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17694 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17695 gcc_assert (teams);
17696 gimple_omp_teams_set_grid_phony (teams, true);
17697 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17698 tgt_bind, wi);
17699 gcc_checking_assert (stmt);
17700 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17701 gcc_assert (dist);
17702 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17703 if (prebody)
17704 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17705 gimple_omp_for_set_grid_phony (dist, true);
17706 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17707 tgt_bind, wi);
17708 gcc_checking_assert (stmt);
17710 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17711 gimple_omp_parallel_set_grid_phony (parallel, true);
17712 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17713 tgt_bind, wi);
17714 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17715 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17716 prebody = gimple_omp_for_pre_body (inner_loop);
17717 if (prebody)
17718 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17720 return inner_loop;
17723 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17724 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17725 is the bind into which temporaries inserted before TARGET should be
17726 added. */
17728 static void
17729 grid_attempt_target_gridification (gomp_target *target,
17730 gimple_stmt_iterator *gsi,
17731 gbind *tgt_bind)
17733 tree group_size;
17734 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17735 return;
17737 location_t loc = gimple_location (target);
17738 if (dump_enabled_p ())
17739 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17740 "Target construct will be turned into a gridified GPGPU "
17741 "kernel\n");
17743 /* Copy target body to a GPUKERNEL construct: */
17744 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17745 (gimple_omp_body (target));
17747 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17748 struct walk_stmt_info wi;
17749 memset (&wi, 0, sizeof (struct walk_stmt_info));
17750 wi.info = declmap;
17752 /* Copy assignments in between OMP statements before target, mark OMP
17753 statements within copy appropriatly. */
17754 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17755 tgt_bind, &wi);
17757 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17758 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17759 tree new_block = gimple_bind_block (new_bind);
17760 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17761 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17762 BLOCK_SUBBLOCKS (enc_block) = new_block;
17763 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17764 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17765 gimple_seq_add_stmt
17766 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17767 gpukernel);
17769 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17770 push_gimplify_context ();
17771 size_t collapse = gimple_omp_for_collapse (inner_loop);
17772 for (size_t i = 0; i < collapse; i++)
17774 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17775 if (POINTER_TYPE_P (type))
17776 itype = signed_type_for (type);
17777 else
17778 itype = type;
17780 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17781 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17782 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17783 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17784 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17785 adjust_for_condition (loc, &cond_code, &n2);
17786 tree step;
17787 step = get_omp_for_step_from_incr (loc,
17788 gimple_omp_for_incr (inner_loop, i));
17789 gimple_seq tmpseq = NULL;
17790 n1 = fold_convert (itype, n1);
17791 n2 = fold_convert (itype, n2);
17792 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17793 t = fold_build2 (PLUS_EXPR, itype, step, t);
17794 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17795 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17796 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17797 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17798 fold_build1 (NEGATE_EXPR, itype, t),
17799 fold_build1 (NEGATE_EXPR, itype, step));
17800 else
17801 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17802 tree gs = fold_convert (uint32_type_node, t);
17803 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17804 if (!gimple_seq_empty_p (tmpseq))
17805 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17807 tree ws;
17808 if (i == 0 && group_size)
17810 ws = fold_convert (uint32_type_node, group_size);
17811 tmpseq = NULL;
17812 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17813 if (!gimple_seq_empty_p (tmpseq))
17814 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17816 else
17817 ws = build_zero_cst (uint32_type_node);
17819 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17820 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17821 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17822 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17823 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17824 gimple_omp_target_set_clauses (target, c);
17826 pop_gimplify_context (tgt_bind);
17827 delete declmap;
17828 return;
17831 /* Walker function doing all the work for create_target_kernels. */
17833 static tree
17834 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17835 bool *handled_ops_p,
17836 struct walk_stmt_info *incoming)
17838 *handled_ops_p = false;
17840 gimple *stmt = gsi_stmt (*gsi);
17841 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17842 if (target)
17844 gbind *tgt_bind = (gbind *) incoming->info;
17845 gcc_checking_assert (tgt_bind);
17846 grid_attempt_target_gridification (target, gsi, tgt_bind);
17847 return NULL_TREE;
17849 gbind *bind = dyn_cast <gbind *> (stmt);
17850 if (bind)
17852 *handled_ops_p = true;
17853 struct walk_stmt_info wi;
17854 memset (&wi, 0, sizeof (wi));
17855 wi.info = bind;
17856 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17857 grid_gridify_all_targets_stmt, NULL, &wi);
17859 return NULL_TREE;
17862 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17863 have their bodies duplicated, with the new copy being put into a
17864 gimple_omp_grid_body statement. All kernel-related construct within the
17865 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17866 re-structuring is often needed, such as copying pre-bodies before the target
17867 construct so that kernel grid sizes can be computed. */
17869 static void
17870 grid_gridify_all_targets (gimple_seq *body_p)
17872 struct walk_stmt_info wi;
17873 memset (&wi, 0, sizeof (wi));
17874 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17878 /* Main entry point. */
17880 static unsigned int
17881 execute_lower_omp (void)
17883 gimple_seq body;
17884 int i;
17885 omp_context *ctx;
17887 /* This pass always runs, to provide PROP_gimple_lomp.
17888 But often, there is nothing to do. */
17889 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17890 && flag_openmp_simd == 0)
17891 return 0;
17893 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17894 delete_omp_context);
17896 body = gimple_body (current_function_decl);
17898 if (hsa_gen_requested_p ())
17899 grid_gridify_all_targets (&body);
17901 scan_omp (&body, NULL);
17902 gcc_assert (taskreg_nesting_level == 0);
17903 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17904 finish_taskreg_scan (ctx);
17905 taskreg_contexts.release ();
17907 if (all_contexts->root)
17909 if (task_shared_vars)
17910 push_gimplify_context ();
17911 lower_omp (&body, NULL);
17912 if (task_shared_vars)
17913 pop_gimplify_context (NULL);
17916 if (all_contexts)
17918 splay_tree_delete (all_contexts);
17919 all_contexts = NULL;
17921 BITMAP_FREE (task_shared_vars);
17922 return 0;
17925 namespace {
17927 const pass_data pass_data_lower_omp =
17929 GIMPLE_PASS, /* type */
17930 "omplower", /* name */
17931 OPTGROUP_NONE, /* optinfo_flags */
17932 TV_NONE, /* tv_id */
17933 PROP_gimple_any, /* properties_required */
17934 PROP_gimple_lomp, /* properties_provided */
17935 0, /* properties_destroyed */
17936 0, /* todo_flags_start */
17937 0, /* todo_flags_finish */
17940 class pass_lower_omp : public gimple_opt_pass
17942 public:
17943 pass_lower_omp (gcc::context *ctxt)
17944 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17947 /* opt_pass methods: */
17948 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17950 }; // class pass_lower_omp
17952 } // anon namespace
17954 gimple_opt_pass *
17955 make_pass_lower_omp (gcc::context *ctxt)
17957 return new pass_lower_omp (ctxt);
17960 /* The following is a utility to diagnose structured block violations.
17961 It is not part of the "omplower" pass, as that's invoked too late. It
17962 should be invoked by the respective front ends after gimplification. */
17964 static splay_tree all_labels;
17966 /* Check for mismatched contexts and generate an error if needed. Return
17967 true if an error is detected. */
17969 static bool
17970 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17971 gimple *branch_ctx, gimple *label_ctx)
17973 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17974 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17976 if (label_ctx == branch_ctx)
17977 return false;
17979 const char* kind = NULL;
17981 if (flag_cilkplus)
17983 if ((branch_ctx
17984 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17985 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17986 || (label_ctx
17987 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17988 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17989 kind = "Cilk Plus";
17991 if (flag_openacc)
17993 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17994 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17996 gcc_checking_assert (kind == NULL);
17997 kind = "OpenACC";
18000 if (kind == NULL)
18002 gcc_checking_assert (flag_openmp);
18003 kind = "OpenMP";
18007 Previously we kept track of the label's entire context in diagnose_sb_[12]
18008 so we could traverse it and issue a correct "exit" or "enter" error
18009 message upon a structured block violation.
18011 We built the context by building a list with tree_cons'ing, but there is
18012 no easy counterpart in gimple tuples. It seems like far too much work
18013 for issuing exit/enter error messages. If someone really misses the
18014 distinct error message... patches welcome.
18017 #if 0
18018 /* Try to avoid confusing the user by producing and error message
18019 with correct "exit" or "enter" verbiage. We prefer "exit"
18020 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
18021 if (branch_ctx == NULL)
18022 exit_p = false;
18023 else
18025 while (label_ctx)
18027 if (TREE_VALUE (label_ctx) == branch_ctx)
18029 exit_p = false;
18030 break;
18032 label_ctx = TREE_CHAIN (label_ctx);
18036 if (exit_p)
18037 error ("invalid exit from %s structured block", kind);
18038 else
18039 error ("invalid entry to %s structured block", kind);
18040 #endif
18042 /* If it's obvious we have an invalid entry, be specific about the error. */
18043 if (branch_ctx == NULL)
18044 error ("invalid entry to %s structured block", kind);
18045 else
18047 /* Otherwise, be vague and lazy, but efficient. */
18048 error ("invalid branch to/from %s structured block", kind);
18051 gsi_replace (gsi_p, gimple_build_nop (), false);
18052 return true;
18055 /* Pass 1: Create a minimal tree of structured blocks, and record
18056 where each label is found. */
18058 static tree
18059 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18060 struct walk_stmt_info *wi)
18062 gimple *context = (gimple *) wi->info;
18063 gimple *inner_context;
18064 gimple *stmt = gsi_stmt (*gsi_p);
18066 *handled_ops_p = true;
18068 switch (gimple_code (stmt))
18070 WALK_SUBSTMTS;
18072 case GIMPLE_OMP_PARALLEL:
18073 case GIMPLE_OMP_TASK:
18074 case GIMPLE_OMP_SECTIONS:
18075 case GIMPLE_OMP_SINGLE:
18076 case GIMPLE_OMP_SECTION:
18077 case GIMPLE_OMP_MASTER:
18078 case GIMPLE_OMP_ORDERED:
18079 case GIMPLE_OMP_CRITICAL:
18080 case GIMPLE_OMP_TARGET:
18081 case GIMPLE_OMP_TEAMS:
18082 case GIMPLE_OMP_TASKGROUP:
18083 /* The minimal context here is just the current OMP construct. */
18084 inner_context = stmt;
18085 wi->info = inner_context;
18086 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18087 wi->info = context;
18088 break;
18090 case GIMPLE_OMP_FOR:
18091 inner_context = stmt;
18092 wi->info = inner_context;
18093 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18094 walk them. */
18095 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18096 diagnose_sb_1, NULL, wi);
18097 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18098 wi->info = context;
18099 break;
18101 case GIMPLE_LABEL:
18102 splay_tree_insert (all_labels,
18103 (splay_tree_key) gimple_label_label (
18104 as_a <glabel *> (stmt)),
18105 (splay_tree_value) context);
18106 break;
18108 default:
18109 break;
18112 return NULL_TREE;
18115 /* Pass 2: Check each branch and see if its context differs from that of
18116 the destination label's context. */
18118 static tree
18119 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18120 struct walk_stmt_info *wi)
18122 gimple *context = (gimple *) wi->info;
18123 splay_tree_node n;
18124 gimple *stmt = gsi_stmt (*gsi_p);
18126 *handled_ops_p = true;
18128 switch (gimple_code (stmt))
18130 WALK_SUBSTMTS;
18132 case GIMPLE_OMP_PARALLEL:
18133 case GIMPLE_OMP_TASK:
18134 case GIMPLE_OMP_SECTIONS:
18135 case GIMPLE_OMP_SINGLE:
18136 case GIMPLE_OMP_SECTION:
18137 case GIMPLE_OMP_MASTER:
18138 case GIMPLE_OMP_ORDERED:
18139 case GIMPLE_OMP_CRITICAL:
18140 case GIMPLE_OMP_TARGET:
18141 case GIMPLE_OMP_TEAMS:
18142 case GIMPLE_OMP_TASKGROUP:
18143 wi->info = stmt;
18144 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18145 wi->info = context;
18146 break;
18148 case GIMPLE_OMP_FOR:
18149 wi->info = stmt;
18150 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18151 walk them. */
18152 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18153 diagnose_sb_2, NULL, wi);
18154 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18155 wi->info = context;
18156 break;
18158 case GIMPLE_COND:
18160 gcond *cond_stmt = as_a <gcond *> (stmt);
18161 tree lab = gimple_cond_true_label (cond_stmt);
18162 if (lab)
18164 n = splay_tree_lookup (all_labels,
18165 (splay_tree_key) lab);
18166 diagnose_sb_0 (gsi_p, context,
18167 n ? (gimple *) n->value : NULL);
18169 lab = gimple_cond_false_label (cond_stmt);
18170 if (lab)
18172 n = splay_tree_lookup (all_labels,
18173 (splay_tree_key) lab);
18174 diagnose_sb_0 (gsi_p, context,
18175 n ? (gimple *) n->value : NULL);
18178 break;
18180 case GIMPLE_GOTO:
18182 tree lab = gimple_goto_dest (stmt);
18183 if (TREE_CODE (lab) != LABEL_DECL)
18184 break;
18186 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18187 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18189 break;
18191 case GIMPLE_SWITCH:
18193 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18194 unsigned int i;
18195 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18197 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18198 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18199 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18200 break;
18203 break;
18205 case GIMPLE_RETURN:
18206 diagnose_sb_0 (gsi_p, context, NULL);
18207 break;
18209 default:
18210 break;
18213 return NULL_TREE;
18216 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18217 GIMPLE_* codes. */
18218 bool
18219 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18220 int *region_idx)
18222 gimple *last = last_stmt (bb);
18223 enum gimple_code code = gimple_code (last);
18224 struct omp_region *cur_region = *region;
18225 bool fallthru = false;
18227 switch (code)
18229 case GIMPLE_OMP_PARALLEL:
18230 case GIMPLE_OMP_TASK:
18231 case GIMPLE_OMP_FOR:
18232 case GIMPLE_OMP_SINGLE:
18233 case GIMPLE_OMP_TEAMS:
18234 case GIMPLE_OMP_MASTER:
18235 case GIMPLE_OMP_TASKGROUP:
18236 case GIMPLE_OMP_CRITICAL:
18237 case GIMPLE_OMP_SECTION:
18238 case GIMPLE_OMP_GRID_BODY:
18239 cur_region = new_omp_region (bb, code, cur_region);
18240 fallthru = true;
18241 break;
18243 case GIMPLE_OMP_ORDERED:
18244 cur_region = new_omp_region (bb, code, cur_region);
18245 fallthru = true;
18246 if (find_omp_clause (gimple_omp_ordered_clauses
18247 (as_a <gomp_ordered *> (last)),
18248 OMP_CLAUSE_DEPEND))
18249 cur_region = cur_region->outer;
18250 break;
18252 case GIMPLE_OMP_TARGET:
18253 cur_region = new_omp_region (bb, code, cur_region);
18254 fallthru = true;
18255 switch (gimple_omp_target_kind (last))
18257 case GF_OMP_TARGET_KIND_REGION:
18258 case GF_OMP_TARGET_KIND_DATA:
18259 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18260 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18261 case GF_OMP_TARGET_KIND_OACC_DATA:
18262 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18263 break;
18264 case GF_OMP_TARGET_KIND_UPDATE:
18265 case GF_OMP_TARGET_KIND_ENTER_DATA:
18266 case GF_OMP_TARGET_KIND_EXIT_DATA:
18267 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18268 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18269 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18270 cur_region = cur_region->outer;
18271 break;
18272 default:
18273 gcc_unreachable ();
18275 break;
18277 case GIMPLE_OMP_SECTIONS:
18278 cur_region = new_omp_region (bb, code, cur_region);
18279 fallthru = true;
18280 break;
18282 case GIMPLE_OMP_SECTIONS_SWITCH:
18283 fallthru = false;
18284 break;
18286 case GIMPLE_OMP_ATOMIC_LOAD:
18287 case GIMPLE_OMP_ATOMIC_STORE:
18288 fallthru = true;
18289 break;
18291 case GIMPLE_OMP_RETURN:
18292 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18293 somewhere other than the next block. This will be
18294 created later. */
18295 cur_region->exit = bb;
18296 if (cur_region->type == GIMPLE_OMP_TASK)
18297 /* Add an edge corresponding to not scheduling the task
18298 immediately. */
18299 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18300 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18301 cur_region = cur_region->outer;
18302 break;
18304 case GIMPLE_OMP_CONTINUE:
18305 cur_region->cont = bb;
18306 switch (cur_region->type)
18308 case GIMPLE_OMP_FOR:
18309 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18310 succs edges as abnormal to prevent splitting
18311 them. */
18312 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18313 /* Make the loopback edge. */
18314 make_edge (bb, single_succ (cur_region->entry),
18315 EDGE_ABNORMAL);
18317 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18318 corresponds to the case that the body of the loop
18319 is not executed at all. */
18320 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18321 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18322 fallthru = false;
18323 break;
18325 case GIMPLE_OMP_SECTIONS:
18326 /* Wire up the edges into and out of the nested sections. */
18328 basic_block switch_bb = single_succ (cur_region->entry);
18330 struct omp_region *i;
18331 for (i = cur_region->inner; i ; i = i->next)
18333 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18334 make_edge (switch_bb, i->entry, 0);
18335 make_edge (i->exit, bb, EDGE_FALLTHRU);
18338 /* Make the loopback edge to the block with
18339 GIMPLE_OMP_SECTIONS_SWITCH. */
18340 make_edge (bb, switch_bb, 0);
18342 /* Make the edge from the switch to exit. */
18343 make_edge (switch_bb, bb->next_bb, 0);
18344 fallthru = false;
18346 break;
18348 case GIMPLE_OMP_TASK:
18349 fallthru = true;
18350 break;
18352 default:
18353 gcc_unreachable ();
18355 break;
18357 default:
18358 gcc_unreachable ();
18361 if (*region != cur_region)
18363 *region = cur_region;
18364 if (cur_region)
18365 *region_idx = cur_region->entry->index;
18366 else
18367 *region_idx = 0;
18370 return fallthru;
18373 static unsigned int
18374 diagnose_omp_structured_block_errors (void)
18376 struct walk_stmt_info wi;
18377 gimple_seq body = gimple_body (current_function_decl);
18379 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18381 memset (&wi, 0, sizeof (wi));
18382 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18384 memset (&wi, 0, sizeof (wi));
18385 wi.want_locations = true;
18386 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18388 gimple_set_body (current_function_decl, body);
18390 splay_tree_delete (all_labels);
18391 all_labels = NULL;
18393 return 0;
18396 namespace {
18398 const pass_data pass_data_diagnose_omp_blocks =
18400 GIMPLE_PASS, /* type */
18401 "*diagnose_omp_blocks", /* name */
18402 OPTGROUP_NONE, /* optinfo_flags */
18403 TV_NONE, /* tv_id */
18404 PROP_gimple_any, /* properties_required */
18405 0, /* properties_provided */
18406 0, /* properties_destroyed */
18407 0, /* todo_flags_start */
18408 0, /* todo_flags_finish */
18411 class pass_diagnose_omp_blocks : public gimple_opt_pass
18413 public:
18414 pass_diagnose_omp_blocks (gcc::context *ctxt)
18415 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18418 /* opt_pass methods: */
18419 virtual bool gate (function *)
18421 return flag_cilkplus || flag_openacc || flag_openmp;
18423 virtual unsigned int execute (function *)
18425 return diagnose_omp_structured_block_errors ();
18428 }; // class pass_diagnose_omp_blocks
18430 } // anon namespace
18432 gimple_opt_pass *
18433 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18435 return new pass_diagnose_omp_blocks (ctxt);
18438 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18439 adds their addresses and sizes to constructor-vector V_CTOR. */
18440 static void
18441 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18442 vec<constructor_elt, va_gc> *v_ctor)
18444 unsigned len = vec_safe_length (v_decls);
18445 for (unsigned i = 0; i < len; i++)
18447 tree it = (*v_decls)[i];
18448 bool is_var = VAR_P (it);
18449 bool is_link_var
18450 = is_var
18451 #ifdef ACCEL_COMPILER
18452 && DECL_HAS_VALUE_EXPR_P (it)
18453 #endif
18454 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18456 tree size = NULL_TREE;
18457 if (is_var)
18458 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18460 tree addr;
18461 if (!is_link_var)
18462 addr = build_fold_addr_expr (it);
18463 else
18465 #ifdef ACCEL_COMPILER
18466 /* For "omp declare target link" vars add address of the pointer to
18467 the target table, instead of address of the var. */
18468 tree value_expr = DECL_VALUE_EXPR (it);
18469 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18470 varpool_node::finalize_decl (link_ptr_decl);
18471 addr = build_fold_addr_expr (link_ptr_decl);
18472 #else
18473 addr = build_fold_addr_expr (it);
18474 #endif
18476 /* Most significant bit of the size marks "omp declare target link"
18477 vars in host and target tables. */
18478 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18479 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18480 * BITS_PER_UNIT - 1);
18481 size = wide_int_to_tree (const_ptr_type_node, isize);
18484 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18485 if (is_var)
18486 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18490 /* Create new symbols containing (address, size) pairs for global variables,
18491 marked with "omp declare target" attribute, as well as addresses for the
18492 functions, which are outlined offloading regions. */
18493 void
18494 omp_finish_file (void)
18496 unsigned num_funcs = vec_safe_length (offload_funcs);
18497 unsigned num_vars = vec_safe_length (offload_vars);
18499 if (num_funcs == 0 && num_vars == 0)
18500 return;
18502 if (targetm_common.have_named_sections)
18504 vec<constructor_elt, va_gc> *v_f, *v_v;
18505 vec_alloc (v_f, num_funcs);
18506 vec_alloc (v_v, num_vars * 2);
18508 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18509 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18511 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18512 num_vars * 2);
18513 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18514 num_funcs);
18515 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18516 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18517 tree ctor_v = build_constructor (vars_decl_type, v_v);
18518 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18519 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18520 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18521 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18522 get_identifier (".offload_func_table"),
18523 funcs_decl_type);
18524 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18525 get_identifier (".offload_var_table"),
18526 vars_decl_type);
18527 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18528 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18529 otherwise a joint table in a binary will contain padding between
18530 tables from multiple object files. */
18531 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18532 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18533 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18534 DECL_INITIAL (funcs_decl) = ctor_f;
18535 DECL_INITIAL (vars_decl) = ctor_v;
18536 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18537 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18539 varpool_node::finalize_decl (vars_decl);
18540 varpool_node::finalize_decl (funcs_decl);
18542 else
18544 for (unsigned i = 0; i < num_funcs; i++)
18546 tree it = (*offload_funcs)[i];
18547 targetm.record_offload_symbol (it);
18549 for (unsigned i = 0; i < num_vars; i++)
18551 tree it = (*offload_vars)[i];
18552 targetm.record_offload_symbol (it);
18557 /* Find the number of threads (POS = false), or thread number (POS =
18558 true) for an OpenACC region partitioned as MASK. Setup code
18559 required for the calculation is added to SEQ. */
18561 static tree
18562 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18564 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18565 unsigned ix;
18567 /* Start at gang level, and examine relevant dimension indices. */
18568 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18569 if (GOMP_DIM_MASK (ix) & mask)
18571 tree arg = build_int_cst (unsigned_type_node, ix);
18573 if (res)
18575 /* We had an outer index, so scale that by the size of
18576 this dimension. */
18577 tree n = create_tmp_var (integer_type_node);
18578 gimple *call
18579 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18581 gimple_call_set_lhs (call, n);
18582 gimple_seq_add_stmt (seq, call);
18583 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18585 if (pos)
18587 /* Determine index in this dimension. */
18588 tree id = create_tmp_var (integer_type_node);
18589 gimple *call = gimple_build_call_internal
18590 (IFN_GOACC_DIM_POS, 1, arg);
18592 gimple_call_set_lhs (call, id);
18593 gimple_seq_add_stmt (seq, call);
18594 if (res)
18595 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18596 else
18597 res = id;
18601 if (res == NULL_TREE)
18602 res = integer_zero_node;
18604 return res;
18607 /* Transform IFN_GOACC_LOOP calls to actual code. See
18608 expand_oacc_for for where these are generated. At the vector
18609 level, we stride loops, such that each member of a warp will
18610 operate on adjacent iterations. At the worker and gang level,
18611 each gang/warp executes a set of contiguous iterations. Chunking
18612 can override this such that each iteration engine executes a
18613 contiguous chunk, and then moves on to stride to the next chunk. */
18615 static void
18616 oacc_xform_loop (gcall *call)
18618 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18619 enum ifn_goacc_loop_kind code
18620 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18621 tree dir = gimple_call_arg (call, 1);
18622 tree range = gimple_call_arg (call, 2);
18623 tree step = gimple_call_arg (call, 3);
18624 tree chunk_size = NULL_TREE;
18625 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18626 tree lhs = gimple_call_lhs (call);
18627 tree type = TREE_TYPE (lhs);
18628 tree diff_type = TREE_TYPE (range);
18629 tree r = NULL_TREE;
18630 gimple_seq seq = NULL;
18631 bool chunking = false, striding = true;
18632 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18633 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18635 #ifdef ACCEL_COMPILER
18636 chunk_size = gimple_call_arg (call, 4);
18637 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18638 || integer_zerop (chunk_size)) /* Default (also static). */
18640 /* If we're at the gang level, we want each to execute a
18641 contiguous run of iterations. Otherwise we want each element
18642 to stride. */
18643 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18644 chunking = false;
18646 else
18648 /* Chunk of size 1 is striding. */
18649 striding = integer_onep (chunk_size);
18650 chunking = !striding;
18652 #endif
18654 /* striding=true, chunking=true
18655 -> invalid.
18656 striding=true, chunking=false
18657 -> chunks=1
18658 striding=false,chunking=true
18659 -> chunks=ceil (range/(chunksize*threads*step))
18660 striding=false,chunking=false
18661 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18662 push_gimplify_context (true);
18664 switch (code)
18666 default: gcc_unreachable ();
18668 case IFN_GOACC_LOOP_CHUNKS:
18669 if (!chunking)
18670 r = build_int_cst (type, 1);
18671 else
18673 /* chunk_max
18674 = (range - dir) / (chunks * step * num_threads) + dir */
18675 tree per = oacc_thread_numbers (false, mask, &seq);
18676 per = fold_convert (type, per);
18677 chunk_size = fold_convert (type, chunk_size);
18678 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18679 per = fold_build2 (MULT_EXPR, type, per, step);
18680 r = build2 (MINUS_EXPR, type, range, dir);
18681 r = build2 (PLUS_EXPR, type, r, per);
18682 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18684 break;
18686 case IFN_GOACC_LOOP_STEP:
18688 /* If striding, step by the entire compute volume, otherwise
18689 step by the inner volume. */
18690 unsigned volume = striding ? mask : inner_mask;
18692 r = oacc_thread_numbers (false, volume, &seq);
18693 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18695 break;
18697 case IFN_GOACC_LOOP_OFFSET:
18698 if (striding)
18700 r = oacc_thread_numbers (true, mask, &seq);
18701 r = fold_convert (diff_type, r);
18703 else
18705 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18706 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18707 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18708 inner_size, outer_size);
18710 volume = fold_convert (diff_type, volume);
18711 if (chunking)
18712 chunk_size = fold_convert (diff_type, chunk_size);
18713 else
18715 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18717 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18718 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18719 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18722 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18723 fold_convert (diff_type, inner_size));
18724 r = oacc_thread_numbers (true, outer_mask, &seq);
18725 r = fold_convert (diff_type, r);
18726 r = build2 (MULT_EXPR, diff_type, r, span);
18728 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18729 inner = fold_convert (diff_type, inner);
18730 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18732 if (chunking)
18734 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18735 tree per
18736 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18737 per = build2 (MULT_EXPR, diff_type, per, chunk);
18739 r = build2 (PLUS_EXPR, diff_type, r, per);
18742 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18743 if (type != diff_type)
18744 r = fold_convert (type, r);
18745 break;
18747 case IFN_GOACC_LOOP_BOUND:
18748 if (striding)
18749 r = range;
18750 else
18752 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18753 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18754 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18755 inner_size, outer_size);
18757 volume = fold_convert (diff_type, volume);
18758 if (chunking)
18759 chunk_size = fold_convert (diff_type, chunk_size);
18760 else
18762 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18764 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18765 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18766 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18769 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18770 fold_convert (diff_type, inner_size));
18772 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18774 tree offset = gimple_call_arg (call, 6);
18775 r = build2 (PLUS_EXPR, diff_type, r,
18776 fold_convert (diff_type, offset));
18777 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18778 diff_type, r, range);
18780 if (diff_type != type)
18781 r = fold_convert (type, r);
18782 break;
18785 gimplify_assign (lhs, r, &seq);
18787 pop_gimplify_context (NULL);
18789 gsi_replace_with_seq (&gsi, seq, true);
18792 /* Default partitioned and minimum partitioned dimensions. */
18794 static int oacc_default_dims[GOMP_DIM_MAX];
18795 static int oacc_min_dims[GOMP_DIM_MAX];
18797 /* Parse the default dimension parameter. This is a set of
18798 :-separated optional compute dimensions. Each specified dimension
18799 is a positive integer. When device type support is added, it is
18800 planned to be a comma separated list of such compute dimensions,
18801 with all but the first prefixed by the colon-terminated device
18802 type. */
18804 static void
18805 oacc_parse_default_dims (const char *dims)
18807 int ix;
18809 for (ix = GOMP_DIM_MAX; ix--;)
18811 oacc_default_dims[ix] = -1;
18812 oacc_min_dims[ix] = 1;
18815 #ifndef ACCEL_COMPILER
18816 /* Cannot be overridden on the host. */
18817 dims = NULL;
18818 #endif
18819 if (dims)
18821 const char *pos = dims;
18823 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18825 if (ix)
18827 if (*pos != ':')
18828 goto malformed;
18829 pos++;
18832 if (*pos != ':')
18834 long val;
18835 const char *eptr;
18837 errno = 0;
18838 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18839 if (errno || val <= 0 || (int) val != val)
18840 goto malformed;
18841 pos = eptr;
18842 oacc_default_dims[ix] = (int) val;
18845 if (*pos)
18847 malformed:
18848 error_at (UNKNOWN_LOCATION,
18849 "-fopenacc-dim operand is malformed at '%s'", pos);
18853 /* Allow the backend to validate the dimensions. */
18854 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18855 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18858 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18859 raw attribute. DIMS is an array of dimensions, which is filled in.
18860 LEVEL is the partitioning level of a routine, or -1 for an offload
18861 region itself. USED is the mask of partitioned execution in the
18862 function. */
18864 static void
18865 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18867 tree purpose[GOMP_DIM_MAX];
18868 unsigned ix;
18869 tree pos = TREE_VALUE (attrs);
18870 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18872 /* Make sure the attribute creator attached the dimension
18873 information. */
18874 gcc_assert (pos);
18876 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18878 purpose[ix] = TREE_PURPOSE (pos);
18879 tree val = TREE_VALUE (pos);
18880 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18881 pos = TREE_CHAIN (pos);
18884 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18886 /* Default anything left to 1 or a partitioned default. */
18887 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18888 if (dims[ix] < 0)
18890 /* The OpenACC spec says 'If the [num_gangs] clause is not
18891 specified, an implementation-defined default will be used;
18892 the default may depend on the code within the construct.'
18893 (2.5.6). Thus an implementation is free to choose
18894 non-unity default for a parallel region that doesn't have
18895 any gang-partitioned loops. However, it appears that there
18896 is a sufficient body of user code that expects non-gang
18897 partitioned regions to not execute in gang-redundant mode.
18898 So we (a) don't warn about the non-portability and (b) pick
18899 the minimum permissible dimension size when there is no
18900 partitioned execution. Otherwise we pick the global
18901 default for the dimension, which the user can control. The
18902 same wording and logic applies to num_workers and
18903 vector_length, however the worker- or vector- single
18904 execution doesn't have the same impact as gang-redundant
18905 execution. (If the minimum gang-level partioning is not 1,
18906 the target is probably too confusing.) */
18907 dims[ix] = (used & GOMP_DIM_MASK (ix)
18908 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18909 changed = true;
18912 if (changed)
18914 /* Replace the attribute with new values. */
18915 pos = NULL_TREE;
18916 for (ix = GOMP_DIM_MAX; ix--;)
18918 pos = tree_cons (purpose[ix],
18919 build_int_cst (integer_type_node, dims[ix]),
18920 pos);
18921 if (is_kernel)
18922 TREE_PUBLIC (pos) = 1;
18924 replace_oacc_fn_attrib (fn, pos);
18928 /* Create an empty OpenACC loop structure at LOC. */
18930 static oacc_loop *
18931 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18933 oacc_loop *loop = XCNEW (oacc_loop);
18935 loop->parent = parent;
18936 loop->child = loop->sibling = NULL;
18938 if (parent)
18940 loop->sibling = parent->child;
18941 parent->child = loop;
18944 loop->loc = loc;
18945 loop->marker = NULL;
18946 memset (loop->heads, 0, sizeof (loop->heads));
18947 memset (loop->tails, 0, sizeof (loop->tails));
18948 loop->routine = NULL_TREE;
18950 loop->mask = loop->flags = loop->inner = 0;
18951 loop->ifns = 0;
18952 loop->chunk_size = 0;
18953 loop->head_end = NULL;
18955 return loop;
18958 /* Create an outermost, dummy OpenACC loop for offloaded function
18959 DECL. */
18961 static oacc_loop *
18962 new_oacc_loop_outer (tree decl)
18964 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18967 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18968 Link into PARENT loop. Return the new loop. */
18970 static oacc_loop *
18971 new_oacc_loop (oacc_loop *parent, gcall *marker)
18973 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18975 loop->marker = marker;
18977 /* TODO: This is where device_type flattening would occur for the loop
18978 flags. */
18980 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18982 tree chunk_size = integer_zero_node;
18983 if (loop->flags & OLF_GANG_STATIC)
18984 chunk_size = gimple_call_arg (marker, 4);
18985 loop->chunk_size = chunk_size;
18987 return loop;
18990 /* Create a dummy loop encompassing a call to a openACC routine.
18991 Extract the routine's partitioning requirements. */
18993 static void
18994 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18996 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18997 int level = oacc_fn_attrib_level (attrs);
18999 gcc_assert (level >= 0);
19001 loop->marker = call;
19002 loop->routine = decl;
19003 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19004 ^ (GOMP_DIM_MASK (level) - 1));
19007 /* Finish off the current OpenACC loop ending at tail marker TAIL.
19008 Return the parent loop. */
19010 static oacc_loop *
19011 finish_oacc_loop (oacc_loop *loop)
19013 /* If the loop has been collapsed, don't partition it. */
19014 if (!loop->ifns)
19015 loop->mask = loop->flags = 0;
19016 return loop->parent;
19019 /* Free all OpenACC loop structures within LOOP (inclusive). */
19021 static void
19022 free_oacc_loop (oacc_loop *loop)
19024 if (loop->sibling)
19025 free_oacc_loop (loop->sibling);
19026 if (loop->child)
19027 free_oacc_loop (loop->child);
19029 free (loop);
19032 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19034 static void
19035 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19036 const char *title, int level)
19038 enum ifn_unique_kind kind
19039 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19041 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19042 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19044 gimple *stmt = gsi_stmt (gsi);
19046 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19048 enum ifn_unique_kind k
19049 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19050 (gimple_call_arg (stmt, 0)));
19052 if (k == kind && stmt != from)
19053 break;
19055 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19057 gsi_next (&gsi);
19058 while (gsi_end_p (gsi))
19059 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19063 /* Dump OpenACC loops LOOP, its siblings and its children. */
19065 static void
19066 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19068 int ix;
19070 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19071 loop->flags, loop->mask,
19072 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19074 if (loop->marker)
19075 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19077 if (loop->routine)
19078 fprintf (file, "%*sRoutine %s:%u:%s\n",
19079 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19080 DECL_SOURCE_LINE (loop->routine),
19081 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19083 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19084 if (loop->heads[ix])
19085 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19086 for (ix = GOMP_DIM_MAX; ix--;)
19087 if (loop->tails[ix])
19088 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19090 if (loop->child)
19091 dump_oacc_loop (file, loop->child, depth + 1);
19092 if (loop->sibling)
19093 dump_oacc_loop (file, loop->sibling, depth);
19096 void debug_oacc_loop (oacc_loop *);
19098 /* Dump loops to stderr. */
19100 DEBUG_FUNCTION void
19101 debug_oacc_loop (oacc_loop *loop)
19103 dump_oacc_loop (stderr, loop, 0);
19106 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19107 structures as we go. By construction these loops are properly
19108 nested. */
19110 static void
19111 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19113 int marker = 0;
19114 int remaining = 0;
19116 if (bb->flags & BB_VISITED)
19117 return;
19119 follow:
19120 bb->flags |= BB_VISITED;
19122 /* Scan for loop markers. */
19123 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19124 gsi_next (&gsi))
19126 gimple *stmt = gsi_stmt (gsi);
19128 if (!is_gimple_call (stmt))
19129 continue;
19131 gcall *call = as_a <gcall *> (stmt);
19133 /* If this is a routine, make a dummy loop for it. */
19134 if (tree decl = gimple_call_fndecl (call))
19135 if (tree attrs = get_oacc_fn_attrib (decl))
19137 gcc_assert (!marker);
19138 new_oacc_loop_routine (loop, call, decl, attrs);
19141 if (!gimple_call_internal_p (call))
19142 continue;
19144 switch (gimple_call_internal_fn (call))
19146 default:
19147 break;
19149 case IFN_GOACC_LOOP:
19150 /* Count the goacc loop abstraction fns, to determine if the
19151 loop was collapsed already. */
19152 loop->ifns++;
19153 break;
19155 case IFN_UNIQUE:
19156 enum ifn_unique_kind kind
19157 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19158 (gimple_call_arg (call, 0)));
19159 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19160 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19162 if (gimple_call_num_args (call) == 2)
19164 gcc_assert (marker && !remaining);
19165 marker = 0;
19166 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19167 loop = finish_oacc_loop (loop);
19168 else
19169 loop->head_end = call;
19171 else
19173 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19175 if (!marker)
19177 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19178 loop = new_oacc_loop (loop, call);
19179 remaining = count;
19181 gcc_assert (count == remaining);
19182 if (remaining)
19184 remaining--;
19185 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19186 loop->heads[marker] = call;
19187 else
19188 loop->tails[remaining] = call;
19190 marker++;
19195 if (remaining || marker)
19197 bb = single_succ (bb);
19198 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19199 goto follow;
19202 /* Walk successor blocks. */
19203 edge e;
19204 edge_iterator ei;
19206 FOR_EACH_EDGE (e, ei, bb->succs)
19207 oacc_loop_discover_walk (loop, e->dest);
19210 /* LOOP is the first sibling. Reverse the order in place and return
19211 the new first sibling. Recurse to child loops. */
19213 static oacc_loop *
19214 oacc_loop_sibling_nreverse (oacc_loop *loop)
19216 oacc_loop *last = NULL;
19219 if (loop->child)
19220 loop->child = oacc_loop_sibling_nreverse (loop->child);
19222 oacc_loop *next = loop->sibling;
19223 loop->sibling = last;
19224 last = loop;
19225 loop = next;
19227 while (loop);
19229 return last;
19232 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19233 the current function. */
19235 static oacc_loop *
19236 oacc_loop_discovery ()
19238 basic_block bb;
19240 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19241 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19243 /* The siblings were constructed in reverse order, reverse them so
19244 that diagnostics come out in an unsurprising order. */
19245 top = oacc_loop_sibling_nreverse (top);
19247 /* Reset the visited flags. */
19248 FOR_ALL_BB_FN (bb, cfun)
19249 bb->flags &= ~BB_VISITED;
19251 return top;
19254 /* Transform the abstract internal function markers starting at FROM
19255 to be for partitioning level LEVEL. Stop when we meet another HEAD
19256 or TAIL marker. */
19258 static void
19259 oacc_loop_xform_head_tail (gcall *from, int level)
19261 enum ifn_unique_kind kind
19262 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19263 tree replacement = build_int_cst (unsigned_type_node, level);
19265 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19267 gimple *stmt = gsi_stmt (gsi);
19269 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19271 enum ifn_unique_kind k
19272 = ((enum ifn_unique_kind)
19273 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19275 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19276 *gimple_call_arg_ptr (stmt, 2) = replacement;
19277 else if (k == kind && stmt != from)
19278 break;
19280 else if (gimple_call_internal_p (stmt, IFN_GOACC_REDUCTION))
19281 *gimple_call_arg_ptr (stmt, 3) = replacement;
19283 gsi_next (&gsi);
19284 while (gsi_end_p (gsi))
19285 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19289 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19290 determined partitioning mask and chunking argument. END_MARKER
19291 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19292 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19293 the replacement partitioning mask and CHUNK_ARG is the replacement
19294 chunking arg. */
19296 static void
19297 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19298 tree mask_arg, tree chunk_arg)
19300 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19302 gcc_checking_assert (ifns);
19303 for (;;)
19305 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19307 gimple *stmt = gsi_stmt (gsi);
19309 if (!is_gimple_call (stmt))
19310 continue;
19312 gcall *call = as_a <gcall *> (stmt);
19314 if (!gimple_call_internal_p (call))
19315 continue;
19317 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19318 continue;
19320 *gimple_call_arg_ptr (call, 5) = mask_arg;
19321 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19322 ifns--;
19323 if (!ifns)
19324 return;
19327 /* The LOOP_BOUND ifn could be in the single successor
19328 block. */
19329 basic_block bb = single_succ (gsi_bb (gsi));
19330 gsi = gsi_start_bb (bb);
19334 /* Process the discovered OpenACC loops, setting the correct
19335 partitioning level etc. */
19337 static void
19338 oacc_loop_process (oacc_loop *loop)
19340 if (loop->child)
19341 oacc_loop_process (loop->child);
19343 if (loop->mask && !loop->routine)
19345 int ix;
19346 unsigned mask = loop->mask;
19347 unsigned dim = GOMP_DIM_GANG;
19348 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19349 tree chunk_arg = loop->chunk_size;
19351 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19353 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19355 while (!(GOMP_DIM_MASK (dim) & mask))
19356 dim++;
19358 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19359 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19361 mask ^= GOMP_DIM_MASK (dim);
19365 if (loop->sibling)
19366 oacc_loop_process (loop->sibling);
19369 /* Walk the OpenACC loop heirarchy checking and assigning the
19370 programmer-specified partitionings. OUTER_MASK is the partitioning
19371 this loop is contained within. Return mask of partitioning
19372 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19373 bit. */
19375 static unsigned
19376 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19378 unsigned this_mask = loop->mask;
19379 unsigned mask_all = 0;
19380 bool noisy = true;
19382 #ifdef ACCEL_COMPILER
19383 /* When device_type is supported, we want the device compiler to be
19384 noisy, if the loop parameters are device_type-specific. */
19385 noisy = false;
19386 #endif
19388 if (!loop->routine)
19390 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19391 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19393 this_mask = ((loop->flags >> OLF_DIM_BASE)
19394 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19396 if ((this_mask != 0) + auto_par + seq_par > 1)
19398 if (noisy)
19399 error_at (loop->loc,
19400 seq_par
19401 ? "%<seq%> overrides other OpenACC loop specifiers"
19402 : "%<auto%> conflicts with other OpenACC loop specifiers");
19403 auto_par = false;
19404 loop->flags &= ~OLF_AUTO;
19405 if (seq_par)
19407 loop->flags &=
19408 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19409 this_mask = 0;
19412 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19413 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19416 if (this_mask & outer_mask)
19418 const oacc_loop *outer;
19419 for (outer = loop->parent; outer; outer = outer->parent)
19420 if (outer->mask & this_mask)
19421 break;
19423 if (noisy)
19425 if (outer)
19427 error_at (loop->loc,
19428 "%s uses same OpenACC parallelism as containing loop",
19429 loop->routine ? "routine call" : "inner loop");
19430 inform (outer->loc, "containing loop here");
19432 else
19433 error_at (loop->loc,
19434 "%s uses OpenACC parallelism disallowed by containing routine",
19435 loop->routine ? "routine call" : "loop");
19437 if (loop->routine)
19438 inform (DECL_SOURCE_LOCATION (loop->routine),
19439 "routine %qD declared here", loop->routine);
19441 this_mask &= ~outer_mask;
19443 else
19445 unsigned outermost = least_bit_hwi (this_mask);
19447 if (outermost && outermost <= outer_mask)
19449 if (noisy)
19451 error_at (loop->loc,
19452 "incorrectly nested OpenACC loop parallelism");
19454 const oacc_loop *outer;
19455 for (outer = loop->parent;
19456 outer->flags && outer->flags < outermost;
19457 outer = outer->parent)
19458 continue;
19459 inform (outer->loc, "containing loop here");
19462 this_mask &= ~outermost;
19466 loop->mask = this_mask;
19467 mask_all |= this_mask;
19469 if (loop->child)
19471 loop->inner = oacc_loop_fixed_partitions (loop->child,
19472 outer_mask | this_mask);
19473 mask_all |= loop->inner;
19476 if (loop->sibling)
19477 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19479 return mask_all;
19482 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19483 OUTER_MASK is the partitioning this loop is contained within.
19484 Return the cumulative partitioning used by this loop, siblings and
19485 children. */
19487 static unsigned
19488 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19490 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19491 bool noisy = true;
19493 #ifdef ACCEL_COMPILER
19494 /* When device_type is supported, we want the device compiler to be
19495 noisy, if the loop parameters are device_type-specific. */
19496 noisy = false;
19497 #endif
19499 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19501 /* Allocate the outermost loop at the outermost available
19502 level. */
19503 unsigned this_mask = outer_mask + 1;
19505 if (!(this_mask & loop->inner))
19506 loop->mask = this_mask;
19509 if (loop->child)
19511 unsigned child_mask = outer_mask | loop->mask;
19513 if (loop->mask || assign)
19514 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19516 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19519 if (assign && !loop->mask)
19521 /* Allocate the loop at the innermost available level. */
19522 unsigned this_mask = 0;
19524 /* Determine the outermost partitioning used within this loop. */
19525 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19526 this_mask = least_bit_hwi (this_mask);
19528 /* Pick the partitioning just inside that one. */
19529 this_mask >>= 1;
19531 /* And avoid picking one use by an outer loop. */
19532 this_mask &= ~outer_mask;
19534 if (!this_mask && noisy)
19535 warning_at (loop->loc, 0,
19536 "insufficient partitioning available to parallelize loop");
19538 loop->mask = this_mask;
19541 if (assign && dump_file)
19542 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19543 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19544 loop->mask);
19546 unsigned inner_mask = 0;
19548 if (loop->sibling)
19549 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19551 inner_mask |= loop->inner | loop->mask;
19553 return inner_mask;
19556 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19557 axes. Return mask of partitioning. */
19559 static unsigned
19560 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19562 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19564 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19566 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19567 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19569 return mask_all;
19572 /* Default fork/join early expander. Delete the function calls if
19573 there is no RTL expander. */
19575 bool
19576 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19577 const int *ARG_UNUSED (dims), bool is_fork)
19579 if (is_fork)
19580 return targetm.have_oacc_fork ();
19581 else
19582 return targetm.have_oacc_join ();
19585 /* Default goacc.reduction early expander.
19587 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19588 If RES_PTR is not integer-zerop:
19589 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19590 TEARDOWN - emit '*RES_PTR = VAR'
19591 If LHS is not NULL
19592 emit 'LHS = VAR' */
19594 void
19595 default_goacc_reduction (gcall *call)
19597 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19598 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19599 tree lhs = gimple_call_lhs (call);
19600 tree var = gimple_call_arg (call, 2);
19601 gimple_seq seq = NULL;
19603 if (code == IFN_GOACC_REDUCTION_SETUP
19604 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19606 /* Setup and Teardown need to copy from/to the receiver object,
19607 if there is one. */
19608 tree ref_to_res = gimple_call_arg (call, 1);
19610 if (!integer_zerop (ref_to_res))
19612 tree dst = build_simple_mem_ref (ref_to_res);
19613 tree src = var;
19615 if (code == IFN_GOACC_REDUCTION_SETUP)
19617 src = dst;
19618 dst = lhs;
19619 lhs = NULL;
19621 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19625 /* Copy VAR to LHS, if there is an LHS. */
19626 if (lhs)
19627 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19629 gsi_replace_with_seq (&gsi, seq, true);
19632 /* Main entry point for oacc transformations which run on the device
19633 compiler after LTO, so we know what the target device is at this
19634 point (including the host fallback). */
19636 static unsigned int
19637 execute_oacc_device_lower ()
19639 tree attrs = get_oacc_fn_attrib (current_function_decl);
19641 if (!attrs)
19642 /* Not an offloaded function. */
19643 return 0;
19645 /* Parse the default dim argument exactly once. */
19646 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19648 oacc_parse_default_dims (flag_openacc_dims);
19649 flag_openacc_dims = (char *)&flag_openacc_dims;
19652 /* Discover, partition and process the loops. */
19653 oacc_loop *loops = oacc_loop_discovery ();
19654 int fn_level = oacc_fn_attrib_level (attrs);
19656 if (dump_file)
19657 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19658 ? "Function is kernels offload\n"
19659 : fn_level < 0 ? "Function is parallel offload\n"
19660 : "Function is routine level %d\n", fn_level);
19662 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19663 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19664 int dims[GOMP_DIM_MAX];
19666 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19668 if (dump_file)
19670 const char *comma = "Compute dimensions [";
19671 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19672 fprintf (dump_file, "%s%d", comma, dims[ix]);
19673 fprintf (dump_file, "]\n");
19676 oacc_loop_process (loops);
19677 if (dump_file)
19679 fprintf (dump_file, "OpenACC loops\n");
19680 dump_oacc_loop (dump_file, loops, 0);
19681 fprintf (dump_file, "\n");
19684 /* Offloaded targets may introduce new basic blocks, which require
19685 dominance information to update SSA. */
19686 calculate_dominance_info (CDI_DOMINATORS);
19688 /* Now lower internal loop functions to target-specific code
19689 sequences. */
19690 basic_block bb;
19691 FOR_ALL_BB_FN (bb, cfun)
19692 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19694 gimple *stmt = gsi_stmt (gsi);
19695 if (!is_gimple_call (stmt))
19697 gsi_next (&gsi);
19698 continue;
19701 gcall *call = as_a <gcall *> (stmt);
19702 if (!gimple_call_internal_p (call))
19704 gsi_next (&gsi);
19705 continue;
19708 /* Rewind to allow rescan. */
19709 gsi_prev (&gsi);
19710 bool rescan = false, remove = false;
19711 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19713 switch (ifn_code)
19715 default: break;
19717 case IFN_GOACC_LOOP:
19718 oacc_xform_loop (call);
19719 rescan = true;
19720 break;
19722 case IFN_GOACC_REDUCTION:
19723 /* Mark the function for SSA renaming. */
19724 mark_virtual_operands_for_renaming (cfun);
19726 /* If the level is -1, this ended up being an unused
19727 axis. Handle as a default. */
19728 if (integer_minus_onep (gimple_call_arg (call, 3)))
19729 default_goacc_reduction (call);
19730 else
19731 targetm.goacc.reduction (call);
19732 rescan = true;
19733 break;
19735 case IFN_UNIQUE:
19737 enum ifn_unique_kind kind
19738 = ((enum ifn_unique_kind)
19739 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19741 switch (kind)
19743 default:
19744 gcc_unreachable ();
19746 case IFN_UNIQUE_OACC_FORK:
19747 case IFN_UNIQUE_OACC_JOIN:
19748 if (integer_minus_onep (gimple_call_arg (call, 2)))
19749 remove = true;
19750 else if (!targetm.goacc.fork_join
19751 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19752 remove = true;
19753 break;
19755 case IFN_UNIQUE_OACC_HEAD_MARK:
19756 case IFN_UNIQUE_OACC_TAIL_MARK:
19757 remove = true;
19758 break;
19760 break;
19764 if (gsi_end_p (gsi))
19765 /* We rewound past the beginning of the BB. */
19766 gsi = gsi_start_bb (bb);
19767 else
19768 /* Undo the rewind. */
19769 gsi_next (&gsi);
19771 if (remove)
19773 if (gimple_vdef (call))
19774 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19775 if (gimple_call_lhs (call))
19777 /* Propagate the data dependency var. */
19778 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19779 gimple_call_arg (call, 1));
19780 gsi_replace (&gsi, ass, false);
19782 else
19783 gsi_remove (&gsi, true);
19785 else if (!rescan)
19786 /* If not rescanning, advance over the call. */
19787 gsi_next (&gsi);
19790 free_oacc_loop (loops);
19792 return 0;
19795 /* Default launch dimension validator. Force everything to 1. A
19796 backend that wants to provide larger dimensions must override this
19797 hook. */
19799 bool
19800 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19801 int ARG_UNUSED (fn_level))
19803 bool changed = false;
19805 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19807 if (dims[ix] != 1)
19809 dims[ix] = 1;
19810 changed = true;
19814 return changed;
19817 /* Default dimension bound is unknown on accelerator and 1 on host. */
19820 default_goacc_dim_limit (int ARG_UNUSED (axis))
19822 #ifdef ACCEL_COMPILER
19823 return 0;
19824 #else
19825 return 1;
19826 #endif
19829 namespace {
19831 const pass_data pass_data_oacc_device_lower =
19833 GIMPLE_PASS, /* type */
19834 "oaccdevlow", /* name */
19835 OPTGROUP_NONE, /* optinfo_flags */
19836 TV_NONE, /* tv_id */
19837 PROP_cfg, /* properties_required */
19838 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19839 0, /* properties_destroyed */
19840 0, /* todo_flags_start */
19841 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19844 class pass_oacc_device_lower : public gimple_opt_pass
19846 public:
19847 pass_oacc_device_lower (gcc::context *ctxt)
19848 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19851 /* opt_pass methods: */
19852 virtual unsigned int execute (function *)
19854 bool gate = flag_openacc != 0;
19856 if (!gate)
19857 return 0;
19859 return execute_oacc_device_lower ();
19862 }; // class pass_oacc_device_lower
19864 } // anon namespace
19866 gimple_opt_pass *
19867 make_pass_oacc_device_lower (gcc::context *ctxt)
19869 return new pass_oacc_device_lower (ctxt);
19872 /* "omp declare target link" handling pass. */
19874 namespace {
19876 const pass_data pass_data_omp_target_link =
19878 GIMPLE_PASS, /* type */
19879 "omptargetlink", /* name */
19880 OPTGROUP_NONE, /* optinfo_flags */
19881 TV_NONE, /* tv_id */
19882 PROP_ssa, /* properties_required */
19883 0, /* properties_provided */
19884 0, /* properties_destroyed */
19885 0, /* todo_flags_start */
19886 TODO_update_ssa, /* todo_flags_finish */
19889 class pass_omp_target_link : public gimple_opt_pass
19891 public:
19892 pass_omp_target_link (gcc::context *ctxt)
19893 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19896 /* opt_pass methods: */
19897 virtual bool gate (function *fun)
19899 #ifdef ACCEL_COMPILER
19900 tree attrs = DECL_ATTRIBUTES (fun->decl);
19901 return lookup_attribute ("omp declare target", attrs)
19902 || lookup_attribute ("omp target entrypoint", attrs);
19903 #else
19904 (void) fun;
19905 return false;
19906 #endif
19909 virtual unsigned execute (function *);
19912 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19914 static tree
19915 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19917 tree t = *tp;
19919 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t)
19920 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19922 *walk_subtrees = 0;
19923 return t;
19926 return NULL_TREE;
19929 unsigned
19930 pass_omp_target_link::execute (function *fun)
19932 basic_block bb;
19933 FOR_EACH_BB_FN (bb, fun)
19935 gimple_stmt_iterator gsi;
19936 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19937 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19938 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19941 return 0;
19944 } // anon namespace
19946 gimple_opt_pass *
19947 make_pass_omp_target_link (gcc::context *ctxt)
19949 return new pass_omp_target_link (ctxt);
19952 #include "gt-omp-low.h"