* es.po: Update.
[official-gcc.git] / gcc / omp-low.c
blobe5b9e4c10916f60730550f9c0f7c85147c5a17cf
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 "memmodel.h"
29 #include "backend.h"
30 #include "target.h"
31 #include "rtl.h"
32 #include "tree.h"
33 #include "gimple.h"
34 #include "cfghooks.h"
35 #include "alloc-pool.h"
36 #include "tree-pass.h"
37 #include "ssa.h"
38 #include "expmed.h"
39 #include "optabs.h"
40 #include "emit-rtl.h"
41 #include "cgraph.h"
42 #include "pretty-print.h"
43 #include "diagnostic-core.h"
44 #include "alias.h"
45 #include "fold-const.h"
46 #include "stor-layout.h"
47 #include "cfganal.h"
48 #include "internal-fn.h"
49 #include "gimple-fold.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "tree-cfg.h"
58 #include "tree-into-ssa.h"
59 #include "flags.h"
60 #include "dojump.h"
61 #include "explow.h"
62 #include "calls.h"
63 #include "varasm.h"
64 #include "stmt.h"
65 #include "expr.h"
66 #include "tree-dfa.h"
67 #include "tree-ssa.h"
68 #include "except.h"
69 #include "splay-tree.h"
70 #include "cfgloop.h"
71 #include "common/common-target.h"
72 #include "omp-low.h"
73 #include "gimple-low.h"
74 #include "tree-cfgcleanup.h"
75 #include "symbol-summary.h"
76 #include "ipa-prop.h"
77 #include "tree-nested.h"
78 #include "tree-eh.h"
79 #include "cilk.h"
80 #include "context.h"
81 #include "lto-section-names.h"
82 #include "gomp-constants.h"
83 #include "gimple-pretty-print.h"
84 #include "symbol-summary.h"
85 #include "hsa.h"
86 #include "params.h"
88 /* Lowering of OMP parallel and workshare constructs proceeds in two
89 phases. The first phase scans the function looking for OMP statements
90 and then for variables that must be replaced to satisfy data sharing
91 clauses. The second phase expands code for the constructs, as well as
92 re-gimplifying things when variables have been replaced with complex
93 expressions.
95 Final code generation is done by pass_expand_omp. The flowgraph is
96 scanned for regions which are then moved to a new
97 function, to be invoked by the thread library, or offloaded. */
99 /* OMP region information. Every parallel and workshare
100 directive is enclosed between two markers, the OMP_* directive
101 and a corresponding GIMPLE_OMP_RETURN statement. */
103 struct omp_region
105 /* The enclosing region. */
106 struct omp_region *outer;
108 /* First child region. */
109 struct omp_region *inner;
111 /* Next peer region. */
112 struct omp_region *next;
114 /* Block containing the omp directive as its last stmt. */
115 basic_block entry;
117 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
118 basic_block exit;
120 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
121 basic_block cont;
123 /* If this is a combined parallel+workshare region, this is a list
124 of additional arguments needed by the combined parallel+workshare
125 library call. */
126 vec<tree, va_gc> *ws_args;
128 /* The code for the omp directive of this region. */
129 enum gimple_code type;
131 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
132 enum omp_clause_schedule_kind sched_kind;
134 /* Schedule modifiers. */
135 unsigned char sched_modifiers;
137 /* True if this is a combined parallel+workshare region. */
138 bool is_combined_parallel;
140 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
141 a depend clause. */
142 gomp_ordered *ord_stmt;
145 /* Context structure. Used to store information about each parallel
146 directive in the code. */
148 struct omp_context
150 /* This field must be at the beginning, as we do "inheritance": Some
151 callback functions for tree-inline.c (e.g., omp_copy_decl)
152 receive a copy_body_data pointer that is up-casted to an
153 omp_context pointer. */
154 copy_body_data cb;
156 /* The tree of contexts corresponding to the encountered constructs. */
157 struct omp_context *outer;
158 gimple *stmt;
160 /* Map variables to fields in a structure that allows communication
161 between sending and receiving threads. */
162 splay_tree field_map;
163 tree record_type;
164 tree sender_decl;
165 tree receiver_decl;
167 /* These are used just by task contexts, if task firstprivate fn is
168 needed. srecord_type is used to communicate from the thread
169 that encountered the task construct to task firstprivate fn,
170 record_type is allocated by GOMP_task, initialized by task firstprivate
171 fn and passed to the task body fn. */
172 splay_tree sfield_map;
173 tree srecord_type;
175 /* A chain of variables to add to the top-level block surrounding the
176 construct. In the case of a parallel, this is in the child function. */
177 tree block_vars;
179 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
180 barriers should jump to during omplower pass. */
181 tree cancel_label;
183 /* What to do with variables with implicitly determined sharing
184 attributes. */
185 enum omp_clause_default_kind default_kind;
187 /* Nesting depth of this context. Used to beautify error messages re
188 invalid gotos. The outermost ctx is depth 1, with depth 0 being
189 reserved for the main body of the function. */
190 int depth;
192 /* True if this parallel directive is nested within another. */
193 bool is_nested;
195 /* True if this construct can be cancelled. */
196 bool cancellable;
199 /* A structure holding the elements of:
200 for (V = N1; V cond N2; V += STEP) [...] */
202 struct omp_for_data_loop
204 tree v, n1, n2, step;
205 enum tree_code cond_code;
208 /* A structure describing the main elements of a parallel loop. */
210 struct omp_for_data
212 struct omp_for_data_loop loop;
213 tree chunk_size;
214 gomp_for *for_stmt;
215 tree pre, iter_type;
216 int collapse;
217 int ordered;
218 bool have_nowait, have_ordered, simd_schedule;
219 unsigned char sched_modifiers;
220 enum omp_clause_schedule_kind sched_kind;
221 struct omp_for_data_loop *loops;
224 /* Describe the OpenACC looping structure of a function. The entire
225 function is held in a 'NULL' loop. */
227 struct oacc_loop
229 oacc_loop *parent; /* Containing loop. */
231 oacc_loop *child; /* First inner loop. */
233 oacc_loop *sibling; /* Next loop within same parent. */
235 location_t loc; /* Location of the loop start. */
237 gcall *marker; /* Initial head marker. */
239 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
240 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
242 tree routine; /* Pseudo-loop enclosing a routine. */
244 unsigned mask; /* Partitioning mask. */
245 unsigned inner; /* Partitioning of inner loops. */
246 unsigned flags; /* Partitioning flags. */
247 unsigned ifns; /* Contained loop abstraction functions. */
248 tree chunk_size; /* Chunk size. */
249 gcall *head_end; /* Final marker of head sequence. */
252 /* Flags for an OpenACC loop. */
254 enum oacc_loop_flags {
255 OLF_SEQ = 1u << 0, /* Explicitly sequential */
256 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
257 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
258 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
260 /* Explicitly specified loop axes. */
261 OLF_DIM_BASE = 4,
262 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
263 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
264 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
266 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
270 static splay_tree all_contexts;
271 static int taskreg_nesting_level;
272 static int target_nesting_level;
273 static struct omp_region *root_omp_region;
274 static bitmap task_shared_vars;
275 static vec<omp_context *> taskreg_contexts;
276 static bool omp_any_child_fn_dumped;
278 static void scan_omp (gimple_seq *, omp_context *);
279 static tree scan_omp_1_op (tree *, int *, void *);
280 static gphi *find_phi_with_arg_on_edge (tree, edge);
282 #define WALK_SUBSTMTS \
283 case GIMPLE_BIND: \
284 case GIMPLE_TRY: \
285 case GIMPLE_CATCH: \
286 case GIMPLE_EH_FILTER: \
287 case GIMPLE_TRANSACTION: \
288 /* The sub-statements for these should be walked. */ \
289 *handled_ops_p = false; \
290 break;
292 /* Return true if CTX corresponds to an oacc parallel region. */
294 static bool
295 is_oacc_parallel (omp_context *ctx)
297 enum gimple_code outer_type = gimple_code (ctx->stmt);
298 return ((outer_type == GIMPLE_OMP_TARGET)
299 && (gimple_omp_target_kind (ctx->stmt)
300 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
303 /* Return true if CTX corresponds to an oacc kernels region. */
305 static bool
306 is_oacc_kernels (omp_context *ctx)
308 enum gimple_code outer_type = gimple_code (ctx->stmt);
309 return ((outer_type == GIMPLE_OMP_TARGET)
310 && (gimple_omp_target_kind (ctx->stmt)
311 == GF_OMP_TARGET_KIND_OACC_KERNELS));
314 /* If DECL is the artificial dummy VAR_DECL created for non-static
315 data member privatization, return the underlying "this" parameter,
316 otherwise return NULL. */
318 tree
319 omp_member_access_dummy_var (tree decl)
321 if (!VAR_P (decl)
322 || !DECL_ARTIFICIAL (decl)
323 || !DECL_IGNORED_P (decl)
324 || !DECL_HAS_VALUE_EXPR_P (decl)
325 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
326 return NULL_TREE;
328 tree v = DECL_VALUE_EXPR (decl);
329 if (TREE_CODE (v) != COMPONENT_REF)
330 return NULL_TREE;
332 while (1)
333 switch (TREE_CODE (v))
335 case COMPONENT_REF:
336 case MEM_REF:
337 case INDIRECT_REF:
338 CASE_CONVERT:
339 case POINTER_PLUS_EXPR:
340 v = TREE_OPERAND (v, 0);
341 continue;
342 case PARM_DECL:
343 if (DECL_CONTEXT (v) == current_function_decl
344 && DECL_ARTIFICIAL (v)
345 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
346 return v;
347 return NULL_TREE;
348 default:
349 return NULL_TREE;
353 /* Helper for unshare_and_remap, called through walk_tree. */
355 static tree
356 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
358 tree *pair = (tree *) data;
359 if (*tp == pair[0])
361 *tp = unshare_expr (pair[1]);
362 *walk_subtrees = 0;
364 else if (IS_TYPE_OR_DECL_P (*tp))
365 *walk_subtrees = 0;
366 return NULL_TREE;
369 /* Return unshare_expr (X) with all occurrences of FROM
370 replaced with TO. */
372 static tree
373 unshare_and_remap (tree x, tree from, tree to)
375 tree pair[2] = { from, to };
376 x = unshare_expr (x);
377 walk_tree (&x, unshare_and_remap_1, pair, NULL);
378 return x;
381 /* Holds offload tables with decls. */
382 vec<tree, va_gc> *offload_funcs, *offload_vars;
384 /* Convenience function for calling scan_omp_1_op on tree operands. */
386 static inline tree
387 scan_omp_op (tree *tp, omp_context *ctx)
389 struct walk_stmt_info wi;
391 memset (&wi, 0, sizeof (wi));
392 wi.info = ctx;
393 wi.want_locations = true;
395 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
398 static void lower_omp (gimple_seq *, omp_context *);
399 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
400 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
402 /* Find an OMP clause of type KIND within CLAUSES. */
404 tree
405 find_omp_clause (tree clauses, enum omp_clause_code kind)
407 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
408 if (OMP_CLAUSE_CODE (clauses) == kind)
409 return clauses;
411 return NULL_TREE;
414 /* Return true if CTX is for an omp parallel. */
416 static inline bool
417 is_parallel_ctx (omp_context *ctx)
419 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
423 /* Return true if CTX is for an omp task. */
425 static inline bool
426 is_task_ctx (omp_context *ctx)
428 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
432 /* Return true if CTX is for an omp taskloop. */
434 static inline bool
435 is_taskloop_ctx (omp_context *ctx)
437 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
438 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
442 /* Return true if CTX is for an omp parallel or omp task. */
444 static inline bool
445 is_taskreg_ctx (omp_context *ctx)
447 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
451 /* Return true if REGION is a combined parallel+workshare region. */
453 static inline bool
454 is_combined_parallel (struct omp_region *region)
456 return region->is_combined_parallel;
459 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
460 GT_EXPR. */
462 static void
463 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
465 switch (*cond_code)
467 case LT_EXPR:
468 case GT_EXPR:
469 case NE_EXPR:
470 break;
471 case LE_EXPR:
472 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
473 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
474 else
475 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
476 build_int_cst (TREE_TYPE (*n2), 1));
477 *cond_code = LT_EXPR;
478 break;
479 case GE_EXPR:
480 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
481 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
482 else
483 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
484 build_int_cst (TREE_TYPE (*n2), 1));
485 *cond_code = GT_EXPR;
486 break;
487 default:
488 gcc_unreachable ();
492 /* Return the looping step from INCR, extracted from the step of a gimple omp
493 for statement. */
495 static tree
496 get_omp_for_step_from_incr (location_t loc, tree incr)
498 tree step;
499 switch (TREE_CODE (incr))
501 case PLUS_EXPR:
502 step = TREE_OPERAND (incr, 1);
503 break;
504 case POINTER_PLUS_EXPR:
505 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
506 break;
507 case MINUS_EXPR:
508 step = TREE_OPERAND (incr, 1);
509 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
510 break;
511 default:
512 gcc_unreachable ();
514 return step;
517 /* Extract the header elements of parallel loop FOR_STMT and store
518 them into *FD. */
520 static void
521 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
522 struct omp_for_data_loop *loops)
524 tree t, var, *collapse_iter, *collapse_count;
525 tree count = NULL_TREE, iter_type = long_integer_type_node;
526 struct omp_for_data_loop *loop;
527 int i;
528 struct omp_for_data_loop dummy_loop;
529 location_t loc = gimple_location (for_stmt);
530 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
531 bool distribute = gimple_omp_for_kind (for_stmt)
532 == GF_OMP_FOR_KIND_DISTRIBUTE;
533 bool taskloop = gimple_omp_for_kind (for_stmt)
534 == GF_OMP_FOR_KIND_TASKLOOP;
535 tree iterv, countv;
537 fd->for_stmt = for_stmt;
538 fd->pre = NULL;
539 if (gimple_omp_for_collapse (for_stmt) > 1)
540 fd->loops = loops;
541 else
542 fd->loops = &fd->loop;
544 fd->have_nowait = distribute || simd;
545 fd->have_ordered = false;
546 fd->collapse = 1;
547 fd->ordered = 0;
548 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
549 fd->sched_modifiers = 0;
550 fd->chunk_size = NULL_TREE;
551 fd->simd_schedule = false;
552 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
553 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
554 collapse_iter = NULL;
555 collapse_count = NULL;
557 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
558 switch (OMP_CLAUSE_CODE (t))
560 case OMP_CLAUSE_NOWAIT:
561 fd->have_nowait = true;
562 break;
563 case OMP_CLAUSE_ORDERED:
564 fd->have_ordered = true;
565 if (OMP_CLAUSE_ORDERED_EXPR (t))
566 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
567 break;
568 case OMP_CLAUSE_SCHEDULE:
569 gcc_assert (!distribute && !taskloop);
570 fd->sched_kind
571 = (enum omp_clause_schedule_kind)
572 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
573 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
574 & ~OMP_CLAUSE_SCHEDULE_MASK);
575 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
576 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
577 break;
578 case OMP_CLAUSE_DIST_SCHEDULE:
579 gcc_assert (distribute);
580 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
581 break;
582 case OMP_CLAUSE_COLLAPSE:
583 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
584 if (fd->collapse > 1)
586 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
587 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
589 break;
590 default:
591 break;
593 if (fd->ordered && fd->collapse == 1 && loops != NULL)
595 fd->loops = loops;
596 iterv = NULL_TREE;
597 countv = NULL_TREE;
598 collapse_iter = &iterv;
599 collapse_count = &countv;
602 /* FIXME: for now map schedule(auto) to schedule(static).
603 There should be analysis to determine whether all iterations
604 are approximately the same amount of work (then schedule(static)
605 is best) or if it varies (then schedule(dynamic,N) is better). */
606 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
608 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
609 gcc_assert (fd->chunk_size == NULL);
611 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
612 if (taskloop)
613 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
614 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
615 gcc_assert (fd->chunk_size == NULL);
616 else if (fd->chunk_size == NULL)
618 /* We only need to compute a default chunk size for ordered
619 static loops and dynamic loops. */
620 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
621 || fd->have_ordered)
622 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
623 ? integer_zero_node : integer_one_node;
626 int cnt = fd->ordered ? fd->ordered : fd->collapse;
627 for (i = 0; i < cnt; i++)
629 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
630 loop = &fd->loop;
631 else if (loops != NULL)
632 loop = loops + i;
633 else
634 loop = &dummy_loop;
636 loop->v = gimple_omp_for_index (for_stmt, i);
637 gcc_assert (SSA_VAR_P (loop->v));
638 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
639 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
640 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
641 loop->n1 = gimple_omp_for_initial (for_stmt, i);
643 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
644 loop->n2 = gimple_omp_for_final (for_stmt, i);
645 gcc_assert (loop->cond_code != NE_EXPR
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
647 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
648 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
650 t = gimple_omp_for_incr (for_stmt, i);
651 gcc_assert (TREE_OPERAND (t, 0) == var);
652 loop->step = get_omp_for_step_from_incr (loc, t);
654 if (simd
655 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
656 && !fd->have_ordered))
658 if (fd->collapse == 1)
659 iter_type = TREE_TYPE (loop->v);
660 else if (i == 0
661 || TYPE_PRECISION (iter_type)
662 < TYPE_PRECISION (TREE_TYPE (loop->v)))
663 iter_type
664 = build_nonstandard_integer_type
665 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
667 else if (iter_type != long_long_unsigned_type_node)
669 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
670 iter_type = long_long_unsigned_type_node;
671 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
672 && TYPE_PRECISION (TREE_TYPE (loop->v))
673 >= TYPE_PRECISION (iter_type))
675 tree n;
677 if (loop->cond_code == LT_EXPR)
678 n = fold_build2_loc (loc,
679 PLUS_EXPR, TREE_TYPE (loop->v),
680 loop->n2, loop->step);
681 else
682 n = loop->n1;
683 if (TREE_CODE (n) != INTEGER_CST
684 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
685 iter_type = long_long_unsigned_type_node;
687 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
688 > TYPE_PRECISION (iter_type))
690 tree n1, n2;
692 if (loop->cond_code == LT_EXPR)
694 n1 = loop->n1;
695 n2 = fold_build2_loc (loc,
696 PLUS_EXPR, TREE_TYPE (loop->v),
697 loop->n2, loop->step);
699 else
701 n1 = fold_build2_loc (loc,
702 MINUS_EXPR, TREE_TYPE (loop->v),
703 loop->n2, loop->step);
704 n2 = loop->n1;
706 if (TREE_CODE (n1) != INTEGER_CST
707 || TREE_CODE (n2) != INTEGER_CST
708 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
709 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
710 iter_type = long_long_unsigned_type_node;
714 if (i >= fd->collapse)
715 continue;
717 if (collapse_count && *collapse_count == NULL)
719 t = fold_binary (loop->cond_code, boolean_type_node,
720 fold_convert (TREE_TYPE (loop->v), loop->n1),
721 fold_convert (TREE_TYPE (loop->v), loop->n2));
722 if (t && integer_zerop (t))
723 count = build_zero_cst (long_long_unsigned_type_node);
724 else if ((i == 0 || count != NULL_TREE)
725 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
726 && TREE_CONSTANT (loop->n1)
727 && TREE_CONSTANT (loop->n2)
728 && TREE_CODE (loop->step) == INTEGER_CST)
730 tree itype = TREE_TYPE (loop->v);
732 if (POINTER_TYPE_P (itype))
733 itype = signed_type_for (itype);
734 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
735 t = fold_build2_loc (loc,
736 PLUS_EXPR, itype,
737 fold_convert_loc (loc, itype, loop->step), t);
738 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
739 fold_convert_loc (loc, itype, loop->n2));
740 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
741 fold_convert_loc (loc, itype, loop->n1));
742 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
743 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
744 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
745 fold_build1_loc (loc, NEGATE_EXPR, itype,
746 fold_convert_loc (loc, itype,
747 loop->step)));
748 else
749 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
750 fold_convert_loc (loc, itype, loop->step));
751 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
752 if (count != NULL_TREE)
753 count = fold_build2_loc (loc,
754 MULT_EXPR, long_long_unsigned_type_node,
755 count, t);
756 else
757 count = t;
758 if (TREE_CODE (count) != INTEGER_CST)
759 count = NULL_TREE;
761 else if (count && !integer_zerop (count))
762 count = NULL_TREE;
766 if (count
767 && !simd
768 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
769 || fd->have_ordered))
771 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
772 iter_type = long_long_unsigned_type_node;
773 else
774 iter_type = long_integer_type_node;
776 else if (collapse_iter && *collapse_iter != NULL)
777 iter_type = TREE_TYPE (*collapse_iter);
778 fd->iter_type = iter_type;
779 if (collapse_iter && *collapse_iter == NULL)
780 *collapse_iter = create_tmp_var (iter_type, ".iter");
781 if (collapse_count && *collapse_count == NULL)
783 if (count)
784 *collapse_count = fold_convert_loc (loc, iter_type, count);
785 else
786 *collapse_count = create_tmp_var (iter_type, ".count");
789 if (fd->collapse > 1 || (fd->ordered && loops))
791 fd->loop.v = *collapse_iter;
792 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
793 fd->loop.n2 = *collapse_count;
794 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
795 fd->loop.cond_code = LT_EXPR;
797 else if (loops)
798 loops[0] = fd->loop;
802 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
803 is the immediate dominator of PAR_ENTRY_BB, return true if there
804 are no data dependencies that would prevent expanding the parallel
805 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
807 When expanding a combined parallel+workshare region, the call to
808 the child function may need additional arguments in the case of
809 GIMPLE_OMP_FOR regions. In some cases, these arguments are
810 computed out of variables passed in from the parent to the child
811 via 'struct .omp_data_s'. For instance:
813 #pragma omp parallel for schedule (guided, i * 4)
814 for (j ...)
816 Is lowered into:
818 # BLOCK 2 (PAR_ENTRY_BB)
819 .omp_data_o.i = i;
820 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
822 # BLOCK 3 (WS_ENTRY_BB)
823 .omp_data_i = &.omp_data_o;
824 D.1667 = .omp_data_i->i;
825 D.1598 = D.1667 * 4;
826 #pragma omp for schedule (guided, D.1598)
828 When we outline the parallel region, the call to the child function
829 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
830 that value is computed *after* the call site. So, in principle we
831 cannot do the transformation.
833 To see whether the code in WS_ENTRY_BB blocks the combined
834 parallel+workshare call, we collect all the variables used in the
835 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
836 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
837 call.
839 FIXME. If we had the SSA form built at this point, we could merely
840 hoist the code in block 3 into block 2 and be done with it. But at
841 this point we don't have dataflow information and though we could
842 hack something up here, it is really not worth the aggravation. */
844 static bool
845 workshare_safe_to_combine_p (basic_block ws_entry_bb)
847 struct omp_for_data fd;
848 gimple *ws_stmt = last_stmt (ws_entry_bb);
850 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
851 return true;
853 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
855 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
857 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
858 return false;
859 if (fd.iter_type != long_integer_type_node)
860 return false;
862 /* FIXME. We give up too easily here. If any of these arguments
863 are not constants, they will likely involve variables that have
864 been mapped into fields of .omp_data_s for sharing with the child
865 function. With appropriate data flow, it would be possible to
866 see through this. */
867 if (!is_gimple_min_invariant (fd.loop.n1)
868 || !is_gimple_min_invariant (fd.loop.n2)
869 || !is_gimple_min_invariant (fd.loop.step)
870 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
871 return false;
873 return true;
877 static int omp_max_vf (void);
879 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
880 presence (SIMD_SCHEDULE). */
882 static tree
883 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
885 if (!simd_schedule)
886 return chunk_size;
888 int vf = omp_max_vf ();
889 if (vf == 1)
890 return chunk_size;
892 tree type = TREE_TYPE (chunk_size);
893 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
894 build_int_cst (type, vf - 1));
895 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
896 build_int_cst (type, -vf));
900 /* Collect additional arguments needed to emit a combined
901 parallel+workshare call. WS_STMT is the workshare directive being
902 expanded. */
904 static vec<tree, va_gc> *
905 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
907 tree t;
908 location_t loc = gimple_location (ws_stmt);
909 vec<tree, va_gc> *ws_args;
911 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
913 struct omp_for_data fd;
914 tree n1, n2;
916 extract_omp_for_data (for_stmt, &fd, NULL);
917 n1 = fd.loop.n1;
918 n2 = fd.loop.n2;
920 if (gimple_omp_for_combined_into_p (for_stmt))
922 tree innerc
923 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
924 OMP_CLAUSE__LOOPTEMP_);
925 gcc_assert (innerc);
926 n1 = OMP_CLAUSE_DECL (innerc);
927 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
928 OMP_CLAUSE__LOOPTEMP_);
929 gcc_assert (innerc);
930 n2 = OMP_CLAUSE_DECL (innerc);
933 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
935 t = fold_convert_loc (loc, long_integer_type_node, n1);
936 ws_args->quick_push (t);
938 t = fold_convert_loc (loc, long_integer_type_node, n2);
939 ws_args->quick_push (t);
941 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
942 ws_args->quick_push (t);
944 if (fd.chunk_size)
946 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
947 t = omp_adjust_chunk_size (t, fd.simd_schedule);
948 ws_args->quick_push (t);
951 return ws_args;
953 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
955 /* Number of sections is equal to the number of edges from the
956 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
957 the exit of the sections region. */
958 basic_block bb = single_succ (gimple_bb (ws_stmt));
959 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
960 vec_alloc (ws_args, 1);
961 ws_args->quick_push (t);
962 return ws_args;
965 gcc_unreachable ();
969 /* Discover whether REGION is a combined parallel+workshare region. */
971 static void
972 determine_parallel_type (struct omp_region *region)
974 basic_block par_entry_bb, par_exit_bb;
975 basic_block ws_entry_bb, ws_exit_bb;
977 if (region == NULL || region->inner == NULL
978 || region->exit == NULL || region->inner->exit == NULL
979 || region->inner->cont == NULL)
980 return;
982 /* We only support parallel+for and parallel+sections. */
983 if (region->type != GIMPLE_OMP_PARALLEL
984 || (region->inner->type != GIMPLE_OMP_FOR
985 && region->inner->type != GIMPLE_OMP_SECTIONS))
986 return;
988 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
989 WS_EXIT_BB -> PAR_EXIT_BB. */
990 par_entry_bb = region->entry;
991 par_exit_bb = region->exit;
992 ws_entry_bb = region->inner->entry;
993 ws_exit_bb = region->inner->exit;
995 if (single_succ (par_entry_bb) == ws_entry_bb
996 && single_succ (ws_exit_bb) == par_exit_bb
997 && workshare_safe_to_combine_p (ws_entry_bb)
998 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
999 || (last_and_only_stmt (ws_entry_bb)
1000 && last_and_only_stmt (par_exit_bb))))
1002 gimple *par_stmt = last_stmt (par_entry_bb);
1003 gimple *ws_stmt = last_stmt (ws_entry_bb);
1005 if (region->inner->type == GIMPLE_OMP_FOR)
1007 /* If this is a combined parallel loop, we need to determine
1008 whether or not to use the combined library calls. There
1009 are two cases where we do not apply the transformation:
1010 static loops and any kind of ordered loop. In the first
1011 case, we already open code the loop so there is no need
1012 to do anything else. In the latter case, the combined
1013 parallel loop call would still need extra synchronization
1014 to implement ordered semantics, so there would not be any
1015 gain in using the combined call. */
1016 tree clauses = gimple_omp_for_clauses (ws_stmt);
1017 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1018 if (c == NULL
1019 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1020 == OMP_CLAUSE_SCHEDULE_STATIC)
1021 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1023 region->is_combined_parallel = false;
1024 region->inner->is_combined_parallel = false;
1025 return;
1029 region->is_combined_parallel = true;
1030 region->inner->is_combined_parallel = true;
1031 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1036 /* Return true if EXPR is variable sized. */
1038 static inline bool
1039 is_variable_sized (const_tree expr)
1041 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1044 /* Return true if DECL is a reference type. */
1046 static inline bool
1047 is_reference (tree decl)
1049 return lang_hooks.decls.omp_privatize_by_reference (decl);
1052 /* Return the type of a decl. If the decl is reference type,
1053 return its base type. */
1054 static inline tree
1055 get_base_type (tree decl)
1057 tree type = TREE_TYPE (decl);
1058 if (is_reference (decl))
1059 type = TREE_TYPE (type);
1060 return type;
1063 /* Lookup variables. The "maybe" form
1064 allows for the variable form to not have been entered, otherwise we
1065 assert that the variable must have been entered. */
1067 static inline tree
1068 lookup_decl (tree var, omp_context *ctx)
1070 tree *n = ctx->cb.decl_map->get (var);
1071 return *n;
1074 static inline tree
1075 maybe_lookup_decl (const_tree var, omp_context *ctx)
1077 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1078 return n ? *n : NULL_TREE;
1081 static inline tree
1082 lookup_field (tree var, omp_context *ctx)
1084 splay_tree_node n;
1085 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1086 return (tree) n->value;
1089 static inline tree
1090 lookup_sfield (splay_tree_key key, omp_context *ctx)
1092 splay_tree_node n;
1093 n = splay_tree_lookup (ctx->sfield_map
1094 ? ctx->sfield_map : ctx->field_map, key);
1095 return (tree) n->value;
1098 static inline tree
1099 lookup_sfield (tree var, omp_context *ctx)
1101 return lookup_sfield ((splay_tree_key) var, ctx);
1104 static inline tree
1105 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1107 splay_tree_node n;
1108 n = splay_tree_lookup (ctx->field_map, key);
1109 return n ? (tree) n->value : NULL_TREE;
1112 static inline tree
1113 maybe_lookup_field (tree var, omp_context *ctx)
1115 return maybe_lookup_field ((splay_tree_key) var, ctx);
1118 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1119 the parallel context if DECL is to be shared. */
1121 static bool
1122 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1124 if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
1125 || TYPE_ATOMIC (TREE_TYPE (decl)))
1126 return true;
1128 /* We can only use copy-in/copy-out semantics for shared variables
1129 when we know the value is not accessible from an outer scope. */
1130 if (shared_ctx)
1132 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1134 /* ??? Trivially accessible from anywhere. But why would we even
1135 be passing an address in this case? Should we simply assert
1136 this to be false, or should we have a cleanup pass that removes
1137 these from the list of mappings? */
1138 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1139 return true;
1141 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1142 without analyzing the expression whether or not its location
1143 is accessible to anyone else. In the case of nested parallel
1144 regions it certainly may be. */
1145 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1146 return true;
1148 /* Do not use copy-in/copy-out for variables that have their
1149 address taken. */
1150 if (TREE_ADDRESSABLE (decl))
1151 return true;
1153 /* lower_send_shared_vars only uses copy-in, but not copy-out
1154 for these. */
1155 if (TREE_READONLY (decl)
1156 || ((TREE_CODE (decl) == RESULT_DECL
1157 || TREE_CODE (decl) == PARM_DECL)
1158 && DECL_BY_REFERENCE (decl)))
1159 return false;
1161 /* Disallow copy-in/out in nested parallel if
1162 decl is shared in outer parallel, otherwise
1163 each thread could store the shared variable
1164 in its own copy-in location, making the
1165 variable no longer really shared. */
1166 if (shared_ctx->is_nested)
1168 omp_context *up;
1170 for (up = shared_ctx->outer; up; up = up->outer)
1171 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1172 break;
1174 if (up)
1176 tree c;
1178 for (c = gimple_omp_taskreg_clauses (up->stmt);
1179 c; c = OMP_CLAUSE_CHAIN (c))
1180 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1181 && OMP_CLAUSE_DECL (c) == decl)
1182 break;
1184 if (c)
1185 goto maybe_mark_addressable_and_ret;
1189 /* For tasks avoid using copy-in/out. As tasks can be
1190 deferred or executed in different thread, when GOMP_task
1191 returns, the task hasn't necessarily terminated. */
1192 if (is_task_ctx (shared_ctx))
1194 tree outer;
1195 maybe_mark_addressable_and_ret:
1196 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1197 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1199 /* Taking address of OUTER in lower_send_shared_vars
1200 might need regimplification of everything that uses the
1201 variable. */
1202 if (!task_shared_vars)
1203 task_shared_vars = BITMAP_ALLOC (NULL);
1204 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1205 TREE_ADDRESSABLE (outer) = 1;
1207 return true;
1211 return false;
1214 /* Construct a new automatic decl similar to VAR. */
1216 static tree
1217 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1219 tree copy = copy_var_decl (var, name, type);
1221 DECL_CONTEXT (copy) = current_function_decl;
1222 DECL_CHAIN (copy) = ctx->block_vars;
1223 /* If VAR is listed in task_shared_vars, it means it wasn't
1224 originally addressable and is just because task needs to take
1225 it's address. But we don't need to take address of privatizations
1226 from that var. */
1227 if (TREE_ADDRESSABLE (var)
1228 && task_shared_vars
1229 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1230 TREE_ADDRESSABLE (copy) = 0;
1231 ctx->block_vars = copy;
1233 return copy;
1236 static tree
1237 omp_copy_decl_1 (tree var, omp_context *ctx)
1239 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1242 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1243 as appropriate. */
1244 static tree
1245 omp_build_component_ref (tree obj, tree field)
1247 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1248 if (TREE_THIS_VOLATILE (field))
1249 TREE_THIS_VOLATILE (ret) |= 1;
1250 if (TREE_READONLY (field))
1251 TREE_READONLY (ret) |= 1;
1252 return ret;
1255 /* Build tree nodes to access the field for VAR on the receiver side. */
1257 static tree
1258 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1260 tree x, field = lookup_field (var, ctx);
1262 /* If the receiver record type was remapped in the child function,
1263 remap the field into the new record type. */
1264 x = maybe_lookup_field (field, ctx);
1265 if (x != NULL)
1266 field = x;
1268 x = build_simple_mem_ref (ctx->receiver_decl);
1269 TREE_THIS_NOTRAP (x) = 1;
1270 x = omp_build_component_ref (x, field);
1271 if (by_ref)
1273 x = build_simple_mem_ref (x);
1274 TREE_THIS_NOTRAP (x) = 1;
1277 return x;
1280 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1281 of a parallel, this is a component reference; for workshare constructs
1282 this is some variable. */
1284 static tree
1285 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1287 tree x;
1289 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1290 x = var;
1291 else if (is_variable_sized (var))
1293 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1294 x = build_outer_var_ref (x, ctx, lastprivate);
1295 x = build_simple_mem_ref (x);
1297 else if (is_taskreg_ctx (ctx))
1299 bool by_ref = use_pointer_for_field (var, NULL);
1300 x = build_receiver_ref (var, by_ref, ctx);
1302 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1303 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1305 /* #pragma omp simd isn't a worksharing construct, and can reference even
1306 private vars in its linear etc. clauses. */
1307 x = NULL_TREE;
1308 if (ctx->outer && is_taskreg_ctx (ctx))
1309 x = lookup_decl (var, ctx->outer);
1310 else if (ctx->outer)
1311 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1312 if (x == NULL_TREE)
1313 x = var;
1315 else if (lastprivate && is_taskloop_ctx (ctx))
1317 gcc_assert (ctx->outer);
1318 splay_tree_node n
1319 = splay_tree_lookup (ctx->outer->field_map,
1320 (splay_tree_key) &DECL_UID (var));
1321 if (n == NULL)
1323 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1324 x = var;
1325 else
1326 x = lookup_decl (var, ctx->outer);
1328 else
1330 tree field = (tree) n->value;
1331 /* If the receiver record type was remapped in the child function,
1332 remap the field into the new record type. */
1333 x = maybe_lookup_field (field, ctx->outer);
1334 if (x != NULL)
1335 field = x;
1337 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1338 x = omp_build_component_ref (x, field);
1339 if (use_pointer_for_field (var, ctx->outer))
1340 x = build_simple_mem_ref (x);
1343 else if (ctx->outer)
1345 omp_context *outer = ctx->outer;
1346 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1348 outer = outer->outer;
1349 gcc_assert (outer
1350 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1352 x = lookup_decl (var, outer);
1354 else if (is_reference (var))
1355 /* This can happen with orphaned constructs. If var is reference, it is
1356 possible it is shared and as such valid. */
1357 x = var;
1358 else if (omp_member_access_dummy_var (var))
1359 x = var;
1360 else
1361 gcc_unreachable ();
1363 if (x == var)
1365 tree t = omp_member_access_dummy_var (var);
1366 if (t)
1368 x = DECL_VALUE_EXPR (var);
1369 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1370 if (o != t)
1371 x = unshare_and_remap (x, t, o);
1372 else
1373 x = unshare_expr (x);
1377 if (is_reference (var))
1378 x = build_simple_mem_ref (x);
1380 return x;
1383 /* Build tree nodes to access the field for VAR on the sender side. */
1385 static tree
1386 build_sender_ref (splay_tree_key key, omp_context *ctx)
1388 tree field = lookup_sfield (key, ctx);
1389 return omp_build_component_ref (ctx->sender_decl, field);
1392 static tree
1393 build_sender_ref (tree var, omp_context *ctx)
1395 return build_sender_ref ((splay_tree_key) var, ctx);
1398 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1399 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1401 static void
1402 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1403 bool base_pointers_restrict = false)
1405 tree field, type, sfield = NULL_TREE;
1406 splay_tree_key key = (splay_tree_key) var;
1408 if ((mask & 8) != 0)
1410 key = (splay_tree_key) &DECL_UID (var);
1411 gcc_checking_assert (key != (splay_tree_key) var);
1413 gcc_assert ((mask & 1) == 0
1414 || !splay_tree_lookup (ctx->field_map, key));
1415 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1416 || !splay_tree_lookup (ctx->sfield_map, key));
1417 gcc_assert ((mask & 3) == 3
1418 || !is_gimple_omp_oacc (ctx->stmt));
1420 type = TREE_TYPE (var);
1421 /* Prevent redeclaring the var in the split-off function with a restrict
1422 pointer type. Note that we only clear type itself, restrict qualifiers in
1423 the pointed-to type will be ignored by points-to analysis. */
1424 if (POINTER_TYPE_P (type)
1425 && TYPE_RESTRICT (type))
1426 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1428 if (mask & 4)
1430 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1431 type = build_pointer_type (build_pointer_type (type));
1433 else if (by_ref)
1435 type = build_pointer_type (type);
1436 if (base_pointers_restrict)
1437 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1439 else if ((mask & 3) == 1 && is_reference (var))
1440 type = TREE_TYPE (type);
1442 field = build_decl (DECL_SOURCE_LOCATION (var),
1443 FIELD_DECL, DECL_NAME (var), type);
1445 /* Remember what variable this field was created for. This does have a
1446 side effect of making dwarf2out ignore this member, so for helpful
1447 debugging we clear it later in delete_omp_context. */
1448 DECL_ABSTRACT_ORIGIN (field) = var;
1449 if (type == TREE_TYPE (var))
1451 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1452 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1453 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1455 else
1456 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1458 if ((mask & 3) == 3)
1460 insert_field_into_struct (ctx->record_type, field);
1461 if (ctx->srecord_type)
1463 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1464 FIELD_DECL, DECL_NAME (var), type);
1465 DECL_ABSTRACT_ORIGIN (sfield) = var;
1466 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1467 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1468 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1469 insert_field_into_struct (ctx->srecord_type, sfield);
1472 else
1474 if (ctx->srecord_type == NULL_TREE)
1476 tree t;
1478 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1479 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1480 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1482 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1483 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1484 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1485 insert_field_into_struct (ctx->srecord_type, sfield);
1486 splay_tree_insert (ctx->sfield_map,
1487 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1488 (splay_tree_value) sfield);
1491 sfield = field;
1492 insert_field_into_struct ((mask & 1) ? ctx->record_type
1493 : ctx->srecord_type, field);
1496 if (mask & 1)
1497 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1498 if ((mask & 2) && ctx->sfield_map)
1499 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1502 static tree
1503 install_var_local (tree var, omp_context *ctx)
1505 tree new_var = omp_copy_decl_1 (var, ctx);
1506 insert_decl_map (&ctx->cb, var, new_var);
1507 return new_var;
1510 /* Adjust the replacement for DECL in CTX for the new context. This means
1511 copying the DECL_VALUE_EXPR, and fixing up the type. */
1513 static void
1514 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1516 tree new_decl, size;
1518 new_decl = lookup_decl (decl, ctx);
1520 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1522 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1523 && DECL_HAS_VALUE_EXPR_P (decl))
1525 tree ve = DECL_VALUE_EXPR (decl);
1526 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1527 SET_DECL_VALUE_EXPR (new_decl, ve);
1528 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1531 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1533 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1534 if (size == error_mark_node)
1535 size = TYPE_SIZE (TREE_TYPE (new_decl));
1536 DECL_SIZE (new_decl) = size;
1538 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1539 if (size == error_mark_node)
1540 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1541 DECL_SIZE_UNIT (new_decl) = size;
1545 /* The callback for remap_decl. Search all containing contexts for a
1546 mapping of the variable; this avoids having to duplicate the splay
1547 tree ahead of time. We know a mapping doesn't already exist in the
1548 given context. Create new mappings to implement default semantics. */
1550 static tree
1551 omp_copy_decl (tree var, copy_body_data *cb)
1553 omp_context *ctx = (omp_context *) cb;
1554 tree new_var;
1556 if (TREE_CODE (var) == LABEL_DECL)
1558 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1559 DECL_CONTEXT (new_var) = current_function_decl;
1560 insert_decl_map (&ctx->cb, var, new_var);
1561 return new_var;
1564 while (!is_taskreg_ctx (ctx))
1566 ctx = ctx->outer;
1567 if (ctx == NULL)
1568 return var;
1569 new_var = maybe_lookup_decl (var, ctx);
1570 if (new_var)
1571 return new_var;
1574 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1575 return var;
1577 return error_mark_node;
1581 /* Debugging dumps for parallel regions. */
1582 void dump_omp_region (FILE *, struct omp_region *, int);
1583 void debug_omp_region (struct omp_region *);
1584 void debug_all_omp_regions (void);
1586 /* Dump the parallel region tree rooted at REGION. */
1588 void
1589 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1591 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1592 gimple_code_name[region->type]);
1594 if (region->inner)
1595 dump_omp_region (file, region->inner, indent + 4);
1597 if (region->cont)
1599 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1600 region->cont->index);
1603 if (region->exit)
1604 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1605 region->exit->index);
1606 else
1607 fprintf (file, "%*s[no exit marker]\n", indent, "");
1609 if (region->next)
1610 dump_omp_region (file, region->next, indent);
1613 DEBUG_FUNCTION void
1614 debug_omp_region (struct omp_region *region)
1616 dump_omp_region (stderr, region, 0);
1619 DEBUG_FUNCTION void
1620 debug_all_omp_regions (void)
1622 dump_omp_region (stderr, root_omp_region, 0);
1626 /* Create a new parallel region starting at STMT inside region PARENT. */
1628 static struct omp_region *
1629 new_omp_region (basic_block bb, enum gimple_code type,
1630 struct omp_region *parent)
1632 struct omp_region *region = XCNEW (struct omp_region);
1634 region->outer = parent;
1635 region->entry = bb;
1636 region->type = type;
1638 if (parent)
1640 /* This is a nested region. Add it to the list of inner
1641 regions in PARENT. */
1642 region->next = parent->inner;
1643 parent->inner = region;
1645 else
1647 /* This is a toplevel region. Add it to the list of toplevel
1648 regions in ROOT_OMP_REGION. */
1649 region->next = root_omp_region;
1650 root_omp_region = region;
1653 return region;
1656 /* Release the memory associated with the region tree rooted at REGION. */
1658 static void
1659 free_omp_region_1 (struct omp_region *region)
1661 struct omp_region *i, *n;
1663 for (i = region->inner; i ; i = n)
1665 n = i->next;
1666 free_omp_region_1 (i);
1669 free (region);
1672 /* Release the memory for the entire omp region tree. */
1674 void
1675 free_omp_regions (void)
1677 struct omp_region *r, *n;
1678 for (r = root_omp_region; r ; r = n)
1680 n = r->next;
1681 free_omp_region_1 (r);
1683 root_omp_region = NULL;
1687 /* Create a new context, with OUTER_CTX being the surrounding context. */
1689 static omp_context *
1690 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1692 omp_context *ctx = XCNEW (omp_context);
1694 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1695 (splay_tree_value) ctx);
1696 ctx->stmt = stmt;
1698 if (outer_ctx)
1700 ctx->outer = outer_ctx;
1701 ctx->cb = outer_ctx->cb;
1702 ctx->cb.block = NULL;
1703 ctx->depth = outer_ctx->depth + 1;
1705 else
1707 ctx->cb.src_fn = current_function_decl;
1708 ctx->cb.dst_fn = current_function_decl;
1709 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1710 gcc_checking_assert (ctx->cb.src_node);
1711 ctx->cb.dst_node = ctx->cb.src_node;
1712 ctx->cb.src_cfun = cfun;
1713 ctx->cb.copy_decl = omp_copy_decl;
1714 ctx->cb.eh_lp_nr = 0;
1715 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1716 ctx->depth = 1;
1719 ctx->cb.decl_map = new hash_map<tree, tree>;
1721 return ctx;
1724 static gimple_seq maybe_catch_exception (gimple_seq);
1726 /* Finalize task copyfn. */
1728 static void
1729 finalize_task_copyfn (gomp_task *task_stmt)
1731 struct function *child_cfun;
1732 tree child_fn;
1733 gimple_seq seq = NULL, new_seq;
1734 gbind *bind;
1736 child_fn = gimple_omp_task_copy_fn (task_stmt);
1737 if (child_fn == NULL_TREE)
1738 return;
1740 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1741 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1743 push_cfun (child_cfun);
1744 bind = gimplify_body (child_fn, false);
1745 gimple_seq_add_stmt (&seq, bind);
1746 new_seq = maybe_catch_exception (seq);
1747 if (new_seq != seq)
1749 bind = gimple_build_bind (NULL, new_seq, NULL);
1750 seq = NULL;
1751 gimple_seq_add_stmt (&seq, bind);
1753 gimple_set_body (child_fn, seq);
1754 pop_cfun ();
1756 /* Inform the callgraph about the new function. */
1757 cgraph_node *node = cgraph_node::get_create (child_fn);
1758 node->parallelized_function = 1;
1759 cgraph_node::add_new_function (child_fn, false);
1762 /* Destroy a omp_context data structures. Called through the splay tree
1763 value delete callback. */
1765 static void
1766 delete_omp_context (splay_tree_value value)
1768 omp_context *ctx = (omp_context *) value;
1770 delete ctx->cb.decl_map;
1772 if (ctx->field_map)
1773 splay_tree_delete (ctx->field_map);
1774 if (ctx->sfield_map)
1775 splay_tree_delete (ctx->sfield_map);
1777 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1778 it produces corrupt debug information. */
1779 if (ctx->record_type)
1781 tree t;
1782 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1783 DECL_ABSTRACT_ORIGIN (t) = NULL;
1785 if (ctx->srecord_type)
1787 tree t;
1788 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1789 DECL_ABSTRACT_ORIGIN (t) = NULL;
1792 if (is_task_ctx (ctx))
1793 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1795 XDELETE (ctx);
1798 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1799 context. */
1801 static void
1802 fixup_child_record_type (omp_context *ctx)
1804 tree f, type = ctx->record_type;
1806 if (!ctx->receiver_decl)
1807 return;
1808 /* ??? It isn't sufficient to just call remap_type here, because
1809 variably_modified_type_p doesn't work the way we expect for
1810 record types. Testing each field for whether it needs remapping
1811 and creating a new record by hand works, however. */
1812 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1813 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1814 break;
1815 if (f)
1817 tree name, new_fields = NULL;
1819 type = lang_hooks.types.make_type (RECORD_TYPE);
1820 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1821 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1822 TYPE_DECL, name, type);
1823 TYPE_NAME (type) = name;
1825 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1827 tree new_f = copy_node (f);
1828 DECL_CONTEXT (new_f) = type;
1829 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1830 DECL_CHAIN (new_f) = new_fields;
1831 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1832 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1834 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1835 &ctx->cb, NULL);
1836 new_fields = new_f;
1838 /* Arrange to be able to look up the receiver field
1839 given the sender field. */
1840 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1841 (splay_tree_value) new_f);
1843 TYPE_FIELDS (type) = nreverse (new_fields);
1844 layout_type (type);
1847 /* In a target region we never modify any of the pointers in *.omp_data_i,
1848 so attempt to help the optimizers. */
1849 if (is_gimple_omp_offloaded (ctx->stmt))
1850 type = build_qualified_type (type, TYPE_QUAL_CONST);
1852 TREE_TYPE (ctx->receiver_decl)
1853 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1856 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1857 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1858 restrict. */
1860 static void
1861 scan_sharing_clauses (tree clauses, omp_context *ctx,
1862 bool base_pointers_restrict = false)
1864 tree c, decl;
1865 bool scan_array_reductions = false;
1867 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1869 bool by_ref;
1871 switch (OMP_CLAUSE_CODE (c))
1873 case OMP_CLAUSE_PRIVATE:
1874 decl = OMP_CLAUSE_DECL (c);
1875 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1876 goto do_private;
1877 else if (!is_variable_sized (decl))
1878 install_var_local (decl, ctx);
1879 break;
1881 case OMP_CLAUSE_SHARED:
1882 decl = OMP_CLAUSE_DECL (c);
1883 /* Ignore shared directives in teams construct. */
1884 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1886 /* Global variables don't need to be copied,
1887 the receiver side will use them directly. */
1888 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1889 if (is_global_var (odecl))
1890 break;
1891 insert_decl_map (&ctx->cb, decl, odecl);
1892 break;
1894 gcc_assert (is_taskreg_ctx (ctx));
1895 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1896 || !is_variable_sized (decl));
1897 /* Global variables don't need to be copied,
1898 the receiver side will use them directly. */
1899 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1900 break;
1901 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1903 use_pointer_for_field (decl, ctx);
1904 break;
1906 by_ref = use_pointer_for_field (decl, NULL);
1907 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1908 || TREE_ADDRESSABLE (decl)
1909 || by_ref
1910 || is_reference (decl))
1912 by_ref = use_pointer_for_field (decl, ctx);
1913 install_var_field (decl, by_ref, 3, ctx);
1914 install_var_local (decl, ctx);
1915 break;
1917 /* We don't need to copy const scalar vars back. */
1918 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1919 goto do_private;
1921 case OMP_CLAUSE_REDUCTION:
1922 decl = OMP_CLAUSE_DECL (c);
1923 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1924 && TREE_CODE (decl) == MEM_REF)
1926 tree t = TREE_OPERAND (decl, 0);
1927 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1928 t = TREE_OPERAND (t, 0);
1929 if (TREE_CODE (t) == INDIRECT_REF
1930 || TREE_CODE (t) == ADDR_EXPR)
1931 t = TREE_OPERAND (t, 0);
1932 install_var_local (t, ctx);
1933 if (is_taskreg_ctx (ctx)
1934 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1935 && !is_variable_sized (t))
1937 by_ref = use_pointer_for_field (t, ctx);
1938 install_var_field (t, by_ref, 3, ctx);
1940 break;
1942 goto do_private;
1944 case OMP_CLAUSE_LASTPRIVATE:
1945 /* Let the corresponding firstprivate clause create
1946 the variable. */
1947 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1948 break;
1949 /* FALLTHRU */
1951 case OMP_CLAUSE_FIRSTPRIVATE:
1952 case OMP_CLAUSE_LINEAR:
1953 decl = OMP_CLAUSE_DECL (c);
1954 do_private:
1955 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1956 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1957 && is_gimple_omp_offloaded (ctx->stmt))
1959 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1960 install_var_field (decl, !is_reference (decl), 3, ctx);
1961 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1962 install_var_field (decl, true, 3, ctx);
1963 else
1964 install_var_field (decl, false, 3, ctx);
1966 if (is_variable_sized (decl))
1968 if (is_task_ctx (ctx))
1969 install_var_field (decl, false, 1, ctx);
1970 break;
1972 else if (is_taskreg_ctx (ctx))
1974 bool global
1975 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1976 by_ref = use_pointer_for_field (decl, NULL);
1978 if (is_task_ctx (ctx)
1979 && (global || by_ref || is_reference (decl)))
1981 install_var_field (decl, false, 1, ctx);
1982 if (!global)
1983 install_var_field (decl, by_ref, 2, ctx);
1985 else if (!global)
1986 install_var_field (decl, by_ref, 3, ctx);
1988 install_var_local (decl, ctx);
1989 break;
1991 case OMP_CLAUSE_USE_DEVICE_PTR:
1992 decl = OMP_CLAUSE_DECL (c);
1993 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1994 install_var_field (decl, true, 3, ctx);
1995 else
1996 install_var_field (decl, false, 3, ctx);
1997 if (DECL_SIZE (decl)
1998 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2000 tree decl2 = DECL_VALUE_EXPR (decl);
2001 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2002 decl2 = TREE_OPERAND (decl2, 0);
2003 gcc_assert (DECL_P (decl2));
2004 install_var_local (decl2, ctx);
2006 install_var_local (decl, ctx);
2007 break;
2009 case OMP_CLAUSE_IS_DEVICE_PTR:
2010 decl = OMP_CLAUSE_DECL (c);
2011 goto do_private;
2013 case OMP_CLAUSE__LOOPTEMP_:
2014 gcc_assert (is_taskreg_ctx (ctx));
2015 decl = OMP_CLAUSE_DECL (c);
2016 install_var_field (decl, false, 3, ctx);
2017 install_var_local (decl, ctx);
2018 break;
2020 case OMP_CLAUSE_COPYPRIVATE:
2021 case OMP_CLAUSE_COPYIN:
2022 decl = OMP_CLAUSE_DECL (c);
2023 by_ref = use_pointer_for_field (decl, NULL);
2024 install_var_field (decl, by_ref, 3, ctx);
2025 break;
2027 case OMP_CLAUSE_DEFAULT:
2028 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2029 break;
2031 case OMP_CLAUSE_FINAL:
2032 case OMP_CLAUSE_IF:
2033 case OMP_CLAUSE_NUM_THREADS:
2034 case OMP_CLAUSE_NUM_TEAMS:
2035 case OMP_CLAUSE_THREAD_LIMIT:
2036 case OMP_CLAUSE_DEVICE:
2037 case OMP_CLAUSE_SCHEDULE:
2038 case OMP_CLAUSE_DIST_SCHEDULE:
2039 case OMP_CLAUSE_DEPEND:
2040 case OMP_CLAUSE_PRIORITY:
2041 case OMP_CLAUSE_GRAINSIZE:
2042 case OMP_CLAUSE_NUM_TASKS:
2043 case OMP_CLAUSE__CILK_FOR_COUNT_:
2044 case OMP_CLAUSE_NUM_GANGS:
2045 case OMP_CLAUSE_NUM_WORKERS:
2046 case OMP_CLAUSE_VECTOR_LENGTH:
2047 if (ctx->outer)
2048 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2049 break;
2051 case OMP_CLAUSE_TO:
2052 case OMP_CLAUSE_FROM:
2053 case OMP_CLAUSE_MAP:
2054 if (ctx->outer)
2055 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2056 decl = OMP_CLAUSE_DECL (c);
2057 /* Global variables with "omp declare target" attribute
2058 don't need to be copied, the receiver side will use them
2059 directly. However, global variables with "omp declare target link"
2060 attribute need to be copied. */
2061 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2062 && DECL_P (decl)
2063 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2064 && (OMP_CLAUSE_MAP_KIND (c)
2065 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2066 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2067 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2068 && varpool_node::get_create (decl)->offloadable
2069 && !lookup_attribute ("omp declare target link",
2070 DECL_ATTRIBUTES (decl)))
2071 break;
2072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2073 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2075 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2076 not offloaded; there is nothing to map for those. */
2077 if (!is_gimple_omp_offloaded (ctx->stmt)
2078 && !POINTER_TYPE_P (TREE_TYPE (decl))
2079 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2080 break;
2082 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2083 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2084 || (OMP_CLAUSE_MAP_KIND (c)
2085 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2087 if (TREE_CODE (decl) == COMPONENT_REF
2088 || (TREE_CODE (decl) == INDIRECT_REF
2089 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2090 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2091 == REFERENCE_TYPE)))
2092 break;
2093 if (DECL_SIZE (decl)
2094 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2096 tree decl2 = DECL_VALUE_EXPR (decl);
2097 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2098 decl2 = TREE_OPERAND (decl2, 0);
2099 gcc_assert (DECL_P (decl2));
2100 install_var_local (decl2, ctx);
2102 install_var_local (decl, ctx);
2103 break;
2105 if (DECL_P (decl))
2107 if (DECL_SIZE (decl)
2108 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2110 tree decl2 = DECL_VALUE_EXPR (decl);
2111 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2112 decl2 = TREE_OPERAND (decl2, 0);
2113 gcc_assert (DECL_P (decl2));
2114 install_var_field (decl2, true, 3, ctx);
2115 install_var_local (decl2, ctx);
2116 install_var_local (decl, ctx);
2118 else
2120 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2121 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2122 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2123 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2124 install_var_field (decl, true, 7, ctx);
2125 else
2126 install_var_field (decl, true, 3, ctx,
2127 base_pointers_restrict);
2128 if (is_gimple_omp_offloaded (ctx->stmt)
2129 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2130 install_var_local (decl, ctx);
2133 else
2135 tree base = get_base_address (decl);
2136 tree nc = OMP_CLAUSE_CHAIN (c);
2137 if (DECL_P (base)
2138 && nc != NULL_TREE
2139 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2140 && OMP_CLAUSE_DECL (nc) == base
2141 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2142 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2144 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2145 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2147 else
2149 if (ctx->outer)
2151 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2152 decl = OMP_CLAUSE_DECL (c);
2154 gcc_assert (!splay_tree_lookup (ctx->field_map,
2155 (splay_tree_key) decl));
2156 tree field
2157 = build_decl (OMP_CLAUSE_LOCATION (c),
2158 FIELD_DECL, NULL_TREE, ptr_type_node);
2159 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2160 insert_field_into_struct (ctx->record_type, field);
2161 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2162 (splay_tree_value) field);
2165 break;
2167 case OMP_CLAUSE__GRIDDIM_:
2168 if (ctx->outer)
2170 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2171 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2173 break;
2175 case OMP_CLAUSE_NOWAIT:
2176 case OMP_CLAUSE_ORDERED:
2177 case OMP_CLAUSE_COLLAPSE:
2178 case OMP_CLAUSE_UNTIED:
2179 case OMP_CLAUSE_MERGEABLE:
2180 case OMP_CLAUSE_PROC_BIND:
2181 case OMP_CLAUSE_SAFELEN:
2182 case OMP_CLAUSE_SIMDLEN:
2183 case OMP_CLAUSE_THREADS:
2184 case OMP_CLAUSE_SIMD:
2185 case OMP_CLAUSE_NOGROUP:
2186 case OMP_CLAUSE_DEFAULTMAP:
2187 case OMP_CLAUSE_ASYNC:
2188 case OMP_CLAUSE_WAIT:
2189 case OMP_CLAUSE_GANG:
2190 case OMP_CLAUSE_WORKER:
2191 case OMP_CLAUSE_VECTOR:
2192 case OMP_CLAUSE_INDEPENDENT:
2193 case OMP_CLAUSE_AUTO:
2194 case OMP_CLAUSE_SEQ:
2195 break;
2197 case OMP_CLAUSE_ALIGNED:
2198 decl = OMP_CLAUSE_DECL (c);
2199 if (is_global_var (decl)
2200 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2201 install_var_local (decl, ctx);
2202 break;
2204 case OMP_CLAUSE_TILE:
2205 case OMP_CLAUSE__CACHE_:
2206 default:
2207 gcc_unreachable ();
2211 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2213 switch (OMP_CLAUSE_CODE (c))
2215 case OMP_CLAUSE_LASTPRIVATE:
2216 /* Let the corresponding firstprivate clause create
2217 the variable. */
2218 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2219 scan_array_reductions = true;
2220 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2221 break;
2222 /* FALLTHRU */
2224 case OMP_CLAUSE_FIRSTPRIVATE:
2225 case OMP_CLAUSE_PRIVATE:
2226 case OMP_CLAUSE_LINEAR:
2227 case OMP_CLAUSE_IS_DEVICE_PTR:
2228 decl = OMP_CLAUSE_DECL (c);
2229 if (is_variable_sized (decl))
2231 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2232 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2233 && is_gimple_omp_offloaded (ctx->stmt))
2235 tree decl2 = DECL_VALUE_EXPR (decl);
2236 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2237 decl2 = TREE_OPERAND (decl2, 0);
2238 gcc_assert (DECL_P (decl2));
2239 install_var_local (decl2, ctx);
2240 fixup_remapped_decl (decl2, ctx, false);
2242 install_var_local (decl, ctx);
2244 fixup_remapped_decl (decl, ctx,
2245 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2246 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2247 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2248 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2249 scan_array_reductions = true;
2250 break;
2252 case OMP_CLAUSE_REDUCTION:
2253 decl = OMP_CLAUSE_DECL (c);
2254 if (TREE_CODE (decl) != MEM_REF)
2256 if (is_variable_sized (decl))
2257 install_var_local (decl, ctx);
2258 fixup_remapped_decl (decl, ctx, false);
2260 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2261 scan_array_reductions = true;
2262 break;
2264 case OMP_CLAUSE_SHARED:
2265 /* Ignore shared directives in teams construct. */
2266 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2267 break;
2268 decl = OMP_CLAUSE_DECL (c);
2269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2270 break;
2271 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2273 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2274 ctx->outer)))
2275 break;
2276 bool by_ref = use_pointer_for_field (decl, ctx);
2277 install_var_field (decl, by_ref, 11, ctx);
2278 break;
2280 fixup_remapped_decl (decl, ctx, false);
2281 break;
2283 case OMP_CLAUSE_MAP:
2284 if (!is_gimple_omp_offloaded (ctx->stmt))
2285 break;
2286 decl = OMP_CLAUSE_DECL (c);
2287 if (DECL_P (decl)
2288 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2289 && (OMP_CLAUSE_MAP_KIND (c)
2290 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2291 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2292 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2293 && varpool_node::get_create (decl)->offloadable)
2294 break;
2295 if (DECL_P (decl))
2297 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2298 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2299 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2300 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2302 tree new_decl = lookup_decl (decl, ctx);
2303 TREE_TYPE (new_decl)
2304 = remap_type (TREE_TYPE (decl), &ctx->cb);
2306 else if (DECL_SIZE (decl)
2307 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2309 tree decl2 = DECL_VALUE_EXPR (decl);
2310 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2311 decl2 = TREE_OPERAND (decl2, 0);
2312 gcc_assert (DECL_P (decl2));
2313 fixup_remapped_decl (decl2, ctx, false);
2314 fixup_remapped_decl (decl, ctx, true);
2316 else
2317 fixup_remapped_decl (decl, ctx, false);
2319 break;
2321 case OMP_CLAUSE_COPYPRIVATE:
2322 case OMP_CLAUSE_COPYIN:
2323 case OMP_CLAUSE_DEFAULT:
2324 case OMP_CLAUSE_IF:
2325 case OMP_CLAUSE_NUM_THREADS:
2326 case OMP_CLAUSE_NUM_TEAMS:
2327 case OMP_CLAUSE_THREAD_LIMIT:
2328 case OMP_CLAUSE_DEVICE:
2329 case OMP_CLAUSE_SCHEDULE:
2330 case OMP_CLAUSE_DIST_SCHEDULE:
2331 case OMP_CLAUSE_NOWAIT:
2332 case OMP_CLAUSE_ORDERED:
2333 case OMP_CLAUSE_COLLAPSE:
2334 case OMP_CLAUSE_UNTIED:
2335 case OMP_CLAUSE_FINAL:
2336 case OMP_CLAUSE_MERGEABLE:
2337 case OMP_CLAUSE_PROC_BIND:
2338 case OMP_CLAUSE_SAFELEN:
2339 case OMP_CLAUSE_SIMDLEN:
2340 case OMP_CLAUSE_ALIGNED:
2341 case OMP_CLAUSE_DEPEND:
2342 case OMP_CLAUSE__LOOPTEMP_:
2343 case OMP_CLAUSE_TO:
2344 case OMP_CLAUSE_FROM:
2345 case OMP_CLAUSE_PRIORITY:
2346 case OMP_CLAUSE_GRAINSIZE:
2347 case OMP_CLAUSE_NUM_TASKS:
2348 case OMP_CLAUSE_THREADS:
2349 case OMP_CLAUSE_SIMD:
2350 case OMP_CLAUSE_NOGROUP:
2351 case OMP_CLAUSE_DEFAULTMAP:
2352 case OMP_CLAUSE_USE_DEVICE_PTR:
2353 case OMP_CLAUSE__CILK_FOR_COUNT_:
2354 case OMP_CLAUSE_ASYNC:
2355 case OMP_CLAUSE_WAIT:
2356 case OMP_CLAUSE_NUM_GANGS:
2357 case OMP_CLAUSE_NUM_WORKERS:
2358 case OMP_CLAUSE_VECTOR_LENGTH:
2359 case OMP_CLAUSE_GANG:
2360 case OMP_CLAUSE_WORKER:
2361 case OMP_CLAUSE_VECTOR:
2362 case OMP_CLAUSE_INDEPENDENT:
2363 case OMP_CLAUSE_AUTO:
2364 case OMP_CLAUSE_SEQ:
2365 case OMP_CLAUSE__GRIDDIM_:
2366 break;
2368 case OMP_CLAUSE_TILE:
2369 case OMP_CLAUSE__CACHE_:
2370 default:
2371 gcc_unreachable ();
2375 gcc_checking_assert (!scan_array_reductions
2376 || !is_gimple_omp_oacc (ctx->stmt));
2377 if (scan_array_reductions)
2379 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2381 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2383 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2384 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2386 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2387 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2388 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2389 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2390 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2391 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2395 /* Create a new name for omp child function. Returns an identifier. If
2396 IS_CILK_FOR is true then the suffix for the child function is
2397 "_cilk_for_fn." */
2399 static tree
2400 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2402 if (is_cilk_for)
2403 return clone_function_name (current_function_decl, "_cilk_for_fn");
2404 return clone_function_name (current_function_decl,
2405 task_copy ? "_omp_cpyfn" : "_omp_fn");
2408 /* Returns the type of the induction variable for the child function for
2409 _Cilk_for and the types for _high and _low variables based on TYPE. */
2411 static tree
2412 cilk_for_check_loop_diff_type (tree type)
2414 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2416 if (TYPE_UNSIGNED (type))
2417 return uint32_type_node;
2418 else
2419 return integer_type_node;
2421 else
2423 if (TYPE_UNSIGNED (type))
2424 return uint64_type_node;
2425 else
2426 return long_long_integer_type_node;
2430 /* Build a decl for the omp child function. It'll not contain a body
2431 yet, just the bare decl. */
2433 static void
2434 create_omp_child_function (omp_context *ctx, bool task_copy)
2436 tree decl, type, name, t;
2438 tree cilk_for_count
2439 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2440 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2441 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2442 tree cilk_var_type = NULL_TREE;
2444 name = create_omp_child_function_name (task_copy,
2445 cilk_for_count != NULL_TREE);
2446 if (task_copy)
2447 type = build_function_type_list (void_type_node, ptr_type_node,
2448 ptr_type_node, NULL_TREE);
2449 else if (cilk_for_count)
2451 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2452 cilk_var_type = cilk_for_check_loop_diff_type (type);
2453 type = build_function_type_list (void_type_node, ptr_type_node,
2454 cilk_var_type, cilk_var_type, NULL_TREE);
2456 else
2457 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2459 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2461 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2462 || !task_copy);
2463 if (!task_copy)
2464 ctx->cb.dst_fn = decl;
2465 else
2466 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2468 TREE_STATIC (decl) = 1;
2469 TREE_USED (decl) = 1;
2470 DECL_ARTIFICIAL (decl) = 1;
2471 DECL_IGNORED_P (decl) = 0;
2472 TREE_PUBLIC (decl) = 0;
2473 DECL_UNINLINABLE (decl) = 1;
2474 DECL_EXTERNAL (decl) = 0;
2475 DECL_CONTEXT (decl) = NULL_TREE;
2476 DECL_INITIAL (decl) = make_node (BLOCK);
2477 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2478 if (cgraph_node::get (current_function_decl)->offloadable)
2479 cgraph_node::get_create (decl)->offloadable = 1;
2480 else
2482 omp_context *octx;
2483 for (octx = ctx; octx; octx = octx->outer)
2484 if (is_gimple_omp_offloaded (octx->stmt))
2486 cgraph_node::get_create (decl)->offloadable = 1;
2487 if (ENABLE_OFFLOADING)
2488 g->have_offload = true;
2490 break;
2494 if (cgraph_node::get_create (decl)->offloadable
2495 && !lookup_attribute ("omp declare target",
2496 DECL_ATTRIBUTES (current_function_decl)))
2497 DECL_ATTRIBUTES (decl)
2498 = tree_cons (get_identifier ("omp target entrypoint"),
2499 NULL_TREE, DECL_ATTRIBUTES (decl));
2501 t = build_decl (DECL_SOURCE_LOCATION (decl),
2502 RESULT_DECL, NULL_TREE, void_type_node);
2503 DECL_ARTIFICIAL (t) = 1;
2504 DECL_IGNORED_P (t) = 1;
2505 DECL_CONTEXT (t) = decl;
2506 DECL_RESULT (decl) = t;
2508 /* _Cilk_for's child function requires two extra parameters called
2509 __low and __high that are set the by Cilk runtime when it calls this
2510 function. */
2511 if (cilk_for_count)
2513 t = build_decl (DECL_SOURCE_LOCATION (decl),
2514 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2515 DECL_ARTIFICIAL (t) = 1;
2516 DECL_NAMELESS (t) = 1;
2517 DECL_ARG_TYPE (t) = ptr_type_node;
2518 DECL_CONTEXT (t) = current_function_decl;
2519 TREE_USED (t) = 1;
2520 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2521 DECL_ARGUMENTS (decl) = t;
2523 t = build_decl (DECL_SOURCE_LOCATION (decl),
2524 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2525 DECL_ARTIFICIAL (t) = 1;
2526 DECL_NAMELESS (t) = 1;
2527 DECL_ARG_TYPE (t) = ptr_type_node;
2528 DECL_CONTEXT (t) = current_function_decl;
2529 TREE_USED (t) = 1;
2530 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2531 DECL_ARGUMENTS (decl) = t;
2534 tree data_name = get_identifier (".omp_data_i");
2535 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2536 ptr_type_node);
2537 DECL_ARTIFICIAL (t) = 1;
2538 DECL_NAMELESS (t) = 1;
2539 DECL_ARG_TYPE (t) = ptr_type_node;
2540 DECL_CONTEXT (t) = current_function_decl;
2541 TREE_USED (t) = 1;
2542 TREE_READONLY (t) = 1;
2543 if (cilk_for_count)
2544 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2545 DECL_ARGUMENTS (decl) = t;
2546 if (!task_copy)
2547 ctx->receiver_decl = t;
2548 else
2550 t = build_decl (DECL_SOURCE_LOCATION (decl),
2551 PARM_DECL, get_identifier (".omp_data_o"),
2552 ptr_type_node);
2553 DECL_ARTIFICIAL (t) = 1;
2554 DECL_NAMELESS (t) = 1;
2555 DECL_ARG_TYPE (t) = ptr_type_node;
2556 DECL_CONTEXT (t) = current_function_decl;
2557 TREE_USED (t) = 1;
2558 TREE_ADDRESSABLE (t) = 1;
2559 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2560 DECL_ARGUMENTS (decl) = t;
2563 /* Allocate memory for the function structure. The call to
2564 allocate_struct_function clobbers CFUN, so we need to restore
2565 it afterward. */
2566 push_struct_function (decl);
2567 cfun->function_end_locus = gimple_location (ctx->stmt);
2568 init_tree_ssa (cfun);
2569 pop_cfun ();
2572 /* Callback for walk_gimple_seq. Check if combined parallel
2573 contains gimple_omp_for_combined_into_p OMP_FOR. */
2575 static tree
2576 find_combined_for (gimple_stmt_iterator *gsi_p,
2577 bool *handled_ops_p,
2578 struct walk_stmt_info *wi)
2580 gimple *stmt = gsi_stmt (*gsi_p);
2582 *handled_ops_p = true;
2583 switch (gimple_code (stmt))
2585 WALK_SUBSTMTS;
2587 case GIMPLE_OMP_FOR:
2588 if (gimple_omp_for_combined_into_p (stmt)
2589 && gimple_omp_for_kind (stmt)
2590 == *(const enum gf_mask *) (wi->info))
2592 wi->info = stmt;
2593 return integer_zero_node;
2595 break;
2596 default:
2597 break;
2599 return NULL;
2602 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2604 static void
2605 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2606 omp_context *outer_ctx)
2608 struct walk_stmt_info wi;
2610 memset (&wi, 0, sizeof (wi));
2611 wi.val_only = true;
2612 wi.info = (void *) &msk;
2613 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2614 if (wi.info != (void *) &msk)
2616 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2617 struct omp_for_data fd;
2618 extract_omp_for_data (for_stmt, &fd, NULL);
2619 /* We need two temporaries with fd.loop.v type (istart/iend)
2620 and then (fd.collapse - 1) temporaries with the same
2621 type for count2 ... countN-1 vars if not constant. */
2622 size_t count = 2, i;
2623 tree type = fd.iter_type;
2624 if (fd.collapse > 1
2625 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2627 count += fd.collapse - 1;
2628 /* If there are lastprivate clauses on the inner
2629 GIMPLE_OMP_FOR, add one more temporaries for the total number
2630 of iterations (product of count1 ... countN-1). */
2631 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2632 OMP_CLAUSE_LASTPRIVATE))
2633 count++;
2634 else if (msk == GF_OMP_FOR_KIND_FOR
2635 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2636 OMP_CLAUSE_LASTPRIVATE))
2637 count++;
2639 for (i = 0; i < count; i++)
2641 tree temp = create_tmp_var (type);
2642 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2643 insert_decl_map (&outer_ctx->cb, temp, temp);
2644 OMP_CLAUSE_DECL (c) = temp;
2645 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2646 gimple_omp_taskreg_set_clauses (stmt, c);
2651 /* Scan an OpenMP parallel directive. */
2653 static void
2654 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2656 omp_context *ctx;
2657 tree name;
2658 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2660 /* Ignore parallel directives with empty bodies, unless there
2661 are copyin clauses. */
2662 if (optimize > 0
2663 && empty_body_p (gimple_omp_body (stmt))
2664 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2665 OMP_CLAUSE_COPYIN) == NULL)
2667 gsi_replace (gsi, gimple_build_nop (), false);
2668 return;
2671 if (gimple_omp_parallel_combined_p (stmt))
2672 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2674 ctx = new_omp_context (stmt, outer_ctx);
2675 taskreg_contexts.safe_push (ctx);
2676 if (taskreg_nesting_level > 1)
2677 ctx->is_nested = true;
2678 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2679 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2680 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2681 name = create_tmp_var_name (".omp_data_s");
2682 name = build_decl (gimple_location (stmt),
2683 TYPE_DECL, name, ctx->record_type);
2684 DECL_ARTIFICIAL (name) = 1;
2685 DECL_NAMELESS (name) = 1;
2686 TYPE_NAME (ctx->record_type) = name;
2687 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2688 if (!gimple_omp_parallel_grid_phony (stmt))
2690 create_omp_child_function (ctx, false);
2691 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2694 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2695 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2697 if (TYPE_FIELDS (ctx->record_type) == NULL)
2698 ctx->record_type = ctx->receiver_decl = NULL;
2701 /* Scan an OpenMP task directive. */
2703 static void
2704 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2706 omp_context *ctx;
2707 tree name, t;
2708 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2710 /* Ignore task directives with empty bodies. */
2711 if (optimize > 0
2712 && empty_body_p (gimple_omp_body (stmt)))
2714 gsi_replace (gsi, gimple_build_nop (), false);
2715 return;
2718 if (gimple_omp_task_taskloop_p (stmt))
2719 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2721 ctx = new_omp_context (stmt, outer_ctx);
2722 taskreg_contexts.safe_push (ctx);
2723 if (taskreg_nesting_level > 1)
2724 ctx->is_nested = true;
2725 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2726 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2727 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2728 name = create_tmp_var_name (".omp_data_s");
2729 name = build_decl (gimple_location (stmt),
2730 TYPE_DECL, name, ctx->record_type);
2731 DECL_ARTIFICIAL (name) = 1;
2732 DECL_NAMELESS (name) = 1;
2733 TYPE_NAME (ctx->record_type) = name;
2734 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2735 create_omp_child_function (ctx, false);
2736 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2738 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2740 if (ctx->srecord_type)
2742 name = create_tmp_var_name (".omp_data_a");
2743 name = build_decl (gimple_location (stmt),
2744 TYPE_DECL, name, ctx->srecord_type);
2745 DECL_ARTIFICIAL (name) = 1;
2746 DECL_NAMELESS (name) = 1;
2747 TYPE_NAME (ctx->srecord_type) = name;
2748 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2749 create_omp_child_function (ctx, true);
2752 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2754 if (TYPE_FIELDS (ctx->record_type) == NULL)
2756 ctx->record_type = ctx->receiver_decl = NULL;
2757 t = build_int_cst (long_integer_type_node, 0);
2758 gimple_omp_task_set_arg_size (stmt, t);
2759 t = build_int_cst (long_integer_type_node, 1);
2760 gimple_omp_task_set_arg_align (stmt, t);
2765 /* If any decls have been made addressable during scan_omp,
2766 adjust their fields if needed, and layout record types
2767 of parallel/task constructs. */
2769 static void
2770 finish_taskreg_scan (omp_context *ctx)
2772 if (ctx->record_type == NULL_TREE)
2773 return;
2775 /* If any task_shared_vars were needed, verify all
2776 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2777 statements if use_pointer_for_field hasn't changed
2778 because of that. If it did, update field types now. */
2779 if (task_shared_vars)
2781 tree c;
2783 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2784 c; c = OMP_CLAUSE_CHAIN (c))
2785 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2786 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2788 tree decl = OMP_CLAUSE_DECL (c);
2790 /* Global variables don't need to be copied,
2791 the receiver side will use them directly. */
2792 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2793 continue;
2794 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2795 || !use_pointer_for_field (decl, ctx))
2796 continue;
2797 tree field = lookup_field (decl, ctx);
2798 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2799 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2800 continue;
2801 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2802 TREE_THIS_VOLATILE (field) = 0;
2803 DECL_USER_ALIGN (field) = 0;
2804 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2805 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2806 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2807 if (ctx->srecord_type)
2809 tree sfield = lookup_sfield (decl, ctx);
2810 TREE_TYPE (sfield) = TREE_TYPE (field);
2811 TREE_THIS_VOLATILE (sfield) = 0;
2812 DECL_USER_ALIGN (sfield) = 0;
2813 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2814 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2815 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2820 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2822 layout_type (ctx->record_type);
2823 fixup_child_record_type (ctx);
2825 else
2827 location_t loc = gimple_location (ctx->stmt);
2828 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2829 /* Move VLA fields to the end. */
2830 p = &TYPE_FIELDS (ctx->record_type);
2831 while (*p)
2832 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2833 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2835 *q = *p;
2836 *p = TREE_CHAIN (*p);
2837 TREE_CHAIN (*q) = NULL_TREE;
2838 q = &TREE_CHAIN (*q);
2840 else
2841 p = &DECL_CHAIN (*p);
2842 *p = vla_fields;
2843 if (gimple_omp_task_taskloop_p (ctx->stmt))
2845 /* Move fields corresponding to first and second _looptemp_
2846 clause first. There are filled by GOMP_taskloop
2847 and thus need to be in specific positions. */
2848 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2849 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2850 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2851 OMP_CLAUSE__LOOPTEMP_);
2852 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2853 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2854 p = &TYPE_FIELDS (ctx->record_type);
2855 while (*p)
2856 if (*p == f1 || *p == f2)
2857 *p = DECL_CHAIN (*p);
2858 else
2859 p = &DECL_CHAIN (*p);
2860 DECL_CHAIN (f1) = f2;
2861 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2862 TYPE_FIELDS (ctx->record_type) = f1;
2863 if (ctx->srecord_type)
2865 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2866 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2867 p = &TYPE_FIELDS (ctx->srecord_type);
2868 while (*p)
2869 if (*p == f1 || *p == f2)
2870 *p = DECL_CHAIN (*p);
2871 else
2872 p = &DECL_CHAIN (*p);
2873 DECL_CHAIN (f1) = f2;
2874 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2875 TYPE_FIELDS (ctx->srecord_type) = f1;
2878 layout_type (ctx->record_type);
2879 fixup_child_record_type (ctx);
2880 if (ctx->srecord_type)
2881 layout_type (ctx->srecord_type);
2882 tree t = fold_convert_loc (loc, long_integer_type_node,
2883 TYPE_SIZE_UNIT (ctx->record_type));
2884 gimple_omp_task_set_arg_size (ctx->stmt, t);
2885 t = build_int_cst (long_integer_type_node,
2886 TYPE_ALIGN_UNIT (ctx->record_type));
2887 gimple_omp_task_set_arg_align (ctx->stmt, t);
2891 /* Find the enclosing offload context. */
2893 static omp_context *
2894 enclosing_target_ctx (omp_context *ctx)
2896 for (; ctx; ctx = ctx->outer)
2897 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2898 break;
2900 return ctx;
2903 /* Return true if ctx is part of an oacc kernels region. */
2905 static bool
2906 ctx_in_oacc_kernels_region (omp_context *ctx)
2908 for (;ctx != NULL; ctx = ctx->outer)
2910 gimple *stmt = ctx->stmt;
2911 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2912 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2913 return true;
2916 return false;
2919 /* Check the parallelism clauses inside a kernels regions.
2920 Until kernels handling moves to use the same loop indirection
2921 scheme as parallel, we need to do this checking early. */
2923 static unsigned
2924 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2926 bool checking = true;
2927 unsigned outer_mask = 0;
2928 unsigned this_mask = 0;
2929 bool has_seq = false, has_auto = false;
2931 if (ctx->outer)
2932 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2933 if (!stmt)
2935 checking = false;
2936 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2937 return outer_mask;
2938 stmt = as_a <gomp_for *> (ctx->stmt);
2941 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2943 switch (OMP_CLAUSE_CODE (c))
2945 case OMP_CLAUSE_GANG:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2947 break;
2948 case OMP_CLAUSE_WORKER:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2950 break;
2951 case OMP_CLAUSE_VECTOR:
2952 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2953 break;
2954 case OMP_CLAUSE_SEQ:
2955 has_seq = true;
2956 break;
2957 case OMP_CLAUSE_AUTO:
2958 has_auto = true;
2959 break;
2960 default:
2961 break;
2965 if (checking)
2967 if (has_seq && (this_mask || has_auto))
2968 error_at (gimple_location (stmt), "%<seq%> overrides other"
2969 " OpenACC loop specifiers");
2970 else if (has_auto && this_mask)
2971 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2972 " OpenACC loop specifiers");
2974 if (this_mask & outer_mask)
2975 error_at (gimple_location (stmt), "inner loop uses same"
2976 " OpenACC parallelism as containing loop");
2979 return outer_mask | this_mask;
2982 /* Scan a GIMPLE_OMP_FOR. */
2984 static void
2985 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2987 omp_context *ctx;
2988 size_t i;
2989 tree clauses = gimple_omp_for_clauses (stmt);
2991 ctx = new_omp_context (stmt, outer_ctx);
2993 if (is_gimple_omp_oacc (stmt))
2995 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2997 if (!tgt || is_oacc_parallel (tgt))
2998 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3000 char const *check = NULL;
3002 switch (OMP_CLAUSE_CODE (c))
3004 case OMP_CLAUSE_GANG:
3005 check = "gang";
3006 break;
3008 case OMP_CLAUSE_WORKER:
3009 check = "worker";
3010 break;
3012 case OMP_CLAUSE_VECTOR:
3013 check = "vector";
3014 break;
3016 default:
3017 break;
3020 if (check && OMP_CLAUSE_OPERAND (c, 0))
3021 error_at (gimple_location (stmt),
3022 "argument not permitted on %qs clause in"
3023 " OpenACC %<parallel%>", check);
3026 if (tgt && is_oacc_kernels (tgt))
3028 /* Strip out reductions, as they are not handled yet. */
3029 tree *prev_ptr = &clauses;
3031 while (tree probe = *prev_ptr)
3033 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3035 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3036 *prev_ptr = *next_ptr;
3037 else
3038 prev_ptr = next_ptr;
3041 gimple_omp_for_set_clauses (stmt, clauses);
3042 check_oacc_kernel_gwv (stmt, ctx);
3046 scan_sharing_clauses (clauses, ctx);
3048 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3049 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3051 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3053 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3054 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3056 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3059 /* Scan an OpenMP sections directive. */
3061 static void
3062 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3064 omp_context *ctx;
3066 ctx = new_omp_context (stmt, outer_ctx);
3067 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3068 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3071 /* Scan an OpenMP single directive. */
3073 static void
3074 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3076 omp_context *ctx;
3077 tree name;
3079 ctx = new_omp_context (stmt, outer_ctx);
3080 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3081 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3082 name = create_tmp_var_name (".omp_copy_s");
3083 name = build_decl (gimple_location (stmt),
3084 TYPE_DECL, name, ctx->record_type);
3085 TYPE_NAME (ctx->record_type) = name;
3087 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3088 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3090 if (TYPE_FIELDS (ctx->record_type) == NULL)
3091 ctx->record_type = NULL;
3092 else
3093 layout_type (ctx->record_type);
3096 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3097 used in the corresponding offloaded function are restrict. */
3099 static bool
3100 omp_target_base_pointers_restrict_p (tree clauses)
3102 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3103 used by OpenACC. */
3104 if (flag_openacc == 0)
3105 return false;
3107 /* I. Basic example:
3109 void foo (void)
3111 unsigned int a[2], b[2];
3113 #pragma acc kernels \
3114 copyout (a) \
3115 copyout (b)
3117 a[0] = 0;
3118 b[0] = 1;
3122 After gimplification, we have:
3124 #pragma omp target oacc_kernels \
3125 map(force_from:a [len: 8]) \
3126 map(force_from:b [len: 8])
3128 a[0] = 0;
3129 b[0] = 1;
3132 Because both mappings have the force prefix, we know that they will be
3133 allocated when calling the corresponding offloaded function, which means we
3134 can mark the base pointers for a and b in the offloaded function as
3135 restrict. */
3137 tree c;
3138 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3140 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3141 return false;
3143 switch (OMP_CLAUSE_MAP_KIND (c))
3145 case GOMP_MAP_FORCE_ALLOC:
3146 case GOMP_MAP_FORCE_TO:
3147 case GOMP_MAP_FORCE_FROM:
3148 case GOMP_MAP_FORCE_TOFROM:
3149 break;
3150 default:
3151 return false;
3155 return true;
3158 /* Scan a GIMPLE_OMP_TARGET. */
3160 static void
3161 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3163 omp_context *ctx;
3164 tree name;
3165 bool offloaded = is_gimple_omp_offloaded (stmt);
3166 tree clauses = gimple_omp_target_clauses (stmt);
3168 ctx = new_omp_context (stmt, outer_ctx);
3169 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3170 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3171 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3172 name = create_tmp_var_name (".omp_data_t");
3173 name = build_decl (gimple_location (stmt),
3174 TYPE_DECL, name, ctx->record_type);
3175 DECL_ARTIFICIAL (name) = 1;
3176 DECL_NAMELESS (name) = 1;
3177 TYPE_NAME (ctx->record_type) = name;
3178 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3180 bool base_pointers_restrict = false;
3181 if (offloaded)
3183 create_omp_child_function (ctx, false);
3184 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3186 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3187 if (base_pointers_restrict
3188 && dump_file && (dump_flags & TDF_DETAILS))
3189 fprintf (dump_file,
3190 "Base pointers in offloaded function are restrict\n");
3193 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3194 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3196 if (TYPE_FIELDS (ctx->record_type) == NULL)
3197 ctx->record_type = ctx->receiver_decl = NULL;
3198 else
3200 TYPE_FIELDS (ctx->record_type)
3201 = nreverse (TYPE_FIELDS (ctx->record_type));
3202 if (flag_checking)
3204 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3205 for (tree field = TYPE_FIELDS (ctx->record_type);
3206 field;
3207 field = DECL_CHAIN (field))
3208 gcc_assert (DECL_ALIGN (field) == align);
3210 layout_type (ctx->record_type);
3211 if (offloaded)
3212 fixup_child_record_type (ctx);
3216 /* Scan an OpenMP teams directive. */
3218 static void
3219 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3221 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3222 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3223 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3226 /* Check nesting restrictions. */
3227 static bool
3228 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3230 tree c;
3232 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3233 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3234 the original copy of its contents. */
3235 return true;
3237 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3238 inside an OpenACC CTX. */
3239 if (!(is_gimple_omp (stmt)
3240 && is_gimple_omp_oacc (stmt))
3241 /* Except for atomic codes that we share with OpenMP. */
3242 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3243 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3245 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3247 error_at (gimple_location (stmt),
3248 "non-OpenACC construct inside of OpenACC routine");
3249 return false;
3251 else
3252 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3253 if (is_gimple_omp (octx->stmt)
3254 && is_gimple_omp_oacc (octx->stmt))
3256 error_at (gimple_location (stmt),
3257 "non-OpenACC construct inside of OpenACC region");
3258 return false;
3262 if (ctx != NULL)
3264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3265 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3267 c = NULL_TREE;
3268 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3270 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3271 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3273 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3274 && (ctx->outer == NULL
3275 || !gimple_omp_for_combined_into_p (ctx->stmt)
3276 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3277 || (gimple_omp_for_kind (ctx->outer->stmt)
3278 != GF_OMP_FOR_KIND_FOR)
3279 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3281 error_at (gimple_location (stmt),
3282 "%<ordered simd threads%> must be closely "
3283 "nested inside of %<for simd%> region");
3284 return false;
3286 return true;
3289 error_at (gimple_location (stmt),
3290 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3291 " may not be nested inside %<simd%> region");
3292 return false;
3294 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3296 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3297 || (gimple_omp_for_kind (stmt)
3298 != GF_OMP_FOR_KIND_DISTRIBUTE))
3299 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3301 error_at (gimple_location (stmt),
3302 "only %<distribute%> or %<parallel%> regions are "
3303 "allowed to be strictly nested inside %<teams%> "
3304 "region");
3305 return false;
3309 switch (gimple_code (stmt))
3311 case GIMPLE_OMP_FOR:
3312 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3313 return true;
3314 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3316 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3318 error_at (gimple_location (stmt),
3319 "%<distribute%> region must be strictly nested "
3320 "inside %<teams%> construct");
3321 return false;
3323 return true;
3325 /* We split taskloop into task and nested taskloop in it. */
3326 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3327 return true;
3328 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3330 bool ok = false;
3332 if (ctx)
3333 switch (gimple_code (ctx->stmt))
3335 case GIMPLE_OMP_FOR:
3336 ok = (gimple_omp_for_kind (ctx->stmt)
3337 == GF_OMP_FOR_KIND_OACC_LOOP);
3338 break;
3340 case GIMPLE_OMP_TARGET:
3341 switch (gimple_omp_target_kind (ctx->stmt))
3343 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3344 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3345 ok = true;
3346 break;
3348 default:
3349 break;
3352 default:
3353 break;
3355 else if (get_oacc_fn_attrib (current_function_decl))
3356 ok = true;
3357 if (!ok)
3359 error_at (gimple_location (stmt),
3360 "OpenACC loop directive must be associated with"
3361 " an OpenACC compute region");
3362 return false;
3365 /* FALLTHRU */
3366 case GIMPLE_CALL:
3367 if (is_gimple_call (stmt)
3368 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCEL
3370 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3371 == BUILT_IN_GOMP_CANCELLATION_POINT))
3373 const char *bad = NULL;
3374 const char *kind = NULL;
3375 const char *construct
3376 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3377 == BUILT_IN_GOMP_CANCEL)
3378 ? "#pragma omp cancel"
3379 : "#pragma omp cancellation point";
3380 if (ctx == NULL)
3382 error_at (gimple_location (stmt), "orphaned %qs construct",
3383 construct);
3384 return false;
3386 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3387 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3388 : 0)
3390 case 1:
3391 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3392 bad = "#pragma omp parallel";
3393 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3394 == BUILT_IN_GOMP_CANCEL
3395 && !integer_zerop (gimple_call_arg (stmt, 1)))
3396 ctx->cancellable = true;
3397 kind = "parallel";
3398 break;
3399 case 2:
3400 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3401 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3402 bad = "#pragma omp for";
3403 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3404 == BUILT_IN_GOMP_CANCEL
3405 && !integer_zerop (gimple_call_arg (stmt, 1)))
3407 ctx->cancellable = true;
3408 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3409 OMP_CLAUSE_NOWAIT))
3410 warning_at (gimple_location (stmt), 0,
3411 "%<#pragma omp cancel for%> inside "
3412 "%<nowait%> for construct");
3413 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3414 OMP_CLAUSE_ORDERED))
3415 warning_at (gimple_location (stmt), 0,
3416 "%<#pragma omp cancel for%> inside "
3417 "%<ordered%> for construct");
3419 kind = "for";
3420 break;
3421 case 4:
3422 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3423 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3424 bad = "#pragma omp sections";
3425 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3426 == BUILT_IN_GOMP_CANCEL
3427 && !integer_zerop (gimple_call_arg (stmt, 1)))
3429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3431 ctx->cancellable = true;
3432 if (find_omp_clause (gimple_omp_sections_clauses
3433 (ctx->stmt),
3434 OMP_CLAUSE_NOWAIT))
3435 warning_at (gimple_location (stmt), 0,
3436 "%<#pragma omp cancel sections%> inside "
3437 "%<nowait%> sections construct");
3439 else
3441 gcc_assert (ctx->outer
3442 && gimple_code (ctx->outer->stmt)
3443 == GIMPLE_OMP_SECTIONS);
3444 ctx->outer->cancellable = true;
3445 if (find_omp_clause (gimple_omp_sections_clauses
3446 (ctx->outer->stmt),
3447 OMP_CLAUSE_NOWAIT))
3448 warning_at (gimple_location (stmt), 0,
3449 "%<#pragma omp cancel sections%> inside "
3450 "%<nowait%> sections construct");
3453 kind = "sections";
3454 break;
3455 case 8:
3456 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3457 bad = "#pragma omp task";
3458 else
3460 for (omp_context *octx = ctx->outer;
3461 octx; octx = octx->outer)
3463 switch (gimple_code (octx->stmt))
3465 case GIMPLE_OMP_TASKGROUP:
3466 break;
3467 case GIMPLE_OMP_TARGET:
3468 if (gimple_omp_target_kind (octx->stmt)
3469 != GF_OMP_TARGET_KIND_REGION)
3470 continue;
3471 /* FALLTHRU */
3472 case GIMPLE_OMP_PARALLEL:
3473 case GIMPLE_OMP_TEAMS:
3474 error_at (gimple_location (stmt),
3475 "%<%s taskgroup%> construct not closely "
3476 "nested inside of %<taskgroup%> region",
3477 construct);
3478 return false;
3479 default:
3480 continue;
3482 break;
3484 ctx->cancellable = true;
3486 kind = "taskgroup";
3487 break;
3488 default:
3489 error_at (gimple_location (stmt), "invalid arguments");
3490 return false;
3492 if (bad)
3494 error_at (gimple_location (stmt),
3495 "%<%s %s%> construct not closely nested inside of %qs",
3496 construct, kind, bad);
3497 return false;
3500 /* FALLTHRU */
3501 case GIMPLE_OMP_SECTIONS:
3502 case GIMPLE_OMP_SINGLE:
3503 for (; ctx != NULL; ctx = ctx->outer)
3504 switch (gimple_code (ctx->stmt))
3506 case GIMPLE_OMP_FOR:
3507 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3508 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3509 break;
3510 /* FALLTHRU */
3511 case GIMPLE_OMP_SECTIONS:
3512 case GIMPLE_OMP_SINGLE:
3513 case GIMPLE_OMP_ORDERED:
3514 case GIMPLE_OMP_MASTER:
3515 case GIMPLE_OMP_TASK:
3516 case GIMPLE_OMP_CRITICAL:
3517 if (is_gimple_call (stmt))
3519 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3520 != BUILT_IN_GOMP_BARRIER)
3521 return true;
3522 error_at (gimple_location (stmt),
3523 "barrier region may not be closely nested inside "
3524 "of work-sharing, %<critical%>, %<ordered%>, "
3525 "%<master%>, explicit %<task%> or %<taskloop%> "
3526 "region");
3527 return false;
3529 error_at (gimple_location (stmt),
3530 "work-sharing region may not be closely nested inside "
3531 "of work-sharing, %<critical%>, %<ordered%>, "
3532 "%<master%>, explicit %<task%> or %<taskloop%> region");
3533 return false;
3534 case GIMPLE_OMP_PARALLEL:
3535 case GIMPLE_OMP_TEAMS:
3536 return true;
3537 case GIMPLE_OMP_TARGET:
3538 if (gimple_omp_target_kind (ctx->stmt)
3539 == GF_OMP_TARGET_KIND_REGION)
3540 return true;
3541 break;
3542 default:
3543 break;
3545 break;
3546 case GIMPLE_OMP_MASTER:
3547 for (; ctx != NULL; ctx = ctx->outer)
3548 switch (gimple_code (ctx->stmt))
3550 case GIMPLE_OMP_FOR:
3551 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3552 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3553 break;
3554 /* FALLTHRU */
3555 case GIMPLE_OMP_SECTIONS:
3556 case GIMPLE_OMP_SINGLE:
3557 case GIMPLE_OMP_TASK:
3558 error_at (gimple_location (stmt),
3559 "%<master%> region may not be closely nested inside "
3560 "of work-sharing, explicit %<task%> or %<taskloop%> "
3561 "region");
3562 return false;
3563 case GIMPLE_OMP_PARALLEL:
3564 case GIMPLE_OMP_TEAMS:
3565 return true;
3566 case GIMPLE_OMP_TARGET:
3567 if (gimple_omp_target_kind (ctx->stmt)
3568 == GF_OMP_TARGET_KIND_REGION)
3569 return true;
3570 break;
3571 default:
3572 break;
3574 break;
3575 case GIMPLE_OMP_TASK:
3576 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3578 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3579 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3581 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3582 error_at (OMP_CLAUSE_LOCATION (c),
3583 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3584 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3585 return false;
3587 break;
3588 case GIMPLE_OMP_ORDERED:
3589 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3590 c; c = OMP_CLAUSE_CHAIN (c))
3592 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3594 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3595 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3596 continue;
3598 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3599 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3600 || kind == OMP_CLAUSE_DEPEND_SINK)
3602 tree oclause;
3603 /* Look for containing ordered(N) loop. */
3604 if (ctx == NULL
3605 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3606 || (oclause
3607 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3608 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3610 error_at (OMP_CLAUSE_LOCATION (c),
3611 "%<ordered%> construct with %<depend%> clause "
3612 "must be closely nested inside an %<ordered%> "
3613 "loop");
3614 return false;
3616 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3618 error_at (OMP_CLAUSE_LOCATION (c),
3619 "%<ordered%> construct with %<depend%> clause "
3620 "must be closely nested inside a loop with "
3621 "%<ordered%> clause with a parameter");
3622 return false;
3625 else
3627 error_at (OMP_CLAUSE_LOCATION (c),
3628 "invalid depend kind in omp %<ordered%> %<depend%>");
3629 return false;
3632 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3633 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3635 /* ordered simd must be closely nested inside of simd region,
3636 and simd region must not encounter constructs other than
3637 ordered simd, therefore ordered simd may be either orphaned,
3638 or ctx->stmt must be simd. The latter case is handled already
3639 earlier. */
3640 if (ctx != NULL)
3642 error_at (gimple_location (stmt),
3643 "%<ordered%> %<simd%> must be closely nested inside "
3644 "%<simd%> region");
3645 return false;
3648 for (; ctx != NULL; ctx = ctx->outer)
3649 switch (gimple_code (ctx->stmt))
3651 case GIMPLE_OMP_CRITICAL:
3652 case GIMPLE_OMP_TASK:
3653 case GIMPLE_OMP_ORDERED:
3654 ordered_in_taskloop:
3655 error_at (gimple_location (stmt),
3656 "%<ordered%> region may not be closely nested inside "
3657 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3658 "%<taskloop%> region");
3659 return false;
3660 case GIMPLE_OMP_FOR:
3661 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3662 goto ordered_in_taskloop;
3663 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3664 OMP_CLAUSE_ORDERED) == NULL)
3666 error_at (gimple_location (stmt),
3667 "%<ordered%> region must be closely nested inside "
3668 "a loop region with an %<ordered%> clause");
3669 return false;
3671 return true;
3672 case GIMPLE_OMP_TARGET:
3673 if (gimple_omp_target_kind (ctx->stmt)
3674 != GF_OMP_TARGET_KIND_REGION)
3675 break;
3676 /* FALLTHRU */
3677 case GIMPLE_OMP_PARALLEL:
3678 case GIMPLE_OMP_TEAMS:
3679 error_at (gimple_location (stmt),
3680 "%<ordered%> region must be closely nested inside "
3681 "a loop region with an %<ordered%> clause");
3682 return false;
3683 default:
3684 break;
3686 break;
3687 case GIMPLE_OMP_CRITICAL:
3689 tree this_stmt_name
3690 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3691 for (; ctx != NULL; ctx = ctx->outer)
3692 if (gomp_critical *other_crit
3693 = dyn_cast <gomp_critical *> (ctx->stmt))
3694 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3696 error_at (gimple_location (stmt),
3697 "%<critical%> region may not be nested inside "
3698 "a %<critical%> region with the same name");
3699 return false;
3702 break;
3703 case GIMPLE_OMP_TEAMS:
3704 if (ctx == NULL
3705 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3706 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3708 error_at (gimple_location (stmt),
3709 "%<teams%> construct not closely nested inside of "
3710 "%<target%> construct");
3711 return false;
3713 break;
3714 case GIMPLE_OMP_TARGET:
3715 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3716 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3717 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3718 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3720 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3721 error_at (OMP_CLAUSE_LOCATION (c),
3722 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3723 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3724 return false;
3726 if (is_gimple_omp_offloaded (stmt)
3727 && get_oacc_fn_attrib (cfun->decl) != NULL)
3729 error_at (gimple_location (stmt),
3730 "OpenACC region inside of OpenACC routine, nested "
3731 "parallelism not supported yet");
3732 return false;
3734 for (; ctx != NULL; ctx = ctx->outer)
3736 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3738 if (is_gimple_omp (stmt)
3739 && is_gimple_omp_oacc (stmt)
3740 && is_gimple_omp (ctx->stmt))
3742 error_at (gimple_location (stmt),
3743 "OpenACC construct inside of non-OpenACC region");
3744 return false;
3746 continue;
3749 const char *stmt_name, *ctx_stmt_name;
3750 switch (gimple_omp_target_kind (stmt))
3752 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3753 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3754 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3755 case GF_OMP_TARGET_KIND_ENTER_DATA:
3756 stmt_name = "target enter data"; break;
3757 case GF_OMP_TARGET_KIND_EXIT_DATA:
3758 stmt_name = "target exit data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3760 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3761 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3763 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3764 stmt_name = "enter/exit data"; break;
3765 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3766 break;
3767 default: gcc_unreachable ();
3769 switch (gimple_omp_target_kind (ctx->stmt))
3771 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3772 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3773 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3774 ctx_stmt_name = "parallel"; break;
3775 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3776 ctx_stmt_name = "kernels"; break;
3777 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3778 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3779 ctx_stmt_name = "host_data"; break;
3780 default: gcc_unreachable ();
3783 /* OpenACC/OpenMP mismatch? */
3784 if (is_gimple_omp_oacc (stmt)
3785 != is_gimple_omp_oacc (ctx->stmt))
3787 error_at (gimple_location (stmt),
3788 "%s %qs construct inside of %s %qs region",
3789 (is_gimple_omp_oacc (stmt)
3790 ? "OpenACC" : "OpenMP"), stmt_name,
3791 (is_gimple_omp_oacc (ctx->stmt)
3792 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3793 return false;
3795 if (is_gimple_omp_offloaded (ctx->stmt))
3797 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3798 if (is_gimple_omp_oacc (ctx->stmt))
3800 error_at (gimple_location (stmt),
3801 "%qs construct inside of %qs region",
3802 stmt_name, ctx_stmt_name);
3803 return false;
3805 else
3807 warning_at (gimple_location (stmt), 0,
3808 "%qs construct inside of %qs region",
3809 stmt_name, ctx_stmt_name);
3813 break;
3814 default:
3815 break;
3817 return true;
3821 /* Helper function scan_omp.
3823 Callback for walk_tree or operators in walk_gimple_stmt used to
3824 scan for OMP directives in TP. */
3826 static tree
3827 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3829 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3830 omp_context *ctx = (omp_context *) wi->info;
3831 tree t = *tp;
3833 switch (TREE_CODE (t))
3835 case VAR_DECL:
3836 case PARM_DECL:
3837 case LABEL_DECL:
3838 case RESULT_DECL:
3839 if (ctx)
3841 tree repl = remap_decl (t, &ctx->cb);
3842 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3843 *tp = repl;
3845 break;
3847 default:
3848 if (ctx && TYPE_P (t))
3849 *tp = remap_type (t, &ctx->cb);
3850 else if (!DECL_P (t))
3852 *walk_subtrees = 1;
3853 if (ctx)
3855 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3856 if (tem != TREE_TYPE (t))
3858 if (TREE_CODE (t) == INTEGER_CST)
3859 *tp = wide_int_to_tree (tem, t);
3860 else
3861 TREE_TYPE (t) = tem;
3865 break;
3868 return NULL_TREE;
3871 /* Return true if FNDECL is a setjmp or a longjmp. */
3873 static bool
3874 setjmp_or_longjmp_p (const_tree fndecl)
3876 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3877 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3878 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3879 return true;
3881 tree declname = DECL_NAME (fndecl);
3882 if (!declname)
3883 return false;
3884 const char *name = IDENTIFIER_POINTER (declname);
3885 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3889 /* Helper function for scan_omp.
3891 Callback for walk_gimple_stmt used to scan for OMP directives in
3892 the current statement in GSI. */
3894 static tree
3895 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3896 struct walk_stmt_info *wi)
3898 gimple *stmt = gsi_stmt (*gsi);
3899 omp_context *ctx = (omp_context *) wi->info;
3901 if (gimple_has_location (stmt))
3902 input_location = gimple_location (stmt);
3904 /* Check the nesting restrictions. */
3905 bool remove = false;
3906 if (is_gimple_omp (stmt))
3907 remove = !check_omp_nesting_restrictions (stmt, ctx);
3908 else if (is_gimple_call (stmt))
3910 tree fndecl = gimple_call_fndecl (stmt);
3911 if (fndecl)
3913 if (setjmp_or_longjmp_p (fndecl)
3914 && ctx
3915 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3916 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3918 remove = true;
3919 error_at (gimple_location (stmt),
3920 "setjmp/longjmp inside simd construct");
3922 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3923 switch (DECL_FUNCTION_CODE (fndecl))
3925 case BUILT_IN_GOMP_BARRIER:
3926 case BUILT_IN_GOMP_CANCEL:
3927 case BUILT_IN_GOMP_CANCELLATION_POINT:
3928 case BUILT_IN_GOMP_TASKYIELD:
3929 case BUILT_IN_GOMP_TASKWAIT:
3930 case BUILT_IN_GOMP_TASKGROUP_START:
3931 case BUILT_IN_GOMP_TASKGROUP_END:
3932 remove = !check_omp_nesting_restrictions (stmt, ctx);
3933 break;
3934 default:
3935 break;
3939 if (remove)
3941 stmt = gimple_build_nop ();
3942 gsi_replace (gsi, stmt, false);
3945 *handled_ops_p = true;
3947 switch (gimple_code (stmt))
3949 case GIMPLE_OMP_PARALLEL:
3950 taskreg_nesting_level++;
3951 scan_omp_parallel (gsi, ctx);
3952 taskreg_nesting_level--;
3953 break;
3955 case GIMPLE_OMP_TASK:
3956 taskreg_nesting_level++;
3957 scan_omp_task (gsi, ctx);
3958 taskreg_nesting_level--;
3959 break;
3961 case GIMPLE_OMP_FOR:
3962 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3963 break;
3965 case GIMPLE_OMP_SECTIONS:
3966 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3967 break;
3969 case GIMPLE_OMP_SINGLE:
3970 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3971 break;
3973 case GIMPLE_OMP_SECTION:
3974 case GIMPLE_OMP_MASTER:
3975 case GIMPLE_OMP_TASKGROUP:
3976 case GIMPLE_OMP_ORDERED:
3977 case GIMPLE_OMP_CRITICAL:
3978 case GIMPLE_OMP_GRID_BODY:
3979 ctx = new_omp_context (stmt, ctx);
3980 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3981 break;
3983 case GIMPLE_OMP_TARGET:
3984 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3985 break;
3987 case GIMPLE_OMP_TEAMS:
3988 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3989 break;
3991 case GIMPLE_BIND:
3993 tree var;
3995 *handled_ops_p = false;
3996 if (ctx)
3997 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3998 var ;
3999 var = DECL_CHAIN (var))
4000 insert_decl_map (&ctx->cb, var, var);
4002 break;
4003 default:
4004 *handled_ops_p = false;
4005 break;
4008 return NULL_TREE;
4012 /* Scan all the statements starting at the current statement. CTX
4013 contains context information about the OMP directives and
4014 clauses found during the scan. */
4016 static void
4017 scan_omp (gimple_seq *body_p, omp_context *ctx)
4019 location_t saved_location;
4020 struct walk_stmt_info wi;
4022 memset (&wi, 0, sizeof (wi));
4023 wi.info = ctx;
4024 wi.want_locations = true;
4026 saved_location = input_location;
4027 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4028 input_location = saved_location;
4031 /* Re-gimplification and code generation routines. */
4033 /* Build a call to GOMP_barrier. */
4035 static gimple *
4036 build_omp_barrier (tree lhs)
4038 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4039 : BUILT_IN_GOMP_BARRIER);
4040 gcall *g = gimple_build_call (fndecl, 0);
4041 if (lhs)
4042 gimple_call_set_lhs (g, lhs);
4043 return g;
4046 /* If a context was created for STMT when it was scanned, return it. */
4048 static omp_context *
4049 maybe_lookup_ctx (gimple *stmt)
4051 splay_tree_node n;
4052 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4053 return n ? (omp_context *) n->value : NULL;
4057 /* Find the mapping for DECL in CTX or the immediately enclosing
4058 context that has a mapping for DECL.
4060 If CTX is a nested parallel directive, we may have to use the decl
4061 mappings created in CTX's parent context. Suppose that we have the
4062 following parallel nesting (variable UIDs showed for clarity):
4064 iD.1562 = 0;
4065 #omp parallel shared(iD.1562) -> outer parallel
4066 iD.1562 = iD.1562 + 1;
4068 #omp parallel shared (iD.1562) -> inner parallel
4069 iD.1562 = iD.1562 - 1;
4071 Each parallel structure will create a distinct .omp_data_s structure
4072 for copying iD.1562 in/out of the directive:
4074 outer parallel .omp_data_s.1.i -> iD.1562
4075 inner parallel .omp_data_s.2.i -> iD.1562
4077 A shared variable mapping will produce a copy-out operation before
4078 the parallel directive and a copy-in operation after it. So, in
4079 this case we would have:
4081 iD.1562 = 0;
4082 .omp_data_o.1.i = iD.1562;
4083 #omp parallel shared(iD.1562) -> outer parallel
4084 .omp_data_i.1 = &.omp_data_o.1
4085 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4087 .omp_data_o.2.i = iD.1562; -> **
4088 #omp parallel shared(iD.1562) -> inner parallel
4089 .omp_data_i.2 = &.omp_data_o.2
4090 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4093 ** This is a problem. The symbol iD.1562 cannot be referenced
4094 inside the body of the outer parallel region. But since we are
4095 emitting this copy operation while expanding the inner parallel
4096 directive, we need to access the CTX structure of the outer
4097 parallel directive to get the correct mapping:
4099 .omp_data_o.2.i = .omp_data_i.1->i
4101 Since there may be other workshare or parallel directives enclosing
4102 the parallel directive, it may be necessary to walk up the context
4103 parent chain. This is not a problem in general because nested
4104 parallelism happens only rarely. */
4106 static tree
4107 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4109 tree t;
4110 omp_context *up;
4112 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4113 t = maybe_lookup_decl (decl, up);
4115 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4117 return t ? t : decl;
4121 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4122 in outer contexts. */
4124 static tree
4125 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4127 tree t = NULL;
4128 omp_context *up;
4130 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4131 t = maybe_lookup_decl (decl, up);
4133 return t ? t : decl;
4137 /* Construct the initialization value for reduction operation OP. */
4139 tree
4140 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4142 switch (op)
4144 case PLUS_EXPR:
4145 case MINUS_EXPR:
4146 case BIT_IOR_EXPR:
4147 case BIT_XOR_EXPR:
4148 case TRUTH_OR_EXPR:
4149 case TRUTH_ORIF_EXPR:
4150 case TRUTH_XOR_EXPR:
4151 case NE_EXPR:
4152 return build_zero_cst (type);
4154 case MULT_EXPR:
4155 case TRUTH_AND_EXPR:
4156 case TRUTH_ANDIF_EXPR:
4157 case EQ_EXPR:
4158 return fold_convert_loc (loc, type, integer_one_node);
4160 case BIT_AND_EXPR:
4161 return fold_convert_loc (loc, type, integer_minus_one_node);
4163 case MAX_EXPR:
4164 if (SCALAR_FLOAT_TYPE_P (type))
4166 REAL_VALUE_TYPE max, min;
4167 if (HONOR_INFINITIES (type))
4169 real_inf (&max);
4170 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4172 else
4173 real_maxval (&min, 1, TYPE_MODE (type));
4174 return build_real (type, min);
4176 else if (POINTER_TYPE_P (type))
4178 wide_int min
4179 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4180 return wide_int_to_tree (type, min);
4182 else
4184 gcc_assert (INTEGRAL_TYPE_P (type));
4185 return TYPE_MIN_VALUE (type);
4188 case MIN_EXPR:
4189 if (SCALAR_FLOAT_TYPE_P (type))
4191 REAL_VALUE_TYPE max;
4192 if (HONOR_INFINITIES (type))
4193 real_inf (&max);
4194 else
4195 real_maxval (&max, 0, TYPE_MODE (type));
4196 return build_real (type, max);
4198 else if (POINTER_TYPE_P (type))
4200 wide_int max
4201 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4202 return wide_int_to_tree (type, max);
4204 else
4206 gcc_assert (INTEGRAL_TYPE_P (type));
4207 return TYPE_MAX_VALUE (type);
4210 default:
4211 gcc_unreachable ();
4215 /* Construct the initialization value for reduction CLAUSE. */
4217 tree
4218 omp_reduction_init (tree clause, tree type)
4220 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4221 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4224 /* Return alignment to be assumed for var in CLAUSE, which should be
4225 OMP_CLAUSE_ALIGNED. */
4227 static tree
4228 omp_clause_aligned_alignment (tree clause)
4230 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4231 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4233 /* Otherwise return implementation defined alignment. */
4234 unsigned int al = 1;
4235 machine_mode mode, vmode;
4236 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4237 if (vs)
4238 vs = 1 << floor_log2 (vs);
4239 static enum mode_class classes[]
4240 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4241 for (int i = 0; i < 4; i += 2)
4242 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4243 mode != VOIDmode;
4244 mode = GET_MODE_WIDER_MODE (mode))
4246 vmode = targetm.vectorize.preferred_simd_mode (mode);
4247 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4248 continue;
4249 while (vs
4250 && GET_MODE_SIZE (vmode) < vs
4251 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4252 vmode = GET_MODE_2XWIDER_MODE (vmode);
4254 tree type = lang_hooks.types.type_for_mode (mode, 1);
4255 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4256 continue;
4257 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4258 / GET_MODE_SIZE (mode));
4259 if (TYPE_MODE (type) != vmode)
4260 continue;
4261 if (TYPE_ALIGN_UNIT (type) > al)
4262 al = TYPE_ALIGN_UNIT (type);
4264 return build_int_cst (integer_type_node, al);
4267 /* Return maximum possible vectorization factor for the target. */
4269 static int
4270 omp_max_vf (void)
4272 if (!optimize
4273 || optimize_debug
4274 || !flag_tree_loop_optimize
4275 || (!flag_tree_loop_vectorize
4276 && (global_options_set.x_flag_tree_loop_vectorize
4277 || global_options_set.x_flag_tree_vectorize)))
4278 return 1;
4280 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4281 if (vs)
4283 vs = 1 << floor_log2 (vs);
4284 return vs;
4286 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4287 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4288 return GET_MODE_NUNITS (vqimode);
4289 return 1;
4292 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4293 privatization. */
4295 static bool
4296 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4297 tree &idx, tree &lane, tree &ivar, tree &lvar)
4299 if (max_vf == 0)
4301 max_vf = omp_max_vf ();
4302 if (max_vf > 1)
4304 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4305 OMP_CLAUSE_SAFELEN);
4306 if (c
4307 && (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST
4308 || tree_int_cst_sgn (OMP_CLAUSE_SAFELEN_EXPR (c)) != 1))
4309 max_vf = 1;
4310 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4311 max_vf) == -1)
4312 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4314 if (max_vf > 1)
4316 idx = create_tmp_var (unsigned_type_node);
4317 lane = create_tmp_var (unsigned_type_node);
4320 if (max_vf == 1)
4321 return false;
4323 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4324 tree avar = create_tmp_var_raw (atype);
4325 if (TREE_ADDRESSABLE (new_var))
4326 TREE_ADDRESSABLE (avar) = 1;
4327 DECL_ATTRIBUTES (avar)
4328 = tree_cons (get_identifier ("omp simd array"), NULL,
4329 DECL_ATTRIBUTES (avar));
4330 gimple_add_tmp_var (avar);
4331 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4332 NULL_TREE, NULL_TREE);
4333 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4334 NULL_TREE, NULL_TREE);
4335 if (DECL_P (new_var))
4337 SET_DECL_VALUE_EXPR (new_var, lvar);
4338 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4340 return true;
4343 /* Helper function of lower_rec_input_clauses. For a reference
4344 in simd reduction, add an underlying variable it will reference. */
4346 static void
4347 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4349 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4350 if (TREE_CONSTANT (z))
4352 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4353 get_name (new_vard));
4354 gimple_add_tmp_var (z);
4355 TREE_ADDRESSABLE (z) = 1;
4356 z = build_fold_addr_expr_loc (loc, z);
4357 gimplify_assign (new_vard, z, ilist);
4361 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4362 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4363 private variables. Initialization statements go in ILIST, while calls
4364 to destructors go in DLIST. */
4366 static void
4367 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4368 omp_context *ctx, struct omp_for_data *fd)
4370 tree c, dtor, copyin_seq, x, ptr;
4371 bool copyin_by_ref = false;
4372 bool lastprivate_firstprivate = false;
4373 bool reduction_omp_orig_ref = false;
4374 int pass;
4375 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4376 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4377 int max_vf = 0;
4378 tree lane = NULL_TREE, idx = NULL_TREE;
4379 tree ivar = NULL_TREE, lvar = NULL_TREE;
4380 gimple_seq llist[2] = { NULL, NULL };
4382 copyin_seq = NULL;
4384 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4385 with data sharing clauses referencing variable sized vars. That
4386 is unnecessarily hard to support and very unlikely to result in
4387 vectorized code anyway. */
4388 if (is_simd)
4389 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4390 switch (OMP_CLAUSE_CODE (c))
4392 case OMP_CLAUSE_LINEAR:
4393 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4394 max_vf = 1;
4395 /* FALLTHRU */
4396 case OMP_CLAUSE_PRIVATE:
4397 case OMP_CLAUSE_FIRSTPRIVATE:
4398 case OMP_CLAUSE_LASTPRIVATE:
4399 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4400 max_vf = 1;
4401 break;
4402 case OMP_CLAUSE_REDUCTION:
4403 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4404 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4405 max_vf = 1;
4406 break;
4407 default:
4408 continue;
4411 /* Do all the fixed sized types in the first pass, and the variable sized
4412 types in the second pass. This makes sure that the scalar arguments to
4413 the variable sized types are processed before we use them in the
4414 variable sized operations. */
4415 for (pass = 0; pass < 2; ++pass)
4417 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4419 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4420 tree var, new_var;
4421 bool by_ref;
4422 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4424 switch (c_kind)
4426 case OMP_CLAUSE_PRIVATE:
4427 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4428 continue;
4429 break;
4430 case OMP_CLAUSE_SHARED:
4431 /* Ignore shared directives in teams construct. */
4432 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4433 continue;
4434 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4436 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4437 || is_global_var (OMP_CLAUSE_DECL (c)));
4438 continue;
4440 case OMP_CLAUSE_FIRSTPRIVATE:
4441 case OMP_CLAUSE_COPYIN:
4442 break;
4443 case OMP_CLAUSE_LINEAR:
4444 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4445 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4446 lastprivate_firstprivate = true;
4447 break;
4448 case OMP_CLAUSE_REDUCTION:
4449 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4450 reduction_omp_orig_ref = true;
4451 break;
4452 case OMP_CLAUSE__LOOPTEMP_:
4453 /* Handle _looptemp_ clauses only on parallel/task. */
4454 if (fd)
4455 continue;
4456 break;
4457 case OMP_CLAUSE_LASTPRIVATE:
4458 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4460 lastprivate_firstprivate = true;
4461 if (pass != 0 || is_taskloop_ctx (ctx))
4462 continue;
4464 /* Even without corresponding firstprivate, if
4465 decl is Fortran allocatable, it needs outer var
4466 reference. */
4467 else if (pass == 0
4468 && lang_hooks.decls.omp_private_outer_ref
4469 (OMP_CLAUSE_DECL (c)))
4470 lastprivate_firstprivate = true;
4471 break;
4472 case OMP_CLAUSE_ALIGNED:
4473 if (pass == 0)
4474 continue;
4475 var = OMP_CLAUSE_DECL (c);
4476 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4477 && !is_global_var (var))
4479 new_var = maybe_lookup_decl (var, ctx);
4480 if (new_var == NULL_TREE)
4481 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4482 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4483 tree alarg = omp_clause_aligned_alignment (c);
4484 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4485 x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
4486 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4487 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4488 gimplify_and_add (x, ilist);
4490 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4491 && is_global_var (var))
4493 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4494 new_var = lookup_decl (var, ctx);
4495 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4496 t = build_fold_addr_expr_loc (clause_loc, t);
4497 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4498 tree alarg = omp_clause_aligned_alignment (c);
4499 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4500 t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
4501 t = fold_convert_loc (clause_loc, ptype, t);
4502 x = create_tmp_var (ptype);
4503 t = build2 (MODIFY_EXPR, ptype, x, t);
4504 gimplify_and_add (t, ilist);
4505 t = build_simple_mem_ref_loc (clause_loc, x);
4506 SET_DECL_VALUE_EXPR (new_var, t);
4507 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4509 continue;
4510 default:
4511 continue;
4514 new_var = var = OMP_CLAUSE_DECL (c);
4515 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4517 var = TREE_OPERAND (var, 0);
4518 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4519 var = TREE_OPERAND (var, 0);
4520 if (TREE_CODE (var) == INDIRECT_REF
4521 || TREE_CODE (var) == ADDR_EXPR)
4522 var = TREE_OPERAND (var, 0);
4523 if (is_variable_sized (var))
4525 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4526 var = DECL_VALUE_EXPR (var);
4527 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4528 var = TREE_OPERAND (var, 0);
4529 gcc_assert (DECL_P (var));
4531 new_var = var;
4533 if (c_kind != OMP_CLAUSE_COPYIN)
4534 new_var = lookup_decl (var, ctx);
4536 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4538 if (pass != 0)
4539 continue;
4541 /* C/C++ array section reductions. */
4542 else if (c_kind == OMP_CLAUSE_REDUCTION
4543 && var != OMP_CLAUSE_DECL (c))
4545 if (pass == 0)
4546 continue;
4548 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4549 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4550 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4552 tree b = TREE_OPERAND (orig_var, 1);
4553 b = maybe_lookup_decl (b, ctx);
4554 if (b == NULL)
4556 b = TREE_OPERAND (orig_var, 1);
4557 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4559 if (integer_zerop (bias))
4560 bias = b;
4561 else
4563 bias = fold_convert_loc (clause_loc,
4564 TREE_TYPE (b), bias);
4565 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4566 TREE_TYPE (b), b, bias);
4568 orig_var = TREE_OPERAND (orig_var, 0);
4570 if (TREE_CODE (orig_var) == INDIRECT_REF
4571 || TREE_CODE (orig_var) == ADDR_EXPR)
4572 orig_var = TREE_OPERAND (orig_var, 0);
4573 tree d = OMP_CLAUSE_DECL (c);
4574 tree type = TREE_TYPE (d);
4575 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4576 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4577 const char *name = get_name (orig_var);
4578 if (TREE_CONSTANT (v))
4580 x = create_tmp_var_raw (type, name);
4581 gimple_add_tmp_var (x);
4582 TREE_ADDRESSABLE (x) = 1;
4583 x = build_fold_addr_expr_loc (clause_loc, x);
4585 else
4587 tree atmp
4588 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4589 tree t = maybe_lookup_decl (v, ctx);
4590 if (t)
4591 v = t;
4592 else
4593 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4594 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4595 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4596 TREE_TYPE (v), v,
4597 build_int_cst (TREE_TYPE (v), 1));
4598 t = fold_build2_loc (clause_loc, MULT_EXPR,
4599 TREE_TYPE (v), t,
4600 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4601 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4602 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4605 tree ptype = build_pointer_type (TREE_TYPE (type));
4606 x = fold_convert_loc (clause_loc, ptype, x);
4607 tree y = create_tmp_var (ptype, name);
4608 gimplify_assign (y, x, ilist);
4609 x = y;
4610 tree yb = y;
4612 if (!integer_zerop (bias))
4614 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4615 bias);
4616 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4618 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4619 pointer_sized_int_node, yb, bias);
4620 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4621 yb = create_tmp_var (ptype, name);
4622 gimplify_assign (yb, x, ilist);
4623 x = yb;
4626 d = TREE_OPERAND (d, 0);
4627 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4628 d = TREE_OPERAND (d, 0);
4629 if (TREE_CODE (d) == ADDR_EXPR)
4631 if (orig_var != var)
4633 gcc_assert (is_variable_sized (orig_var));
4634 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4636 gimplify_assign (new_var, x, ilist);
4637 tree new_orig_var = lookup_decl (orig_var, ctx);
4638 tree t = build_fold_indirect_ref (new_var);
4639 DECL_IGNORED_P (new_var) = 0;
4640 TREE_THIS_NOTRAP (t);
4641 SET_DECL_VALUE_EXPR (new_orig_var, t);
4642 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4644 else
4646 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4647 build_int_cst (ptype, 0));
4648 SET_DECL_VALUE_EXPR (new_var, x);
4649 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4652 else
4654 gcc_assert (orig_var == var);
4655 if (TREE_CODE (d) == INDIRECT_REF)
4657 x = create_tmp_var (ptype, name);
4658 TREE_ADDRESSABLE (x) = 1;
4659 gimplify_assign (x, yb, ilist);
4660 x = build_fold_addr_expr_loc (clause_loc, x);
4662 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4663 gimplify_assign (new_var, x, ilist);
4665 tree y1 = create_tmp_var (ptype, NULL);
4666 gimplify_assign (y1, y, ilist);
4667 tree i2 = NULL_TREE, y2 = NULL_TREE;
4668 tree body2 = NULL_TREE, end2 = NULL_TREE;
4669 tree y3 = NULL_TREE, y4 = NULL_TREE;
4670 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4672 y2 = create_tmp_var (ptype, NULL);
4673 gimplify_assign (y2, y, ilist);
4674 tree ref = build_outer_var_ref (var, ctx);
4675 /* For ref build_outer_var_ref already performs this. */
4676 if (TREE_CODE (d) == INDIRECT_REF)
4677 gcc_assert (is_reference (var));
4678 else if (TREE_CODE (d) == ADDR_EXPR)
4679 ref = build_fold_addr_expr (ref);
4680 else if (is_reference (var))
4681 ref = build_fold_addr_expr (ref);
4682 ref = fold_convert_loc (clause_loc, ptype, ref);
4683 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4684 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4686 y3 = create_tmp_var (ptype, NULL);
4687 gimplify_assign (y3, unshare_expr (ref), ilist);
4689 if (is_simd)
4691 y4 = create_tmp_var (ptype, NULL);
4692 gimplify_assign (y4, ref, dlist);
4695 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4696 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4697 tree body = create_artificial_label (UNKNOWN_LOCATION);
4698 tree end = create_artificial_label (UNKNOWN_LOCATION);
4699 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4700 if (y2)
4702 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4703 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4704 body2 = create_artificial_label (UNKNOWN_LOCATION);
4705 end2 = create_artificial_label (UNKNOWN_LOCATION);
4706 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4708 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4710 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4711 tree decl_placeholder
4712 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4713 SET_DECL_VALUE_EXPR (decl_placeholder,
4714 build_simple_mem_ref (y1));
4715 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4716 SET_DECL_VALUE_EXPR (placeholder,
4717 y3 ? build_simple_mem_ref (y3)
4718 : error_mark_node);
4719 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4720 x = lang_hooks.decls.omp_clause_default_ctor
4721 (c, build_simple_mem_ref (y1),
4722 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4723 if (x)
4724 gimplify_and_add (x, ilist);
4725 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4727 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4728 lower_omp (&tseq, ctx);
4729 gimple_seq_add_seq (ilist, tseq);
4731 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4732 if (is_simd)
4734 SET_DECL_VALUE_EXPR (decl_placeholder,
4735 build_simple_mem_ref (y2));
4736 SET_DECL_VALUE_EXPR (placeholder,
4737 build_simple_mem_ref (y4));
4738 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4739 lower_omp (&tseq, ctx);
4740 gimple_seq_add_seq (dlist, tseq);
4741 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4743 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4744 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4745 x = lang_hooks.decls.omp_clause_dtor
4746 (c, build_simple_mem_ref (y2));
4747 if (x)
4749 gimple_seq tseq = NULL;
4750 dtor = x;
4751 gimplify_stmt (&dtor, &tseq);
4752 gimple_seq_add_seq (dlist, tseq);
4755 else
4757 x = omp_reduction_init (c, TREE_TYPE (type));
4758 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4760 /* reduction(-:var) sums up the partial results, so it
4761 acts identically to reduction(+:var). */
4762 if (code == MINUS_EXPR)
4763 code = PLUS_EXPR;
4765 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4766 if (is_simd)
4768 x = build2 (code, TREE_TYPE (type),
4769 build_simple_mem_ref (y4),
4770 build_simple_mem_ref (y2));
4771 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4774 gimple *g
4775 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4776 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4777 gimple_seq_add_stmt (ilist, g);
4778 if (y3)
4780 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4781 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4782 gimple_seq_add_stmt (ilist, g);
4784 g = gimple_build_assign (i, PLUS_EXPR, i,
4785 build_int_cst (TREE_TYPE (i), 1));
4786 gimple_seq_add_stmt (ilist, g);
4787 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4788 gimple_seq_add_stmt (ilist, g);
4789 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4790 if (y2)
4792 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4793 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4794 gimple_seq_add_stmt (dlist, g);
4795 if (y4)
4797 g = gimple_build_assign
4798 (y4, POINTER_PLUS_EXPR, y4,
4799 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4800 gimple_seq_add_stmt (dlist, g);
4802 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4803 build_int_cst (TREE_TYPE (i2), 1));
4804 gimple_seq_add_stmt (dlist, g);
4805 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4806 gimple_seq_add_stmt (dlist, g);
4807 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4809 continue;
4811 else if (is_variable_sized (var))
4813 /* For variable sized types, we need to allocate the
4814 actual storage here. Call alloca and store the
4815 result in the pointer decl that we created elsewhere. */
4816 if (pass == 0)
4817 continue;
4819 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4821 gcall *stmt;
4822 tree tmp, atmp;
4824 ptr = DECL_VALUE_EXPR (new_var);
4825 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4826 ptr = TREE_OPERAND (ptr, 0);
4827 gcc_assert (DECL_P (ptr));
4828 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4830 /* void *tmp = __builtin_alloca */
4831 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4832 stmt = gimple_build_call (atmp, 2, x,
4833 size_int (DECL_ALIGN (var)));
4834 tmp = create_tmp_var_raw (ptr_type_node);
4835 gimple_add_tmp_var (tmp);
4836 gimple_call_set_lhs (stmt, tmp);
4838 gimple_seq_add_stmt (ilist, stmt);
4840 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4841 gimplify_assign (ptr, x, ilist);
4844 else if (is_reference (var))
4846 /* For references that are being privatized for Fortran,
4847 allocate new backing storage for the new pointer
4848 variable. This allows us to avoid changing all the
4849 code that expects a pointer to something that expects
4850 a direct variable. */
4851 if (pass == 0)
4852 continue;
4854 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4855 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4857 x = build_receiver_ref (var, false, ctx);
4858 x = build_fold_addr_expr_loc (clause_loc, x);
4860 else if (TREE_CONSTANT (x))
4862 /* For reduction in SIMD loop, defer adding the
4863 initialization of the reference, because if we decide
4864 to use SIMD array for it, the initilization could cause
4865 expansion ICE. */
4866 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4867 x = NULL_TREE;
4868 else
4870 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4871 get_name (var));
4872 gimple_add_tmp_var (x);
4873 TREE_ADDRESSABLE (x) = 1;
4874 x = build_fold_addr_expr_loc (clause_loc, x);
4877 else
4879 tree atmp
4880 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4881 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4882 tree al = size_int (TYPE_ALIGN (rtype));
4883 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4886 if (x)
4888 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4889 gimplify_assign (new_var, x, ilist);
4892 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4894 else if (c_kind == OMP_CLAUSE_REDUCTION
4895 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4897 if (pass == 0)
4898 continue;
4900 else if (pass != 0)
4901 continue;
4903 switch (OMP_CLAUSE_CODE (c))
4905 case OMP_CLAUSE_SHARED:
4906 /* Ignore shared directives in teams construct. */
4907 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4908 continue;
4909 /* Shared global vars are just accessed directly. */
4910 if (is_global_var (new_var))
4911 break;
4912 /* For taskloop firstprivate/lastprivate, represented
4913 as firstprivate and shared clause on the task, new_var
4914 is the firstprivate var. */
4915 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4916 break;
4917 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4918 needs to be delayed until after fixup_child_record_type so
4919 that we get the correct type during the dereference. */
4920 by_ref = use_pointer_for_field (var, ctx);
4921 x = build_receiver_ref (var, by_ref, ctx);
4922 SET_DECL_VALUE_EXPR (new_var, x);
4923 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4925 /* ??? If VAR is not passed by reference, and the variable
4926 hasn't been initialized yet, then we'll get a warning for
4927 the store into the omp_data_s structure. Ideally, we'd be
4928 able to notice this and not store anything at all, but
4929 we're generating code too early. Suppress the warning. */
4930 if (!by_ref)
4931 TREE_NO_WARNING (var) = 1;
4932 break;
4934 case OMP_CLAUSE_LASTPRIVATE:
4935 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4936 break;
4937 /* FALLTHRU */
4939 case OMP_CLAUSE_PRIVATE:
4940 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4941 x = build_outer_var_ref (var, ctx);
4942 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4944 if (is_task_ctx (ctx))
4945 x = build_receiver_ref (var, false, ctx);
4946 else
4947 x = build_outer_var_ref (var, ctx);
4949 else
4950 x = NULL;
4951 do_private:
4952 tree nx;
4953 nx = lang_hooks.decls.omp_clause_default_ctor
4954 (c, unshare_expr (new_var), x);
4955 if (is_simd)
4957 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4958 if ((TREE_ADDRESSABLE (new_var) || nx || y
4959 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4960 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4961 idx, lane, ivar, lvar))
4963 if (nx)
4964 x = lang_hooks.decls.omp_clause_default_ctor
4965 (c, unshare_expr (ivar), x);
4966 if (nx && x)
4967 gimplify_and_add (x, &llist[0]);
4968 if (y)
4970 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4971 if (y)
4973 gimple_seq tseq = NULL;
4975 dtor = y;
4976 gimplify_stmt (&dtor, &tseq);
4977 gimple_seq_add_seq (&llist[1], tseq);
4980 break;
4983 if (nx)
4984 gimplify_and_add (nx, ilist);
4985 /* FALLTHRU */
4987 do_dtor:
4988 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4989 if (x)
4991 gimple_seq tseq = NULL;
4993 dtor = x;
4994 gimplify_stmt (&dtor, &tseq);
4995 gimple_seq_add_seq (dlist, tseq);
4997 break;
4999 case OMP_CLAUSE_LINEAR:
5000 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5001 goto do_firstprivate;
5002 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5003 x = NULL;
5004 else
5005 x = build_outer_var_ref (var, ctx);
5006 goto do_private;
5008 case OMP_CLAUSE_FIRSTPRIVATE:
5009 if (is_task_ctx (ctx))
5011 if (is_reference (var) || is_variable_sized (var))
5012 goto do_dtor;
5013 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5014 ctx))
5015 || use_pointer_for_field (var, NULL))
5017 x = build_receiver_ref (var, false, ctx);
5018 SET_DECL_VALUE_EXPR (new_var, x);
5019 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5020 goto do_dtor;
5023 do_firstprivate:
5024 x = build_outer_var_ref (var, ctx);
5025 if (is_simd)
5027 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5028 && gimple_omp_for_combined_into_p (ctx->stmt))
5030 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5031 tree stept = TREE_TYPE (t);
5032 tree ct = find_omp_clause (clauses,
5033 OMP_CLAUSE__LOOPTEMP_);
5034 gcc_assert (ct);
5035 tree l = OMP_CLAUSE_DECL (ct);
5036 tree n1 = fd->loop.n1;
5037 tree step = fd->loop.step;
5038 tree itype = TREE_TYPE (l);
5039 if (POINTER_TYPE_P (itype))
5040 itype = signed_type_for (itype);
5041 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5042 if (TYPE_UNSIGNED (itype)
5043 && fd->loop.cond_code == GT_EXPR)
5044 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5045 fold_build1 (NEGATE_EXPR, itype, l),
5046 fold_build1 (NEGATE_EXPR,
5047 itype, step));
5048 else
5049 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5050 t = fold_build2 (MULT_EXPR, stept,
5051 fold_convert (stept, l), t);
5053 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5055 x = lang_hooks.decls.omp_clause_linear_ctor
5056 (c, new_var, x, t);
5057 gimplify_and_add (x, ilist);
5058 goto do_dtor;
5061 if (POINTER_TYPE_P (TREE_TYPE (x)))
5062 x = fold_build2 (POINTER_PLUS_EXPR,
5063 TREE_TYPE (x), x, t);
5064 else
5065 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5068 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5069 || TREE_ADDRESSABLE (new_var))
5070 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5071 idx, lane, ivar, lvar))
5073 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5075 tree iv = create_tmp_var (TREE_TYPE (new_var));
5076 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5077 gimplify_and_add (x, ilist);
5078 gimple_stmt_iterator gsi
5079 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5080 gassign *g
5081 = gimple_build_assign (unshare_expr (lvar), iv);
5082 gsi_insert_before_without_update (&gsi, g,
5083 GSI_SAME_STMT);
5084 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5085 enum tree_code code = PLUS_EXPR;
5086 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5087 code = POINTER_PLUS_EXPR;
5088 g = gimple_build_assign (iv, code, iv, t);
5089 gsi_insert_before_without_update (&gsi, g,
5090 GSI_SAME_STMT);
5091 break;
5093 x = lang_hooks.decls.omp_clause_copy_ctor
5094 (c, unshare_expr (ivar), x);
5095 gimplify_and_add (x, &llist[0]);
5096 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5097 if (x)
5099 gimple_seq tseq = NULL;
5101 dtor = x;
5102 gimplify_stmt (&dtor, &tseq);
5103 gimple_seq_add_seq (&llist[1], tseq);
5105 break;
5108 x = lang_hooks.decls.omp_clause_copy_ctor
5109 (c, unshare_expr (new_var), x);
5110 gimplify_and_add (x, ilist);
5111 goto do_dtor;
5113 case OMP_CLAUSE__LOOPTEMP_:
5114 gcc_assert (is_taskreg_ctx (ctx));
5115 x = build_outer_var_ref (var, ctx);
5116 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5117 gimplify_and_add (x, ilist);
5118 break;
5120 case OMP_CLAUSE_COPYIN:
5121 by_ref = use_pointer_for_field (var, NULL);
5122 x = build_receiver_ref (var, by_ref, ctx);
5123 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5124 append_to_statement_list (x, &copyin_seq);
5125 copyin_by_ref |= by_ref;
5126 break;
5128 case OMP_CLAUSE_REDUCTION:
5129 /* OpenACC reductions are initialized using the
5130 GOACC_REDUCTION internal function. */
5131 if (is_gimple_omp_oacc (ctx->stmt))
5132 break;
5133 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5135 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5136 gimple *tseq;
5137 x = build_outer_var_ref (var, ctx);
5139 if (is_reference (var)
5140 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5141 TREE_TYPE (x)))
5142 x = build_fold_addr_expr_loc (clause_loc, x);
5143 SET_DECL_VALUE_EXPR (placeholder, x);
5144 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5145 tree new_vard = new_var;
5146 if (is_reference (var))
5148 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5149 new_vard = TREE_OPERAND (new_var, 0);
5150 gcc_assert (DECL_P (new_vard));
5152 if (is_simd
5153 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5154 idx, lane, ivar, lvar))
5156 if (new_vard == new_var)
5158 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5159 SET_DECL_VALUE_EXPR (new_var, ivar);
5161 else
5163 SET_DECL_VALUE_EXPR (new_vard,
5164 build_fold_addr_expr (ivar));
5165 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5167 x = lang_hooks.decls.omp_clause_default_ctor
5168 (c, unshare_expr (ivar),
5169 build_outer_var_ref (var, ctx));
5170 if (x)
5171 gimplify_and_add (x, &llist[0]);
5172 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5174 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5175 lower_omp (&tseq, ctx);
5176 gimple_seq_add_seq (&llist[0], tseq);
5178 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5179 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5180 lower_omp (&tseq, ctx);
5181 gimple_seq_add_seq (&llist[1], tseq);
5182 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5183 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5184 if (new_vard == new_var)
5185 SET_DECL_VALUE_EXPR (new_var, lvar);
5186 else
5187 SET_DECL_VALUE_EXPR (new_vard,
5188 build_fold_addr_expr (lvar));
5189 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5190 if (x)
5192 tseq = NULL;
5193 dtor = x;
5194 gimplify_stmt (&dtor, &tseq);
5195 gimple_seq_add_seq (&llist[1], tseq);
5197 break;
5199 /* If this is a reference to constant size reduction var
5200 with placeholder, we haven't emitted the initializer
5201 for it because it is undesirable if SIMD arrays are used.
5202 But if they aren't used, we need to emit the deferred
5203 initialization now. */
5204 else if (is_reference (var) && is_simd)
5205 handle_simd_reference (clause_loc, new_vard, ilist);
5206 x = lang_hooks.decls.omp_clause_default_ctor
5207 (c, unshare_expr (new_var),
5208 build_outer_var_ref (var, ctx));
5209 if (x)
5210 gimplify_and_add (x, ilist);
5211 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5213 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5214 lower_omp (&tseq, ctx);
5215 gimple_seq_add_seq (ilist, tseq);
5217 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5218 if (is_simd)
5220 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5221 lower_omp (&tseq, ctx);
5222 gimple_seq_add_seq (dlist, tseq);
5223 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5225 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5226 goto do_dtor;
5228 else
5230 x = omp_reduction_init (c, TREE_TYPE (new_var));
5231 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5232 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5234 /* reduction(-:var) sums up the partial results, so it
5235 acts identically to reduction(+:var). */
5236 if (code == MINUS_EXPR)
5237 code = PLUS_EXPR;
5239 tree new_vard = new_var;
5240 if (is_simd && is_reference (var))
5242 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5243 new_vard = TREE_OPERAND (new_var, 0);
5244 gcc_assert (DECL_P (new_vard));
5246 if (is_simd
5247 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5248 idx, lane, ivar, lvar))
5250 tree ref = build_outer_var_ref (var, ctx);
5252 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5254 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5255 ref = build_outer_var_ref (var, ctx);
5256 gimplify_assign (ref, x, &llist[1]);
5258 if (new_vard != new_var)
5260 SET_DECL_VALUE_EXPR (new_vard,
5261 build_fold_addr_expr (lvar));
5262 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5265 else
5267 if (is_reference (var) && is_simd)
5268 handle_simd_reference (clause_loc, new_vard, ilist);
5269 gimplify_assign (new_var, x, ilist);
5270 if (is_simd)
5272 tree ref = build_outer_var_ref (var, ctx);
5274 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5275 ref = build_outer_var_ref (var, ctx);
5276 gimplify_assign (ref, x, dlist);
5280 break;
5282 default:
5283 gcc_unreachable ();
5288 if (lane)
5290 tree uid = create_tmp_var (ptr_type_node, "simduid");
5291 /* Don't want uninit warnings on simduid, it is always uninitialized,
5292 but we use it not for the value, but for the DECL_UID only. */
5293 TREE_NO_WARNING (uid) = 1;
5294 gimple *g
5295 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5296 gimple_call_set_lhs (g, lane);
5297 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5298 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5299 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5300 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5301 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5302 gimple_omp_for_set_clauses (ctx->stmt, c);
5303 g = gimple_build_assign (lane, INTEGER_CST,
5304 build_int_cst (unsigned_type_node, 0));
5305 gimple_seq_add_stmt (ilist, g);
5306 for (int i = 0; i < 2; i++)
5307 if (llist[i])
5309 tree vf = create_tmp_var (unsigned_type_node);
5310 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5311 gimple_call_set_lhs (g, vf);
5312 gimple_seq *seq = i == 0 ? ilist : dlist;
5313 gimple_seq_add_stmt (seq, g);
5314 tree t = build_int_cst (unsigned_type_node, 0);
5315 g = gimple_build_assign (idx, INTEGER_CST, t);
5316 gimple_seq_add_stmt (seq, g);
5317 tree body = create_artificial_label (UNKNOWN_LOCATION);
5318 tree header = create_artificial_label (UNKNOWN_LOCATION);
5319 tree end = create_artificial_label (UNKNOWN_LOCATION);
5320 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5321 gimple_seq_add_stmt (seq, gimple_build_label (body));
5322 gimple_seq_add_seq (seq, llist[i]);
5323 t = build_int_cst (unsigned_type_node, 1);
5324 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5325 gimple_seq_add_stmt (seq, g);
5326 gimple_seq_add_stmt (seq, gimple_build_label (header));
5327 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5328 gimple_seq_add_stmt (seq, g);
5329 gimple_seq_add_stmt (seq, gimple_build_label (end));
5333 /* The copyin sequence is not to be executed by the main thread, since
5334 that would result in self-copies. Perhaps not visible to scalars,
5335 but it certainly is to C++ operator=. */
5336 if (copyin_seq)
5338 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5340 x = build2 (NE_EXPR, boolean_type_node, x,
5341 build_int_cst (TREE_TYPE (x), 0));
5342 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5343 gimplify_and_add (x, ilist);
5346 /* If any copyin variable is passed by reference, we must ensure the
5347 master thread doesn't modify it before it is copied over in all
5348 threads. Similarly for variables in both firstprivate and
5349 lastprivate clauses we need to ensure the lastprivate copying
5350 happens after firstprivate copying in all threads. And similarly
5351 for UDRs if initializer expression refers to omp_orig. */
5352 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5354 /* Don't add any barrier for #pragma omp simd or
5355 #pragma omp distribute. */
5356 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5357 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5358 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5361 /* If max_vf is non-zero, then we can use only a vectorization factor
5362 up to the max_vf we chose. So stick it into the safelen clause. */
5363 if (max_vf)
5365 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5366 OMP_CLAUSE_SAFELEN);
5367 if (c == NULL_TREE
5368 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5369 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5370 max_vf) == 1))
5372 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5373 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5374 max_vf);
5375 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5376 gimple_omp_for_set_clauses (ctx->stmt, c);
5382 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5383 both parallel and workshare constructs. PREDICATE may be NULL if it's
5384 always true. */
5386 static void
5387 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5388 omp_context *ctx)
5390 tree x, c, label = NULL, orig_clauses = clauses;
5391 bool par_clauses = false;
5392 tree simduid = NULL, lastlane = NULL;
5394 /* Early exit if there are no lastprivate or linear clauses. */
5395 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5396 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5397 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5398 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5399 break;
5400 if (clauses == NULL)
5402 /* If this was a workshare clause, see if it had been combined
5403 with its parallel. In that case, look for the clauses on the
5404 parallel statement itself. */
5405 if (is_parallel_ctx (ctx))
5406 return;
5408 ctx = ctx->outer;
5409 if (ctx == NULL || !is_parallel_ctx (ctx))
5410 return;
5412 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5413 OMP_CLAUSE_LASTPRIVATE);
5414 if (clauses == NULL)
5415 return;
5416 par_clauses = true;
5419 if (predicate)
5421 gcond *stmt;
5422 tree label_true, arm1, arm2;
5424 label = create_artificial_label (UNKNOWN_LOCATION);
5425 label_true = create_artificial_label (UNKNOWN_LOCATION);
5426 arm1 = TREE_OPERAND (predicate, 0);
5427 arm2 = TREE_OPERAND (predicate, 1);
5428 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5429 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5430 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5431 label_true, label);
5432 gimple_seq_add_stmt (stmt_list, stmt);
5433 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5436 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5437 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5439 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5440 if (simduid)
5441 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5444 for (c = clauses; c ;)
5446 tree var, new_var;
5447 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5449 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5450 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5451 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5453 var = OMP_CLAUSE_DECL (c);
5454 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5455 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5456 && is_taskloop_ctx (ctx))
5458 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5459 new_var = lookup_decl (var, ctx->outer);
5461 else
5463 new_var = lookup_decl (var, ctx);
5464 /* Avoid uninitialized warnings for lastprivate and
5465 for linear iterators. */
5466 if (predicate
5467 && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5468 || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
5469 TREE_NO_WARNING (new_var) = 1;
5472 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5474 tree val = DECL_VALUE_EXPR (new_var);
5475 if (TREE_CODE (val) == ARRAY_REF
5476 && VAR_P (TREE_OPERAND (val, 0))
5477 && lookup_attribute ("omp simd array",
5478 DECL_ATTRIBUTES (TREE_OPERAND (val,
5479 0))))
5481 if (lastlane == NULL)
5483 lastlane = create_tmp_var (unsigned_type_node);
5484 gcall *g
5485 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5486 2, simduid,
5487 TREE_OPERAND (val, 1));
5488 gimple_call_set_lhs (g, lastlane);
5489 gimple_seq_add_stmt (stmt_list, g);
5491 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5492 TREE_OPERAND (val, 0), lastlane,
5493 NULL_TREE, NULL_TREE);
5497 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5498 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5500 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5501 gimple_seq_add_seq (stmt_list,
5502 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5503 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5505 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5506 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5508 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5509 gimple_seq_add_seq (stmt_list,
5510 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5511 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5514 x = NULL_TREE;
5515 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5516 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5518 gcc_checking_assert (is_taskloop_ctx (ctx));
5519 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5520 ctx->outer->outer);
5521 if (is_global_var (ovar))
5522 x = ovar;
5524 if (!x)
5525 x = build_outer_var_ref (var, ctx, true);
5526 if (is_reference (var))
5527 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5528 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5529 gimplify_and_add (x, stmt_list);
5531 c = OMP_CLAUSE_CHAIN (c);
5532 if (c == NULL && !par_clauses)
5534 /* If this was a workshare clause, see if it had been combined
5535 with its parallel. In that case, continue looking for the
5536 clauses also on the parallel statement itself. */
5537 if (is_parallel_ctx (ctx))
5538 break;
5540 ctx = ctx->outer;
5541 if (ctx == NULL || !is_parallel_ctx (ctx))
5542 break;
5544 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5545 OMP_CLAUSE_LASTPRIVATE);
5546 par_clauses = true;
5550 if (label)
5551 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5554 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5555 (which might be a placeholder). INNER is true if this is an inner
5556 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5557 join markers. Generate the before-loop forking sequence in
5558 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5559 general form of these sequences is
5561 GOACC_REDUCTION_SETUP
5562 GOACC_FORK
5563 GOACC_REDUCTION_INIT
5565 GOACC_REDUCTION_FINI
5566 GOACC_JOIN
5567 GOACC_REDUCTION_TEARDOWN. */
5569 static void
5570 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5571 gcall *fork, gcall *join, gimple_seq *fork_seq,
5572 gimple_seq *join_seq, omp_context *ctx)
5574 gimple_seq before_fork = NULL;
5575 gimple_seq after_fork = NULL;
5576 gimple_seq before_join = NULL;
5577 gimple_seq after_join = NULL;
5578 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5579 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5580 unsigned offset = 0;
5582 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5583 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5585 tree orig = OMP_CLAUSE_DECL (c);
5586 tree var = maybe_lookup_decl (orig, ctx);
5587 tree ref_to_res = NULL_TREE;
5588 tree incoming, outgoing, v1, v2, v3;
5589 bool is_private = false;
5591 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5592 if (rcode == MINUS_EXPR)
5593 rcode = PLUS_EXPR;
5594 else if (rcode == TRUTH_ANDIF_EXPR)
5595 rcode = BIT_AND_EXPR;
5596 else if (rcode == TRUTH_ORIF_EXPR)
5597 rcode = BIT_IOR_EXPR;
5598 tree op = build_int_cst (unsigned_type_node, rcode);
5600 if (!var)
5601 var = orig;
5603 incoming = outgoing = var;
5605 if (!inner)
5607 /* See if an outer construct also reduces this variable. */
5608 omp_context *outer = ctx;
5610 while (omp_context *probe = outer->outer)
5612 enum gimple_code type = gimple_code (probe->stmt);
5613 tree cls;
5615 switch (type)
5617 case GIMPLE_OMP_FOR:
5618 cls = gimple_omp_for_clauses (probe->stmt);
5619 break;
5621 case GIMPLE_OMP_TARGET:
5622 if (gimple_omp_target_kind (probe->stmt)
5623 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5624 goto do_lookup;
5626 cls = gimple_omp_target_clauses (probe->stmt);
5627 break;
5629 default:
5630 goto do_lookup;
5633 outer = probe;
5634 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5635 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5636 && orig == OMP_CLAUSE_DECL (cls))
5638 incoming = outgoing = lookup_decl (orig, probe);
5639 goto has_outer_reduction;
5641 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5642 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5643 && orig == OMP_CLAUSE_DECL (cls))
5645 is_private = true;
5646 goto do_lookup;
5650 do_lookup:
5651 /* This is the outermost construct with this reduction,
5652 see if there's a mapping for it. */
5653 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5654 && maybe_lookup_field (orig, outer) && !is_private)
5656 ref_to_res = build_receiver_ref (orig, false, outer);
5657 if (is_reference (orig))
5658 ref_to_res = build_simple_mem_ref (ref_to_res);
5660 tree type = TREE_TYPE (var);
5661 if (POINTER_TYPE_P (type))
5662 type = TREE_TYPE (type);
5664 outgoing = var;
5665 incoming = omp_reduction_init_op (loc, rcode, type);
5667 else
5669 /* Try to look at enclosing contexts for reduction var,
5670 use original if no mapping found. */
5671 tree t = NULL_TREE;
5672 omp_context *c = ctx->outer;
5673 while (c && !t)
5675 t = maybe_lookup_decl (orig, c);
5676 c = c->outer;
5678 incoming = outgoing = (t ? t : orig);
5681 has_outer_reduction:;
5684 if (!ref_to_res)
5685 ref_to_res = integer_zero_node;
5687 if (is_reference (orig))
5689 tree type = TREE_TYPE (var);
5690 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5692 if (!inner)
5694 tree x = create_tmp_var (TREE_TYPE (type), id);
5695 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5698 v1 = create_tmp_var (type, id);
5699 v2 = create_tmp_var (type, id);
5700 v3 = create_tmp_var (type, id);
5702 gimplify_assign (v1, var, fork_seq);
5703 gimplify_assign (v2, var, fork_seq);
5704 gimplify_assign (v3, var, fork_seq);
5706 var = build_simple_mem_ref (var);
5707 v1 = build_simple_mem_ref (v1);
5708 v2 = build_simple_mem_ref (v2);
5709 v3 = build_simple_mem_ref (v3);
5710 outgoing = build_simple_mem_ref (outgoing);
5712 if (!TREE_CONSTANT (incoming))
5713 incoming = build_simple_mem_ref (incoming);
5715 else
5716 v1 = v2 = v3 = var;
5718 /* Determine position in reduction buffer, which may be used
5719 by target. */
5720 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5721 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5722 offset = (offset + align - 1) & ~(align - 1);
5723 tree off = build_int_cst (sizetype, offset);
5724 offset += GET_MODE_SIZE (mode);
5726 if (!init_code)
5728 init_code = build_int_cst (integer_type_node,
5729 IFN_GOACC_REDUCTION_INIT);
5730 fini_code = build_int_cst (integer_type_node,
5731 IFN_GOACC_REDUCTION_FINI);
5732 setup_code = build_int_cst (integer_type_node,
5733 IFN_GOACC_REDUCTION_SETUP);
5734 teardown_code = build_int_cst (integer_type_node,
5735 IFN_GOACC_REDUCTION_TEARDOWN);
5738 tree setup_call
5739 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5740 TREE_TYPE (var), 6, setup_code,
5741 unshare_expr (ref_to_res),
5742 incoming, level, op, off);
5743 tree init_call
5744 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5745 TREE_TYPE (var), 6, init_code,
5746 unshare_expr (ref_to_res),
5747 v1, level, op, off);
5748 tree fini_call
5749 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5750 TREE_TYPE (var), 6, fini_code,
5751 unshare_expr (ref_to_res),
5752 v2, level, op, off);
5753 tree teardown_call
5754 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5755 TREE_TYPE (var), 6, teardown_code,
5756 ref_to_res, v3, level, op, off);
5758 gimplify_assign (v1, setup_call, &before_fork);
5759 gimplify_assign (v2, init_call, &after_fork);
5760 gimplify_assign (v3, fini_call, &before_join);
5761 gimplify_assign (outgoing, teardown_call, &after_join);
5764 /* Now stitch things together. */
5765 gimple_seq_add_seq (fork_seq, before_fork);
5766 if (fork)
5767 gimple_seq_add_stmt (fork_seq, fork);
5768 gimple_seq_add_seq (fork_seq, after_fork);
5770 gimple_seq_add_seq (join_seq, before_join);
5771 if (join)
5772 gimple_seq_add_stmt (join_seq, join);
5773 gimple_seq_add_seq (join_seq, after_join);
5776 /* Generate code to implement the REDUCTION clauses. */
5778 static void
5779 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5781 gimple_seq sub_seq = NULL;
5782 gimple *stmt;
5783 tree x, c;
5784 int count = 0;
5786 /* OpenACC loop reductions are handled elsewhere. */
5787 if (is_gimple_omp_oacc (ctx->stmt))
5788 return;
5790 /* SIMD reductions are handled in lower_rec_input_clauses. */
5791 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5792 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5793 return;
5795 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5796 update in that case, otherwise use a lock. */
5797 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5798 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5800 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5801 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5803 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5804 count = -1;
5805 break;
5807 count++;
5810 if (count == 0)
5811 return;
5813 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5815 tree var, ref, new_var, orig_var;
5816 enum tree_code code;
5817 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5819 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5820 continue;
5822 orig_var = var = OMP_CLAUSE_DECL (c);
5823 if (TREE_CODE (var) == MEM_REF)
5825 var = TREE_OPERAND (var, 0);
5826 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5827 var = TREE_OPERAND (var, 0);
5828 if (TREE_CODE (var) == INDIRECT_REF
5829 || TREE_CODE (var) == ADDR_EXPR)
5830 var = TREE_OPERAND (var, 0);
5831 orig_var = var;
5832 if (is_variable_sized (var))
5834 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5835 var = DECL_VALUE_EXPR (var);
5836 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5837 var = TREE_OPERAND (var, 0);
5838 gcc_assert (DECL_P (var));
5841 new_var = lookup_decl (var, ctx);
5842 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5843 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5844 ref = build_outer_var_ref (var, ctx);
5845 code = OMP_CLAUSE_REDUCTION_CODE (c);
5847 /* reduction(-:var) sums up the partial results, so it acts
5848 identically to reduction(+:var). */
5849 if (code == MINUS_EXPR)
5850 code = PLUS_EXPR;
5852 if (count == 1)
5854 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5856 addr = save_expr (addr);
5857 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5858 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5859 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5860 gimplify_and_add (x, stmt_seqp);
5861 return;
5863 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5865 tree d = OMP_CLAUSE_DECL (c);
5866 tree type = TREE_TYPE (d);
5867 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5868 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5869 tree ptype = build_pointer_type (TREE_TYPE (type));
5870 tree bias = TREE_OPERAND (d, 1);
5871 d = TREE_OPERAND (d, 0);
5872 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5874 tree b = TREE_OPERAND (d, 1);
5875 b = maybe_lookup_decl (b, ctx);
5876 if (b == NULL)
5878 b = TREE_OPERAND (d, 1);
5879 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5881 if (integer_zerop (bias))
5882 bias = b;
5883 else
5885 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5886 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5887 TREE_TYPE (b), b, bias);
5889 d = TREE_OPERAND (d, 0);
5891 /* For ref build_outer_var_ref already performs this, so
5892 only new_var needs a dereference. */
5893 if (TREE_CODE (d) == INDIRECT_REF)
5895 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5896 gcc_assert (is_reference (var) && var == orig_var);
5898 else if (TREE_CODE (d) == ADDR_EXPR)
5900 if (orig_var == var)
5902 new_var = build_fold_addr_expr (new_var);
5903 ref = build_fold_addr_expr (ref);
5906 else
5908 gcc_assert (orig_var == var);
5909 if (is_reference (var))
5910 ref = build_fold_addr_expr (ref);
5912 if (DECL_P (v))
5914 tree t = maybe_lookup_decl (v, ctx);
5915 if (t)
5916 v = t;
5917 else
5918 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5919 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5921 if (!integer_zerop (bias))
5923 bias = fold_convert_loc (clause_loc, sizetype, bias);
5924 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5925 TREE_TYPE (new_var), new_var,
5926 unshare_expr (bias));
5927 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5928 TREE_TYPE (ref), ref, bias);
5930 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5931 ref = fold_convert_loc (clause_loc, ptype, ref);
5932 tree m = create_tmp_var (ptype, NULL);
5933 gimplify_assign (m, new_var, stmt_seqp);
5934 new_var = m;
5935 m = create_tmp_var (ptype, NULL);
5936 gimplify_assign (m, ref, stmt_seqp);
5937 ref = m;
5938 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5939 tree body = create_artificial_label (UNKNOWN_LOCATION);
5940 tree end = create_artificial_label (UNKNOWN_LOCATION);
5941 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5942 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5943 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5944 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5946 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5947 tree decl_placeholder
5948 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5949 SET_DECL_VALUE_EXPR (placeholder, out);
5950 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5951 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5952 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5953 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5954 gimple_seq_add_seq (&sub_seq,
5955 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5956 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5957 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5958 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5960 else
5962 x = build2 (code, TREE_TYPE (out), out, priv);
5963 out = unshare_expr (out);
5964 gimplify_assign (out, x, &sub_seq);
5966 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5967 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5968 gimple_seq_add_stmt (&sub_seq, g);
5969 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5970 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5971 gimple_seq_add_stmt (&sub_seq, g);
5972 g = gimple_build_assign (i, PLUS_EXPR, i,
5973 build_int_cst (TREE_TYPE (i), 1));
5974 gimple_seq_add_stmt (&sub_seq, g);
5975 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5976 gimple_seq_add_stmt (&sub_seq, g);
5977 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5979 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5981 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5983 if (is_reference (var)
5984 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5985 TREE_TYPE (ref)))
5986 ref = build_fold_addr_expr_loc (clause_loc, ref);
5987 SET_DECL_VALUE_EXPR (placeholder, ref);
5988 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5989 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5990 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5991 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5992 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5994 else
5996 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5997 ref = build_outer_var_ref (var, ctx);
5998 gimplify_assign (ref, x, &sub_seq);
6002 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
6004 gimple_seq_add_stmt (stmt_seqp, stmt);
6006 gimple_seq_add_seq (stmt_seqp, sub_seq);
6008 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
6010 gimple_seq_add_stmt (stmt_seqp, stmt);
6014 /* Generate code to implement the COPYPRIVATE clauses. */
6016 static void
6017 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6018 omp_context *ctx)
6020 tree c;
6022 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6024 tree var, new_var, ref, x;
6025 bool by_ref;
6026 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6028 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6029 continue;
6031 var = OMP_CLAUSE_DECL (c);
6032 by_ref = use_pointer_for_field (var, NULL);
6034 ref = build_sender_ref (var, ctx);
6035 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6036 if (by_ref)
6038 x = build_fold_addr_expr_loc (clause_loc, new_var);
6039 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6041 gimplify_assign (ref, x, slist);
6043 ref = build_receiver_ref (var, false, ctx);
6044 if (by_ref)
6046 ref = fold_convert_loc (clause_loc,
6047 build_pointer_type (TREE_TYPE (new_var)),
6048 ref);
6049 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6051 if (is_reference (var))
6053 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6054 ref = build_simple_mem_ref_loc (clause_loc, ref);
6055 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6057 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6058 gimplify_and_add (x, rlist);
6063 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6064 and REDUCTION from the sender (aka parent) side. */
6066 static void
6067 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6068 omp_context *ctx)
6070 tree c, t;
6071 int ignored_looptemp = 0;
6072 bool is_taskloop = false;
6074 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6075 by GOMP_taskloop. */
6076 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6078 ignored_looptemp = 2;
6079 is_taskloop = true;
6082 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6084 tree val, ref, x, var;
6085 bool by_ref, do_in = false, do_out = false;
6086 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6088 switch (OMP_CLAUSE_CODE (c))
6090 case OMP_CLAUSE_PRIVATE:
6091 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6092 break;
6093 continue;
6094 case OMP_CLAUSE_FIRSTPRIVATE:
6095 case OMP_CLAUSE_COPYIN:
6096 case OMP_CLAUSE_LASTPRIVATE:
6097 case OMP_CLAUSE_REDUCTION:
6098 break;
6099 case OMP_CLAUSE_SHARED:
6100 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6101 break;
6102 continue;
6103 case OMP_CLAUSE__LOOPTEMP_:
6104 if (ignored_looptemp)
6106 ignored_looptemp--;
6107 continue;
6109 break;
6110 default:
6111 continue;
6114 val = OMP_CLAUSE_DECL (c);
6115 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6116 && TREE_CODE (val) == MEM_REF)
6118 val = TREE_OPERAND (val, 0);
6119 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6120 val = TREE_OPERAND (val, 0);
6121 if (TREE_CODE (val) == INDIRECT_REF
6122 || TREE_CODE (val) == ADDR_EXPR)
6123 val = TREE_OPERAND (val, 0);
6124 if (is_variable_sized (val))
6125 continue;
6128 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6129 outer taskloop region. */
6130 omp_context *ctx_for_o = ctx;
6131 if (is_taskloop
6132 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6133 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6134 ctx_for_o = ctx->outer;
6136 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6138 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6139 && is_global_var (var))
6140 continue;
6142 t = omp_member_access_dummy_var (var);
6143 if (t)
6145 var = DECL_VALUE_EXPR (var);
6146 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6147 if (o != t)
6148 var = unshare_and_remap (var, t, o);
6149 else
6150 var = unshare_expr (var);
6153 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6155 /* Handle taskloop firstprivate/lastprivate, where the
6156 lastprivate on GIMPLE_OMP_TASK is represented as
6157 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6158 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6159 x = omp_build_component_ref (ctx->sender_decl, f);
6160 if (use_pointer_for_field (val, ctx))
6161 var = build_fold_addr_expr (var);
6162 gimplify_assign (x, var, ilist);
6163 DECL_ABSTRACT_ORIGIN (f) = NULL;
6164 continue;
6167 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6168 || val == OMP_CLAUSE_DECL (c))
6169 && is_variable_sized (val))
6170 continue;
6171 by_ref = use_pointer_for_field (val, NULL);
6173 switch (OMP_CLAUSE_CODE (c))
6175 case OMP_CLAUSE_FIRSTPRIVATE:
6176 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6177 && !by_ref
6178 && is_task_ctx (ctx))
6179 TREE_NO_WARNING (var) = 1;
6180 do_in = true;
6181 break;
6183 case OMP_CLAUSE_PRIVATE:
6184 case OMP_CLAUSE_COPYIN:
6185 case OMP_CLAUSE__LOOPTEMP_:
6186 do_in = true;
6187 break;
6189 case OMP_CLAUSE_LASTPRIVATE:
6190 if (by_ref || is_reference (val))
6192 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6193 continue;
6194 do_in = true;
6196 else
6198 do_out = true;
6199 if (lang_hooks.decls.omp_private_outer_ref (val))
6200 do_in = true;
6202 break;
6204 case OMP_CLAUSE_REDUCTION:
6205 do_in = true;
6206 if (val == OMP_CLAUSE_DECL (c))
6207 do_out = !(by_ref || is_reference (val));
6208 else
6209 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6210 break;
6212 default:
6213 gcc_unreachable ();
6216 if (do_in)
6218 ref = build_sender_ref (val, ctx);
6219 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6220 gimplify_assign (ref, x, ilist);
6221 if (is_task_ctx (ctx))
6222 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6225 if (do_out)
6227 ref = build_sender_ref (val, ctx);
6228 gimplify_assign (var, ref, olist);
6233 /* Generate code to implement SHARED from the sender (aka parent)
6234 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6235 list things that got automatically shared. */
6237 static void
6238 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6240 tree var, ovar, nvar, t, f, x, record_type;
6242 if (ctx->record_type == NULL)
6243 return;
6245 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6246 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6248 ovar = DECL_ABSTRACT_ORIGIN (f);
6249 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6250 continue;
6252 nvar = maybe_lookup_decl (ovar, ctx);
6253 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6254 continue;
6256 /* If CTX is a nested parallel directive. Find the immediately
6257 enclosing parallel or workshare construct that contains a
6258 mapping for OVAR. */
6259 var = lookup_decl_in_outer_ctx (ovar, ctx);
6261 t = omp_member_access_dummy_var (var);
6262 if (t)
6264 var = DECL_VALUE_EXPR (var);
6265 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6266 if (o != t)
6267 var = unshare_and_remap (var, t, o);
6268 else
6269 var = unshare_expr (var);
6272 if (use_pointer_for_field (ovar, ctx))
6274 x = build_sender_ref (ovar, ctx);
6275 var = build_fold_addr_expr (var);
6276 gimplify_assign (x, var, ilist);
6278 else
6280 x = build_sender_ref (ovar, ctx);
6281 gimplify_assign (x, var, ilist);
6283 if (!TREE_READONLY (var)
6284 /* We don't need to receive a new reference to a result
6285 or parm decl. In fact we may not store to it as we will
6286 invalidate any pending RSO and generate wrong gimple
6287 during inlining. */
6288 && !((TREE_CODE (var) == RESULT_DECL
6289 || TREE_CODE (var) == PARM_DECL)
6290 && DECL_BY_REFERENCE (var)))
6292 x = build_sender_ref (ovar, ctx);
6293 gimplify_assign (var, x, olist);
6299 /* Emit an OpenACC head marker call, encapulating the partitioning and
6300 other information that must be processed by the target compiler.
6301 Return the maximum number of dimensions the associated loop might
6302 be partitioned over. */
6304 static unsigned
6305 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6306 gimple_seq *seq, omp_context *ctx)
6308 unsigned levels = 0;
6309 unsigned tag = 0;
6310 tree gang_static = NULL_TREE;
6311 auto_vec<tree, 5> args;
6313 args.quick_push (build_int_cst
6314 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6315 args.quick_push (ddvar);
6316 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6318 switch (OMP_CLAUSE_CODE (c))
6320 case OMP_CLAUSE_GANG:
6321 tag |= OLF_DIM_GANG;
6322 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6323 /* static:* is represented by -1, and we can ignore it, as
6324 scheduling is always static. */
6325 if (gang_static && integer_minus_onep (gang_static))
6326 gang_static = NULL_TREE;
6327 levels++;
6328 break;
6330 case OMP_CLAUSE_WORKER:
6331 tag |= OLF_DIM_WORKER;
6332 levels++;
6333 break;
6335 case OMP_CLAUSE_VECTOR:
6336 tag |= OLF_DIM_VECTOR;
6337 levels++;
6338 break;
6340 case OMP_CLAUSE_SEQ:
6341 tag |= OLF_SEQ;
6342 break;
6344 case OMP_CLAUSE_AUTO:
6345 tag |= OLF_AUTO;
6346 break;
6348 case OMP_CLAUSE_INDEPENDENT:
6349 tag |= OLF_INDEPENDENT;
6350 break;
6352 default:
6353 continue;
6357 if (gang_static)
6359 if (DECL_P (gang_static))
6360 gang_static = build_outer_var_ref (gang_static, ctx);
6361 tag |= OLF_GANG_STATIC;
6364 /* In a parallel region, loops are implicitly INDEPENDENT. */
6365 omp_context *tgt = enclosing_target_ctx (ctx);
6366 if (!tgt || is_oacc_parallel (tgt))
6367 tag |= OLF_INDEPENDENT;
6369 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6370 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6371 | OLF_SEQ)))
6372 tag |= OLF_AUTO;
6374 /* Ensure at least one level. */
6375 if (!levels)
6376 levels++;
6378 args.quick_push (build_int_cst (integer_type_node, levels));
6379 args.quick_push (build_int_cst (integer_type_node, tag));
6380 if (gang_static)
6381 args.quick_push (gang_static);
6383 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6384 gimple_set_location (call, loc);
6385 gimple_set_lhs (call, ddvar);
6386 gimple_seq_add_stmt (seq, call);
6388 return levels;
6391 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6392 partitioning level of the enclosed region. */
6394 static void
6395 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6396 tree tofollow, gimple_seq *seq)
6398 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6399 : IFN_UNIQUE_OACC_TAIL_MARK);
6400 tree marker = build_int_cst (integer_type_node, marker_kind);
6401 int nargs = 2 + (tofollow != NULL_TREE);
6402 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6403 marker, ddvar, tofollow);
6404 gimple_set_location (call, loc);
6405 gimple_set_lhs (call, ddvar);
6406 gimple_seq_add_stmt (seq, call);
6409 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6410 the loop clauses, from which we extract reductions. Initialize
6411 HEAD and TAIL. */
6413 static void
6414 lower_oacc_head_tail (location_t loc, tree clauses,
6415 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6417 bool inner = false;
6418 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6419 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6421 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6422 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6423 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6425 gcc_assert (count);
6426 for (unsigned done = 1; count; count--, done++)
6428 gimple_seq fork_seq = NULL;
6429 gimple_seq join_seq = NULL;
6431 tree place = build_int_cst (integer_type_node, -1);
6432 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6433 fork_kind, ddvar, place);
6434 gimple_set_location (fork, loc);
6435 gimple_set_lhs (fork, ddvar);
6437 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6438 join_kind, ddvar, place);
6439 gimple_set_location (join, loc);
6440 gimple_set_lhs (join, ddvar);
6442 /* Mark the beginning of this level sequence. */
6443 if (inner)
6444 lower_oacc_loop_marker (loc, ddvar, true,
6445 build_int_cst (integer_type_node, count),
6446 &fork_seq);
6447 lower_oacc_loop_marker (loc, ddvar, false,
6448 build_int_cst (integer_type_node, done),
6449 &join_seq);
6451 lower_oacc_reductions (loc, clauses, place, inner,
6452 fork, join, &fork_seq, &join_seq, ctx);
6454 /* Append this level to head. */
6455 gimple_seq_add_seq (head, fork_seq);
6456 /* Prepend it to tail. */
6457 gimple_seq_add_seq (&join_seq, *tail);
6458 *tail = join_seq;
6460 inner = true;
6463 /* Mark the end of the sequence. */
6464 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6465 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6468 /* A convenience function to build an empty GIMPLE_COND with just the
6469 condition. */
6471 static gcond *
6472 gimple_build_cond_empty (tree cond)
6474 enum tree_code pred_code;
6475 tree lhs, rhs;
6477 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6478 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6481 /* Return true if a parallel REGION is within a declare target function or
6482 within a target region and is not a part of a gridified target. */
6484 static bool
6485 parallel_needs_hsa_kernel_p (struct omp_region *region)
6487 bool indirect = false;
6488 for (region = region->outer; region; region = region->outer)
6490 if (region->type == GIMPLE_OMP_PARALLEL)
6491 indirect = true;
6492 else if (region->type == GIMPLE_OMP_TARGET)
6494 gomp_target *tgt_stmt
6495 = as_a <gomp_target *> (last_stmt (region->entry));
6497 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6498 OMP_CLAUSE__GRIDDIM_))
6499 return indirect;
6500 else
6501 return true;
6505 if (lookup_attribute ("omp declare target",
6506 DECL_ATTRIBUTES (current_function_decl)))
6507 return true;
6509 return false;
6512 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6513 bool = false);
6515 /* Build the function calls to GOMP_parallel_start etc to actually
6516 generate the parallel operation. REGION is the parallel region
6517 being expanded. BB is the block where to insert the code. WS_ARGS
6518 will be set if this is a call to a combined parallel+workshare
6519 construct, it contains the list of additional arguments needed by
6520 the workshare construct. */
6522 static void
6523 expand_parallel_call (struct omp_region *region, basic_block bb,
6524 gomp_parallel *entry_stmt,
6525 vec<tree, va_gc> *ws_args)
6527 tree t, t1, t2, val, cond, c, clauses, flags;
6528 gimple_stmt_iterator gsi;
6529 gimple *stmt;
6530 enum built_in_function start_ix;
6531 int start_ix2;
6532 location_t clause_loc;
6533 vec<tree, va_gc> *args;
6535 clauses = gimple_omp_parallel_clauses (entry_stmt);
6537 /* Determine what flavor of GOMP_parallel we will be
6538 emitting. */
6539 start_ix = BUILT_IN_GOMP_PARALLEL;
6540 if (is_combined_parallel (region))
6542 switch (region->inner->type)
6544 case GIMPLE_OMP_FOR:
6545 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6546 switch (region->inner->sched_kind)
6548 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6549 start_ix2 = 3;
6550 break;
6551 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6552 case OMP_CLAUSE_SCHEDULE_GUIDED:
6553 if (region->inner->sched_modifiers
6554 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6556 start_ix2 = 3 + region->inner->sched_kind;
6557 break;
6559 /* FALLTHRU */
6560 default:
6561 start_ix2 = region->inner->sched_kind;
6562 break;
6564 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6565 start_ix = (enum built_in_function) start_ix2;
6566 break;
6567 case GIMPLE_OMP_SECTIONS:
6568 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6569 break;
6570 default:
6571 gcc_unreachable ();
6575 /* By default, the value of NUM_THREADS is zero (selected at run time)
6576 and there is no conditional. */
6577 cond = NULL_TREE;
6578 val = build_int_cst (unsigned_type_node, 0);
6579 flags = build_int_cst (unsigned_type_node, 0);
6581 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6582 if (c)
6583 cond = OMP_CLAUSE_IF_EXPR (c);
6585 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6586 if (c)
6588 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6589 clause_loc = OMP_CLAUSE_LOCATION (c);
6591 else
6592 clause_loc = gimple_location (entry_stmt);
6594 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6595 if (c)
6596 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6598 /* Ensure 'val' is of the correct type. */
6599 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6601 /* If we found the clause 'if (cond)', build either
6602 (cond != 0) or (cond ? val : 1u). */
6603 if (cond)
6605 cond = gimple_boolify (cond);
6607 if (integer_zerop (val))
6608 val = fold_build2_loc (clause_loc,
6609 EQ_EXPR, unsigned_type_node, cond,
6610 build_int_cst (TREE_TYPE (cond), 0));
6611 else
6613 basic_block cond_bb, then_bb, else_bb;
6614 edge e, e_then, e_else;
6615 tree tmp_then, tmp_else, tmp_join, tmp_var;
6617 tmp_var = create_tmp_var (TREE_TYPE (val));
6618 if (gimple_in_ssa_p (cfun))
6620 tmp_then = make_ssa_name (tmp_var);
6621 tmp_else = make_ssa_name (tmp_var);
6622 tmp_join = make_ssa_name (tmp_var);
6624 else
6626 tmp_then = tmp_var;
6627 tmp_else = tmp_var;
6628 tmp_join = tmp_var;
6631 e = split_block_after_labels (bb);
6632 cond_bb = e->src;
6633 bb = e->dest;
6634 remove_edge (e);
6636 then_bb = create_empty_bb (cond_bb);
6637 else_bb = create_empty_bb (then_bb);
6638 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6639 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6641 stmt = gimple_build_cond_empty (cond);
6642 gsi = gsi_start_bb (cond_bb);
6643 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6645 gsi = gsi_start_bb (then_bb);
6646 expand_omp_build_assign (&gsi, tmp_then, val, true);
6648 gsi = gsi_start_bb (else_bb);
6649 expand_omp_build_assign (&gsi, tmp_else,
6650 build_int_cst (unsigned_type_node, 1),
6651 true);
6653 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6654 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6655 add_bb_to_loop (then_bb, cond_bb->loop_father);
6656 add_bb_to_loop (else_bb, cond_bb->loop_father);
6657 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6658 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6660 if (gimple_in_ssa_p (cfun))
6662 gphi *phi = create_phi_node (tmp_join, bb);
6663 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6664 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6667 val = tmp_join;
6670 gsi = gsi_start_bb (bb);
6671 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6672 false, GSI_CONTINUE_LINKING);
6675 gsi = gsi_last_bb (bb);
6676 t = gimple_omp_parallel_data_arg (entry_stmt);
6677 if (t == NULL)
6678 t1 = null_pointer_node;
6679 else
6680 t1 = build_fold_addr_expr (t);
6681 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6682 t2 = build_fold_addr_expr (child_fndecl);
6684 vec_alloc (args, 4 + vec_safe_length (ws_args));
6685 args->quick_push (t2);
6686 args->quick_push (t1);
6687 args->quick_push (val);
6688 if (ws_args)
6689 args->splice (*ws_args);
6690 args->quick_push (flags);
6692 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6693 builtin_decl_explicit (start_ix), args);
6695 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6696 false, GSI_CONTINUE_LINKING);
6698 if (hsa_gen_requested_p ()
6699 && parallel_needs_hsa_kernel_p (region))
6701 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6702 hsa_register_kernel (child_cnode);
6706 /* Insert a function call whose name is FUNC_NAME with the information from
6707 ENTRY_STMT into the basic_block BB. */
6709 static void
6710 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6711 vec <tree, va_gc> *ws_args)
6713 tree t, t1, t2;
6714 gimple_stmt_iterator gsi;
6715 vec <tree, va_gc> *args;
6717 gcc_assert (vec_safe_length (ws_args) == 2);
6718 tree func_name = (*ws_args)[0];
6719 tree grain = (*ws_args)[1];
6721 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6722 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6723 gcc_assert (count != NULL_TREE);
6724 count = OMP_CLAUSE_OPERAND (count, 0);
6726 gsi = gsi_last_bb (bb);
6727 t = gimple_omp_parallel_data_arg (entry_stmt);
6728 if (t == NULL)
6729 t1 = null_pointer_node;
6730 else
6731 t1 = build_fold_addr_expr (t);
6732 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6734 vec_alloc (args, 4);
6735 args->quick_push (t2);
6736 args->quick_push (t1);
6737 args->quick_push (count);
6738 args->quick_push (grain);
6739 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6741 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6742 GSI_CONTINUE_LINKING);
6745 /* Build the function call to GOMP_task to actually
6746 generate the task operation. BB is the block where to insert the code. */
6748 static void
6749 expand_task_call (struct omp_region *region, basic_block bb,
6750 gomp_task *entry_stmt)
6752 tree t1, t2, t3;
6753 gimple_stmt_iterator gsi;
6754 location_t loc = gimple_location (entry_stmt);
6756 tree clauses = gimple_omp_task_clauses (entry_stmt);
6758 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6759 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6760 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6761 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6762 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6763 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6765 unsigned int iflags
6766 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6767 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6768 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6770 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6771 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6772 tree num_tasks = NULL_TREE;
6773 bool ull = false;
6774 if (taskloop_p)
6776 gimple *g = last_stmt (region->outer->entry);
6777 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6778 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6779 struct omp_for_data fd;
6780 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6781 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6782 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6783 OMP_CLAUSE__LOOPTEMP_);
6784 startvar = OMP_CLAUSE_DECL (startvar);
6785 endvar = OMP_CLAUSE_DECL (endvar);
6786 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6787 if (fd.loop.cond_code == LT_EXPR)
6788 iflags |= GOMP_TASK_FLAG_UP;
6789 tree tclauses = gimple_omp_for_clauses (g);
6790 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6791 if (num_tasks)
6792 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6793 else
6795 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6796 if (num_tasks)
6798 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6799 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6801 else
6802 num_tasks = integer_zero_node;
6804 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6805 if (ifc == NULL_TREE)
6806 iflags |= GOMP_TASK_FLAG_IF;
6807 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6808 iflags |= GOMP_TASK_FLAG_NOGROUP;
6809 ull = fd.iter_type == long_long_unsigned_type_node;
6811 else if (priority)
6812 iflags |= GOMP_TASK_FLAG_PRIORITY;
6814 tree flags = build_int_cst (unsigned_type_node, iflags);
6816 tree cond = boolean_true_node;
6817 if (ifc)
6819 if (taskloop_p)
6821 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6822 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6823 build_int_cst (unsigned_type_node,
6824 GOMP_TASK_FLAG_IF),
6825 build_int_cst (unsigned_type_node, 0));
6826 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6827 flags, t);
6829 else
6830 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6833 if (finalc)
6835 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6836 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6837 build_int_cst (unsigned_type_node,
6838 GOMP_TASK_FLAG_FINAL),
6839 build_int_cst (unsigned_type_node, 0));
6840 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6842 if (depend)
6843 depend = OMP_CLAUSE_DECL (depend);
6844 else
6845 depend = build_int_cst (ptr_type_node, 0);
6846 if (priority)
6847 priority = fold_convert (integer_type_node,
6848 OMP_CLAUSE_PRIORITY_EXPR (priority));
6849 else
6850 priority = integer_zero_node;
6852 gsi = gsi_last_bb (bb);
6853 tree t = gimple_omp_task_data_arg (entry_stmt);
6854 if (t == NULL)
6855 t2 = null_pointer_node;
6856 else
6857 t2 = build_fold_addr_expr_loc (loc, t);
6858 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6859 t = gimple_omp_task_copy_fn (entry_stmt);
6860 if (t == NULL)
6861 t3 = null_pointer_node;
6862 else
6863 t3 = build_fold_addr_expr_loc (loc, t);
6865 if (taskloop_p)
6866 t = build_call_expr (ull
6867 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6868 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6869 11, t1, t2, t3,
6870 gimple_omp_task_arg_size (entry_stmt),
6871 gimple_omp_task_arg_align (entry_stmt), flags,
6872 num_tasks, priority, startvar, endvar, step);
6873 else
6874 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6875 9, t1, t2, t3,
6876 gimple_omp_task_arg_size (entry_stmt),
6877 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6878 depend, priority);
6880 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6881 false, GSI_CONTINUE_LINKING);
6885 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6886 catch handler and return it. This prevents programs from violating the
6887 structured block semantics with throws. */
6889 static gimple_seq
6890 maybe_catch_exception (gimple_seq body)
6892 gimple *g;
6893 tree decl;
6895 if (!flag_exceptions)
6896 return body;
6898 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6899 decl = lang_hooks.eh_protect_cleanup_actions ();
6900 else
6901 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6903 g = gimple_build_eh_must_not_throw (decl);
6904 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6905 GIMPLE_TRY_CATCH);
6907 return gimple_seq_alloc_with_stmt (g);
6910 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6912 static tree
6913 vec2chain (vec<tree, va_gc> *v)
6915 tree chain = NULL_TREE, t;
6916 unsigned ix;
6918 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6920 DECL_CHAIN (t) = chain;
6921 chain = t;
6924 return chain;
6928 /* Remove barriers in REGION->EXIT's block. Note that this is only
6929 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6930 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6931 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6932 removed. */
6934 static void
6935 remove_exit_barrier (struct omp_region *region)
6937 gimple_stmt_iterator gsi;
6938 basic_block exit_bb;
6939 edge_iterator ei;
6940 edge e;
6941 gimple *stmt;
6942 int any_addressable_vars = -1;
6944 exit_bb = region->exit;
6946 /* If the parallel region doesn't return, we don't have REGION->EXIT
6947 block at all. */
6948 if (! exit_bb)
6949 return;
6951 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6952 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6953 statements that can appear in between are extremely limited -- no
6954 memory operations at all. Here, we allow nothing at all, so the
6955 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6956 gsi = gsi_last_bb (exit_bb);
6957 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6958 gsi_prev (&gsi);
6959 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6960 return;
6962 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6964 gsi = gsi_last_bb (e->src);
6965 if (gsi_end_p (gsi))
6966 continue;
6967 stmt = gsi_stmt (gsi);
6968 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6969 && !gimple_omp_return_nowait_p (stmt))
6971 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6972 in many cases. If there could be tasks queued, the barrier
6973 might be needed to let the tasks run before some local
6974 variable of the parallel that the task uses as shared
6975 runs out of scope. The task can be spawned either
6976 from within current function (this would be easy to check)
6977 or from some function it calls and gets passed an address
6978 of such a variable. */
6979 if (any_addressable_vars < 0)
6981 gomp_parallel *parallel_stmt
6982 = as_a <gomp_parallel *> (last_stmt (region->entry));
6983 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6984 tree local_decls, block, decl;
6985 unsigned ix;
6987 any_addressable_vars = 0;
6988 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6989 if (TREE_ADDRESSABLE (decl))
6991 any_addressable_vars = 1;
6992 break;
6994 for (block = gimple_block (stmt);
6995 !any_addressable_vars
6996 && block
6997 && TREE_CODE (block) == BLOCK;
6998 block = BLOCK_SUPERCONTEXT (block))
7000 for (local_decls = BLOCK_VARS (block);
7001 local_decls;
7002 local_decls = DECL_CHAIN (local_decls))
7003 if (TREE_ADDRESSABLE (local_decls))
7005 any_addressable_vars = 1;
7006 break;
7008 if (block == gimple_block (parallel_stmt))
7009 break;
7012 if (!any_addressable_vars)
7013 gimple_omp_return_set_nowait (stmt);
7018 static void
7019 remove_exit_barriers (struct omp_region *region)
7021 if (region->type == GIMPLE_OMP_PARALLEL)
7022 remove_exit_barrier (region);
7024 if (region->inner)
7026 region = region->inner;
7027 remove_exit_barriers (region);
7028 while (region->next)
7030 region = region->next;
7031 remove_exit_barriers (region);
7036 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7037 calls. These can't be declared as const functions, but
7038 within one parallel body they are constant, so they can be
7039 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7040 which are declared const. Similarly for task body, except
7041 that in untied task omp_get_thread_num () can change at any task
7042 scheduling point. */
7044 static void
7045 optimize_omp_library_calls (gimple *entry_stmt)
7047 basic_block bb;
7048 gimple_stmt_iterator gsi;
7049 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7050 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7051 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7052 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7053 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7054 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7055 OMP_CLAUSE_UNTIED) != NULL);
7057 FOR_EACH_BB_FN (bb, cfun)
7058 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7060 gimple *call = gsi_stmt (gsi);
7061 tree decl;
7063 if (is_gimple_call (call)
7064 && (decl = gimple_call_fndecl (call))
7065 && DECL_EXTERNAL (decl)
7066 && TREE_PUBLIC (decl)
7067 && DECL_INITIAL (decl) == NULL)
7069 tree built_in;
7071 if (DECL_NAME (decl) == thr_num_id)
7073 /* In #pragma omp task untied omp_get_thread_num () can change
7074 during the execution of the task region. */
7075 if (untied_task)
7076 continue;
7077 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7079 else if (DECL_NAME (decl) == num_thr_id)
7080 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7081 else
7082 continue;
7084 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7085 || gimple_call_num_args (call) != 0)
7086 continue;
7088 if (flag_exceptions && !TREE_NOTHROW (decl))
7089 continue;
7091 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7092 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7093 TREE_TYPE (TREE_TYPE (built_in))))
7094 continue;
7096 gimple_call_set_fndecl (call, built_in);
7101 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7102 regimplified. */
7104 static tree
7105 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7107 tree t = *tp;
7109 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7110 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
7111 return t;
7113 if (TREE_CODE (t) == ADDR_EXPR)
7114 recompute_tree_invariant_for_addr_expr (t);
7116 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7117 return NULL_TREE;
7120 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7122 static void
7123 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7124 bool after)
7126 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7127 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7128 !after, after ? GSI_CONTINUE_LINKING
7129 : GSI_SAME_STMT);
7130 gimple *stmt = gimple_build_assign (to, from);
7131 if (after)
7132 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7133 else
7134 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7135 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7136 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7138 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7139 gimple_regimplify_operands (stmt, &gsi);
7143 /* Expand the OpenMP parallel or task directive starting at REGION. */
7145 static void
7146 expand_omp_taskreg (struct omp_region *region)
7148 basic_block entry_bb, exit_bb, new_bb;
7149 struct function *child_cfun;
7150 tree child_fn, block, t;
7151 gimple_stmt_iterator gsi;
7152 gimple *entry_stmt, *stmt;
7153 edge e;
7154 vec<tree, va_gc> *ws_args;
7156 entry_stmt = last_stmt (region->entry);
7157 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7158 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7160 entry_bb = region->entry;
7161 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7162 exit_bb = region->cont;
7163 else
7164 exit_bb = region->exit;
7166 bool is_cilk_for
7167 = (flag_cilkplus
7168 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7169 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7170 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7172 if (is_cilk_for)
7173 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7174 and the inner statement contains the name of the built-in function
7175 and grain. */
7176 ws_args = region->inner->ws_args;
7177 else if (is_combined_parallel (region))
7178 ws_args = region->ws_args;
7179 else
7180 ws_args = NULL;
7182 if (child_cfun->cfg)
7184 /* Due to inlining, it may happen that we have already outlined
7185 the region, in which case all we need to do is make the
7186 sub-graph unreachable and emit the parallel call. */
7187 edge entry_succ_e, exit_succ_e;
7189 entry_succ_e = single_succ_edge (entry_bb);
7191 gsi = gsi_last_bb (entry_bb);
7192 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7193 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7194 gsi_remove (&gsi, true);
7196 new_bb = entry_bb;
7197 if (exit_bb)
7199 exit_succ_e = single_succ_edge (exit_bb);
7200 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7202 remove_edge_and_dominated_blocks (entry_succ_e);
7204 else
7206 unsigned srcidx, dstidx, num;
7208 /* If the parallel region needs data sent from the parent
7209 function, then the very first statement (except possible
7210 tree profile counter updates) of the parallel body
7211 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7212 &.OMP_DATA_O is passed as an argument to the child function,
7213 we need to replace it with the argument as seen by the child
7214 function.
7216 In most cases, this will end up being the identity assignment
7217 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7218 a function call that has been inlined, the original PARM_DECL
7219 .OMP_DATA_I may have been converted into a different local
7220 variable. In which case, we need to keep the assignment. */
7221 if (gimple_omp_taskreg_data_arg (entry_stmt))
7223 basic_block entry_succ_bb
7224 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7225 : FALLTHRU_EDGE (entry_bb)->dest;
7226 tree arg;
7227 gimple *parcopy_stmt = NULL;
7229 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7231 gimple *stmt;
7233 gcc_assert (!gsi_end_p (gsi));
7234 stmt = gsi_stmt (gsi);
7235 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7236 continue;
7238 if (gimple_num_ops (stmt) == 2)
7240 tree arg = gimple_assign_rhs1 (stmt);
7242 /* We're ignore the subcode because we're
7243 effectively doing a STRIP_NOPS. */
7245 if (TREE_CODE (arg) == ADDR_EXPR
7246 && TREE_OPERAND (arg, 0)
7247 == gimple_omp_taskreg_data_arg (entry_stmt))
7249 parcopy_stmt = stmt;
7250 break;
7255 gcc_assert (parcopy_stmt != NULL);
7256 arg = DECL_ARGUMENTS (child_fn);
7258 if (!gimple_in_ssa_p (cfun))
7260 if (gimple_assign_lhs (parcopy_stmt) == arg)
7261 gsi_remove (&gsi, true);
7262 else
7264 /* ?? Is setting the subcode really necessary ?? */
7265 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7266 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7269 else
7271 tree lhs = gimple_assign_lhs (parcopy_stmt);
7272 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7273 /* We'd like to set the rhs to the default def in the child_fn,
7274 but it's too early to create ssa names in the child_fn.
7275 Instead, we set the rhs to the parm. In
7276 move_sese_region_to_fn, we introduce a default def for the
7277 parm, map the parm to it's default def, and once we encounter
7278 this stmt, replace the parm with the default def. */
7279 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7280 update_stmt (parcopy_stmt);
7284 /* Declare local variables needed in CHILD_CFUN. */
7285 block = DECL_INITIAL (child_fn);
7286 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7287 /* The gimplifier could record temporaries in parallel/task block
7288 rather than in containing function's local_decls chain,
7289 which would mean cgraph missed finalizing them. Do it now. */
7290 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7291 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
7292 varpool_node::finalize_decl (t);
7293 DECL_SAVED_TREE (child_fn) = NULL;
7294 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7295 gimple_set_body (child_fn, NULL);
7296 TREE_USED (block) = 1;
7298 /* Reset DECL_CONTEXT on function arguments. */
7299 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7300 DECL_CONTEXT (t) = child_fn;
7302 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7303 so that it can be moved to the child function. */
7304 gsi = gsi_last_bb (entry_bb);
7305 stmt = gsi_stmt (gsi);
7306 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7307 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7308 e = split_block (entry_bb, stmt);
7309 gsi_remove (&gsi, true);
7310 entry_bb = e->dest;
7311 edge e2 = NULL;
7312 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7313 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7314 else
7316 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7317 gcc_assert (e2->dest == region->exit);
7318 remove_edge (BRANCH_EDGE (entry_bb));
7319 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7320 gsi = gsi_last_bb (region->exit);
7321 gcc_assert (!gsi_end_p (gsi)
7322 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7323 gsi_remove (&gsi, true);
7326 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7327 if (exit_bb)
7329 gsi = gsi_last_bb (exit_bb);
7330 gcc_assert (!gsi_end_p (gsi)
7331 && (gimple_code (gsi_stmt (gsi))
7332 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7333 stmt = gimple_build_return (NULL);
7334 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7335 gsi_remove (&gsi, true);
7338 /* Move the parallel region into CHILD_CFUN. */
7340 if (gimple_in_ssa_p (cfun))
7342 init_tree_ssa (child_cfun);
7343 init_ssa_operands (child_cfun);
7344 child_cfun->gimple_df->in_ssa_p = true;
7345 block = NULL_TREE;
7347 else
7348 block = gimple_block (entry_stmt);
7350 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7351 if (exit_bb)
7352 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7353 if (e2)
7355 basic_block dest_bb = e2->dest;
7356 if (!exit_bb)
7357 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7358 remove_edge (e2);
7359 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7361 /* When the OMP expansion process cannot guarantee an up-to-date
7362 loop tree arrange for the child function to fixup loops. */
7363 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7364 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7366 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7367 num = vec_safe_length (child_cfun->local_decls);
7368 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7370 t = (*child_cfun->local_decls)[srcidx];
7371 if (DECL_CONTEXT (t) == cfun->decl)
7372 continue;
7373 if (srcidx != dstidx)
7374 (*child_cfun->local_decls)[dstidx] = t;
7375 dstidx++;
7377 if (dstidx != num)
7378 vec_safe_truncate (child_cfun->local_decls, dstidx);
7380 /* Inform the callgraph about the new function. */
7381 child_cfun->curr_properties = cfun->curr_properties;
7382 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7383 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7384 cgraph_node *node = cgraph_node::get_create (child_fn);
7385 node->parallelized_function = 1;
7386 cgraph_node::add_new_function (child_fn, true);
7388 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7389 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7391 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7392 fixed in a following pass. */
7393 push_cfun (child_cfun);
7394 if (need_asm)
7395 assign_assembler_name_if_neeeded (child_fn);
7397 if (optimize)
7398 optimize_omp_library_calls (entry_stmt);
7399 cgraph_edge::rebuild_edges ();
7401 /* Some EH regions might become dead, see PR34608. If
7402 pass_cleanup_cfg isn't the first pass to happen with the
7403 new child, these dead EH edges might cause problems.
7404 Clean them up now. */
7405 if (flag_exceptions)
7407 basic_block bb;
7408 bool changed = false;
7410 FOR_EACH_BB_FN (bb, cfun)
7411 changed |= gimple_purge_dead_eh_edges (bb);
7412 if (changed)
7413 cleanup_tree_cfg ();
7415 if (gimple_in_ssa_p (cfun))
7416 update_ssa (TODO_update_ssa);
7417 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7418 verify_loop_structure ();
7419 pop_cfun ();
7421 if (dump_file && !gimple_in_ssa_p (cfun))
7423 omp_any_child_fn_dumped = true;
7424 dump_function_header (dump_file, child_fn, dump_flags);
7425 dump_function_to_file (child_fn, dump_file, dump_flags);
7429 /* Emit a library call to launch the children threads. */
7430 if (is_cilk_for)
7431 expand_cilk_for_call (new_bb,
7432 as_a <gomp_parallel *> (entry_stmt), ws_args);
7433 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7434 expand_parallel_call (region, new_bb,
7435 as_a <gomp_parallel *> (entry_stmt), ws_args);
7436 else
7437 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7438 if (gimple_in_ssa_p (cfun))
7439 update_ssa (TODO_update_ssa_only_virtuals);
7442 /* Information about members of an OpenACC collapsed loop nest. */
7444 struct oacc_collapse
7446 tree base; /* Base value. */
7447 tree iters; /* Number of steps. */
7448 tree step; /* step size. */
7451 /* Helper for expand_oacc_for. Determine collapsed loop information.
7452 Fill in COUNTS array. Emit any initialization code before GSI.
7453 Return the calculated outer loop bound of BOUND_TYPE. */
7455 static tree
7456 expand_oacc_collapse_init (const struct omp_for_data *fd,
7457 gimple_stmt_iterator *gsi,
7458 oacc_collapse *counts, tree bound_type)
7460 tree total = build_int_cst (bound_type, 1);
7461 int ix;
7463 gcc_assert (integer_onep (fd->loop.step));
7464 gcc_assert (integer_zerop (fd->loop.n1));
7466 for (ix = 0; ix != fd->collapse; ix++)
7468 const omp_for_data_loop *loop = &fd->loops[ix];
7470 tree iter_type = TREE_TYPE (loop->v);
7471 tree diff_type = iter_type;
7472 tree plus_type = iter_type;
7474 gcc_assert (loop->cond_code == fd->loop.cond_code);
7476 if (POINTER_TYPE_P (iter_type))
7477 plus_type = sizetype;
7478 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7479 diff_type = signed_type_for (diff_type);
7481 tree b = loop->n1;
7482 tree e = loop->n2;
7483 tree s = loop->step;
7484 bool up = loop->cond_code == LT_EXPR;
7485 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7486 bool negating;
7487 tree expr;
7489 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7490 true, GSI_SAME_STMT);
7491 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7492 true, GSI_SAME_STMT);
7494 /* Convert the step, avoiding possible unsigned->signed overflow. */
7495 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7496 if (negating)
7497 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7498 s = fold_convert (diff_type, s);
7499 if (negating)
7500 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7501 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7502 true, GSI_SAME_STMT);
7504 /* Determine the range, avoiding possible unsigned->signed overflow. */
7505 negating = !up && TYPE_UNSIGNED (iter_type);
7506 expr = fold_build2 (MINUS_EXPR, plus_type,
7507 fold_convert (plus_type, negating ? b : e),
7508 fold_convert (plus_type, negating ? e : b));
7509 expr = fold_convert (diff_type, expr);
7510 if (negating)
7511 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7512 tree range = force_gimple_operand_gsi
7513 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7515 /* Determine number of iterations. */
7516 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7517 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7518 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7520 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7521 true, GSI_SAME_STMT);
7523 counts[ix].base = b;
7524 counts[ix].iters = iters;
7525 counts[ix].step = s;
7527 total = fold_build2 (MULT_EXPR, bound_type, total,
7528 fold_convert (bound_type, iters));
7531 return total;
7534 /* Emit initializers for collapsed loop members. IVAR is the outer
7535 loop iteration variable, from which collapsed loop iteration values
7536 are calculated. COUNTS array has been initialized by
7537 expand_oacc_collapse_inits. */
7539 static void
7540 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7541 gimple_stmt_iterator *gsi,
7542 const oacc_collapse *counts, tree ivar)
7544 tree ivar_type = TREE_TYPE (ivar);
7546 /* The most rapidly changing iteration variable is the innermost
7547 one. */
7548 for (int ix = fd->collapse; ix--;)
7550 const omp_for_data_loop *loop = &fd->loops[ix];
7551 const oacc_collapse *collapse = &counts[ix];
7552 tree iter_type = TREE_TYPE (loop->v);
7553 tree diff_type = TREE_TYPE (collapse->step);
7554 tree plus_type = iter_type;
7555 enum tree_code plus_code = PLUS_EXPR;
7556 tree expr;
7558 if (POINTER_TYPE_P (iter_type))
7560 plus_code = POINTER_PLUS_EXPR;
7561 plus_type = sizetype;
7564 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7565 fold_convert (ivar_type, collapse->iters));
7566 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7567 collapse->step);
7568 expr = fold_build2 (plus_code, iter_type, collapse->base,
7569 fold_convert (plus_type, expr));
7570 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7571 true, GSI_SAME_STMT);
7572 gassign *ass = gimple_build_assign (loop->v, expr);
7573 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7575 if (ix)
7577 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7578 fold_convert (ivar_type, collapse->iters));
7579 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7580 true, GSI_SAME_STMT);
7586 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7587 of the combined collapse > 1 loop constructs, generate code like:
7588 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7589 if (cond3 is <)
7590 adj = STEP3 - 1;
7591 else
7592 adj = STEP3 + 1;
7593 count3 = (adj + N32 - N31) / STEP3;
7594 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7595 if (cond2 is <)
7596 adj = STEP2 - 1;
7597 else
7598 adj = STEP2 + 1;
7599 count2 = (adj + N22 - N21) / STEP2;
7600 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7601 if (cond1 is <)
7602 adj = STEP1 - 1;
7603 else
7604 adj = STEP1 + 1;
7605 count1 = (adj + N12 - N11) / STEP1;
7606 count = count1 * count2 * count3;
7607 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7608 count = 0;
7609 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7610 of the combined loop constructs, just initialize COUNTS array
7611 from the _looptemp_ clauses. */
7613 /* NOTE: It *could* be better to moosh all of the BBs together,
7614 creating one larger BB with all the computation and the unexpected
7615 jump at the end. I.e.
7617 bool zero3, zero2, zero1, zero;
7619 zero3 = N32 c3 N31;
7620 count3 = (N32 - N31) /[cl] STEP3;
7621 zero2 = N22 c2 N21;
7622 count2 = (N22 - N21) /[cl] STEP2;
7623 zero1 = N12 c1 N11;
7624 count1 = (N12 - N11) /[cl] STEP1;
7625 zero = zero3 || zero2 || zero1;
7626 count = count1 * count2 * count3;
7627 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7629 After all, we expect the zero=false, and thus we expect to have to
7630 evaluate all of the comparison expressions, so short-circuiting
7631 oughtn't be a win. Since the condition isn't protecting a
7632 denominator, we're not concerned about divide-by-zero, so we can
7633 fully evaluate count even if a numerator turned out to be wrong.
7635 It seems like putting this all together would create much better
7636 scheduling opportunities, and less pressure on the chip's branch
7637 predictor. */
7639 static void
7640 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7641 basic_block &entry_bb, tree *counts,
7642 basic_block &zero_iter1_bb, int &first_zero_iter1,
7643 basic_block &zero_iter2_bb, int &first_zero_iter2,
7644 basic_block &l2_dom_bb)
7646 tree t, type = TREE_TYPE (fd->loop.v);
7647 edge e, ne;
7648 int i;
7650 /* Collapsed loops need work for expansion into SSA form. */
7651 gcc_assert (!gimple_in_ssa_p (cfun));
7653 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7654 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7656 gcc_assert (fd->ordered == 0);
7657 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7658 isn't supposed to be handled, as the inner loop doesn't
7659 use it. */
7660 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 for (i = 0; i < fd->collapse; i++)
7665 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7666 OMP_CLAUSE__LOOPTEMP_);
7667 gcc_assert (innerc);
7668 if (i)
7669 counts[i] = OMP_CLAUSE_DECL (innerc);
7670 else
7671 counts[0] = NULL_TREE;
7673 return;
7676 for (i = fd->collapse; i < fd->ordered; i++)
7678 tree itype = TREE_TYPE (fd->loops[i].v);
7679 counts[i] = NULL_TREE;
7680 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7681 fold_convert (itype, fd->loops[i].n1),
7682 fold_convert (itype, fd->loops[i].n2));
7683 if (t && integer_zerop (t))
7685 for (i = fd->collapse; i < fd->ordered; i++)
7686 counts[i] = build_int_cst (type, 0);
7687 break;
7690 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7692 tree itype = TREE_TYPE (fd->loops[i].v);
7694 if (i >= fd->collapse && counts[i])
7695 continue;
7696 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7697 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7698 fold_convert (itype, fd->loops[i].n1),
7699 fold_convert (itype, fd->loops[i].n2)))
7700 == NULL_TREE || !integer_onep (t)))
7702 gcond *cond_stmt;
7703 tree n1, n2;
7704 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7705 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7706 true, GSI_SAME_STMT);
7707 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7708 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7709 true, GSI_SAME_STMT);
7710 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7711 NULL_TREE, NULL_TREE);
7712 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7713 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7714 expand_omp_regimplify_p, NULL, NULL)
7715 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7716 expand_omp_regimplify_p, NULL, NULL))
7718 *gsi = gsi_for_stmt (cond_stmt);
7719 gimple_regimplify_operands (cond_stmt, gsi);
7721 e = split_block (entry_bb, cond_stmt);
7722 basic_block &zero_iter_bb
7723 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7724 int &first_zero_iter
7725 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7726 if (zero_iter_bb == NULL)
7728 gassign *assign_stmt;
7729 first_zero_iter = i;
7730 zero_iter_bb = create_empty_bb (entry_bb);
7731 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7732 *gsi = gsi_after_labels (zero_iter_bb);
7733 if (i < fd->collapse)
7734 assign_stmt = gimple_build_assign (fd->loop.n2,
7735 build_zero_cst (type));
7736 else
7738 counts[i] = create_tmp_reg (type, ".count");
7739 assign_stmt
7740 = gimple_build_assign (counts[i], build_zero_cst (type));
7742 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7743 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7744 entry_bb);
7746 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7747 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7748 e->flags = EDGE_TRUE_VALUE;
7749 e->probability = REG_BR_PROB_BASE - ne->probability;
7750 if (l2_dom_bb == NULL)
7751 l2_dom_bb = entry_bb;
7752 entry_bb = e->dest;
7753 *gsi = gsi_last_bb (entry_bb);
7756 if (POINTER_TYPE_P (itype))
7757 itype = signed_type_for (itype);
7758 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7759 ? -1 : 1));
7760 t = fold_build2 (PLUS_EXPR, itype,
7761 fold_convert (itype, fd->loops[i].step), t);
7762 t = fold_build2 (PLUS_EXPR, itype, t,
7763 fold_convert (itype, fd->loops[i].n2));
7764 t = fold_build2 (MINUS_EXPR, itype, t,
7765 fold_convert (itype, fd->loops[i].n1));
7766 /* ?? We could probably use CEIL_DIV_EXPR instead of
7767 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7768 generate the same code in the end because generically we
7769 don't know that the values involved must be negative for
7770 GT?? */
7771 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7772 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7773 fold_build1 (NEGATE_EXPR, itype, t),
7774 fold_build1 (NEGATE_EXPR, itype,
7775 fold_convert (itype,
7776 fd->loops[i].step)));
7777 else
7778 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7779 fold_convert (itype, fd->loops[i].step));
7780 t = fold_convert (type, t);
7781 if (TREE_CODE (t) == INTEGER_CST)
7782 counts[i] = t;
7783 else
7785 if (i < fd->collapse || i != first_zero_iter2)
7786 counts[i] = create_tmp_reg (type, ".count");
7787 expand_omp_build_assign (gsi, counts[i], t);
7789 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7791 if (i == 0)
7792 t = counts[0];
7793 else
7794 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7795 expand_omp_build_assign (gsi, fd->loop.n2, t);
7801 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7802 T = V;
7803 V3 = N31 + (T % count3) * STEP3;
7804 T = T / count3;
7805 V2 = N21 + (T % count2) * STEP2;
7806 T = T / count2;
7807 V1 = N11 + T * STEP1;
7808 if this loop doesn't have an inner loop construct combined with it.
7809 If it does have an inner loop construct combined with it and the
7810 iteration count isn't known constant, store values from counts array
7811 into its _looptemp_ temporaries instead. */
7813 static void
7814 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7815 tree *counts, gimple *inner_stmt, tree startvar)
7817 int i;
7818 if (gimple_omp_for_combined_p (fd->for_stmt))
7820 /* If fd->loop.n2 is constant, then no propagation of the counts
7821 is needed, they are constant. */
7822 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7823 return;
7825 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7826 ? gimple_omp_taskreg_clauses (inner_stmt)
7827 : gimple_omp_for_clauses (inner_stmt);
7828 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7829 isn't supposed to be handled, as the inner loop doesn't
7830 use it. */
7831 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7832 gcc_assert (innerc);
7833 for (i = 0; i < fd->collapse; i++)
7835 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7836 OMP_CLAUSE__LOOPTEMP_);
7837 gcc_assert (innerc);
7838 if (i)
7840 tree tem = OMP_CLAUSE_DECL (innerc);
7841 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7842 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7843 false, GSI_CONTINUE_LINKING);
7844 gassign *stmt = gimple_build_assign (tem, t);
7845 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7848 return;
7851 tree type = TREE_TYPE (fd->loop.v);
7852 tree tem = create_tmp_reg (type, ".tem");
7853 gassign *stmt = gimple_build_assign (tem, startvar);
7854 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7856 for (i = fd->collapse - 1; i >= 0; i--)
7858 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7859 itype = vtype;
7860 if (POINTER_TYPE_P (vtype))
7861 itype = signed_type_for (vtype);
7862 if (i != 0)
7863 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7864 else
7865 t = tem;
7866 t = fold_convert (itype, t);
7867 t = fold_build2 (MULT_EXPR, itype, t,
7868 fold_convert (itype, fd->loops[i].step));
7869 if (POINTER_TYPE_P (vtype))
7870 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7871 else
7872 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7873 t = force_gimple_operand_gsi (gsi, t,
7874 DECL_P (fd->loops[i].v)
7875 && TREE_ADDRESSABLE (fd->loops[i].v),
7876 NULL_TREE, false,
7877 GSI_CONTINUE_LINKING);
7878 stmt = gimple_build_assign (fd->loops[i].v, t);
7879 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7880 if (i != 0)
7882 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7883 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7884 false, GSI_CONTINUE_LINKING);
7885 stmt = gimple_build_assign (tem, t);
7886 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7892 /* Helper function for expand_omp_for_*. Generate code like:
7893 L10:
7894 V3 += STEP3;
7895 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7896 L11:
7897 V3 = N31;
7898 V2 += STEP2;
7899 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7900 L12:
7901 V2 = N21;
7902 V1 += STEP1;
7903 goto BODY_BB; */
7905 static basic_block
7906 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7907 basic_block body_bb)
7909 basic_block last_bb, bb, collapse_bb = NULL;
7910 int i;
7911 gimple_stmt_iterator gsi;
7912 edge e;
7913 tree t;
7914 gimple *stmt;
7916 last_bb = cont_bb;
7917 for (i = fd->collapse - 1; i >= 0; i--)
7919 tree vtype = TREE_TYPE (fd->loops[i].v);
7921 bb = create_empty_bb (last_bb);
7922 add_bb_to_loop (bb, last_bb->loop_father);
7923 gsi = gsi_start_bb (bb);
7925 if (i < fd->collapse - 1)
7927 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7928 e->probability = REG_BR_PROB_BASE / 8;
7930 t = fd->loops[i + 1].n1;
7931 t = force_gimple_operand_gsi (&gsi, t,
7932 DECL_P (fd->loops[i + 1].v)
7933 && TREE_ADDRESSABLE (fd->loops[i
7934 + 1].v),
7935 NULL_TREE, false,
7936 GSI_CONTINUE_LINKING);
7937 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7938 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7940 else
7941 collapse_bb = bb;
7943 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7945 if (POINTER_TYPE_P (vtype))
7946 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7947 else
7948 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7949 t = force_gimple_operand_gsi (&gsi, t,
7950 DECL_P (fd->loops[i].v)
7951 && TREE_ADDRESSABLE (fd->loops[i].v),
7952 NULL_TREE, false, GSI_CONTINUE_LINKING);
7953 stmt = gimple_build_assign (fd->loops[i].v, t);
7954 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7956 if (i > 0)
7958 t = fd->loops[i].n2;
7959 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7960 false, GSI_CONTINUE_LINKING);
7961 tree v = fd->loops[i].v;
7962 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7963 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7964 false, GSI_CONTINUE_LINKING);
7965 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7966 stmt = gimple_build_cond_empty (t);
7967 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7968 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7969 e->probability = REG_BR_PROB_BASE * 7 / 8;
7971 else
7972 make_edge (bb, body_bb, EDGE_FALLTHRU);
7973 last_bb = bb;
7976 return collapse_bb;
7980 /* Expand #pragma omp ordered depend(source). */
7982 static void
7983 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7984 tree *counts, location_t loc)
7986 enum built_in_function source_ix
7987 = fd->iter_type == long_integer_type_node
7988 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7989 gimple *g
7990 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7991 build_fold_addr_expr (counts[fd->ordered]));
7992 gimple_set_location (g, loc);
7993 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7996 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7998 static void
7999 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
8000 tree *counts, tree c, location_t loc)
8002 auto_vec<tree, 10> args;
8003 enum built_in_function sink_ix
8004 = fd->iter_type == long_integer_type_node
8005 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
8006 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
8007 int i;
8008 gimple_stmt_iterator gsi2 = *gsi;
8009 bool warned_step = false;
8011 for (i = 0; i < fd->ordered; i++)
8013 off = TREE_PURPOSE (deps);
8014 if (!integer_zerop (off))
8016 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8017 || fd->loops[i].cond_code == GT_EXPR);
8018 bool forward = fd->loops[i].cond_code == LT_EXPR;
8019 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8020 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8021 "lexically later iteration");
8022 break;
8024 deps = TREE_CHAIN (deps);
8026 /* If all offsets corresponding to the collapsed loops are zero,
8027 this depend clause can be ignored. FIXME: but there is still a
8028 flush needed. We need to emit one __sync_synchronize () for it
8029 though (perhaps conditionally)? Solve this together with the
8030 conservative dependence folding optimization.
8031 if (i >= fd->collapse)
8032 return; */
8034 deps = OMP_CLAUSE_DECL (c);
8035 gsi_prev (&gsi2);
8036 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8037 edge e2 = split_block_after_labels (e1->dest);
8039 *gsi = gsi_after_labels (e1->dest);
8040 for (i = 0; i < fd->ordered; i++)
8042 tree itype = TREE_TYPE (fd->loops[i].v);
8043 if (POINTER_TYPE_P (itype))
8044 itype = sizetype;
8045 if (i)
8046 deps = TREE_CHAIN (deps);
8047 off = TREE_PURPOSE (deps);
8048 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8050 if (integer_zerop (off))
8051 t = boolean_true_node;
8052 else
8054 tree a;
8055 tree co = fold_convert_loc (loc, itype, off);
8056 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8058 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8059 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8060 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8061 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8062 co);
8064 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8065 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8066 fd->loops[i].v, co);
8067 else
8068 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8069 fd->loops[i].v, co);
8070 if (fd->loops[i].cond_code == LT_EXPR)
8072 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8073 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8074 fd->loops[i].n1);
8075 else
8076 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8077 fd->loops[i].n2);
8079 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8080 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8081 fd->loops[i].n2);
8082 else
8083 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8084 fd->loops[i].n1);
8086 if (cond)
8087 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8088 else
8089 cond = t;
8091 off = fold_convert_loc (loc, itype, off);
8093 if (fd->loops[i].cond_code == LT_EXPR
8094 ? !integer_onep (fd->loops[i].step)
8095 : !integer_minus_onep (fd->loops[i].step))
8097 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8098 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8099 fold_build1_loc (loc, NEGATE_EXPR, itype,
8100 s));
8101 else
8102 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8103 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8104 build_int_cst (itype, 0));
8105 if (integer_zerop (t) && !warned_step)
8107 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8108 "in the iteration space");
8109 warned_step = true;
8111 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8112 cond, t);
8115 if (i <= fd->collapse - 1 && fd->collapse > 1)
8116 t = fd->loop.v;
8117 else if (counts[i])
8118 t = counts[i];
8119 else
8121 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8122 fd->loops[i].v, fd->loops[i].n1);
8123 t = fold_convert_loc (loc, fd->iter_type, t);
8125 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8126 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8127 fold_build1_loc (loc, NEGATE_EXPR, itype,
8128 s));
8129 else
8130 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8131 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8132 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8133 off = fold_convert_loc (loc, fd->iter_type, off);
8134 if (i <= fd->collapse - 1 && fd->collapse > 1)
8136 if (i)
8137 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8138 off);
8139 if (i < fd->collapse - 1)
8141 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8142 counts[i]);
8143 continue;
8146 off = unshare_expr (off);
8147 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8148 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8149 true, GSI_SAME_STMT);
8150 args.safe_push (t);
8152 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8153 gimple_set_location (g, loc);
8154 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8156 *gsi = gsi_last_bb (e1->src);
8157 cond = unshare_expr (cond);
8158 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8159 GSI_CONTINUE_LINKING);
8160 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8161 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8162 e3->probability = REG_BR_PROB_BASE / 8;
8163 e1->probability = REG_BR_PROB_BASE - e3->probability;
8164 e1->flags = EDGE_TRUE_VALUE;
8165 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8167 *gsi = gsi_after_labels (e2->dest);
8170 /* Expand all #pragma omp ordered depend(source) and
8171 #pragma omp ordered depend(sink:...) constructs in the current
8172 #pragma omp for ordered(n) region. */
8174 static void
8175 expand_omp_ordered_source_sink (struct omp_region *region,
8176 struct omp_for_data *fd, tree *counts,
8177 basic_block cont_bb)
8179 struct omp_region *inner;
8180 int i;
8181 for (i = fd->collapse - 1; i < fd->ordered; i++)
8182 if (i == fd->collapse - 1 && fd->collapse > 1)
8183 counts[i] = NULL_TREE;
8184 else if (i >= fd->collapse && !cont_bb)
8185 counts[i] = build_zero_cst (fd->iter_type);
8186 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8187 && integer_onep (fd->loops[i].step))
8188 counts[i] = NULL_TREE;
8189 else
8190 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8191 tree atype
8192 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8193 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8194 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8196 for (inner = region->inner; inner; inner = inner->next)
8197 if (inner->type == GIMPLE_OMP_ORDERED)
8199 gomp_ordered *ord_stmt = inner->ord_stmt;
8200 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8201 location_t loc = gimple_location (ord_stmt);
8202 tree c;
8203 for (c = gimple_omp_ordered_clauses (ord_stmt);
8204 c; c = OMP_CLAUSE_CHAIN (c))
8205 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8206 break;
8207 if (c)
8208 expand_omp_ordered_source (&gsi, fd, counts, loc);
8209 for (c = gimple_omp_ordered_clauses (ord_stmt);
8210 c; c = OMP_CLAUSE_CHAIN (c))
8211 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8212 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8213 gsi_remove (&gsi, true);
8217 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8218 collapsed. */
8220 static basic_block
8221 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8222 basic_block cont_bb, basic_block body_bb,
8223 bool ordered_lastprivate)
8225 if (fd->ordered == fd->collapse)
8226 return cont_bb;
8228 if (!cont_bb)
8230 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8231 for (int i = fd->collapse; i < fd->ordered; i++)
8233 tree type = TREE_TYPE (fd->loops[i].v);
8234 tree n1 = fold_convert (type, fd->loops[i].n1);
8235 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8236 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8237 size_int (i - fd->collapse + 1),
8238 NULL_TREE, NULL_TREE);
8239 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8241 return NULL;
8244 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8246 tree t, type = TREE_TYPE (fd->loops[i].v);
8247 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8248 expand_omp_build_assign (&gsi, fd->loops[i].v,
8249 fold_convert (type, fd->loops[i].n1));
8250 if (counts[i])
8251 expand_omp_build_assign (&gsi, counts[i],
8252 build_zero_cst (fd->iter_type));
8253 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8254 size_int (i - fd->collapse + 1),
8255 NULL_TREE, NULL_TREE);
8256 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8257 if (!gsi_end_p (gsi))
8258 gsi_prev (&gsi);
8259 else
8260 gsi = gsi_last_bb (body_bb);
8261 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8262 basic_block new_body = e1->dest;
8263 if (body_bb == cont_bb)
8264 cont_bb = new_body;
8265 edge e2 = NULL;
8266 basic_block new_header;
8267 if (EDGE_COUNT (cont_bb->preds) > 0)
8269 gsi = gsi_last_bb (cont_bb);
8270 if (POINTER_TYPE_P (type))
8271 t = fold_build_pointer_plus (fd->loops[i].v,
8272 fold_convert (sizetype,
8273 fd->loops[i].step));
8274 else
8275 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8276 fold_convert (type, fd->loops[i].step));
8277 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8278 if (counts[i])
8280 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8281 build_int_cst (fd->iter_type, 1));
8282 expand_omp_build_assign (&gsi, counts[i], t);
8283 t = counts[i];
8285 else
8287 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8288 fd->loops[i].v, fd->loops[i].n1);
8289 t = fold_convert (fd->iter_type, t);
8290 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8291 true, GSI_SAME_STMT);
8293 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8294 size_int (i - fd->collapse + 1),
8295 NULL_TREE, NULL_TREE);
8296 expand_omp_build_assign (&gsi, aref, t);
8297 gsi_prev (&gsi);
8298 e2 = split_block (cont_bb, gsi_stmt (gsi));
8299 new_header = e2->dest;
8301 else
8302 new_header = cont_bb;
8303 gsi = gsi_after_labels (new_header);
8304 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8305 true, GSI_SAME_STMT);
8306 tree n2
8307 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8308 true, NULL_TREE, true, GSI_SAME_STMT);
8309 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8310 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8311 edge e3 = split_block (new_header, gsi_stmt (gsi));
8312 cont_bb = e3->dest;
8313 remove_edge (e1);
8314 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8315 e3->flags = EDGE_FALSE_VALUE;
8316 e3->probability = REG_BR_PROB_BASE / 8;
8317 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8318 e1->probability = REG_BR_PROB_BASE - e3->probability;
8320 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8321 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8323 if (e2)
8325 struct loop *loop = alloc_loop ();
8326 loop->header = new_header;
8327 loop->latch = e2->src;
8328 add_loop (loop, body_bb->loop_father);
8332 /* If there are any lastprivate clauses and it is possible some loops
8333 might have zero iterations, ensure all the decls are initialized,
8334 otherwise we could crash evaluating C++ class iterators with lastprivate
8335 clauses. */
8336 bool need_inits = false;
8337 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8338 if (need_inits)
8340 tree type = TREE_TYPE (fd->loops[i].v);
8341 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8342 expand_omp_build_assign (&gsi, fd->loops[i].v,
8343 fold_convert (type, fd->loops[i].n1));
8345 else
8347 tree type = TREE_TYPE (fd->loops[i].v);
8348 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8349 boolean_type_node,
8350 fold_convert (type, fd->loops[i].n1),
8351 fold_convert (type, fd->loops[i].n2));
8352 if (!integer_onep (this_cond))
8353 need_inits = true;
8356 return cont_bb;
8360 /* A subroutine of expand_omp_for. Generate code for a parallel
8361 loop with any schedule. Given parameters:
8363 for (V = N1; V cond N2; V += STEP) BODY;
8365 where COND is "<" or ">", we generate pseudocode
8367 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8368 if (more) goto L0; else goto L3;
8370 V = istart0;
8371 iend = iend0;
8373 BODY;
8374 V += STEP;
8375 if (V cond iend) goto L1; else goto L2;
8377 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8380 If this is a combined omp parallel loop, instead of the call to
8381 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8382 If this is gimple_omp_for_combined_p loop, then instead of assigning
8383 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8384 inner GIMPLE_OMP_FOR and V += STEP; and
8385 if (V cond iend) goto L1; else goto L2; are removed.
8387 For collapsed loops, given parameters:
8388 collapse(3)
8389 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8390 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8391 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8392 BODY;
8394 we generate pseudocode
8396 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8397 if (cond3 is <)
8398 adj = STEP3 - 1;
8399 else
8400 adj = STEP3 + 1;
8401 count3 = (adj + N32 - N31) / STEP3;
8402 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8403 if (cond2 is <)
8404 adj = STEP2 - 1;
8405 else
8406 adj = STEP2 + 1;
8407 count2 = (adj + N22 - N21) / STEP2;
8408 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8409 if (cond1 is <)
8410 adj = STEP1 - 1;
8411 else
8412 adj = STEP1 + 1;
8413 count1 = (adj + N12 - N11) / STEP1;
8414 count = count1 * count2 * count3;
8415 goto Z1;
8417 count = 0;
8419 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8420 if (more) goto L0; else goto L3;
8422 V = istart0;
8423 T = V;
8424 V3 = N31 + (T % count3) * STEP3;
8425 T = T / count3;
8426 V2 = N21 + (T % count2) * STEP2;
8427 T = T / count2;
8428 V1 = N11 + T * STEP1;
8429 iend = iend0;
8431 BODY;
8432 V += 1;
8433 if (V < iend) goto L10; else goto L2;
8434 L10:
8435 V3 += STEP3;
8436 if (V3 cond3 N32) goto L1; else goto L11;
8437 L11:
8438 V3 = N31;
8439 V2 += STEP2;
8440 if (V2 cond2 N22) goto L1; else goto L12;
8441 L12:
8442 V2 = N21;
8443 V1 += STEP1;
8444 goto L1;
8446 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8451 static void
8452 expand_omp_for_generic (struct omp_region *region,
8453 struct omp_for_data *fd,
8454 enum built_in_function start_fn,
8455 enum built_in_function next_fn,
8456 gimple *inner_stmt)
8458 tree type, istart0, iend0, iend;
8459 tree t, vmain, vback, bias = NULL_TREE;
8460 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8461 basic_block l2_bb = NULL, l3_bb = NULL;
8462 gimple_stmt_iterator gsi;
8463 gassign *assign_stmt;
8464 bool in_combined_parallel = is_combined_parallel (region);
8465 bool broken_loop = region->cont == NULL;
8466 edge e, ne;
8467 tree *counts = NULL;
8468 int i;
8469 bool ordered_lastprivate = false;
8471 gcc_assert (!broken_loop || !in_combined_parallel);
8472 gcc_assert (fd->iter_type == long_integer_type_node
8473 || !in_combined_parallel);
8475 entry_bb = region->entry;
8476 cont_bb = region->cont;
8477 collapse_bb = NULL;
8478 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8479 gcc_assert (broken_loop
8480 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8481 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8482 l1_bb = single_succ (l0_bb);
8483 if (!broken_loop)
8485 l2_bb = create_empty_bb (cont_bb);
8486 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8487 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8488 == l1_bb));
8489 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8491 else
8492 l2_bb = NULL;
8493 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8494 exit_bb = region->exit;
8496 gsi = gsi_last_bb (entry_bb);
8498 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8499 if (fd->ordered
8500 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8501 OMP_CLAUSE_LASTPRIVATE))
8502 ordered_lastprivate = false;
8503 if (fd->collapse > 1 || fd->ordered)
8505 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8506 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8508 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8509 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8510 zero_iter1_bb, first_zero_iter1,
8511 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8513 if (zero_iter1_bb)
8515 /* Some counts[i] vars might be uninitialized if
8516 some loop has zero iterations. But the body shouldn't
8517 be executed in that case, so just avoid uninit warnings. */
8518 for (i = first_zero_iter1;
8519 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8520 if (SSA_VAR_P (counts[i]))
8521 TREE_NO_WARNING (counts[i]) = 1;
8522 gsi_prev (&gsi);
8523 e = split_block (entry_bb, gsi_stmt (gsi));
8524 entry_bb = e->dest;
8525 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8526 gsi = gsi_last_bb (entry_bb);
8527 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8528 get_immediate_dominator (CDI_DOMINATORS,
8529 zero_iter1_bb));
8531 if (zero_iter2_bb)
8533 /* Some counts[i] vars might be uninitialized if
8534 some loop has zero iterations. But the body shouldn't
8535 be executed in that case, so just avoid uninit warnings. */
8536 for (i = first_zero_iter2; i < fd->ordered; i++)
8537 if (SSA_VAR_P (counts[i]))
8538 TREE_NO_WARNING (counts[i]) = 1;
8539 if (zero_iter1_bb)
8540 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8541 else
8543 gsi_prev (&gsi);
8544 e = split_block (entry_bb, gsi_stmt (gsi));
8545 entry_bb = e->dest;
8546 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8547 gsi = gsi_last_bb (entry_bb);
8548 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8549 get_immediate_dominator
8550 (CDI_DOMINATORS, zero_iter2_bb));
8553 if (fd->collapse == 1)
8555 counts[0] = fd->loop.n2;
8556 fd->loop = fd->loops[0];
8560 type = TREE_TYPE (fd->loop.v);
8561 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8562 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8563 TREE_ADDRESSABLE (istart0) = 1;
8564 TREE_ADDRESSABLE (iend0) = 1;
8566 /* See if we need to bias by LLONG_MIN. */
8567 if (fd->iter_type == long_long_unsigned_type_node
8568 && TREE_CODE (type) == INTEGER_TYPE
8569 && !TYPE_UNSIGNED (type)
8570 && fd->ordered == 0)
8572 tree n1, n2;
8574 if (fd->loop.cond_code == LT_EXPR)
8576 n1 = fd->loop.n1;
8577 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8579 else
8581 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8582 n2 = fd->loop.n1;
8584 if (TREE_CODE (n1) != INTEGER_CST
8585 || TREE_CODE (n2) != INTEGER_CST
8586 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8587 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8590 gimple_stmt_iterator gsif = gsi;
8591 gsi_prev (&gsif);
8593 tree arr = NULL_TREE;
8594 if (in_combined_parallel)
8596 gcc_assert (fd->ordered == 0);
8597 /* In a combined parallel loop, emit a call to
8598 GOMP_loop_foo_next. */
8599 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8600 build_fold_addr_expr (istart0),
8601 build_fold_addr_expr (iend0));
8603 else
8605 tree t0, t1, t2, t3, t4;
8606 /* If this is not a combined parallel loop, emit a call to
8607 GOMP_loop_foo_start in ENTRY_BB. */
8608 t4 = build_fold_addr_expr (iend0);
8609 t3 = build_fold_addr_expr (istart0);
8610 if (fd->ordered)
8612 t0 = build_int_cst (unsigned_type_node,
8613 fd->ordered - fd->collapse + 1);
8614 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8615 fd->ordered
8616 - fd->collapse + 1),
8617 ".omp_counts");
8618 DECL_NAMELESS (arr) = 1;
8619 TREE_ADDRESSABLE (arr) = 1;
8620 TREE_STATIC (arr) = 1;
8621 vec<constructor_elt, va_gc> *v;
8622 vec_alloc (v, fd->ordered - fd->collapse + 1);
8623 int idx;
8625 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8627 tree c;
8628 if (idx == 0 && fd->collapse > 1)
8629 c = fd->loop.n2;
8630 else
8631 c = counts[idx + fd->collapse - 1];
8632 tree purpose = size_int (idx);
8633 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8634 if (TREE_CODE (c) != INTEGER_CST)
8635 TREE_STATIC (arr) = 0;
8638 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8639 if (!TREE_STATIC (arr))
8640 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8641 void_type_node, arr),
8642 true, NULL_TREE, true, GSI_SAME_STMT);
8643 t1 = build_fold_addr_expr (arr);
8644 t2 = NULL_TREE;
8646 else
8648 t2 = fold_convert (fd->iter_type, fd->loop.step);
8649 t1 = fd->loop.n2;
8650 t0 = fd->loop.n1;
8651 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8653 tree innerc
8654 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8655 OMP_CLAUSE__LOOPTEMP_);
8656 gcc_assert (innerc);
8657 t0 = OMP_CLAUSE_DECL (innerc);
8658 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8659 OMP_CLAUSE__LOOPTEMP_);
8660 gcc_assert (innerc);
8661 t1 = OMP_CLAUSE_DECL (innerc);
8663 if (POINTER_TYPE_P (TREE_TYPE (t0))
8664 && TYPE_PRECISION (TREE_TYPE (t0))
8665 != TYPE_PRECISION (fd->iter_type))
8667 /* Avoid casting pointers to integer of a different size. */
8668 tree itype = signed_type_for (type);
8669 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8670 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8672 else
8674 t1 = fold_convert (fd->iter_type, t1);
8675 t0 = fold_convert (fd->iter_type, t0);
8677 if (bias)
8679 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8680 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8683 if (fd->iter_type == long_integer_type_node || fd->ordered)
8685 if (fd->chunk_size)
8687 t = fold_convert (fd->iter_type, fd->chunk_size);
8688 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8689 if (fd->ordered)
8690 t = build_call_expr (builtin_decl_explicit (start_fn),
8691 5, t0, t1, t, t3, t4);
8692 else
8693 t = build_call_expr (builtin_decl_explicit (start_fn),
8694 6, t0, t1, t2, t, t3, t4);
8696 else if (fd->ordered)
8697 t = build_call_expr (builtin_decl_explicit (start_fn),
8698 4, t0, t1, t3, t4);
8699 else
8700 t = build_call_expr (builtin_decl_explicit (start_fn),
8701 5, t0, t1, t2, t3, t4);
8703 else
8705 tree t5;
8706 tree c_bool_type;
8707 tree bfn_decl;
8709 /* The GOMP_loop_ull_*start functions have additional boolean
8710 argument, true for < loops and false for > loops.
8711 In Fortran, the C bool type can be different from
8712 boolean_type_node. */
8713 bfn_decl = builtin_decl_explicit (start_fn);
8714 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8715 t5 = build_int_cst (c_bool_type,
8716 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8717 if (fd->chunk_size)
8719 tree bfn_decl = builtin_decl_explicit (start_fn);
8720 t = fold_convert (fd->iter_type, fd->chunk_size);
8721 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8722 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8724 else
8725 t = build_call_expr (builtin_decl_explicit (start_fn),
8726 6, t5, t0, t1, t2, t3, t4);
8729 if (TREE_TYPE (t) != boolean_type_node)
8730 t = fold_build2 (NE_EXPR, boolean_type_node,
8731 t, build_int_cst (TREE_TYPE (t), 0));
8732 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8733 true, GSI_SAME_STMT);
8734 if (arr && !TREE_STATIC (arr))
8736 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8737 TREE_THIS_VOLATILE (clobber) = 1;
8738 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8739 GSI_SAME_STMT);
8741 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8743 /* Remove the GIMPLE_OMP_FOR statement. */
8744 gsi_remove (&gsi, true);
8746 if (gsi_end_p (gsif))
8747 gsif = gsi_after_labels (gsi_bb (gsif));
8748 gsi_next (&gsif);
8750 /* Iteration setup for sequential loop goes in L0_BB. */
8751 tree startvar = fd->loop.v;
8752 tree endvar = NULL_TREE;
8754 if (gimple_omp_for_combined_p (fd->for_stmt))
8756 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8757 && gimple_omp_for_kind (inner_stmt)
8758 == GF_OMP_FOR_KIND_SIMD);
8759 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8760 OMP_CLAUSE__LOOPTEMP_);
8761 gcc_assert (innerc);
8762 startvar = OMP_CLAUSE_DECL (innerc);
8763 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8764 OMP_CLAUSE__LOOPTEMP_);
8765 gcc_assert (innerc);
8766 endvar = OMP_CLAUSE_DECL (innerc);
8769 gsi = gsi_start_bb (l0_bb);
8770 t = istart0;
8771 if (fd->ordered && fd->collapse == 1)
8772 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8773 fold_convert (fd->iter_type, fd->loop.step));
8774 else if (bias)
8775 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8776 if (fd->ordered && fd->collapse == 1)
8778 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8779 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8780 fd->loop.n1, fold_convert (sizetype, t));
8781 else
8783 t = fold_convert (TREE_TYPE (startvar), t);
8784 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8785 fd->loop.n1, t);
8788 else
8790 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8791 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8792 t = fold_convert (TREE_TYPE (startvar), t);
8794 t = force_gimple_operand_gsi (&gsi, t,
8795 DECL_P (startvar)
8796 && TREE_ADDRESSABLE (startvar),
8797 NULL_TREE, false, GSI_CONTINUE_LINKING);
8798 assign_stmt = gimple_build_assign (startvar, t);
8799 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8801 t = iend0;
8802 if (fd->ordered && fd->collapse == 1)
8803 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8804 fold_convert (fd->iter_type, fd->loop.step));
8805 else if (bias)
8806 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8807 if (fd->ordered && fd->collapse == 1)
8809 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8810 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8811 fd->loop.n1, fold_convert (sizetype, t));
8812 else
8814 t = fold_convert (TREE_TYPE (startvar), t);
8815 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8816 fd->loop.n1, t);
8819 else
8821 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8822 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8823 t = fold_convert (TREE_TYPE (startvar), t);
8825 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8826 false, GSI_CONTINUE_LINKING);
8827 if (endvar)
8829 assign_stmt = gimple_build_assign (endvar, iend);
8830 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8831 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8832 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8833 else
8834 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8835 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8837 /* Handle linear clause adjustments. */
8838 tree itercnt = NULL_TREE;
8839 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8840 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8841 c; c = OMP_CLAUSE_CHAIN (c))
8842 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8843 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8845 tree d = OMP_CLAUSE_DECL (c);
8846 bool is_ref = is_reference (d);
8847 tree t = d, a, dest;
8848 if (is_ref)
8849 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8850 tree type = TREE_TYPE (t);
8851 if (POINTER_TYPE_P (type))
8852 type = sizetype;
8853 dest = unshare_expr (t);
8854 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8855 expand_omp_build_assign (&gsif, v, t);
8856 if (itercnt == NULL_TREE)
8858 itercnt = startvar;
8859 tree n1 = fd->loop.n1;
8860 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8862 itercnt
8863 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8864 itercnt);
8865 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8867 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8868 itercnt, n1);
8869 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8870 itercnt, fd->loop.step);
8871 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8872 NULL_TREE, false,
8873 GSI_CONTINUE_LINKING);
8875 a = fold_build2 (MULT_EXPR, type,
8876 fold_convert (type, itercnt),
8877 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8878 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8879 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8880 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8881 false, GSI_CONTINUE_LINKING);
8882 assign_stmt = gimple_build_assign (dest, t);
8883 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8885 if (fd->collapse > 1)
8886 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8888 if (fd->ordered)
8890 /* Until now, counts array contained number of iterations or
8891 variable containing it for ith loop. From now on, we need
8892 those counts only for collapsed loops, and only for the 2nd
8893 till the last collapsed one. Move those one element earlier,
8894 we'll use counts[fd->collapse - 1] for the first source/sink
8895 iteration counter and so on and counts[fd->ordered]
8896 as the array holding the current counter values for
8897 depend(source). */
8898 if (fd->collapse > 1)
8899 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8900 if (broken_loop)
8902 int i;
8903 for (i = fd->collapse; i < fd->ordered; i++)
8905 tree type = TREE_TYPE (fd->loops[i].v);
8906 tree this_cond
8907 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8908 fold_convert (type, fd->loops[i].n1),
8909 fold_convert (type, fd->loops[i].n2));
8910 if (!integer_onep (this_cond))
8911 break;
8913 if (i < fd->ordered)
8915 cont_bb
8916 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8917 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8918 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8919 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8920 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8921 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8922 make_edge (cont_bb, l1_bb, 0);
8923 l2_bb = create_empty_bb (cont_bb);
8924 broken_loop = false;
8927 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8928 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8929 ordered_lastprivate);
8930 if (counts[fd->collapse - 1])
8932 gcc_assert (fd->collapse == 1);
8933 gsi = gsi_last_bb (l0_bb);
8934 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8935 istart0, true);
8936 gsi = gsi_last_bb (cont_bb);
8937 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8938 build_int_cst (fd->iter_type, 1));
8939 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8940 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8941 size_zero_node, NULL_TREE, NULL_TREE);
8942 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8943 t = counts[fd->collapse - 1];
8945 else if (fd->collapse > 1)
8946 t = fd->loop.v;
8947 else
8949 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8950 fd->loops[0].v, fd->loops[0].n1);
8951 t = fold_convert (fd->iter_type, t);
8953 gsi = gsi_last_bb (l0_bb);
8954 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8955 size_zero_node, NULL_TREE, NULL_TREE);
8956 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8957 false, GSI_CONTINUE_LINKING);
8958 expand_omp_build_assign (&gsi, aref, t, true);
8961 if (!broken_loop)
8963 /* Code to control the increment and predicate for the sequential
8964 loop goes in the CONT_BB. */
8965 gsi = gsi_last_bb (cont_bb);
8966 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8967 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8968 vmain = gimple_omp_continue_control_use (cont_stmt);
8969 vback = gimple_omp_continue_control_def (cont_stmt);
8971 if (!gimple_omp_for_combined_p (fd->for_stmt))
8973 if (POINTER_TYPE_P (type))
8974 t = fold_build_pointer_plus (vmain, fd->loop.step);
8975 else
8976 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8977 t = force_gimple_operand_gsi (&gsi, t,
8978 DECL_P (vback)
8979 && TREE_ADDRESSABLE (vback),
8980 NULL_TREE, true, GSI_SAME_STMT);
8981 assign_stmt = gimple_build_assign (vback, t);
8982 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8984 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8986 if (fd->collapse > 1)
8987 t = fd->loop.v;
8988 else
8990 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8991 fd->loops[0].v, fd->loops[0].n1);
8992 t = fold_convert (fd->iter_type, t);
8994 tree aref = build4 (ARRAY_REF, fd->iter_type,
8995 counts[fd->ordered], size_zero_node,
8996 NULL_TREE, NULL_TREE);
8997 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8998 true, GSI_SAME_STMT);
8999 expand_omp_build_assign (&gsi, aref, t);
9002 t = build2 (fd->loop.cond_code, boolean_type_node,
9003 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
9004 iend);
9005 gcond *cond_stmt = gimple_build_cond_empty (t);
9006 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9009 /* Remove GIMPLE_OMP_CONTINUE. */
9010 gsi_remove (&gsi, true);
9012 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9013 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9015 /* Emit code to get the next parallel iteration in L2_BB. */
9016 gsi = gsi_start_bb (l2_bb);
9018 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9019 build_fold_addr_expr (istart0),
9020 build_fold_addr_expr (iend0));
9021 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9022 false, GSI_CONTINUE_LINKING);
9023 if (TREE_TYPE (t) != boolean_type_node)
9024 t = fold_build2 (NE_EXPR, boolean_type_node,
9025 t, build_int_cst (TREE_TYPE (t), 0));
9026 gcond *cond_stmt = gimple_build_cond_empty (t);
9027 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9030 /* Add the loop cleanup function. */
9031 gsi = gsi_last_bb (exit_bb);
9032 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9033 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9034 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9035 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9036 else
9037 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9038 gcall *call_stmt = gimple_build_call (t, 0);
9039 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9040 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9041 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9042 if (fd->ordered)
9044 tree arr = counts[fd->ordered];
9045 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9046 TREE_THIS_VOLATILE (clobber) = 1;
9047 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9048 GSI_SAME_STMT);
9050 gsi_remove (&gsi, true);
9052 /* Connect the new blocks. */
9053 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9054 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9056 if (!broken_loop)
9058 gimple_seq phis;
9060 e = find_edge (cont_bb, l3_bb);
9061 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9063 phis = phi_nodes (l3_bb);
9064 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9066 gimple *phi = gsi_stmt (gsi);
9067 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9068 PHI_ARG_DEF_FROM_EDGE (phi, e));
9070 remove_edge (e);
9072 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9073 e = find_edge (cont_bb, l1_bb);
9074 if (e == NULL)
9076 e = BRANCH_EDGE (cont_bb);
9077 gcc_assert (single_succ (e->dest) == l1_bb);
9079 if (gimple_omp_for_combined_p (fd->for_stmt))
9081 remove_edge (e);
9082 e = NULL;
9084 else if (fd->collapse > 1)
9086 remove_edge (e);
9087 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9089 else
9090 e->flags = EDGE_TRUE_VALUE;
9091 if (e)
9093 e->probability = REG_BR_PROB_BASE * 7 / 8;
9094 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9096 else
9098 e = find_edge (cont_bb, l2_bb);
9099 e->flags = EDGE_FALLTHRU;
9101 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9103 if (gimple_in_ssa_p (cfun))
9105 /* Add phis to the outer loop that connect to the phis in the inner,
9106 original loop, and move the loop entry value of the inner phi to
9107 the loop entry value of the outer phi. */
9108 gphi_iterator psi;
9109 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9111 source_location locus;
9112 gphi *nphi;
9113 gphi *exit_phi = psi.phi ();
9115 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9116 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9118 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9119 edge latch_to_l1 = find_edge (latch, l1_bb);
9120 gphi *inner_phi
9121 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9123 tree t = gimple_phi_result (exit_phi);
9124 tree new_res = copy_ssa_name (t, NULL);
9125 nphi = create_phi_node (new_res, l0_bb);
9127 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9128 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9129 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9130 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9131 add_phi_arg (nphi, t, entry_to_l0, locus);
9133 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9134 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9136 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9140 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9141 recompute_dominator (CDI_DOMINATORS, l2_bb));
9142 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9143 recompute_dominator (CDI_DOMINATORS, l3_bb));
9144 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9145 recompute_dominator (CDI_DOMINATORS, l0_bb));
9146 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9147 recompute_dominator (CDI_DOMINATORS, l1_bb));
9149 /* We enter expand_omp_for_generic with a loop. This original loop may
9150 have its own loop struct, or it may be part of an outer loop struct
9151 (which may be the fake loop). */
9152 struct loop *outer_loop = entry_bb->loop_father;
9153 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9155 add_bb_to_loop (l2_bb, outer_loop);
9157 /* We've added a new loop around the original loop. Allocate the
9158 corresponding loop struct. */
9159 struct loop *new_loop = alloc_loop ();
9160 new_loop->header = l0_bb;
9161 new_loop->latch = l2_bb;
9162 add_loop (new_loop, outer_loop);
9164 /* Allocate a loop structure for the original loop unless we already
9165 had one. */
9166 if (!orig_loop_has_loop_struct
9167 && !gimple_omp_for_combined_p (fd->for_stmt))
9169 struct loop *orig_loop = alloc_loop ();
9170 orig_loop->header = l1_bb;
9171 /* The loop may have multiple latches. */
9172 add_loop (orig_loop, new_loop);
9178 /* A subroutine of expand_omp_for. Generate code for a parallel
9179 loop with static schedule and no specified chunk size. Given
9180 parameters:
9182 for (V = N1; V cond N2; V += STEP) BODY;
9184 where COND is "<" or ">", we generate pseudocode
9186 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9187 if (cond is <)
9188 adj = STEP - 1;
9189 else
9190 adj = STEP + 1;
9191 if ((__typeof (V)) -1 > 0 && cond is >)
9192 n = -(adj + N2 - N1) / -STEP;
9193 else
9194 n = (adj + N2 - N1) / STEP;
9195 q = n / nthreads;
9196 tt = n % nthreads;
9197 if (threadid < tt) goto L3; else goto L4;
9199 tt = 0;
9200 q = q + 1;
9202 s0 = q * threadid + tt;
9203 e0 = s0 + q;
9204 V = s0 * STEP + N1;
9205 if (s0 >= e0) goto L2; else goto L0;
9207 e = e0 * STEP + N1;
9209 BODY;
9210 V += STEP;
9211 if (V cond e) goto L1;
9215 static void
9216 expand_omp_for_static_nochunk (struct omp_region *region,
9217 struct omp_for_data *fd,
9218 gimple *inner_stmt)
9220 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9221 tree type, itype, vmain, vback;
9222 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9223 basic_block body_bb, cont_bb, collapse_bb = NULL;
9224 basic_block fin_bb;
9225 gimple_stmt_iterator gsi;
9226 edge ep;
9227 bool broken_loop = region->cont == NULL;
9228 tree *counts = NULL;
9229 tree n1, n2, step;
9231 itype = type = TREE_TYPE (fd->loop.v);
9232 if (POINTER_TYPE_P (type))
9233 itype = signed_type_for (type);
9235 entry_bb = region->entry;
9236 cont_bb = region->cont;
9237 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9238 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9239 gcc_assert (broken_loop
9240 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9241 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9242 body_bb = single_succ (seq_start_bb);
9243 if (!broken_loop)
9245 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9246 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9247 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9249 exit_bb = region->exit;
9251 /* Iteration space partitioning goes in ENTRY_BB. */
9252 gsi = gsi_last_bb (entry_bb);
9253 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9255 if (fd->collapse > 1)
9257 int first_zero_iter = -1, dummy = -1;
9258 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9260 counts = XALLOCAVEC (tree, fd->collapse);
9261 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9262 fin_bb, first_zero_iter,
9263 dummy_bb, dummy, l2_dom_bb);
9264 t = NULL_TREE;
9266 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9267 t = integer_one_node;
9268 else
9269 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9270 fold_convert (type, fd->loop.n1),
9271 fold_convert (type, fd->loop.n2));
9272 if (fd->collapse == 1
9273 && TYPE_UNSIGNED (type)
9274 && (t == NULL_TREE || !integer_onep (t)))
9276 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9277 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9278 true, GSI_SAME_STMT);
9279 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9280 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9281 true, GSI_SAME_STMT);
9282 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9283 NULL_TREE, NULL_TREE);
9284 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9285 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9286 expand_omp_regimplify_p, NULL, NULL)
9287 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9288 expand_omp_regimplify_p, NULL, NULL))
9290 gsi = gsi_for_stmt (cond_stmt);
9291 gimple_regimplify_operands (cond_stmt, &gsi);
9293 ep = split_block (entry_bb, cond_stmt);
9294 ep->flags = EDGE_TRUE_VALUE;
9295 entry_bb = ep->dest;
9296 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9297 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9298 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9299 if (gimple_in_ssa_p (cfun))
9301 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9302 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9303 !gsi_end_p (gpi); gsi_next (&gpi))
9305 gphi *phi = gpi.phi ();
9306 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9307 ep, UNKNOWN_LOCATION);
9310 gsi = gsi_last_bb (entry_bb);
9313 switch (gimple_omp_for_kind (fd->for_stmt))
9315 case GF_OMP_FOR_KIND_FOR:
9316 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9317 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9318 break;
9319 case GF_OMP_FOR_KIND_DISTRIBUTE:
9320 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9321 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9322 break;
9323 default:
9324 gcc_unreachable ();
9326 nthreads = build_call_expr (nthreads, 0);
9327 nthreads = fold_convert (itype, nthreads);
9328 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9329 true, GSI_SAME_STMT);
9330 threadid = build_call_expr (threadid, 0);
9331 threadid = fold_convert (itype, threadid);
9332 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9333 true, GSI_SAME_STMT);
9335 n1 = fd->loop.n1;
9336 n2 = fd->loop.n2;
9337 step = fd->loop.step;
9338 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9340 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9341 OMP_CLAUSE__LOOPTEMP_);
9342 gcc_assert (innerc);
9343 n1 = OMP_CLAUSE_DECL (innerc);
9344 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9345 OMP_CLAUSE__LOOPTEMP_);
9346 gcc_assert (innerc);
9347 n2 = OMP_CLAUSE_DECL (innerc);
9349 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9350 true, NULL_TREE, true, GSI_SAME_STMT);
9351 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9352 true, NULL_TREE, true, GSI_SAME_STMT);
9353 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9354 true, NULL_TREE, true, GSI_SAME_STMT);
9356 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9357 t = fold_build2 (PLUS_EXPR, itype, step, t);
9358 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9359 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9360 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9361 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9362 fold_build1 (NEGATE_EXPR, itype, t),
9363 fold_build1 (NEGATE_EXPR, itype, step));
9364 else
9365 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9366 t = fold_convert (itype, t);
9367 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9369 q = create_tmp_reg (itype, "q");
9370 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9371 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9372 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9374 tt = create_tmp_reg (itype, "tt");
9375 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9376 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9377 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9379 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9380 gcond *cond_stmt = gimple_build_cond_empty (t);
9381 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9383 second_bb = split_block (entry_bb, cond_stmt)->dest;
9384 gsi = gsi_last_bb (second_bb);
9385 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9387 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9388 GSI_SAME_STMT);
9389 gassign *assign_stmt
9390 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9391 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9393 third_bb = split_block (second_bb, assign_stmt)->dest;
9394 gsi = gsi_last_bb (third_bb);
9395 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9397 t = build2 (MULT_EXPR, itype, q, threadid);
9398 t = build2 (PLUS_EXPR, itype, t, tt);
9399 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9401 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9402 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9404 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9405 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9407 /* Remove the GIMPLE_OMP_FOR statement. */
9408 gsi_remove (&gsi, true);
9410 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9411 gsi = gsi_start_bb (seq_start_bb);
9413 tree startvar = fd->loop.v;
9414 tree endvar = NULL_TREE;
9416 if (gimple_omp_for_combined_p (fd->for_stmt))
9418 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9419 ? gimple_omp_parallel_clauses (inner_stmt)
9420 : gimple_omp_for_clauses (inner_stmt);
9421 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9422 gcc_assert (innerc);
9423 startvar = OMP_CLAUSE_DECL (innerc);
9424 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9425 OMP_CLAUSE__LOOPTEMP_);
9426 gcc_assert (innerc);
9427 endvar = OMP_CLAUSE_DECL (innerc);
9428 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9429 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9431 int i;
9432 for (i = 1; i < fd->collapse; i++)
9434 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9435 OMP_CLAUSE__LOOPTEMP_);
9436 gcc_assert (innerc);
9438 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9439 OMP_CLAUSE__LOOPTEMP_);
9440 if (innerc)
9442 /* If needed (distribute parallel for with lastprivate),
9443 propagate down the total number of iterations. */
9444 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9445 fd->loop.n2);
9446 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9447 GSI_CONTINUE_LINKING);
9448 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9449 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9453 t = fold_convert (itype, s0);
9454 t = fold_build2 (MULT_EXPR, itype, t, step);
9455 if (POINTER_TYPE_P (type))
9456 t = fold_build_pointer_plus (n1, t);
9457 else
9458 t = fold_build2 (PLUS_EXPR, type, t, n1);
9459 t = fold_convert (TREE_TYPE (startvar), t);
9460 t = force_gimple_operand_gsi (&gsi, t,
9461 DECL_P (startvar)
9462 && TREE_ADDRESSABLE (startvar),
9463 NULL_TREE, false, GSI_CONTINUE_LINKING);
9464 assign_stmt = gimple_build_assign (startvar, t);
9465 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9467 t = fold_convert (itype, e0);
9468 t = fold_build2 (MULT_EXPR, itype, t, step);
9469 if (POINTER_TYPE_P (type))
9470 t = fold_build_pointer_plus (n1, t);
9471 else
9472 t = fold_build2 (PLUS_EXPR, type, t, n1);
9473 t = fold_convert (TREE_TYPE (startvar), t);
9474 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9475 false, GSI_CONTINUE_LINKING);
9476 if (endvar)
9478 assign_stmt = gimple_build_assign (endvar, e);
9479 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9480 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9481 assign_stmt = gimple_build_assign (fd->loop.v, e);
9482 else
9483 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9484 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9486 /* Handle linear clause adjustments. */
9487 tree itercnt = NULL_TREE;
9488 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9489 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9490 c; c = OMP_CLAUSE_CHAIN (c))
9491 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9492 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9494 tree d = OMP_CLAUSE_DECL (c);
9495 bool is_ref = is_reference (d);
9496 tree t = d, a, dest;
9497 if (is_ref)
9498 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9499 if (itercnt == NULL_TREE)
9501 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9503 itercnt = fold_build2 (MINUS_EXPR, itype,
9504 fold_convert (itype, n1),
9505 fold_convert (itype, fd->loop.n1));
9506 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9507 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9508 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9509 NULL_TREE, false,
9510 GSI_CONTINUE_LINKING);
9512 else
9513 itercnt = s0;
9515 tree type = TREE_TYPE (t);
9516 if (POINTER_TYPE_P (type))
9517 type = sizetype;
9518 a = fold_build2 (MULT_EXPR, type,
9519 fold_convert (type, itercnt),
9520 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9521 dest = unshare_expr (t);
9522 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9523 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9524 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9525 false, GSI_CONTINUE_LINKING);
9526 assign_stmt = gimple_build_assign (dest, t);
9527 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9529 if (fd->collapse > 1)
9530 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9532 if (!broken_loop)
9534 /* The code controlling the sequential loop replaces the
9535 GIMPLE_OMP_CONTINUE. */
9536 gsi = gsi_last_bb (cont_bb);
9537 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9538 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9539 vmain = gimple_omp_continue_control_use (cont_stmt);
9540 vback = gimple_omp_continue_control_def (cont_stmt);
9542 if (!gimple_omp_for_combined_p (fd->for_stmt))
9544 if (POINTER_TYPE_P (type))
9545 t = fold_build_pointer_plus (vmain, step);
9546 else
9547 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9548 t = force_gimple_operand_gsi (&gsi, t,
9549 DECL_P (vback)
9550 && TREE_ADDRESSABLE (vback),
9551 NULL_TREE, true, GSI_SAME_STMT);
9552 assign_stmt = gimple_build_assign (vback, t);
9553 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9555 t = build2 (fd->loop.cond_code, boolean_type_node,
9556 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9557 ? t : vback, e);
9558 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9561 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9562 gsi_remove (&gsi, true);
9564 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9565 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9568 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9569 gsi = gsi_last_bb (exit_bb);
9570 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9572 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9573 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9575 gsi_remove (&gsi, true);
9577 /* Connect all the blocks. */
9578 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9579 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9580 ep = find_edge (entry_bb, second_bb);
9581 ep->flags = EDGE_TRUE_VALUE;
9582 ep->probability = REG_BR_PROB_BASE / 4;
9583 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9584 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9586 if (!broken_loop)
9588 ep = find_edge (cont_bb, body_bb);
9589 if (ep == NULL)
9591 ep = BRANCH_EDGE (cont_bb);
9592 gcc_assert (single_succ (ep->dest) == body_bb);
9594 if (gimple_omp_for_combined_p (fd->for_stmt))
9596 remove_edge (ep);
9597 ep = NULL;
9599 else if (fd->collapse > 1)
9601 remove_edge (ep);
9602 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9604 else
9605 ep->flags = EDGE_TRUE_VALUE;
9606 find_edge (cont_bb, fin_bb)->flags
9607 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9610 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9611 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9612 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9614 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9615 recompute_dominator (CDI_DOMINATORS, body_bb));
9616 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9617 recompute_dominator (CDI_DOMINATORS, fin_bb));
9619 struct loop *loop = body_bb->loop_father;
9620 if (loop != entry_bb->loop_father)
9622 gcc_assert (loop->header == body_bb);
9623 gcc_assert (broken_loop
9624 || loop->latch == region->cont
9625 || single_pred (loop->latch) == region->cont);
9626 return;
9629 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9631 loop = alloc_loop ();
9632 loop->header = body_bb;
9633 if (collapse_bb == NULL)
9634 loop->latch = cont_bb;
9635 add_loop (loop, body_bb->loop_father);
9639 /* Return phi in E->DEST with ARG on edge E. */
9641 static gphi *
9642 find_phi_with_arg_on_edge (tree arg, edge e)
9644 basic_block bb = e->dest;
9646 for (gphi_iterator gpi = gsi_start_phis (bb);
9647 !gsi_end_p (gpi);
9648 gsi_next (&gpi))
9650 gphi *phi = gpi.phi ();
9651 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9652 return phi;
9655 return NULL;
9658 /* A subroutine of expand_omp_for. Generate code for a parallel
9659 loop with static schedule and a specified chunk size. Given
9660 parameters:
9662 for (V = N1; V cond N2; V += STEP) BODY;
9664 where COND is "<" or ">", we generate pseudocode
9666 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9667 if (cond is <)
9668 adj = STEP - 1;
9669 else
9670 adj = STEP + 1;
9671 if ((__typeof (V)) -1 > 0 && cond is >)
9672 n = -(adj + N2 - N1) / -STEP;
9673 else
9674 n = (adj + N2 - N1) / STEP;
9675 trip = 0;
9676 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9677 here so that V is defined
9678 if the loop is not entered
9680 s0 = (trip * nthreads + threadid) * CHUNK;
9681 e0 = min(s0 + CHUNK, n);
9682 if (s0 < n) goto L1; else goto L4;
9684 V = s0 * STEP + N1;
9685 e = e0 * STEP + N1;
9687 BODY;
9688 V += STEP;
9689 if (V cond e) goto L2; else goto L3;
9691 trip += 1;
9692 goto L0;
9696 static void
9697 expand_omp_for_static_chunk (struct omp_region *region,
9698 struct omp_for_data *fd, gimple *inner_stmt)
9700 tree n, s0, e0, e, t;
9701 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9702 tree type, itype, vmain, vback, vextra;
9703 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9704 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9705 gimple_stmt_iterator gsi;
9706 edge se;
9707 bool broken_loop = region->cont == NULL;
9708 tree *counts = NULL;
9709 tree n1, n2, step;
9711 itype = type = TREE_TYPE (fd->loop.v);
9712 if (POINTER_TYPE_P (type))
9713 itype = signed_type_for (type);
9715 entry_bb = region->entry;
9716 se = split_block (entry_bb, last_stmt (entry_bb));
9717 entry_bb = se->src;
9718 iter_part_bb = se->dest;
9719 cont_bb = region->cont;
9720 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9721 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9722 gcc_assert (broken_loop
9723 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9724 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9725 body_bb = single_succ (seq_start_bb);
9726 if (!broken_loop)
9728 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9729 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9730 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9731 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9733 exit_bb = region->exit;
9735 /* Trip and adjustment setup goes in ENTRY_BB. */
9736 gsi = gsi_last_bb (entry_bb);
9737 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9739 if (fd->collapse > 1)
9741 int first_zero_iter = -1, dummy = -1;
9742 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9744 counts = XALLOCAVEC (tree, fd->collapse);
9745 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9746 fin_bb, first_zero_iter,
9747 dummy_bb, dummy, l2_dom_bb);
9748 t = NULL_TREE;
9750 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9751 t = integer_one_node;
9752 else
9753 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9754 fold_convert (type, fd->loop.n1),
9755 fold_convert (type, fd->loop.n2));
9756 if (fd->collapse == 1
9757 && TYPE_UNSIGNED (type)
9758 && (t == NULL_TREE || !integer_onep (t)))
9760 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9761 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9762 true, GSI_SAME_STMT);
9763 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9764 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9765 true, GSI_SAME_STMT);
9766 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9767 NULL_TREE, NULL_TREE);
9768 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9769 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9770 expand_omp_regimplify_p, NULL, NULL)
9771 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9772 expand_omp_regimplify_p, NULL, NULL))
9774 gsi = gsi_for_stmt (cond_stmt);
9775 gimple_regimplify_operands (cond_stmt, &gsi);
9777 se = split_block (entry_bb, cond_stmt);
9778 se->flags = EDGE_TRUE_VALUE;
9779 entry_bb = se->dest;
9780 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9781 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9782 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9783 if (gimple_in_ssa_p (cfun))
9785 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9786 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9787 !gsi_end_p (gpi); gsi_next (&gpi))
9789 gphi *phi = gpi.phi ();
9790 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9791 se, UNKNOWN_LOCATION);
9794 gsi = gsi_last_bb (entry_bb);
9797 switch (gimple_omp_for_kind (fd->for_stmt))
9799 case GF_OMP_FOR_KIND_FOR:
9800 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9801 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9802 break;
9803 case GF_OMP_FOR_KIND_DISTRIBUTE:
9804 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9805 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9806 break;
9807 default:
9808 gcc_unreachable ();
9810 nthreads = build_call_expr (nthreads, 0);
9811 nthreads = fold_convert (itype, nthreads);
9812 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9813 true, GSI_SAME_STMT);
9814 threadid = build_call_expr (threadid, 0);
9815 threadid = fold_convert (itype, threadid);
9816 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9817 true, GSI_SAME_STMT);
9819 n1 = fd->loop.n1;
9820 n2 = fd->loop.n2;
9821 step = fd->loop.step;
9822 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9824 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9825 OMP_CLAUSE__LOOPTEMP_);
9826 gcc_assert (innerc);
9827 n1 = OMP_CLAUSE_DECL (innerc);
9828 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9829 OMP_CLAUSE__LOOPTEMP_);
9830 gcc_assert (innerc);
9831 n2 = OMP_CLAUSE_DECL (innerc);
9833 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9834 true, NULL_TREE, true, GSI_SAME_STMT);
9835 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9836 true, NULL_TREE, true, GSI_SAME_STMT);
9837 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9838 true, NULL_TREE, true, GSI_SAME_STMT);
9839 tree chunk_size = fold_convert (itype, fd->chunk_size);
9840 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9841 chunk_size
9842 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9843 GSI_SAME_STMT);
9845 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9846 t = fold_build2 (PLUS_EXPR, itype, step, t);
9847 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9848 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9849 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9850 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9851 fold_build1 (NEGATE_EXPR, itype, t),
9852 fold_build1 (NEGATE_EXPR, itype, step));
9853 else
9854 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9855 t = fold_convert (itype, t);
9856 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9857 true, GSI_SAME_STMT);
9859 trip_var = create_tmp_reg (itype, ".trip");
9860 if (gimple_in_ssa_p (cfun))
9862 trip_init = make_ssa_name (trip_var);
9863 trip_main = make_ssa_name (trip_var);
9864 trip_back = make_ssa_name (trip_var);
9866 else
9868 trip_init = trip_var;
9869 trip_main = trip_var;
9870 trip_back = trip_var;
9873 gassign *assign_stmt
9874 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9875 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9877 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9878 t = fold_build2 (MULT_EXPR, itype, t, step);
9879 if (POINTER_TYPE_P (type))
9880 t = fold_build_pointer_plus (n1, t);
9881 else
9882 t = fold_build2 (PLUS_EXPR, type, t, n1);
9883 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9884 true, GSI_SAME_STMT);
9886 /* Remove the GIMPLE_OMP_FOR. */
9887 gsi_remove (&gsi, true);
9889 gimple_stmt_iterator gsif = gsi;
9891 /* Iteration space partitioning goes in ITER_PART_BB. */
9892 gsi = gsi_last_bb (iter_part_bb);
9894 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9895 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9896 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9897 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9898 false, GSI_CONTINUE_LINKING);
9900 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9901 t = fold_build2 (MIN_EXPR, itype, t, n);
9902 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9903 false, GSI_CONTINUE_LINKING);
9905 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9906 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9908 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9909 gsi = gsi_start_bb (seq_start_bb);
9911 tree startvar = fd->loop.v;
9912 tree endvar = NULL_TREE;
9914 if (gimple_omp_for_combined_p (fd->for_stmt))
9916 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9917 ? gimple_omp_parallel_clauses (inner_stmt)
9918 : gimple_omp_for_clauses (inner_stmt);
9919 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9920 gcc_assert (innerc);
9921 startvar = OMP_CLAUSE_DECL (innerc);
9922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9923 OMP_CLAUSE__LOOPTEMP_);
9924 gcc_assert (innerc);
9925 endvar = OMP_CLAUSE_DECL (innerc);
9926 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9927 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9929 int i;
9930 for (i = 1; i < fd->collapse; i++)
9932 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9933 OMP_CLAUSE__LOOPTEMP_);
9934 gcc_assert (innerc);
9936 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9937 OMP_CLAUSE__LOOPTEMP_);
9938 if (innerc)
9940 /* If needed (distribute parallel for with lastprivate),
9941 propagate down the total number of iterations. */
9942 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9943 fd->loop.n2);
9944 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9945 GSI_CONTINUE_LINKING);
9946 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9947 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9952 t = fold_convert (itype, s0);
9953 t = fold_build2 (MULT_EXPR, itype, t, step);
9954 if (POINTER_TYPE_P (type))
9955 t = fold_build_pointer_plus (n1, t);
9956 else
9957 t = fold_build2 (PLUS_EXPR, type, t, n1);
9958 t = fold_convert (TREE_TYPE (startvar), t);
9959 t = force_gimple_operand_gsi (&gsi, t,
9960 DECL_P (startvar)
9961 && TREE_ADDRESSABLE (startvar),
9962 NULL_TREE, false, GSI_CONTINUE_LINKING);
9963 assign_stmt = gimple_build_assign (startvar, t);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9966 t = fold_convert (itype, e0);
9967 t = fold_build2 (MULT_EXPR, itype, t, step);
9968 if (POINTER_TYPE_P (type))
9969 t = fold_build_pointer_plus (n1, t);
9970 else
9971 t = fold_build2 (PLUS_EXPR, type, t, n1);
9972 t = fold_convert (TREE_TYPE (startvar), t);
9973 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9974 false, GSI_CONTINUE_LINKING);
9975 if (endvar)
9977 assign_stmt = gimple_build_assign (endvar, e);
9978 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9979 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9980 assign_stmt = gimple_build_assign (fd->loop.v, e);
9981 else
9982 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9983 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9985 /* Handle linear clause adjustments. */
9986 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9987 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9988 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9989 c; c = OMP_CLAUSE_CHAIN (c))
9990 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9991 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9993 tree d = OMP_CLAUSE_DECL (c);
9994 bool is_ref = is_reference (d);
9995 tree t = d, a, dest;
9996 if (is_ref)
9997 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9998 tree type = TREE_TYPE (t);
9999 if (POINTER_TYPE_P (type))
10000 type = sizetype;
10001 dest = unshare_expr (t);
10002 tree v = create_tmp_var (TREE_TYPE (t), NULL);
10003 expand_omp_build_assign (&gsif, v, t);
10004 if (itercnt == NULL_TREE)
10006 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10008 itercntbias
10009 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
10010 fold_convert (itype, fd->loop.n1));
10011 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
10012 itercntbias, step);
10013 itercntbias
10014 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10015 NULL_TREE, true,
10016 GSI_SAME_STMT);
10017 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10018 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10019 NULL_TREE, false,
10020 GSI_CONTINUE_LINKING);
10022 else
10023 itercnt = s0;
10025 a = fold_build2 (MULT_EXPR, type,
10026 fold_convert (type, itercnt),
10027 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10028 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10029 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10030 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10031 false, GSI_CONTINUE_LINKING);
10032 assign_stmt = gimple_build_assign (dest, t);
10033 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10035 if (fd->collapse > 1)
10036 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10038 if (!broken_loop)
10040 /* The code controlling the sequential loop goes in CONT_BB,
10041 replacing the GIMPLE_OMP_CONTINUE. */
10042 gsi = gsi_last_bb (cont_bb);
10043 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10044 vmain = gimple_omp_continue_control_use (cont_stmt);
10045 vback = gimple_omp_continue_control_def (cont_stmt);
10047 if (!gimple_omp_for_combined_p (fd->for_stmt))
10049 if (POINTER_TYPE_P (type))
10050 t = fold_build_pointer_plus (vmain, step);
10051 else
10052 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10053 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10054 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10055 true, GSI_SAME_STMT);
10056 assign_stmt = gimple_build_assign (vback, t);
10057 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10059 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10060 t = build2 (EQ_EXPR, boolean_type_node,
10061 build_int_cst (itype, 0),
10062 build_int_cst (itype, 1));
10063 else
10064 t = build2 (fd->loop.cond_code, boolean_type_node,
10065 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10066 ? t : vback, e);
10067 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10070 /* Remove GIMPLE_OMP_CONTINUE. */
10071 gsi_remove (&gsi, true);
10073 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10074 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10076 /* Trip update code goes into TRIP_UPDATE_BB. */
10077 gsi = gsi_start_bb (trip_update_bb);
10079 t = build_int_cst (itype, 1);
10080 t = build2 (PLUS_EXPR, itype, trip_main, t);
10081 assign_stmt = gimple_build_assign (trip_back, t);
10082 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10085 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10086 gsi = gsi_last_bb (exit_bb);
10087 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10089 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10090 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10092 gsi_remove (&gsi, true);
10094 /* Connect the new blocks. */
10095 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10096 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10098 if (!broken_loop)
10100 se = find_edge (cont_bb, body_bb);
10101 if (se == NULL)
10103 se = BRANCH_EDGE (cont_bb);
10104 gcc_assert (single_succ (se->dest) == body_bb);
10106 if (gimple_omp_for_combined_p (fd->for_stmt))
10108 remove_edge (se);
10109 se = NULL;
10111 else if (fd->collapse > 1)
10113 remove_edge (se);
10114 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10116 else
10117 se->flags = EDGE_TRUE_VALUE;
10118 find_edge (cont_bb, trip_update_bb)->flags
10119 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10121 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10124 if (gimple_in_ssa_p (cfun))
10126 gphi_iterator psi;
10127 gphi *phi;
10128 edge re, ene;
10129 edge_var_map *vm;
10130 size_t i;
10132 gcc_assert (fd->collapse == 1 && !broken_loop);
10134 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10135 remove arguments of the phi nodes in fin_bb. We need to create
10136 appropriate phi nodes in iter_part_bb instead. */
10137 se = find_edge (iter_part_bb, fin_bb);
10138 re = single_succ_edge (trip_update_bb);
10139 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10140 ene = single_succ_edge (entry_bb);
10142 psi = gsi_start_phis (fin_bb);
10143 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10144 gsi_next (&psi), ++i)
10146 gphi *nphi;
10147 source_location locus;
10149 phi = psi.phi ();
10150 t = gimple_phi_result (phi);
10151 gcc_assert (t == redirect_edge_var_map_result (vm));
10153 if (!single_pred_p (fin_bb))
10154 t = copy_ssa_name (t, phi);
10156 nphi = create_phi_node (t, iter_part_bb);
10158 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10159 locus = gimple_phi_arg_location_from_edge (phi, se);
10161 /* A special case -- fd->loop.v is not yet computed in
10162 iter_part_bb, we need to use vextra instead. */
10163 if (t == fd->loop.v)
10164 t = vextra;
10165 add_phi_arg (nphi, t, ene, locus);
10166 locus = redirect_edge_var_map_location (vm);
10167 tree back_arg = redirect_edge_var_map_def (vm);
10168 add_phi_arg (nphi, back_arg, re, locus);
10169 edge ce = find_edge (cont_bb, body_bb);
10170 if (ce == NULL)
10172 ce = BRANCH_EDGE (cont_bb);
10173 gcc_assert (single_succ (ce->dest) == body_bb);
10174 ce = single_succ_edge (ce->dest);
10176 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10177 gcc_assert (inner_loop_phi != NULL);
10178 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10179 find_edge (seq_start_bb, body_bb), locus);
10181 if (!single_pred_p (fin_bb))
10182 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10184 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10185 redirect_edge_var_map_clear (re);
10186 if (single_pred_p (fin_bb))
10187 while (1)
10189 psi = gsi_start_phis (fin_bb);
10190 if (gsi_end_p (psi))
10191 break;
10192 remove_phi_node (&psi, false);
10195 /* Make phi node for trip. */
10196 phi = create_phi_node (trip_main, iter_part_bb);
10197 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10198 UNKNOWN_LOCATION);
10199 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10200 UNKNOWN_LOCATION);
10203 if (!broken_loop)
10204 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10205 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10206 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10207 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10208 recompute_dominator (CDI_DOMINATORS, fin_bb));
10209 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10210 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10211 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10212 recompute_dominator (CDI_DOMINATORS, body_bb));
10214 if (!broken_loop)
10216 struct loop *loop = body_bb->loop_father;
10217 struct loop *trip_loop = alloc_loop ();
10218 trip_loop->header = iter_part_bb;
10219 trip_loop->latch = trip_update_bb;
10220 add_loop (trip_loop, iter_part_bb->loop_father);
10222 if (loop != entry_bb->loop_father)
10224 gcc_assert (loop->header == body_bb);
10225 gcc_assert (loop->latch == region->cont
10226 || single_pred (loop->latch) == region->cont);
10227 trip_loop->inner = loop;
10228 return;
10231 if (!gimple_omp_for_combined_p (fd->for_stmt))
10233 loop = alloc_loop ();
10234 loop->header = body_bb;
10235 if (collapse_bb == NULL)
10236 loop->latch = cont_bb;
10237 add_loop (loop, trip_loop);
10242 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10243 Given parameters:
10244 for (V = N1; V cond N2; V += STEP) BODY;
10246 where COND is "<" or ">" or "!=", we generate pseudocode
10248 for (ind_var = low; ind_var < high; ind_var++)
10250 V = n1 + (ind_var * STEP)
10252 <BODY>
10255 In the above pseudocode, low and high are function parameters of the
10256 child function. In the function below, we are inserting a temp.
10257 variable that will be making a call to two OMP functions that will not be
10258 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10259 with _Cilk_for). These functions are replaced with low and high
10260 by the function that handles taskreg. */
10263 static void
10264 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10266 bool broken_loop = region->cont == NULL;
10267 basic_block entry_bb = region->entry;
10268 basic_block cont_bb = region->cont;
10270 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10271 gcc_assert (broken_loop
10272 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10273 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10274 basic_block l1_bb, l2_bb;
10276 if (!broken_loop)
10278 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10279 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10280 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10281 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10283 else
10285 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10286 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10287 l2_bb = single_succ (l1_bb);
10289 basic_block exit_bb = region->exit;
10290 basic_block l2_dom_bb = NULL;
10292 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10294 /* Below statements until the "tree high_val = ..." are pseudo statements
10295 used to pass information to be used by expand_omp_taskreg.
10296 low_val and high_val will be replaced by the __low and __high
10297 parameter from the child function.
10299 The call_exprs part is a place-holder, it is mainly used
10300 to distinctly identify to the top-level part that this is
10301 where we should put low and high (reasoning given in header
10302 comment). */
10304 tree child_fndecl
10305 = gimple_omp_parallel_child_fn (
10306 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10307 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10308 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10310 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10311 high_val = t;
10312 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10313 low_val = t;
10315 gcc_assert (low_val && high_val);
10317 tree type = TREE_TYPE (low_val);
10318 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10319 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10321 /* Not needed in SSA form right now. */
10322 gcc_assert (!gimple_in_ssa_p (cfun));
10323 if (l2_dom_bb == NULL)
10324 l2_dom_bb = l1_bb;
10326 tree n1 = low_val;
10327 tree n2 = high_val;
10329 gimple *stmt = gimple_build_assign (ind_var, n1);
10331 /* Replace the GIMPLE_OMP_FOR statement. */
10332 gsi_replace (&gsi, stmt, true);
10334 if (!broken_loop)
10336 /* Code to control the increment goes in the CONT_BB. */
10337 gsi = gsi_last_bb (cont_bb);
10338 stmt = gsi_stmt (gsi);
10339 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10340 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10341 build_one_cst (type));
10343 /* Replace GIMPLE_OMP_CONTINUE. */
10344 gsi_replace (&gsi, stmt, true);
10347 /* Emit the condition in L1_BB. */
10348 gsi = gsi_after_labels (l1_bb);
10349 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10350 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10351 fd->loop.step);
10352 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10353 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10354 fd->loop.n1, fold_convert (sizetype, t));
10355 else
10356 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10357 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10358 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10359 expand_omp_build_assign (&gsi, fd->loop.v, t);
10361 /* The condition is always '<' since the runtime will fill in the low
10362 and high values. */
10363 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10364 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10366 /* Remove GIMPLE_OMP_RETURN. */
10367 gsi = gsi_last_bb (exit_bb);
10368 gsi_remove (&gsi, true);
10370 /* Connect the new blocks. */
10371 remove_edge (FALLTHRU_EDGE (entry_bb));
10373 edge e, ne;
10374 if (!broken_loop)
10376 remove_edge (BRANCH_EDGE (entry_bb));
10377 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10379 e = BRANCH_EDGE (l1_bb);
10380 ne = FALLTHRU_EDGE (l1_bb);
10381 e->flags = EDGE_TRUE_VALUE;
10383 else
10385 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10387 ne = single_succ_edge (l1_bb);
10388 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10391 ne->flags = EDGE_FALSE_VALUE;
10392 e->probability = REG_BR_PROB_BASE * 7 / 8;
10393 ne->probability = REG_BR_PROB_BASE / 8;
10395 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10396 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10397 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10399 if (!broken_loop)
10401 struct loop *loop = alloc_loop ();
10402 loop->header = l1_bb;
10403 loop->latch = cont_bb;
10404 add_loop (loop, l1_bb->loop_father);
10405 loop->safelen = INT_MAX;
10408 /* Pick the correct library function based on the precision of the
10409 induction variable type. */
10410 tree lib_fun = NULL_TREE;
10411 if (TYPE_PRECISION (type) == 32)
10412 lib_fun = cilk_for_32_fndecl;
10413 else if (TYPE_PRECISION (type) == 64)
10414 lib_fun = cilk_for_64_fndecl;
10415 else
10416 gcc_unreachable ();
10418 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10420 /* WS_ARGS contains the library function flavor to call:
10421 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10422 user-defined grain value. If the user does not define one, then zero
10423 is passed in by the parser. */
10424 vec_alloc (region->ws_args, 2);
10425 region->ws_args->quick_push (lib_fun);
10426 region->ws_args->quick_push (fd->chunk_size);
10429 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10430 loop. Given parameters:
10432 for (V = N1; V cond N2; V += STEP) BODY;
10434 where COND is "<" or ">", we generate pseudocode
10436 V = N1;
10437 goto L1;
10439 BODY;
10440 V += STEP;
10442 if (V cond N2) goto L0; else goto L2;
10445 For collapsed loops, given parameters:
10446 collapse(3)
10447 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10448 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10449 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10450 BODY;
10452 we generate pseudocode
10454 if (cond3 is <)
10455 adj = STEP3 - 1;
10456 else
10457 adj = STEP3 + 1;
10458 count3 = (adj + N32 - N31) / STEP3;
10459 if (cond2 is <)
10460 adj = STEP2 - 1;
10461 else
10462 adj = STEP2 + 1;
10463 count2 = (adj + N22 - N21) / STEP2;
10464 if (cond1 is <)
10465 adj = STEP1 - 1;
10466 else
10467 adj = STEP1 + 1;
10468 count1 = (adj + N12 - N11) / STEP1;
10469 count = count1 * count2 * count3;
10470 V = 0;
10471 V1 = N11;
10472 V2 = N21;
10473 V3 = N31;
10474 goto L1;
10476 BODY;
10477 V += 1;
10478 V3 += STEP3;
10479 V2 += (V3 cond3 N32) ? 0 : STEP2;
10480 V3 = (V3 cond3 N32) ? V3 : N31;
10481 V1 += (V2 cond2 N22) ? 0 : STEP1;
10482 V2 = (V2 cond2 N22) ? V2 : N21;
10484 if (V < count) goto L0; else goto L2;
10489 static void
10490 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10492 tree type, t;
10493 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10494 gimple_stmt_iterator gsi;
10495 gimple *stmt;
10496 gcond *cond_stmt;
10497 bool broken_loop = region->cont == NULL;
10498 edge e, ne;
10499 tree *counts = NULL;
10500 int i;
10501 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10502 OMP_CLAUSE_SAFELEN);
10503 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10504 OMP_CLAUSE__SIMDUID_);
10505 tree n1, n2;
10507 type = TREE_TYPE (fd->loop.v);
10508 entry_bb = region->entry;
10509 cont_bb = region->cont;
10510 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10511 gcc_assert (broken_loop
10512 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10513 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10514 if (!broken_loop)
10516 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10517 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10518 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10519 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10521 else
10523 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10524 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10525 l2_bb = single_succ (l1_bb);
10527 exit_bb = region->exit;
10528 l2_dom_bb = NULL;
10530 gsi = gsi_last_bb (entry_bb);
10532 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10533 /* Not needed in SSA form right now. */
10534 gcc_assert (!gimple_in_ssa_p (cfun));
10535 if (fd->collapse > 1)
10537 int first_zero_iter = -1, dummy = -1;
10538 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10540 counts = XALLOCAVEC (tree, fd->collapse);
10541 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10542 zero_iter_bb, first_zero_iter,
10543 dummy_bb, dummy, l2_dom_bb);
10545 if (l2_dom_bb == NULL)
10546 l2_dom_bb = l1_bb;
10548 n1 = fd->loop.n1;
10549 n2 = fd->loop.n2;
10550 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10552 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10553 OMP_CLAUSE__LOOPTEMP_);
10554 gcc_assert (innerc);
10555 n1 = OMP_CLAUSE_DECL (innerc);
10556 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10557 OMP_CLAUSE__LOOPTEMP_);
10558 gcc_assert (innerc);
10559 n2 = OMP_CLAUSE_DECL (innerc);
10560 expand_omp_build_assign (&gsi, fd->loop.v,
10561 fold_convert (type, n1));
10562 if (fd->collapse > 1)
10564 gsi_prev (&gsi);
10565 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10566 gsi_next (&gsi);
10569 else
10571 expand_omp_build_assign (&gsi, fd->loop.v,
10572 fold_convert (type, fd->loop.n1));
10573 if (fd->collapse > 1)
10574 for (i = 0; i < fd->collapse; i++)
10576 tree itype = TREE_TYPE (fd->loops[i].v);
10577 if (POINTER_TYPE_P (itype))
10578 itype = signed_type_for (itype);
10579 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10580 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10584 /* Remove the GIMPLE_OMP_FOR statement. */
10585 gsi_remove (&gsi, true);
10587 if (!broken_loop)
10589 /* Code to control the increment goes in the CONT_BB. */
10590 gsi = gsi_last_bb (cont_bb);
10591 stmt = gsi_stmt (gsi);
10592 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10594 if (POINTER_TYPE_P (type))
10595 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10596 else
10597 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10598 expand_omp_build_assign (&gsi, fd->loop.v, t);
10600 if (fd->collapse > 1)
10602 i = fd->collapse - 1;
10603 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10605 t = fold_convert (sizetype, fd->loops[i].step);
10606 t = fold_build_pointer_plus (fd->loops[i].v, t);
10608 else
10610 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10611 fd->loops[i].step);
10612 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10613 fd->loops[i].v, t);
10615 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10617 for (i = fd->collapse - 1; i > 0; i--)
10619 tree itype = TREE_TYPE (fd->loops[i].v);
10620 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10621 if (POINTER_TYPE_P (itype2))
10622 itype2 = signed_type_for (itype2);
10623 t = build3 (COND_EXPR, itype2,
10624 build2 (fd->loops[i].cond_code, boolean_type_node,
10625 fd->loops[i].v,
10626 fold_convert (itype, fd->loops[i].n2)),
10627 build_int_cst (itype2, 0),
10628 fold_convert (itype2, fd->loops[i - 1].step));
10629 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10630 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10631 else
10632 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10633 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10635 t = build3 (COND_EXPR, itype,
10636 build2 (fd->loops[i].cond_code, boolean_type_node,
10637 fd->loops[i].v,
10638 fold_convert (itype, fd->loops[i].n2)),
10639 fd->loops[i].v,
10640 fold_convert (itype, fd->loops[i].n1));
10641 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10645 /* Remove GIMPLE_OMP_CONTINUE. */
10646 gsi_remove (&gsi, true);
10649 /* Emit the condition in L1_BB. */
10650 gsi = gsi_start_bb (l1_bb);
10652 t = fold_convert (type, n2);
10653 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10654 false, GSI_CONTINUE_LINKING);
10655 tree v = fd->loop.v;
10656 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10657 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10658 false, GSI_CONTINUE_LINKING);
10659 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10660 cond_stmt = gimple_build_cond_empty (t);
10661 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10662 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10663 NULL, NULL)
10664 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10665 NULL, NULL))
10667 gsi = gsi_for_stmt (cond_stmt);
10668 gimple_regimplify_operands (cond_stmt, &gsi);
10671 /* Remove GIMPLE_OMP_RETURN. */
10672 gsi = gsi_last_bb (exit_bb);
10673 gsi_remove (&gsi, true);
10675 /* Connect the new blocks. */
10676 remove_edge (FALLTHRU_EDGE (entry_bb));
10678 if (!broken_loop)
10680 remove_edge (BRANCH_EDGE (entry_bb));
10681 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10683 e = BRANCH_EDGE (l1_bb);
10684 ne = FALLTHRU_EDGE (l1_bb);
10685 e->flags = EDGE_TRUE_VALUE;
10687 else
10689 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10691 ne = single_succ_edge (l1_bb);
10692 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10695 ne->flags = EDGE_FALSE_VALUE;
10696 e->probability = REG_BR_PROB_BASE * 7 / 8;
10697 ne->probability = REG_BR_PROB_BASE / 8;
10699 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10700 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10701 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10703 if (!broken_loop)
10705 struct loop *loop = alloc_loop ();
10706 loop->header = l1_bb;
10707 loop->latch = cont_bb;
10708 add_loop (loop, l1_bb->loop_father);
10709 if (safelen == NULL_TREE)
10710 loop->safelen = INT_MAX;
10711 else
10713 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10714 if (TREE_CODE (safelen) != INTEGER_CST)
10715 loop->safelen = 0;
10716 else if (!tree_fits_uhwi_p (safelen)
10717 || tree_to_uhwi (safelen) > INT_MAX)
10718 loop->safelen = INT_MAX;
10719 else
10720 loop->safelen = tree_to_uhwi (safelen);
10721 if (loop->safelen == 1)
10722 loop->safelen = 0;
10724 if (simduid)
10726 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10727 cfun->has_simduid_loops = true;
10729 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10730 the loop. */
10731 if ((flag_tree_loop_vectorize
10732 || (!global_options_set.x_flag_tree_loop_vectorize
10733 && !global_options_set.x_flag_tree_vectorize))
10734 && flag_tree_loop_optimize
10735 && loop->safelen > 1)
10737 loop->force_vectorize = true;
10738 cfun->has_force_vectorize_loops = true;
10741 else if (simduid)
10742 cfun->has_simduid_loops = true;
10745 /* Taskloop construct is represented after gimplification with
10746 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10747 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10748 which should just compute all the needed loop temporaries
10749 for GIMPLE_OMP_TASK. */
10751 static void
10752 expand_omp_taskloop_for_outer (struct omp_region *region,
10753 struct omp_for_data *fd,
10754 gimple *inner_stmt)
10756 tree type, bias = NULL_TREE;
10757 basic_block entry_bb, cont_bb, exit_bb;
10758 gimple_stmt_iterator gsi;
10759 gassign *assign_stmt;
10760 tree *counts = NULL;
10761 int i;
10763 gcc_assert (inner_stmt);
10764 gcc_assert (region->cont);
10765 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10766 && gimple_omp_task_taskloop_p (inner_stmt));
10767 type = TREE_TYPE (fd->loop.v);
10769 /* See if we need to bias by LLONG_MIN. */
10770 if (fd->iter_type == long_long_unsigned_type_node
10771 && TREE_CODE (type) == INTEGER_TYPE
10772 && !TYPE_UNSIGNED (type))
10774 tree n1, n2;
10776 if (fd->loop.cond_code == LT_EXPR)
10778 n1 = fd->loop.n1;
10779 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10781 else
10783 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10784 n2 = fd->loop.n1;
10786 if (TREE_CODE (n1) != INTEGER_CST
10787 || TREE_CODE (n2) != INTEGER_CST
10788 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10789 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10792 entry_bb = region->entry;
10793 cont_bb = region->cont;
10794 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10795 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10796 exit_bb = region->exit;
10798 gsi = gsi_last_bb (entry_bb);
10799 gimple *for_stmt = gsi_stmt (gsi);
10800 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10801 if (fd->collapse > 1)
10803 int first_zero_iter = -1, dummy = -1;
10804 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10806 counts = XALLOCAVEC (tree, fd->collapse);
10807 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10808 zero_iter_bb, first_zero_iter,
10809 dummy_bb, dummy, l2_dom_bb);
10811 if (zero_iter_bb)
10813 /* Some counts[i] vars might be uninitialized if
10814 some loop has zero iterations. But the body shouldn't
10815 be executed in that case, so just avoid uninit warnings. */
10816 for (i = first_zero_iter; i < fd->collapse; i++)
10817 if (SSA_VAR_P (counts[i]))
10818 TREE_NO_WARNING (counts[i]) = 1;
10819 gsi_prev (&gsi);
10820 edge e = split_block (entry_bb, gsi_stmt (gsi));
10821 entry_bb = e->dest;
10822 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10823 gsi = gsi_last_bb (entry_bb);
10824 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10825 get_immediate_dominator (CDI_DOMINATORS,
10826 zero_iter_bb));
10830 tree t0, t1;
10831 t1 = fd->loop.n2;
10832 t0 = fd->loop.n1;
10833 if (POINTER_TYPE_P (TREE_TYPE (t0))
10834 && TYPE_PRECISION (TREE_TYPE (t0))
10835 != TYPE_PRECISION (fd->iter_type))
10837 /* Avoid casting pointers to integer of a different size. */
10838 tree itype = signed_type_for (type);
10839 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10840 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10842 else
10844 t1 = fold_convert (fd->iter_type, t1);
10845 t0 = fold_convert (fd->iter_type, t0);
10847 if (bias)
10849 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10850 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10853 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10854 OMP_CLAUSE__LOOPTEMP_);
10855 gcc_assert (innerc);
10856 tree startvar = OMP_CLAUSE_DECL (innerc);
10857 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10858 gcc_assert (innerc);
10859 tree endvar = OMP_CLAUSE_DECL (innerc);
10860 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10862 gcc_assert (innerc);
10863 for (i = 1; i < fd->collapse; i++)
10865 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10866 OMP_CLAUSE__LOOPTEMP_);
10867 gcc_assert (innerc);
10869 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10870 OMP_CLAUSE__LOOPTEMP_);
10871 if (innerc)
10873 /* If needed (inner taskloop has lastprivate clause), propagate
10874 down the total number of iterations. */
10875 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10876 NULL_TREE, false,
10877 GSI_CONTINUE_LINKING);
10878 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10879 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10883 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10884 GSI_CONTINUE_LINKING);
10885 assign_stmt = gimple_build_assign (startvar, t0);
10886 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10888 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10889 GSI_CONTINUE_LINKING);
10890 assign_stmt = gimple_build_assign (endvar, t1);
10891 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10892 if (fd->collapse > 1)
10893 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10895 /* Remove the GIMPLE_OMP_FOR statement. */
10896 gsi = gsi_for_stmt (for_stmt);
10897 gsi_remove (&gsi, true);
10899 gsi = gsi_last_bb (cont_bb);
10900 gsi_remove (&gsi, true);
10902 gsi = gsi_last_bb (exit_bb);
10903 gsi_remove (&gsi, true);
10905 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10906 remove_edge (BRANCH_EDGE (entry_bb));
10907 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10908 remove_edge (BRANCH_EDGE (cont_bb));
10909 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10910 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10911 recompute_dominator (CDI_DOMINATORS, region->entry));
10914 /* Taskloop construct is represented after gimplification with
10915 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10916 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10917 GOMP_taskloop{,_ull} function arranges for each task to be given just
10918 a single range of iterations. */
10920 static void
10921 expand_omp_taskloop_for_inner (struct omp_region *region,
10922 struct omp_for_data *fd,
10923 gimple *inner_stmt)
10925 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10926 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10927 basic_block fin_bb;
10928 gimple_stmt_iterator gsi;
10929 edge ep;
10930 bool broken_loop = region->cont == NULL;
10931 tree *counts = NULL;
10932 tree n1, n2, step;
10934 itype = type = TREE_TYPE (fd->loop.v);
10935 if (POINTER_TYPE_P (type))
10936 itype = signed_type_for (type);
10938 /* See if we need to bias by LLONG_MIN. */
10939 if (fd->iter_type == long_long_unsigned_type_node
10940 && TREE_CODE (type) == INTEGER_TYPE
10941 && !TYPE_UNSIGNED (type))
10943 tree n1, n2;
10945 if (fd->loop.cond_code == LT_EXPR)
10947 n1 = fd->loop.n1;
10948 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10950 else
10952 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10953 n2 = fd->loop.n1;
10955 if (TREE_CODE (n1) != INTEGER_CST
10956 || TREE_CODE (n2) != INTEGER_CST
10957 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10958 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10961 entry_bb = region->entry;
10962 cont_bb = region->cont;
10963 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10964 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10965 gcc_assert (broken_loop
10966 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10967 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10968 if (!broken_loop)
10970 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10971 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10973 exit_bb = region->exit;
10975 /* Iteration space partitioning goes in ENTRY_BB. */
10976 gsi = gsi_last_bb (entry_bb);
10977 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10979 if (fd->collapse > 1)
10981 int first_zero_iter = -1, dummy = -1;
10982 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10984 counts = XALLOCAVEC (tree, fd->collapse);
10985 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10986 fin_bb, first_zero_iter,
10987 dummy_bb, dummy, l2_dom_bb);
10988 t = NULL_TREE;
10990 else
10991 t = integer_one_node;
10993 step = fd->loop.step;
10994 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10995 OMP_CLAUSE__LOOPTEMP_);
10996 gcc_assert (innerc);
10997 n1 = OMP_CLAUSE_DECL (innerc);
10998 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10999 gcc_assert (innerc);
11000 n2 = OMP_CLAUSE_DECL (innerc);
11001 if (bias)
11003 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
11004 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
11006 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
11007 true, NULL_TREE, true, GSI_SAME_STMT);
11008 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
11009 true, NULL_TREE, true, GSI_SAME_STMT);
11010 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
11011 true, NULL_TREE, true, GSI_SAME_STMT);
11013 tree startvar = fd->loop.v;
11014 tree endvar = NULL_TREE;
11016 if (gimple_omp_for_combined_p (fd->for_stmt))
11018 tree clauses = gimple_omp_for_clauses (inner_stmt);
11019 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11020 gcc_assert (innerc);
11021 startvar = OMP_CLAUSE_DECL (innerc);
11022 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11023 OMP_CLAUSE__LOOPTEMP_);
11024 gcc_assert (innerc);
11025 endvar = OMP_CLAUSE_DECL (innerc);
11027 t = fold_convert (TREE_TYPE (startvar), n1);
11028 t = force_gimple_operand_gsi (&gsi, t,
11029 DECL_P (startvar)
11030 && TREE_ADDRESSABLE (startvar),
11031 NULL_TREE, false, GSI_CONTINUE_LINKING);
11032 gimple *assign_stmt = gimple_build_assign (startvar, t);
11033 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11035 t = fold_convert (TREE_TYPE (startvar), n2);
11036 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11037 false, GSI_CONTINUE_LINKING);
11038 if (endvar)
11040 assign_stmt = gimple_build_assign (endvar, e);
11041 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11042 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11043 assign_stmt = gimple_build_assign (fd->loop.v, e);
11044 else
11045 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11046 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11048 if (fd->collapse > 1)
11049 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11051 if (!broken_loop)
11053 /* The code controlling the sequential loop replaces the
11054 GIMPLE_OMP_CONTINUE. */
11055 gsi = gsi_last_bb (cont_bb);
11056 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11057 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11058 vmain = gimple_omp_continue_control_use (cont_stmt);
11059 vback = gimple_omp_continue_control_def (cont_stmt);
11061 if (!gimple_omp_for_combined_p (fd->for_stmt))
11063 if (POINTER_TYPE_P (type))
11064 t = fold_build_pointer_plus (vmain, step);
11065 else
11066 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11067 t = force_gimple_operand_gsi (&gsi, t,
11068 DECL_P (vback)
11069 && TREE_ADDRESSABLE (vback),
11070 NULL_TREE, true, GSI_SAME_STMT);
11071 assign_stmt = gimple_build_assign (vback, t);
11072 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11074 t = build2 (fd->loop.cond_code, boolean_type_node,
11075 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11076 ? t : vback, e);
11077 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11080 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11081 gsi_remove (&gsi, true);
11083 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11084 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11087 /* Remove the GIMPLE_OMP_FOR statement. */
11088 gsi = gsi_for_stmt (fd->for_stmt);
11089 gsi_remove (&gsi, true);
11091 /* Remove the GIMPLE_OMP_RETURN statement. */
11092 gsi = gsi_last_bb (exit_bb);
11093 gsi_remove (&gsi, true);
11095 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11096 if (!broken_loop)
11097 remove_edge (BRANCH_EDGE (entry_bb));
11098 else
11100 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11101 region->outer->cont = NULL;
11104 /* Connect all the blocks. */
11105 if (!broken_loop)
11107 ep = find_edge (cont_bb, body_bb);
11108 if (gimple_omp_for_combined_p (fd->for_stmt))
11110 remove_edge (ep);
11111 ep = NULL;
11113 else if (fd->collapse > 1)
11115 remove_edge (ep);
11116 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11118 else
11119 ep->flags = EDGE_TRUE_VALUE;
11120 find_edge (cont_bb, fin_bb)->flags
11121 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11124 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11125 recompute_dominator (CDI_DOMINATORS, body_bb));
11126 if (!broken_loop)
11127 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11128 recompute_dominator (CDI_DOMINATORS, fin_bb));
11130 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11132 struct loop *loop = alloc_loop ();
11133 loop->header = body_bb;
11134 if (collapse_bb == NULL)
11135 loop->latch = cont_bb;
11136 add_loop (loop, body_bb->loop_father);
11140 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11141 partitioned loop. The lowering here is abstracted, in that the
11142 loop parameters are passed through internal functions, which are
11143 further lowered by oacc_device_lower, once we get to the target
11144 compiler. The loop is of the form:
11146 for (V = B; V LTGT E; V += S) {BODY}
11148 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11149 (constant 0 for no chunking) and we will have a GWV partitioning
11150 mask, specifying dimensions over which the loop is to be
11151 partitioned (see note below). We generate code that looks like:
11153 <entry_bb> [incoming FALL->body, BRANCH->exit]
11154 typedef signedintify (typeof (V)) T; // underlying signed integral type
11155 T range = E - B;
11156 T chunk_no = 0;
11157 T DIR = LTGT == '<' ? +1 : -1;
11158 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11159 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11161 <head_bb> [created by splitting end of entry_bb]
11162 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11163 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11164 if (!(offset LTGT bound)) goto bottom_bb;
11166 <body_bb> [incoming]
11167 V = B + offset;
11168 {BODY}
11170 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11171 offset += step;
11172 if (offset LTGT bound) goto body_bb; [*]
11174 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11175 chunk_no++;
11176 if (chunk < chunk_max) goto head_bb;
11178 <exit_bb> [incoming]
11179 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11181 [*] Needed if V live at end of loop
11183 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11184 transition, and will be specified by a more general mechanism shortly.
11187 static void
11188 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11190 tree v = fd->loop.v;
11191 enum tree_code cond_code = fd->loop.cond_code;
11192 enum tree_code plus_code = PLUS_EXPR;
11194 tree chunk_size = integer_minus_one_node;
11195 tree gwv = integer_zero_node;
11196 tree iter_type = TREE_TYPE (v);
11197 tree diff_type = iter_type;
11198 tree plus_type = iter_type;
11199 struct oacc_collapse *counts = NULL;
11201 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11202 == GF_OMP_FOR_KIND_OACC_LOOP);
11203 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11204 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11206 if (POINTER_TYPE_P (iter_type))
11208 plus_code = POINTER_PLUS_EXPR;
11209 plus_type = sizetype;
11211 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11212 diff_type = signed_type_for (diff_type);
11214 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11215 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11216 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11217 basic_block bottom_bb = NULL;
11219 /* entry_bb has two sucessors; the branch edge is to the exit
11220 block, fallthrough edge to body. */
11221 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11222 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11224 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11225 body_bb, or to a block whose only successor is the body_bb. Its
11226 fallthrough successor is the final block (same as the branch
11227 successor of the entry_bb). */
11228 if (cont_bb)
11230 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11231 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11233 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11234 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11236 else
11237 gcc_assert (!gimple_in_ssa_p (cfun));
11239 /* The exit block only has entry_bb and cont_bb as predecessors. */
11240 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11242 tree chunk_no;
11243 tree chunk_max = NULL_TREE;
11244 tree bound, offset;
11245 tree step = create_tmp_var (diff_type, ".step");
11246 bool up = cond_code == LT_EXPR;
11247 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11248 bool chunking = !gimple_in_ssa_p (cfun);;
11249 bool negating;
11251 /* SSA instances. */
11252 tree offset_incr = NULL_TREE;
11253 tree offset_init = NULL_TREE;
11255 gimple_stmt_iterator gsi;
11256 gassign *ass;
11257 gcall *call;
11258 gimple *stmt;
11259 tree expr;
11260 location_t loc;
11261 edge split, be, fte;
11263 /* Split the end of entry_bb to create head_bb. */
11264 split = split_block (entry_bb, last_stmt (entry_bb));
11265 basic_block head_bb = split->dest;
11266 entry_bb = split->src;
11268 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11269 gsi = gsi_last_bb (entry_bb);
11270 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11271 loc = gimple_location (for_stmt);
11273 if (gimple_in_ssa_p (cfun))
11275 offset_init = gimple_omp_for_index (for_stmt, 0);
11276 gcc_assert (integer_zerop (fd->loop.n1));
11277 /* The SSA parallelizer does gang parallelism. */
11278 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11281 if (fd->collapse > 1)
11283 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11284 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11285 TREE_TYPE (fd->loop.n2));
11287 if (SSA_VAR_P (fd->loop.n2))
11289 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11290 true, GSI_SAME_STMT);
11291 ass = gimple_build_assign (fd->loop.n2, total);
11292 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11297 tree b = fd->loop.n1;
11298 tree e = fd->loop.n2;
11299 tree s = fd->loop.step;
11301 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11302 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11304 /* Convert the step, avoiding possible unsigned->signed overflow. */
11305 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11306 if (negating)
11307 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11308 s = fold_convert (diff_type, s);
11309 if (negating)
11310 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11311 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11313 if (!chunking)
11314 chunk_size = integer_zero_node;
11315 expr = fold_convert (diff_type, chunk_size);
11316 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11317 NULL_TREE, true, GSI_SAME_STMT);
11318 /* Determine the range, avoiding possible unsigned->signed overflow. */
11319 negating = !up && TYPE_UNSIGNED (iter_type);
11320 expr = fold_build2 (MINUS_EXPR, plus_type,
11321 fold_convert (plus_type, negating ? b : e),
11322 fold_convert (plus_type, negating ? e : b));
11323 expr = fold_convert (diff_type, expr);
11324 if (negating)
11325 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11326 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11327 NULL_TREE, true, GSI_SAME_STMT);
11329 chunk_no = build_int_cst (diff_type, 0);
11330 if (chunking)
11332 gcc_assert (!gimple_in_ssa_p (cfun));
11334 expr = chunk_no;
11335 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11336 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11338 ass = gimple_build_assign (chunk_no, expr);
11339 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11341 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11342 build_int_cst (integer_type_node,
11343 IFN_GOACC_LOOP_CHUNKS),
11344 dir, range, s, chunk_size, gwv);
11345 gimple_call_set_lhs (call, chunk_max);
11346 gimple_set_location (call, loc);
11347 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11349 else
11350 chunk_size = chunk_no;
11352 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11353 build_int_cst (integer_type_node,
11354 IFN_GOACC_LOOP_STEP),
11355 dir, range, s, chunk_size, gwv);
11356 gimple_call_set_lhs (call, step);
11357 gimple_set_location (call, loc);
11358 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11360 /* Remove the GIMPLE_OMP_FOR. */
11361 gsi_remove (&gsi, true);
11363 /* Fixup edges from head_bb */
11364 be = BRANCH_EDGE (head_bb);
11365 fte = FALLTHRU_EDGE (head_bb);
11366 be->flags |= EDGE_FALSE_VALUE;
11367 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11369 basic_block body_bb = fte->dest;
11371 if (gimple_in_ssa_p (cfun))
11373 gsi = gsi_last_bb (cont_bb);
11374 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11376 offset = gimple_omp_continue_control_use (cont_stmt);
11377 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11379 else
11381 offset = create_tmp_var (diff_type, ".offset");
11382 offset_init = offset_incr = offset;
11384 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11386 /* Loop offset & bound go into head_bb. */
11387 gsi = gsi_start_bb (head_bb);
11389 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11390 build_int_cst (integer_type_node,
11391 IFN_GOACC_LOOP_OFFSET),
11392 dir, range, s,
11393 chunk_size, gwv, chunk_no);
11394 gimple_call_set_lhs (call, offset_init);
11395 gimple_set_location (call, loc);
11396 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11398 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11399 build_int_cst (integer_type_node,
11400 IFN_GOACC_LOOP_BOUND),
11401 dir, range, s,
11402 chunk_size, gwv, offset_init);
11403 gimple_call_set_lhs (call, bound);
11404 gimple_set_location (call, loc);
11405 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11407 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11408 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11409 GSI_CONTINUE_LINKING);
11411 /* V assignment goes into body_bb. */
11412 if (!gimple_in_ssa_p (cfun))
11414 gsi = gsi_start_bb (body_bb);
11416 expr = build2 (plus_code, iter_type, b,
11417 fold_convert (plus_type, offset));
11418 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11419 true, GSI_SAME_STMT);
11420 ass = gimple_build_assign (v, expr);
11421 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11422 if (fd->collapse > 1)
11423 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11426 /* Loop increment goes into cont_bb. If this is not a loop, we
11427 will have spawned threads as if it was, and each one will
11428 execute one iteration. The specification is not explicit about
11429 whether such constructs are ill-formed or not, and they can
11430 occur, especially when noreturn routines are involved. */
11431 if (cont_bb)
11433 gsi = gsi_last_bb (cont_bb);
11434 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11435 loc = gimple_location (cont_stmt);
11437 /* Increment offset. */
11438 if (gimple_in_ssa_p (cfun))
11439 expr= build2 (plus_code, iter_type, offset,
11440 fold_convert (plus_type, step));
11441 else
11442 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11443 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11444 true, GSI_SAME_STMT);
11445 ass = gimple_build_assign (offset_incr, expr);
11446 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11447 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11448 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11450 /* Remove the GIMPLE_OMP_CONTINUE. */
11451 gsi_remove (&gsi, true);
11453 /* Fixup edges from cont_bb */
11454 be = BRANCH_EDGE (cont_bb);
11455 fte = FALLTHRU_EDGE (cont_bb);
11456 be->flags |= EDGE_TRUE_VALUE;
11457 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11459 if (chunking)
11461 /* Split the beginning of exit_bb to make bottom_bb. We
11462 need to insert a nop at the start, because splitting is
11463 after a stmt, not before. */
11464 gsi = gsi_start_bb (exit_bb);
11465 stmt = gimple_build_nop ();
11466 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11467 split = split_block (exit_bb, stmt);
11468 bottom_bb = split->src;
11469 exit_bb = split->dest;
11470 gsi = gsi_last_bb (bottom_bb);
11472 /* Chunk increment and test goes into bottom_bb. */
11473 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11474 build_int_cst (diff_type, 1));
11475 ass = gimple_build_assign (chunk_no, expr);
11476 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11478 /* Chunk test at end of bottom_bb. */
11479 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11480 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11481 GSI_CONTINUE_LINKING);
11483 /* Fixup edges from bottom_bb. */
11484 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11485 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11489 gsi = gsi_last_bb (exit_bb);
11490 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11491 loc = gimple_location (gsi_stmt (gsi));
11493 if (!gimple_in_ssa_p (cfun))
11495 /* Insert the final value of V, in case it is live. This is the
11496 value for the only thread that survives past the join. */
11497 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11498 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11499 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11500 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11501 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11502 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11503 true, GSI_SAME_STMT);
11504 ass = gimple_build_assign (v, expr);
11505 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11508 /* Remove the OMP_RETURN. */
11509 gsi_remove (&gsi, true);
11511 if (cont_bb)
11513 /* We now have one or two nested loops. Update the loop
11514 structures. */
11515 struct loop *parent = entry_bb->loop_father;
11516 struct loop *body = body_bb->loop_father;
11518 if (chunking)
11520 struct loop *chunk_loop = alloc_loop ();
11521 chunk_loop->header = head_bb;
11522 chunk_loop->latch = bottom_bb;
11523 add_loop (chunk_loop, parent);
11524 parent = chunk_loop;
11526 else if (parent != body)
11528 gcc_assert (body->header == body_bb);
11529 gcc_assert (body->latch == cont_bb
11530 || single_pred (body->latch) == cont_bb);
11531 parent = NULL;
11534 if (parent)
11536 struct loop *body_loop = alloc_loop ();
11537 body_loop->header = body_bb;
11538 body_loop->latch = cont_bb;
11539 add_loop (body_loop, parent);
11544 /* Expand the OMP loop defined by REGION. */
11546 static void
11547 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11549 struct omp_for_data fd;
11550 struct omp_for_data_loop *loops;
11552 loops
11553 = (struct omp_for_data_loop *)
11554 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11555 * sizeof (struct omp_for_data_loop));
11556 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11557 &fd, loops);
11558 region->sched_kind = fd.sched_kind;
11559 region->sched_modifiers = fd.sched_modifiers;
11561 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11562 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11563 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11564 if (region->cont)
11566 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11567 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11568 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11570 else
11571 /* If there isn't a continue then this is a degerate case where
11572 the introduction of abnormal edges during lowering will prevent
11573 original loops from being detected. Fix that up. */
11574 loops_state_set (LOOPS_NEED_FIXUP);
11576 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11577 expand_omp_simd (region, &fd);
11578 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11579 expand_cilk_for (region, &fd);
11580 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11582 gcc_assert (!inner_stmt);
11583 expand_oacc_for (region, &fd);
11585 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11587 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11588 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11589 else
11590 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11592 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11593 && !fd.have_ordered)
11595 if (fd.chunk_size == NULL)
11596 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11597 else
11598 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11600 else
11602 int fn_index, start_ix, next_ix;
11604 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11605 == GF_OMP_FOR_KIND_FOR);
11606 if (fd.chunk_size == NULL
11607 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11608 fd.chunk_size = integer_zero_node;
11609 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11610 switch (fd.sched_kind)
11612 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11613 fn_index = 3;
11614 break;
11615 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11616 case OMP_CLAUSE_SCHEDULE_GUIDED:
11617 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11618 && !fd.ordered
11619 && !fd.have_ordered)
11621 fn_index = 3 + fd.sched_kind;
11622 break;
11624 /* FALLTHRU */
11625 default:
11626 fn_index = fd.sched_kind;
11627 break;
11629 if (!fd.ordered)
11630 fn_index += fd.have_ordered * 6;
11631 if (fd.ordered)
11632 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11633 else
11634 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11635 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11636 if (fd.iter_type == long_long_unsigned_type_node)
11638 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11639 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11640 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11641 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11643 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11644 (enum built_in_function) next_ix, inner_stmt);
11647 if (gimple_in_ssa_p (cfun))
11648 update_ssa (TODO_update_ssa_only_virtuals);
11652 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11654 v = GOMP_sections_start (n);
11656 switch (v)
11658 case 0:
11659 goto L2;
11660 case 1:
11661 section 1;
11662 goto L1;
11663 case 2:
11665 case n:
11667 default:
11668 abort ();
11671 v = GOMP_sections_next ();
11672 goto L0;
11674 reduction;
11676 If this is a combined parallel sections, replace the call to
11677 GOMP_sections_start with call to GOMP_sections_next. */
11679 static void
11680 expand_omp_sections (struct omp_region *region)
11682 tree t, u, vin = NULL, vmain, vnext, l2;
11683 unsigned len;
11684 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11685 gimple_stmt_iterator si, switch_si;
11686 gomp_sections *sections_stmt;
11687 gimple *stmt;
11688 gomp_continue *cont;
11689 edge_iterator ei;
11690 edge e;
11691 struct omp_region *inner;
11692 unsigned i, casei;
11693 bool exit_reachable = region->cont != NULL;
11695 gcc_assert (region->exit != NULL);
11696 entry_bb = region->entry;
11697 l0_bb = single_succ (entry_bb);
11698 l1_bb = region->cont;
11699 l2_bb = region->exit;
11700 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11701 l2 = gimple_block_label (l2_bb);
11702 else
11704 /* This can happen if there are reductions. */
11705 len = EDGE_COUNT (l0_bb->succs);
11706 gcc_assert (len > 0);
11707 e = EDGE_SUCC (l0_bb, len - 1);
11708 si = gsi_last_bb (e->dest);
11709 l2 = NULL_TREE;
11710 if (gsi_end_p (si)
11711 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11712 l2 = gimple_block_label (e->dest);
11713 else
11714 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11716 si = gsi_last_bb (e->dest);
11717 if (gsi_end_p (si)
11718 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11720 l2 = gimple_block_label (e->dest);
11721 break;
11725 if (exit_reachable)
11726 default_bb = create_empty_bb (l1_bb->prev_bb);
11727 else
11728 default_bb = create_empty_bb (l0_bb);
11730 /* We will build a switch() with enough cases for all the
11731 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11732 and a default case to abort if something goes wrong. */
11733 len = EDGE_COUNT (l0_bb->succs);
11735 /* Use vec::quick_push on label_vec throughout, since we know the size
11736 in advance. */
11737 auto_vec<tree> label_vec (len);
11739 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11740 GIMPLE_OMP_SECTIONS statement. */
11741 si = gsi_last_bb (entry_bb);
11742 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11743 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11744 vin = gimple_omp_sections_control (sections_stmt);
11745 if (!is_combined_parallel (region))
11747 /* If we are not inside a combined parallel+sections region,
11748 call GOMP_sections_start. */
11749 t = build_int_cst (unsigned_type_node, len - 1);
11750 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11751 stmt = gimple_build_call (u, 1, t);
11753 else
11755 /* Otherwise, call GOMP_sections_next. */
11756 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11757 stmt = gimple_build_call (u, 0);
11759 gimple_call_set_lhs (stmt, vin);
11760 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11761 gsi_remove (&si, true);
11763 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11764 L0_BB. */
11765 switch_si = gsi_last_bb (l0_bb);
11766 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11767 if (exit_reachable)
11769 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11770 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11771 vmain = gimple_omp_continue_control_use (cont);
11772 vnext = gimple_omp_continue_control_def (cont);
11774 else
11776 vmain = vin;
11777 vnext = NULL_TREE;
11780 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11781 label_vec.quick_push (t);
11782 i = 1;
11784 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11785 for (inner = region->inner, casei = 1;
11786 inner;
11787 inner = inner->next, i++, casei++)
11789 basic_block s_entry_bb, s_exit_bb;
11791 /* Skip optional reduction region. */
11792 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11794 --i;
11795 --casei;
11796 continue;
11799 s_entry_bb = inner->entry;
11800 s_exit_bb = inner->exit;
11802 t = gimple_block_label (s_entry_bb);
11803 u = build_int_cst (unsigned_type_node, casei);
11804 u = build_case_label (u, NULL, t);
11805 label_vec.quick_push (u);
11807 si = gsi_last_bb (s_entry_bb);
11808 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11809 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11810 gsi_remove (&si, true);
11811 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11813 if (s_exit_bb == NULL)
11814 continue;
11816 si = gsi_last_bb (s_exit_bb);
11817 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11818 gsi_remove (&si, true);
11820 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11823 /* Error handling code goes in DEFAULT_BB. */
11824 t = gimple_block_label (default_bb);
11825 u = build_case_label (NULL, NULL, t);
11826 make_edge (l0_bb, default_bb, 0);
11827 add_bb_to_loop (default_bb, current_loops->tree_root);
11829 stmt = gimple_build_switch (vmain, u, label_vec);
11830 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11831 gsi_remove (&switch_si, true);
11833 si = gsi_start_bb (default_bb);
11834 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11835 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11837 if (exit_reachable)
11839 tree bfn_decl;
11841 /* Code to get the next section goes in L1_BB. */
11842 si = gsi_last_bb (l1_bb);
11843 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11845 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11846 stmt = gimple_build_call (bfn_decl, 0);
11847 gimple_call_set_lhs (stmt, vnext);
11848 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11849 gsi_remove (&si, true);
11851 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11854 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11855 si = gsi_last_bb (l2_bb);
11856 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11857 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11858 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11859 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11860 else
11861 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11862 stmt = gimple_build_call (t, 0);
11863 if (gimple_omp_return_lhs (gsi_stmt (si)))
11864 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11865 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11866 gsi_remove (&si, true);
11868 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11872 /* Expand code for an OpenMP single directive. We've already expanded
11873 much of the code, here we simply place the GOMP_barrier call. */
11875 static void
11876 expand_omp_single (struct omp_region *region)
11878 basic_block entry_bb, exit_bb;
11879 gimple_stmt_iterator si;
11881 entry_bb = region->entry;
11882 exit_bb = region->exit;
11884 si = gsi_last_bb (entry_bb);
11885 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11886 gsi_remove (&si, true);
11887 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11889 si = gsi_last_bb (exit_bb);
11890 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11892 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11893 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11895 gsi_remove (&si, true);
11896 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11900 /* Generic expansion for OpenMP synchronization directives: master,
11901 ordered and critical. All we need to do here is remove the entry
11902 and exit markers for REGION. */
11904 static void
11905 expand_omp_synch (struct omp_region *region)
11907 basic_block entry_bb, exit_bb;
11908 gimple_stmt_iterator si;
11910 entry_bb = region->entry;
11911 exit_bb = region->exit;
11913 si = gsi_last_bb (entry_bb);
11914 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11915 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11916 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11917 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11918 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11919 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11920 gsi_remove (&si, true);
11921 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11923 if (exit_bb)
11925 si = gsi_last_bb (exit_bb);
11926 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11927 gsi_remove (&si, true);
11928 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11932 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11933 operation as a normal volatile load. */
11935 static bool
11936 expand_omp_atomic_load (basic_block load_bb, tree addr,
11937 tree loaded_val, int index)
11939 enum built_in_function tmpbase;
11940 gimple_stmt_iterator gsi;
11941 basic_block store_bb;
11942 location_t loc;
11943 gimple *stmt;
11944 tree decl, call, type, itype;
11946 gsi = gsi_last_bb (load_bb);
11947 stmt = gsi_stmt (gsi);
11948 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11949 loc = gimple_location (stmt);
11951 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11952 is smaller than word size, then expand_atomic_load assumes that the load
11953 is atomic. We could avoid the builtin entirely in this case. */
11955 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11956 decl = builtin_decl_explicit (tmpbase);
11957 if (decl == NULL_TREE)
11958 return false;
11960 type = TREE_TYPE (loaded_val);
11961 itype = TREE_TYPE (TREE_TYPE (decl));
11963 call = build_call_expr_loc (loc, decl, 2, addr,
11964 build_int_cst (NULL,
11965 gimple_omp_atomic_seq_cst_p (stmt)
11966 ? MEMMODEL_SEQ_CST
11967 : MEMMODEL_RELAXED));
11968 if (!useless_type_conversion_p (type, itype))
11969 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11970 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11972 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11973 gsi_remove (&gsi, true);
11975 store_bb = single_succ (load_bb);
11976 gsi = gsi_last_bb (store_bb);
11977 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11978 gsi_remove (&gsi, true);
11980 if (gimple_in_ssa_p (cfun))
11981 update_ssa (TODO_update_ssa_no_phi);
11983 return true;
11986 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11987 operation as a normal volatile store. */
11989 static bool
11990 expand_omp_atomic_store (basic_block load_bb, tree addr,
11991 tree loaded_val, tree stored_val, int index)
11993 enum built_in_function tmpbase;
11994 gimple_stmt_iterator gsi;
11995 basic_block store_bb = single_succ (load_bb);
11996 location_t loc;
11997 gimple *stmt;
11998 tree decl, call, type, itype;
11999 machine_mode imode;
12000 bool exchange;
12002 gsi = gsi_last_bb (load_bb);
12003 stmt = gsi_stmt (gsi);
12004 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
12006 /* If the load value is needed, then this isn't a store but an exchange. */
12007 exchange = gimple_omp_atomic_need_value_p (stmt);
12009 gsi = gsi_last_bb (store_bb);
12010 stmt = gsi_stmt (gsi);
12011 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
12012 loc = gimple_location (stmt);
12014 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12015 is smaller than word size, then expand_atomic_store assumes that the store
12016 is atomic. We could avoid the builtin entirely in this case. */
12018 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12019 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12020 decl = builtin_decl_explicit (tmpbase);
12021 if (decl == NULL_TREE)
12022 return false;
12024 type = TREE_TYPE (stored_val);
12026 /* Dig out the type of the function's second argument. */
12027 itype = TREE_TYPE (decl);
12028 itype = TYPE_ARG_TYPES (itype);
12029 itype = TREE_CHAIN (itype);
12030 itype = TREE_VALUE (itype);
12031 imode = TYPE_MODE (itype);
12033 if (exchange && !can_atomic_exchange_p (imode, true))
12034 return false;
12036 if (!useless_type_conversion_p (itype, type))
12037 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12038 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12039 build_int_cst (NULL,
12040 gimple_omp_atomic_seq_cst_p (stmt)
12041 ? MEMMODEL_SEQ_CST
12042 : MEMMODEL_RELAXED));
12043 if (exchange)
12045 if (!useless_type_conversion_p (type, itype))
12046 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12047 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12050 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12051 gsi_remove (&gsi, true);
12053 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12054 gsi = gsi_last_bb (load_bb);
12055 gsi_remove (&gsi, true);
12057 if (gimple_in_ssa_p (cfun))
12058 update_ssa (TODO_update_ssa_no_phi);
12060 return true;
12063 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12064 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12065 size of the data type, and thus usable to find the index of the builtin
12066 decl. Returns false if the expression is not of the proper form. */
12068 static bool
12069 expand_omp_atomic_fetch_op (basic_block load_bb,
12070 tree addr, tree loaded_val,
12071 tree stored_val, int index)
12073 enum built_in_function oldbase, newbase, tmpbase;
12074 tree decl, itype, call;
12075 tree lhs, rhs;
12076 basic_block store_bb = single_succ (load_bb);
12077 gimple_stmt_iterator gsi;
12078 gimple *stmt;
12079 location_t loc;
12080 enum tree_code code;
12081 bool need_old, need_new;
12082 machine_mode imode;
12083 bool seq_cst;
12085 /* We expect to find the following sequences:
12087 load_bb:
12088 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12090 store_bb:
12091 val = tmp OP something; (or: something OP tmp)
12092 GIMPLE_OMP_STORE (val)
12094 ???FIXME: Allow a more flexible sequence.
12095 Perhaps use data flow to pick the statements.
12099 gsi = gsi_after_labels (store_bb);
12100 stmt = gsi_stmt (gsi);
12101 loc = gimple_location (stmt);
12102 if (!is_gimple_assign (stmt))
12103 return false;
12104 gsi_next (&gsi);
12105 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12106 return false;
12107 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12108 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12109 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12110 gcc_checking_assert (!need_old || !need_new);
12112 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12113 return false;
12115 /* Check for one of the supported fetch-op operations. */
12116 code = gimple_assign_rhs_code (stmt);
12117 switch (code)
12119 case PLUS_EXPR:
12120 case POINTER_PLUS_EXPR:
12121 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12122 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12123 break;
12124 case MINUS_EXPR:
12125 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12126 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12127 break;
12128 case BIT_AND_EXPR:
12129 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12130 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12131 break;
12132 case BIT_IOR_EXPR:
12133 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12134 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12135 break;
12136 case BIT_XOR_EXPR:
12137 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12138 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12139 break;
12140 default:
12141 return false;
12144 /* Make sure the expression is of the proper form. */
12145 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12146 rhs = gimple_assign_rhs2 (stmt);
12147 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12148 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12149 rhs = gimple_assign_rhs1 (stmt);
12150 else
12151 return false;
12153 tmpbase = ((enum built_in_function)
12154 ((need_new ? newbase : oldbase) + index + 1));
12155 decl = builtin_decl_explicit (tmpbase);
12156 if (decl == NULL_TREE)
12157 return false;
12158 itype = TREE_TYPE (TREE_TYPE (decl));
12159 imode = TYPE_MODE (itype);
12161 /* We could test all of the various optabs involved, but the fact of the
12162 matter is that (with the exception of i486 vs i586 and xadd) all targets
12163 that support any atomic operaton optab also implements compare-and-swap.
12164 Let optabs.c take care of expanding any compare-and-swap loop. */
12165 if (!can_compare_and_swap_p (imode, true))
12166 return false;
12168 gsi = gsi_last_bb (load_bb);
12169 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12171 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12172 It only requires that the operation happen atomically. Thus we can
12173 use the RELAXED memory model. */
12174 call = build_call_expr_loc (loc, decl, 3, addr,
12175 fold_convert_loc (loc, itype, rhs),
12176 build_int_cst (NULL,
12177 seq_cst ? MEMMODEL_SEQ_CST
12178 : MEMMODEL_RELAXED));
12180 if (need_old || need_new)
12182 lhs = need_old ? loaded_val : stored_val;
12183 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12184 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12186 else
12187 call = fold_convert_loc (loc, void_type_node, call);
12188 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12189 gsi_remove (&gsi, true);
12191 gsi = gsi_last_bb (store_bb);
12192 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12193 gsi_remove (&gsi, true);
12194 gsi = gsi_last_bb (store_bb);
12195 stmt = gsi_stmt (gsi);
12196 gsi_remove (&gsi, true);
12198 if (gimple_in_ssa_p (cfun))
12200 release_defs (stmt);
12201 update_ssa (TODO_update_ssa_no_phi);
12204 return true;
12207 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12209 oldval = *addr;
12210 repeat:
12211 newval = rhs; // with oldval replacing *addr in rhs
12212 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12213 if (oldval != newval)
12214 goto repeat;
12216 INDEX is log2 of the size of the data type, and thus usable to find the
12217 index of the builtin decl. */
12219 static bool
12220 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12221 tree addr, tree loaded_val, tree stored_val,
12222 int index)
12224 tree loadedi, storedi, initial, new_storedi, old_vali;
12225 tree type, itype, cmpxchg, iaddr;
12226 gimple_stmt_iterator si;
12227 basic_block loop_header = single_succ (load_bb);
12228 gimple *phi, *stmt;
12229 edge e;
12230 enum built_in_function fncode;
12232 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12233 order to use the RELAXED memory model effectively. */
12234 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12235 + index + 1);
12236 cmpxchg = builtin_decl_explicit (fncode);
12237 if (cmpxchg == NULL_TREE)
12238 return false;
12239 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12240 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12242 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12243 return false;
12245 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12246 si = gsi_last_bb (load_bb);
12247 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12249 /* For floating-point values, we'll need to view-convert them to integers
12250 so that we can perform the atomic compare and swap. Simplify the
12251 following code by always setting up the "i"ntegral variables. */
12252 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12254 tree iaddr_val;
12256 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12257 true));
12258 iaddr_val
12259 = force_gimple_operand_gsi (&si,
12260 fold_convert (TREE_TYPE (iaddr), addr),
12261 false, NULL_TREE, true, GSI_SAME_STMT);
12262 stmt = gimple_build_assign (iaddr, iaddr_val);
12263 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12264 loadedi = create_tmp_var (itype);
12265 if (gimple_in_ssa_p (cfun))
12266 loadedi = make_ssa_name (loadedi);
12268 else
12270 iaddr = addr;
12271 loadedi = loaded_val;
12274 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12275 tree loaddecl = builtin_decl_explicit (fncode);
12276 if (loaddecl)
12277 initial
12278 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12279 build_call_expr (loaddecl, 2, iaddr,
12280 build_int_cst (NULL_TREE,
12281 MEMMODEL_RELAXED)));
12282 else
12283 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12284 build_int_cst (TREE_TYPE (iaddr), 0));
12286 initial
12287 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12288 GSI_SAME_STMT);
12290 /* Move the value to the LOADEDI temporary. */
12291 if (gimple_in_ssa_p (cfun))
12293 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12294 phi = create_phi_node (loadedi, loop_header);
12295 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12296 initial);
12298 else
12299 gsi_insert_before (&si,
12300 gimple_build_assign (loadedi, initial),
12301 GSI_SAME_STMT);
12302 if (loadedi != loaded_val)
12304 gimple_stmt_iterator gsi2;
12305 tree x;
12307 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12308 gsi2 = gsi_start_bb (loop_header);
12309 if (gimple_in_ssa_p (cfun))
12311 gassign *stmt;
12312 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12313 true, GSI_SAME_STMT);
12314 stmt = gimple_build_assign (loaded_val, x);
12315 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12317 else
12319 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12320 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12321 true, GSI_SAME_STMT);
12324 gsi_remove (&si, true);
12326 si = gsi_last_bb (store_bb);
12327 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12329 if (iaddr == addr)
12330 storedi = stored_val;
12331 else
12332 storedi =
12333 force_gimple_operand_gsi (&si,
12334 build1 (VIEW_CONVERT_EXPR, itype,
12335 stored_val), true, NULL_TREE, true,
12336 GSI_SAME_STMT);
12338 /* Build the compare&swap statement. */
12339 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12340 new_storedi = force_gimple_operand_gsi (&si,
12341 fold_convert (TREE_TYPE (loadedi),
12342 new_storedi),
12343 true, NULL_TREE,
12344 true, GSI_SAME_STMT);
12346 if (gimple_in_ssa_p (cfun))
12347 old_vali = loadedi;
12348 else
12350 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12351 stmt = gimple_build_assign (old_vali, loadedi);
12352 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12354 stmt = gimple_build_assign (loadedi, new_storedi);
12355 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12358 /* Note that we always perform the comparison as an integer, even for
12359 floating point. This allows the atomic operation to properly
12360 succeed even with NaNs and -0.0. */
12361 stmt = gimple_build_cond_empty
12362 (build2 (NE_EXPR, boolean_type_node,
12363 new_storedi, old_vali));
12364 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12366 /* Update cfg. */
12367 e = single_succ_edge (store_bb);
12368 e->flags &= ~EDGE_FALLTHRU;
12369 e->flags |= EDGE_FALSE_VALUE;
12371 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12373 /* Copy the new value to loadedi (we already did that before the condition
12374 if we are not in SSA). */
12375 if (gimple_in_ssa_p (cfun))
12377 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12378 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12381 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12382 gsi_remove (&si, true);
12384 struct loop *loop = alloc_loop ();
12385 loop->header = loop_header;
12386 loop->latch = store_bb;
12387 add_loop (loop, loop_header->loop_father);
12389 if (gimple_in_ssa_p (cfun))
12390 update_ssa (TODO_update_ssa_no_phi);
12392 return true;
12395 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12397 GOMP_atomic_start ();
12398 *addr = rhs;
12399 GOMP_atomic_end ();
12401 The result is not globally atomic, but works so long as all parallel
12402 references are within #pragma omp atomic directives. According to
12403 responses received from omp@openmp.org, appears to be within spec.
12404 Which makes sense, since that's how several other compilers handle
12405 this situation as well.
12406 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12407 expanding. STORED_VAL is the operand of the matching
12408 GIMPLE_OMP_ATOMIC_STORE.
12410 We replace
12411 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12412 loaded_val = *addr;
12414 and replace
12415 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12416 *addr = stored_val;
12419 static bool
12420 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12421 tree addr, tree loaded_val, tree stored_val)
12423 gimple_stmt_iterator si;
12424 gassign *stmt;
12425 tree t;
12427 si = gsi_last_bb (load_bb);
12428 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12430 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12431 t = build_call_expr (t, 0);
12432 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12434 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12435 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12436 gsi_remove (&si, true);
12438 si = gsi_last_bb (store_bb);
12439 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12441 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12442 stored_val);
12443 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12445 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12446 t = build_call_expr (t, 0);
12447 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12448 gsi_remove (&si, true);
12450 if (gimple_in_ssa_p (cfun))
12451 update_ssa (TODO_update_ssa_no_phi);
12452 return true;
12455 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12456 using expand_omp_atomic_fetch_op. If it failed, we try to
12457 call expand_omp_atomic_pipeline, and if it fails too, the
12458 ultimate fallback is wrapping the operation in a mutex
12459 (expand_omp_atomic_mutex). REGION is the atomic region built
12460 by build_omp_regions_1(). */
12462 static void
12463 expand_omp_atomic (struct omp_region *region)
12465 basic_block load_bb = region->entry, store_bb = region->exit;
12466 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12467 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12468 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12469 tree addr = gimple_omp_atomic_load_rhs (load);
12470 tree stored_val = gimple_omp_atomic_store_val (store);
12471 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12472 HOST_WIDE_INT index;
12474 /* Make sure the type is one of the supported sizes. */
12475 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12476 index = exact_log2 (index);
12477 if (index >= 0 && index <= 4)
12479 unsigned int align = TYPE_ALIGN_UNIT (type);
12481 /* __sync builtins require strict data alignment. */
12482 if (exact_log2 (align) >= index)
12484 /* Atomic load. */
12485 if (loaded_val == stored_val
12486 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12487 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12488 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12489 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12490 return;
12492 /* Atomic store. */
12493 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12494 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12495 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12496 && store_bb == single_succ (load_bb)
12497 && first_stmt (store_bb) == store
12498 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12499 stored_val, index))
12500 return;
12502 /* When possible, use specialized atomic update functions. */
12503 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12504 && store_bb == single_succ (load_bb)
12505 && expand_omp_atomic_fetch_op (load_bb, addr,
12506 loaded_val, stored_val, index))
12507 return;
12509 /* If we don't have specialized __sync builtins, try and implement
12510 as a compare and swap loop. */
12511 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12512 loaded_val, stored_val, index))
12513 return;
12517 /* The ultimate fallback is wrapping the operation in a mutex. */
12518 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12522 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12523 macro on gomp-constants.h. We do not check for overflow. */
12525 static tree
12526 oacc_launch_pack (unsigned code, tree device, unsigned op)
12528 tree res;
12530 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12531 if (device)
12533 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12534 device, build_int_cst (unsigned_type_node,
12535 GOMP_LAUNCH_DEVICE_SHIFT));
12536 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12538 return res;
12541 /* Look for compute grid dimension clauses and convert to an attribute
12542 attached to FN. This permits the target-side code to (a) massage
12543 the dimensions, (b) emit that data and (c) optimize. Non-constant
12544 dimensions are pushed onto ARGS.
12546 The attribute value is a TREE_LIST. A set of dimensions is
12547 represented as a list of INTEGER_CST. Those that are runtime
12548 exprs are represented as an INTEGER_CST of zero.
12550 TOOO. Normally the attribute will just contain a single such list. If
12551 however it contains a list of lists, this will represent the use of
12552 device_type. Each member of the outer list is an assoc list of
12553 dimensions, keyed by the device type. The first entry will be the
12554 default. Well, that's the plan. */
12556 #define OACC_FN_ATTRIB "oacc function"
12558 /* Replace any existing oacc fn attribute with updated dimensions. */
12560 void
12561 replace_oacc_fn_attrib (tree fn, tree dims)
12563 tree ident = get_identifier (OACC_FN_ATTRIB);
12564 tree attribs = DECL_ATTRIBUTES (fn);
12566 /* If we happen to be present as the first attrib, drop it. */
12567 if (attribs && TREE_PURPOSE (attribs) == ident)
12568 attribs = TREE_CHAIN (attribs);
12569 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12572 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12573 function attribute. Push any that are non-constant onto the ARGS
12574 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12575 true, if these are for a kernels region offload function. */
12577 void
12578 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12580 /* Must match GOMP_DIM ordering. */
12581 static const omp_clause_code ids[]
12582 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12583 OMP_CLAUSE_VECTOR_LENGTH };
12584 unsigned ix;
12585 tree dims[GOMP_DIM_MAX];
12586 tree attr = NULL_TREE;
12587 unsigned non_const = 0;
12589 for (ix = GOMP_DIM_MAX; ix--;)
12591 tree clause = find_omp_clause (clauses, ids[ix]);
12592 tree dim = NULL_TREE;
12594 if (clause)
12595 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12596 dims[ix] = dim;
12597 if (dim && TREE_CODE (dim) != INTEGER_CST)
12599 dim = integer_zero_node;
12600 non_const |= GOMP_DIM_MASK (ix);
12602 attr = tree_cons (NULL_TREE, dim, attr);
12603 /* Note kernelness with TREE_PUBLIC. */
12604 if (is_kernel)
12605 TREE_PUBLIC (attr) = 1;
12608 replace_oacc_fn_attrib (fn, attr);
12610 if (non_const)
12612 /* Push a dynamic argument set. */
12613 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12614 NULL_TREE, non_const));
12615 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12616 if (non_const & GOMP_DIM_MASK (ix))
12617 args->safe_push (dims[ix]);
12621 /* Process the routine's dimension clauess to generate an attribute
12622 value. Issue diagnostics as appropriate. We default to SEQ
12623 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12624 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12625 can have a loop partitioned on it. non-zero indicates
12626 yes, zero indicates no. By construction once a non-zero has been
12627 reached, further inner dimensions must also be non-zero. We set
12628 TREE_VALUE to zero for the dimensions that may be partitioned and
12629 1 for the other ones -- if a loop is (erroneously) spawned at
12630 an outer level, we don't want to try and partition it. */
12632 tree
12633 build_oacc_routine_dims (tree clauses)
12635 /* Must match GOMP_DIM ordering. */
12636 static const omp_clause_code ids[] =
12637 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12638 int ix;
12639 int level = -1;
12641 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12642 for (ix = GOMP_DIM_MAX + 1; ix--;)
12643 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12645 if (level >= 0)
12646 error_at (OMP_CLAUSE_LOCATION (clauses),
12647 "multiple loop axes specified for routine");
12648 level = ix;
12649 break;
12652 /* Default to SEQ. */
12653 if (level < 0)
12654 level = GOMP_DIM_MAX;
12656 tree dims = NULL_TREE;
12658 for (ix = GOMP_DIM_MAX; ix--;)
12659 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12660 build_int_cst (integer_type_node, ix < level), dims);
12662 return dims;
12665 /* Retrieve the oacc function attrib and return it. Non-oacc
12666 functions will return NULL. */
12668 tree
12669 get_oacc_fn_attrib (tree fn)
12671 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12674 /* Return true if this oacc fn attrib is for a kernels offload
12675 region. We use the TREE_PUBLIC flag of each dimension -- only
12676 need to check the first one. */
12678 bool
12679 oacc_fn_attrib_kernels_p (tree attr)
12681 return TREE_PUBLIC (TREE_VALUE (attr));
12684 /* Return level at which oacc routine may spawn a partitioned loop, or
12685 -1 if it is not a routine (i.e. is an offload fn). */
12687 static int
12688 oacc_fn_attrib_level (tree attr)
12690 tree pos = TREE_VALUE (attr);
12692 if (!TREE_PURPOSE (pos))
12693 return -1;
12695 int ix = 0;
12696 for (ix = 0; ix != GOMP_DIM_MAX;
12697 ix++, pos = TREE_CHAIN (pos))
12698 if (!integer_zerop (TREE_PURPOSE (pos)))
12699 break;
12701 return ix;
12704 /* Extract an oacc execution dimension from FN. FN must be an
12705 offloaded function or routine that has already had its execution
12706 dimensions lowered to the target-specific values. */
12709 get_oacc_fn_dim_size (tree fn, int axis)
12711 tree attrs = get_oacc_fn_attrib (fn);
12713 gcc_assert (axis < GOMP_DIM_MAX);
12715 tree dims = TREE_VALUE (attrs);
12716 while (axis--)
12717 dims = TREE_CHAIN (dims);
12719 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12721 return size;
12724 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12725 IFN_GOACC_DIM_SIZE call. */
12728 get_oacc_ifn_dim_arg (const gimple *stmt)
12730 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12731 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12732 tree arg = gimple_call_arg (stmt, 0);
12733 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12735 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12736 return (int) axis;
12739 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12740 at REGION_EXIT. */
12742 static void
12743 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12744 basic_block region_exit)
12746 struct loop *outer = region_entry->loop_father;
12747 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12749 /* Don't parallelize the kernels region if it contains more than one outer
12750 loop. */
12751 unsigned int nr_outer_loops = 0;
12752 struct loop *single_outer = NULL;
12753 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12755 gcc_assert (loop_outer (loop) == outer);
12757 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12758 continue;
12760 if (region_exit != NULL
12761 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12762 continue;
12764 nr_outer_loops++;
12765 single_outer = loop;
12767 if (nr_outer_loops != 1)
12768 return;
12770 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12771 if (loop->next)
12772 return;
12774 /* Mark the loops in the region. */
12775 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12776 loop->in_oacc_kernels_region = true;
12779 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12781 struct GTY(()) grid_launch_attributes_trees
12783 tree kernel_dim_array_type;
12784 tree kernel_lattrs_dimnum_decl;
12785 tree kernel_lattrs_grid_decl;
12786 tree kernel_lattrs_group_decl;
12787 tree kernel_launch_attributes_type;
12790 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12792 /* Create types used to pass kernel launch attributes to target. */
12794 static void
12795 grid_create_kernel_launch_attr_types (void)
12797 if (grid_attr_trees)
12798 return;
12799 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12801 tree dim_arr_index_type
12802 = build_index_type (build_int_cst (integer_type_node, 2));
12803 grid_attr_trees->kernel_dim_array_type
12804 = build_array_type (uint32_type_node, dim_arr_index_type);
12806 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12807 grid_attr_trees->kernel_lattrs_dimnum_decl
12808 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12809 uint32_type_node);
12810 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12812 grid_attr_trees->kernel_lattrs_grid_decl
12813 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12814 grid_attr_trees->kernel_dim_array_type);
12815 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12816 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12817 grid_attr_trees->kernel_lattrs_group_decl
12818 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12819 grid_attr_trees->kernel_dim_array_type);
12820 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12821 = grid_attr_trees->kernel_lattrs_grid_decl;
12822 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12823 "__gomp_kernel_launch_attributes",
12824 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12827 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12828 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12829 of type uint32_type_node. */
12831 static void
12832 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12833 tree fld_decl, int index, tree value)
12835 tree ref = build4 (ARRAY_REF, uint32_type_node,
12836 build3 (COMPONENT_REF,
12837 grid_attr_trees->kernel_dim_array_type,
12838 range_var, fld_decl, NULL_TREE),
12839 build_int_cst (integer_type_node, index),
12840 NULL_TREE, NULL_TREE);
12841 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12844 /* Return a tree representation of a pointer to a structure with grid and
12845 work-group size information. Statements filling that information will be
12846 inserted before GSI, TGT_STMT is the target statement which has the
12847 necessary information in it. */
12849 static tree
12850 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12851 gomp_target *tgt_stmt)
12853 grid_create_kernel_launch_attr_types ();
12854 tree u32_one = build_one_cst (uint32_type_node);
12855 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12856 "__kernel_launch_attrs");
12858 unsigned max_dim = 0;
12859 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12860 clause;
12861 clause = OMP_CLAUSE_CHAIN (clause))
12863 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12864 continue;
12866 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12867 max_dim = MAX (dim, max_dim);
12869 grid_insert_store_range_dim (gsi, lattrs,
12870 grid_attr_trees->kernel_lattrs_grid_decl,
12871 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12872 grid_insert_store_range_dim (gsi, lattrs,
12873 grid_attr_trees->kernel_lattrs_group_decl,
12874 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12877 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12878 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12879 /* At this moment we cannot gridify a loop with a collapse clause. */
12880 /* TODO: Adjust when we support bigger collapse. */
12881 gcc_assert (max_dim == 0);
12882 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12883 TREE_ADDRESSABLE (lattrs) = 1;
12884 return build_fold_addr_expr (lattrs);
12887 /* Build target argument identifier from the DEVICE identifier, value
12888 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12890 static tree
12891 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12893 tree t = build_int_cst (integer_type_node, device);
12894 if (subseqent_param)
12895 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12896 build_int_cst (integer_type_node,
12897 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12898 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12899 build_int_cst (integer_type_node, id));
12900 return t;
12903 /* Like above but return it in type that can be directly stored as an element
12904 of the argument array. */
12906 static tree
12907 get_target_argument_identifier (int device, bool subseqent_param, int id)
12909 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12910 return fold_convert (ptr_type_node, t);
12913 /* Return a target argument consisting of DEVICE identifier, value identifier
12914 ID, and the actual VALUE. */
12916 static tree
12917 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12918 tree value)
12920 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12921 fold_convert (integer_type_node, value),
12922 build_int_cst (unsigned_type_node,
12923 GOMP_TARGET_ARG_VALUE_SHIFT));
12924 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12925 get_target_argument_identifier_1 (device, false, id));
12926 t = fold_convert (ptr_type_node, t);
12927 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12930 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12931 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12932 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12933 arguments. */
12935 static void
12936 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12937 int id, tree value, vec <tree> *args)
12939 if (tree_fits_shwi_p (value)
12940 && tree_to_shwi (value) > -(1 << 15)
12941 && tree_to_shwi (value) < (1 << 15))
12942 args->quick_push (get_target_argument_value (gsi, device, id, value));
12943 else
12945 args->quick_push (get_target_argument_identifier (device, true, id));
12946 value = fold_convert (ptr_type_node, value);
12947 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12948 GSI_SAME_STMT);
12949 args->quick_push (value);
12953 /* Create an array of arguments that is then passed to GOMP_target. */
12955 static tree
12956 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12958 auto_vec <tree, 6> args;
12959 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12960 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12961 if (c)
12962 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12963 else
12964 t = integer_minus_one_node;
12965 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12966 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12968 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12969 if (c)
12970 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12971 else
12972 t = integer_minus_one_node;
12973 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12974 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12975 &args);
12977 /* Add HSA-specific grid sizes, if available. */
12978 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12979 OMP_CLAUSE__GRIDDIM_))
12981 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12982 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12983 args.quick_push (t);
12984 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12987 /* Produce more, perhaps device specific, arguments here. */
12989 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12990 args.length () + 1),
12991 ".omp_target_args");
12992 for (unsigned i = 0; i < args.length (); i++)
12994 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12995 build_int_cst (integer_type_node, i),
12996 NULL_TREE, NULL_TREE);
12997 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12998 GSI_SAME_STMT);
13000 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
13001 build_int_cst (integer_type_node, args.length ()),
13002 NULL_TREE, NULL_TREE);
13003 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
13004 GSI_SAME_STMT);
13005 TREE_ADDRESSABLE (argarray) = 1;
13006 return build_fold_addr_expr (argarray);
13009 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
13011 static void
13012 expand_omp_target (struct omp_region *region)
13014 basic_block entry_bb, exit_bb, new_bb;
13015 struct function *child_cfun;
13016 tree child_fn, block, t;
13017 gimple_stmt_iterator gsi;
13018 gomp_target *entry_stmt;
13019 gimple *stmt;
13020 edge e;
13021 bool offloaded, data_region;
13023 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13024 new_bb = region->entry;
13026 offloaded = is_gimple_omp_offloaded (entry_stmt);
13027 switch (gimple_omp_target_kind (entry_stmt))
13029 case GF_OMP_TARGET_KIND_REGION:
13030 case GF_OMP_TARGET_KIND_UPDATE:
13031 case GF_OMP_TARGET_KIND_ENTER_DATA:
13032 case GF_OMP_TARGET_KIND_EXIT_DATA:
13033 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13034 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13035 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13036 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13037 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13038 data_region = false;
13039 break;
13040 case GF_OMP_TARGET_KIND_DATA:
13041 case GF_OMP_TARGET_KIND_OACC_DATA:
13042 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13043 data_region = true;
13044 break;
13045 default:
13046 gcc_unreachable ();
13049 child_fn = NULL_TREE;
13050 child_cfun = NULL;
13051 if (offloaded)
13053 child_fn = gimple_omp_target_child_fn (entry_stmt);
13054 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13057 /* Supported by expand_omp_taskreg, but not here. */
13058 if (child_cfun != NULL)
13059 gcc_checking_assert (!child_cfun->cfg);
13060 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13062 entry_bb = region->entry;
13063 exit_bb = region->exit;
13065 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13066 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13068 if (offloaded)
13070 unsigned srcidx, dstidx, num;
13072 /* If the offloading region needs data sent from the parent
13073 function, then the very first statement (except possible
13074 tree profile counter updates) of the offloading body
13075 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13076 &.OMP_DATA_O is passed as an argument to the child function,
13077 we need to replace it with the argument as seen by the child
13078 function.
13080 In most cases, this will end up being the identity assignment
13081 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13082 a function call that has been inlined, the original PARM_DECL
13083 .OMP_DATA_I may have been converted into a different local
13084 variable. In which case, we need to keep the assignment. */
13085 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13086 if (data_arg)
13088 basic_block entry_succ_bb = single_succ (entry_bb);
13089 gimple_stmt_iterator gsi;
13090 tree arg;
13091 gimple *tgtcopy_stmt = NULL;
13092 tree sender = TREE_VEC_ELT (data_arg, 0);
13094 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13096 gcc_assert (!gsi_end_p (gsi));
13097 stmt = gsi_stmt (gsi);
13098 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13099 continue;
13101 if (gimple_num_ops (stmt) == 2)
13103 tree arg = gimple_assign_rhs1 (stmt);
13105 /* We're ignoring the subcode because we're
13106 effectively doing a STRIP_NOPS. */
13108 if (TREE_CODE (arg) == ADDR_EXPR
13109 && TREE_OPERAND (arg, 0) == sender)
13111 tgtcopy_stmt = stmt;
13112 break;
13117 gcc_assert (tgtcopy_stmt != NULL);
13118 arg = DECL_ARGUMENTS (child_fn);
13120 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13121 gsi_remove (&gsi, true);
13124 /* Declare local variables needed in CHILD_CFUN. */
13125 block = DECL_INITIAL (child_fn);
13126 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13127 /* The gimplifier could record temporaries in the offloading block
13128 rather than in containing function's local_decls chain,
13129 which would mean cgraph missed finalizing them. Do it now. */
13130 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13131 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
13132 varpool_node::finalize_decl (t);
13133 DECL_SAVED_TREE (child_fn) = NULL;
13134 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13135 gimple_set_body (child_fn, NULL);
13136 TREE_USED (block) = 1;
13138 /* Reset DECL_CONTEXT on function arguments. */
13139 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13140 DECL_CONTEXT (t) = child_fn;
13142 /* Split ENTRY_BB at GIMPLE_*,
13143 so that it can be moved to the child function. */
13144 gsi = gsi_last_bb (entry_bb);
13145 stmt = gsi_stmt (gsi);
13146 gcc_assert (stmt
13147 && gimple_code (stmt) == gimple_code (entry_stmt));
13148 e = split_block (entry_bb, stmt);
13149 gsi_remove (&gsi, true);
13150 entry_bb = e->dest;
13151 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13153 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13154 if (exit_bb)
13156 gsi = gsi_last_bb (exit_bb);
13157 gcc_assert (!gsi_end_p (gsi)
13158 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13159 stmt = gimple_build_return (NULL);
13160 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13161 gsi_remove (&gsi, true);
13164 /* Move the offloading region into CHILD_CFUN. */
13166 block = gimple_block (entry_stmt);
13168 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13169 if (exit_bb)
13170 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13171 /* When the OMP expansion process cannot guarantee an up-to-date
13172 loop tree arrange for the child function to fixup loops. */
13173 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13174 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13176 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13177 num = vec_safe_length (child_cfun->local_decls);
13178 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13180 t = (*child_cfun->local_decls)[srcidx];
13181 if (DECL_CONTEXT (t) == cfun->decl)
13182 continue;
13183 if (srcidx != dstidx)
13184 (*child_cfun->local_decls)[dstidx] = t;
13185 dstidx++;
13187 if (dstidx != num)
13188 vec_safe_truncate (child_cfun->local_decls, dstidx);
13190 /* Inform the callgraph about the new function. */
13191 child_cfun->curr_properties = cfun->curr_properties;
13192 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13193 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13194 cgraph_node *node = cgraph_node::get_create (child_fn);
13195 node->parallelized_function = 1;
13196 cgraph_node::add_new_function (child_fn, true);
13198 /* Add the new function to the offload table. */
13199 if (ENABLE_OFFLOADING)
13200 vec_safe_push (offload_funcs, child_fn);
13202 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13203 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13205 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13206 fixed in a following pass. */
13207 push_cfun (child_cfun);
13208 if (need_asm)
13209 assign_assembler_name_if_neeeded (child_fn);
13210 cgraph_edge::rebuild_edges ();
13212 /* Some EH regions might become dead, see PR34608. If
13213 pass_cleanup_cfg isn't the first pass to happen with the
13214 new child, these dead EH edges might cause problems.
13215 Clean them up now. */
13216 if (flag_exceptions)
13218 basic_block bb;
13219 bool changed = false;
13221 FOR_EACH_BB_FN (bb, cfun)
13222 changed |= gimple_purge_dead_eh_edges (bb);
13223 if (changed)
13224 cleanup_tree_cfg ();
13226 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13227 verify_loop_structure ();
13228 pop_cfun ();
13230 if (dump_file && !gimple_in_ssa_p (cfun))
13232 omp_any_child_fn_dumped = true;
13233 dump_function_header (dump_file, child_fn, dump_flags);
13234 dump_function_to_file (child_fn, dump_file, dump_flags);
13238 /* Emit a library call to launch the offloading region, or do data
13239 transfers. */
13240 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13241 enum built_in_function start_ix;
13242 location_t clause_loc;
13243 unsigned int flags_i = 0;
13244 bool oacc_kernels_p = false;
13246 switch (gimple_omp_target_kind (entry_stmt))
13248 case GF_OMP_TARGET_KIND_REGION:
13249 start_ix = BUILT_IN_GOMP_TARGET;
13250 break;
13251 case GF_OMP_TARGET_KIND_DATA:
13252 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13253 break;
13254 case GF_OMP_TARGET_KIND_UPDATE:
13255 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13256 break;
13257 case GF_OMP_TARGET_KIND_ENTER_DATA:
13258 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13259 break;
13260 case GF_OMP_TARGET_KIND_EXIT_DATA:
13261 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13262 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13263 break;
13264 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13265 oacc_kernels_p = true;
13266 /* FALLTHROUGH */
13267 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13268 start_ix = BUILT_IN_GOACC_PARALLEL;
13269 break;
13270 case GF_OMP_TARGET_KIND_OACC_DATA:
13271 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13272 start_ix = BUILT_IN_GOACC_DATA_START;
13273 break;
13274 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13275 start_ix = BUILT_IN_GOACC_UPDATE;
13276 break;
13277 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13278 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13279 break;
13280 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13281 start_ix = BUILT_IN_GOACC_DECLARE;
13282 break;
13283 default:
13284 gcc_unreachable ();
13287 clauses = gimple_omp_target_clauses (entry_stmt);
13289 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13290 library choose) and there is no conditional. */
13291 cond = NULL_TREE;
13292 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13294 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13295 if (c)
13296 cond = OMP_CLAUSE_IF_EXPR (c);
13298 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13299 if (c)
13301 /* Even if we pass it to all library function calls, it is currently only
13302 defined/used for the OpenMP target ones. */
13303 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13304 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13305 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13306 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13308 device = OMP_CLAUSE_DEVICE_ID (c);
13309 clause_loc = OMP_CLAUSE_LOCATION (c);
13311 else
13312 clause_loc = gimple_location (entry_stmt);
13314 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13315 if (c)
13316 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13318 /* Ensure 'device' is of the correct type. */
13319 device = fold_convert_loc (clause_loc, integer_type_node, device);
13321 /* If we found the clause 'if (cond)', build
13322 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13323 if (cond)
13325 cond = gimple_boolify (cond);
13327 basic_block cond_bb, then_bb, else_bb;
13328 edge e;
13329 tree tmp_var;
13331 tmp_var = create_tmp_var (TREE_TYPE (device));
13332 if (offloaded)
13333 e = split_block_after_labels (new_bb);
13334 else
13336 gsi = gsi_last_bb (new_bb);
13337 gsi_prev (&gsi);
13338 e = split_block (new_bb, gsi_stmt (gsi));
13340 cond_bb = e->src;
13341 new_bb = e->dest;
13342 remove_edge (e);
13344 then_bb = create_empty_bb (cond_bb);
13345 else_bb = create_empty_bb (then_bb);
13346 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13347 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13349 stmt = gimple_build_cond_empty (cond);
13350 gsi = gsi_last_bb (cond_bb);
13351 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13353 gsi = gsi_start_bb (then_bb);
13354 stmt = gimple_build_assign (tmp_var, device);
13355 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13357 gsi = gsi_start_bb (else_bb);
13358 stmt = gimple_build_assign (tmp_var,
13359 build_int_cst (integer_type_node,
13360 GOMP_DEVICE_HOST_FALLBACK));
13361 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13363 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13364 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13365 add_bb_to_loop (then_bb, cond_bb->loop_father);
13366 add_bb_to_loop (else_bb, cond_bb->loop_father);
13367 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13368 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13370 device = tmp_var;
13371 gsi = gsi_last_bb (new_bb);
13373 else
13375 gsi = gsi_last_bb (new_bb);
13376 device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
13377 true, GSI_SAME_STMT);
13380 t = gimple_omp_target_data_arg (entry_stmt);
13381 if (t == NULL)
13383 t1 = size_zero_node;
13384 t2 = build_zero_cst (ptr_type_node);
13385 t3 = t2;
13386 t4 = t2;
13388 else
13390 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13391 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13392 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13393 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13394 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13397 gimple *g;
13398 bool tagging = false;
13399 /* The maximum number used by any start_ix, without varargs. */
13400 auto_vec<tree, 11> args;
13401 args.quick_push (device);
13402 if (offloaded)
13403 args.quick_push (build_fold_addr_expr (child_fn));
13404 args.quick_push (t1);
13405 args.quick_push (t2);
13406 args.quick_push (t3);
13407 args.quick_push (t4);
13408 switch (start_ix)
13410 case BUILT_IN_GOACC_DATA_START:
13411 case BUILT_IN_GOACC_DECLARE:
13412 case BUILT_IN_GOMP_TARGET_DATA:
13413 break;
13414 case BUILT_IN_GOMP_TARGET:
13415 case BUILT_IN_GOMP_TARGET_UPDATE:
13416 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13417 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13418 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13419 if (c)
13420 depend = OMP_CLAUSE_DECL (c);
13421 else
13422 depend = build_int_cst (ptr_type_node, 0);
13423 args.quick_push (depend);
13424 if (start_ix == BUILT_IN_GOMP_TARGET)
13425 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13426 break;
13427 case BUILT_IN_GOACC_PARALLEL:
13429 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13430 tagging = true;
13432 /* FALLTHRU */
13433 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13434 case BUILT_IN_GOACC_UPDATE:
13436 tree t_async = NULL_TREE;
13438 /* If present, use the value specified by the respective
13439 clause, making sure that is of the correct type. */
13440 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13441 if (c)
13442 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13443 integer_type_node,
13444 OMP_CLAUSE_ASYNC_EXPR (c));
13445 else if (!tagging)
13446 /* Default values for t_async. */
13447 t_async = fold_convert_loc (gimple_location (entry_stmt),
13448 integer_type_node,
13449 build_int_cst (integer_type_node,
13450 GOMP_ASYNC_SYNC));
13451 if (tagging && t_async)
13453 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13455 if (TREE_CODE (t_async) == INTEGER_CST)
13457 /* See if we can pack the async arg in to the tag's
13458 operand. */
13459 i_async = TREE_INT_CST_LOW (t_async);
13460 if (i_async < GOMP_LAUNCH_OP_MAX)
13461 t_async = NULL_TREE;
13462 else
13463 i_async = GOMP_LAUNCH_OP_MAX;
13465 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13466 i_async));
13468 if (t_async)
13469 args.safe_push (t_async);
13471 /* Save the argument index, and ... */
13472 unsigned t_wait_idx = args.length ();
13473 unsigned num_waits = 0;
13474 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13475 if (!tagging || c)
13476 /* ... push a placeholder. */
13477 args.safe_push (integer_zero_node);
13479 for (; c; c = OMP_CLAUSE_CHAIN (c))
13480 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13482 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13483 integer_type_node,
13484 OMP_CLAUSE_WAIT_EXPR (c)));
13485 num_waits++;
13488 if (!tagging || num_waits)
13490 tree len;
13492 /* Now that we know the number, update the placeholder. */
13493 if (tagging)
13494 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13495 else
13496 len = build_int_cst (integer_type_node, num_waits);
13497 len = fold_convert_loc (gimple_location (entry_stmt),
13498 unsigned_type_node, len);
13499 args[t_wait_idx] = len;
13502 break;
13503 default:
13504 gcc_unreachable ();
13506 if (tagging)
13507 /* Push terminal marker - zero. */
13508 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13510 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13511 gimple_set_location (g, gimple_location (entry_stmt));
13512 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13513 if (!offloaded)
13515 g = gsi_stmt (gsi);
13516 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13517 gsi_remove (&gsi, true);
13519 if (data_region && region->exit)
13521 gsi = gsi_last_bb (region->exit);
13522 g = gsi_stmt (gsi);
13523 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13524 gsi_remove (&gsi, true);
13528 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13529 variable derived from the thread number. */
13531 static void
13532 grid_expand_omp_for_loop (struct omp_region *kfor)
13534 tree t, threadid;
13535 tree type, itype;
13536 gimple_stmt_iterator gsi;
13537 tree n1, step;
13538 struct omp_for_data fd;
13540 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13541 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13542 == GF_OMP_FOR_KIND_GRID_LOOP);
13543 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13545 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13546 gcc_assert (kfor->cont);
13547 extract_omp_for_data (for_stmt, &fd, NULL);
13549 itype = type = TREE_TYPE (fd.loop.v);
13550 if (POINTER_TYPE_P (type))
13551 itype = signed_type_for (type);
13553 gsi = gsi_start_bb (body_bb);
13555 n1 = fd.loop.n1;
13556 step = fd.loop.step;
13557 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13558 true, NULL_TREE, true, GSI_SAME_STMT);
13559 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13560 true, NULL_TREE, true, GSI_SAME_STMT);
13561 threadid = build_call_expr (builtin_decl_explicit
13562 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13563 threadid = fold_convert (itype, threadid);
13564 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13565 true, GSI_SAME_STMT);
13567 tree startvar = fd.loop.v;
13568 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13569 if (POINTER_TYPE_P (type))
13570 t = fold_build_pointer_plus (n1, t);
13571 else
13572 t = fold_build2 (PLUS_EXPR, type, t, n1);
13573 t = fold_convert (type, t);
13574 t = force_gimple_operand_gsi (&gsi, t,
13575 DECL_P (startvar)
13576 && TREE_ADDRESSABLE (startvar),
13577 NULL_TREE, true, GSI_SAME_STMT);
13578 gassign *assign_stmt = gimple_build_assign (startvar, t);
13579 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13581 /* Remove the omp for statement */
13582 gsi = gsi_last_bb (kfor->entry);
13583 gsi_remove (&gsi, true);
13585 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13586 gsi = gsi_last_bb (kfor->cont);
13587 gcc_assert (!gsi_end_p (gsi)
13588 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13589 gsi_remove (&gsi, true);
13591 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13592 gsi = gsi_last_bb (kfor->exit);
13593 gcc_assert (!gsi_end_p (gsi)
13594 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13595 gsi_remove (&gsi, true);
13597 /* Fixup the much simpler CFG. */
13598 remove_edge (find_edge (kfor->cont, body_bb));
13600 if (kfor->cont != body_bb)
13601 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13602 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13605 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13606 argument_decls. */
13608 struct grid_arg_decl_map
13610 tree old_arg;
13611 tree new_arg;
13614 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13615 pertaining to kernel function. */
13617 static tree
13618 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13620 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13621 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13622 tree t = *tp;
13624 if (t == adm->old_arg)
13625 *tp = adm->new_arg;
13626 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13627 return NULL_TREE;
13630 static void expand_omp (struct omp_region *region);
13632 /* If TARGET region contains a kernel body for loop, remove its region from the
13633 TARGET and expand it in GPGPU kernel fashion. */
13635 static void
13636 grid_expand_target_grid_body (struct omp_region *target)
13638 if (!hsa_gen_requested_p ())
13639 return;
13641 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13642 struct omp_region **pp;
13644 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13645 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13646 break;
13648 struct omp_region *gpukernel = *pp;
13650 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13651 if (!gpukernel)
13653 /* HSA cannot handle OACC stuff. */
13654 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13655 return;
13656 gcc_checking_assert (orig_child_fndecl);
13657 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13658 OMP_CLAUSE__GRIDDIM_));
13659 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13661 hsa_register_kernel (n);
13662 return;
13665 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13666 OMP_CLAUSE__GRIDDIM_));
13667 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13668 *pp = gpukernel->next;
13669 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13670 if ((*pp)->type == GIMPLE_OMP_FOR)
13671 break;
13673 struct omp_region *kfor = *pp;
13674 gcc_assert (kfor);
13675 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13676 == GF_OMP_FOR_KIND_GRID_LOOP);
13677 *pp = kfor->next;
13678 if (kfor->inner)
13679 expand_omp (kfor->inner);
13680 if (gpukernel->inner)
13681 expand_omp (gpukernel->inner);
13683 tree kern_fndecl = copy_node (orig_child_fndecl);
13684 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13685 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13686 tree tgtblock = gimple_block (tgt_stmt);
13687 tree fniniblock = make_node (BLOCK);
13688 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13689 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13690 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13691 BLOCK_SUPERCONTEXT (fniniblock) = kern_fndecl;
13692 DECL_INITIAL (kern_fndecl) = fniniblock;
13693 push_struct_function (kern_fndecl);
13694 cfun->function_end_locus = gimple_location (tgt_stmt);
13695 init_tree_ssa (cfun);
13696 pop_cfun ();
13698 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13699 gcc_assert (!DECL_CHAIN (old_parm_decl));
13700 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13701 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13702 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13703 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13704 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13705 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13706 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13707 kern_cfun->curr_properties = cfun->curr_properties;
13709 remove_edge (BRANCH_EDGE (kfor->entry));
13710 grid_expand_omp_for_loop (kfor);
13712 /* Remove the omp for statement */
13713 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13714 gsi_remove (&gsi, true);
13715 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13716 return. */
13717 gsi = gsi_last_bb (gpukernel->exit);
13718 gcc_assert (!gsi_end_p (gsi)
13719 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13720 gimple *ret_stmt = gimple_build_return (NULL);
13721 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13722 gsi_remove (&gsi, true);
13724 /* Statements in the first BB in the target construct have been produced by
13725 target lowering and must be copied inside the GPUKERNEL, with the two
13726 exceptions of the first OMP statement and the OMP_DATA assignment
13727 statement. */
13728 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13729 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13730 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13731 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13732 !gsi_end_p (tsi); gsi_next (&tsi))
13734 gimple *stmt = gsi_stmt (tsi);
13735 if (is_gimple_omp (stmt))
13736 break;
13737 if (sender
13738 && is_gimple_assign (stmt)
13739 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13740 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13741 continue;
13742 gimple *copy = gimple_copy (stmt);
13743 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13744 gimple_set_block (copy, fniniblock);
13747 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13748 gpukernel->exit, inside_block);
13750 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13751 kcn->mark_force_output ();
13752 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13754 hsa_register_kernel (kcn, orig_child);
13756 cgraph_node::add_new_function (kern_fndecl, true);
13757 push_cfun (kern_cfun);
13758 cgraph_edge::rebuild_edges ();
13760 /* Re-map any mention of the PARM_DECL of the original function to the
13761 PARM_DECL of the new one.
13763 TODO: It would be great if lowering produced references into the GPU
13764 kernel decl straight away and we did not have to do this. */
13765 struct grid_arg_decl_map adm;
13766 adm.old_arg = old_parm_decl;
13767 adm.new_arg = new_parm_decl;
13768 basic_block bb;
13769 FOR_EACH_BB_FN (bb, kern_cfun)
13771 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13773 gimple *stmt = gsi_stmt (gsi);
13774 struct walk_stmt_info wi;
13775 memset (&wi, 0, sizeof (wi));
13776 wi.info = &adm;
13777 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13780 pop_cfun ();
13782 return;
13785 /* Expand the parallel region tree rooted at REGION. Expansion
13786 proceeds in depth-first order. Innermost regions are expanded
13787 first. This way, parallel regions that require a new function to
13788 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13789 internal dependencies in their body. */
13791 static void
13792 expand_omp (struct omp_region *region)
13794 omp_any_child_fn_dumped = false;
13795 while (region)
13797 location_t saved_location;
13798 gimple *inner_stmt = NULL;
13800 /* First, determine whether this is a combined parallel+workshare
13801 region. */
13802 if (region->type == GIMPLE_OMP_PARALLEL)
13803 determine_parallel_type (region);
13804 else if (region->type == GIMPLE_OMP_TARGET)
13805 grid_expand_target_grid_body (region);
13807 if (region->type == GIMPLE_OMP_FOR
13808 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13809 inner_stmt = last_stmt (region->inner->entry);
13811 if (region->inner)
13812 expand_omp (region->inner);
13814 saved_location = input_location;
13815 if (gimple_has_location (last_stmt (region->entry)))
13816 input_location = gimple_location (last_stmt (region->entry));
13818 switch (region->type)
13820 case GIMPLE_OMP_PARALLEL:
13821 case GIMPLE_OMP_TASK:
13822 expand_omp_taskreg (region);
13823 break;
13825 case GIMPLE_OMP_FOR:
13826 expand_omp_for (region, inner_stmt);
13827 break;
13829 case GIMPLE_OMP_SECTIONS:
13830 expand_omp_sections (region);
13831 break;
13833 case GIMPLE_OMP_SECTION:
13834 /* Individual omp sections are handled together with their
13835 parent GIMPLE_OMP_SECTIONS region. */
13836 break;
13838 case GIMPLE_OMP_SINGLE:
13839 expand_omp_single (region);
13840 break;
13842 case GIMPLE_OMP_ORDERED:
13844 gomp_ordered *ord_stmt
13845 = as_a <gomp_ordered *> (last_stmt (region->entry));
13846 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13847 OMP_CLAUSE_DEPEND))
13849 /* We'll expand these when expanding corresponding
13850 worksharing region with ordered(n) clause. */
13851 gcc_assert (region->outer
13852 && region->outer->type == GIMPLE_OMP_FOR);
13853 region->ord_stmt = ord_stmt;
13854 break;
13857 /* FALLTHRU */
13858 case GIMPLE_OMP_MASTER:
13859 case GIMPLE_OMP_TASKGROUP:
13860 case GIMPLE_OMP_CRITICAL:
13861 case GIMPLE_OMP_TEAMS:
13862 expand_omp_synch (region);
13863 break;
13865 case GIMPLE_OMP_ATOMIC_LOAD:
13866 expand_omp_atomic (region);
13867 break;
13869 case GIMPLE_OMP_TARGET:
13870 expand_omp_target (region);
13871 break;
13873 default:
13874 gcc_unreachable ();
13877 input_location = saved_location;
13878 region = region->next;
13880 if (omp_any_child_fn_dumped)
13882 if (dump_file)
13883 dump_function_header (dump_file, current_function_decl, dump_flags);
13884 omp_any_child_fn_dumped = false;
13889 /* Helper for build_omp_regions. Scan the dominator tree starting at
13890 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13891 true, the function ends once a single tree is built (otherwise, whole
13892 forest of OMP constructs may be built). */
13894 static void
13895 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13896 bool single_tree)
13898 gimple_stmt_iterator gsi;
13899 gimple *stmt;
13900 basic_block son;
13902 gsi = gsi_last_bb (bb);
13903 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13905 struct omp_region *region;
13906 enum gimple_code code;
13908 stmt = gsi_stmt (gsi);
13909 code = gimple_code (stmt);
13910 if (code == GIMPLE_OMP_RETURN)
13912 /* STMT is the return point out of region PARENT. Mark it
13913 as the exit point and make PARENT the immediately
13914 enclosing region. */
13915 gcc_assert (parent);
13916 region = parent;
13917 region->exit = bb;
13918 parent = parent->outer;
13920 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13922 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13923 GIMPLE_OMP_RETURN, but matches with
13924 GIMPLE_OMP_ATOMIC_LOAD. */
13925 gcc_assert (parent);
13926 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13927 region = parent;
13928 region->exit = bb;
13929 parent = parent->outer;
13931 else if (code == GIMPLE_OMP_CONTINUE)
13933 gcc_assert (parent);
13934 parent->cont = bb;
13936 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13938 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13939 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13941 else
13943 region = new_omp_region (bb, code, parent);
13944 /* Otherwise... */
13945 if (code == GIMPLE_OMP_TARGET)
13947 switch (gimple_omp_target_kind (stmt))
13949 case GF_OMP_TARGET_KIND_REGION:
13950 case GF_OMP_TARGET_KIND_DATA:
13951 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13952 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13953 case GF_OMP_TARGET_KIND_OACC_DATA:
13954 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13955 break;
13956 case GF_OMP_TARGET_KIND_UPDATE:
13957 case GF_OMP_TARGET_KIND_ENTER_DATA:
13958 case GF_OMP_TARGET_KIND_EXIT_DATA:
13959 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13960 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13961 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13962 /* ..., other than for those stand-alone directives... */
13963 region = NULL;
13964 break;
13965 default:
13966 gcc_unreachable ();
13969 else if (code == GIMPLE_OMP_ORDERED
13970 && find_omp_clause (gimple_omp_ordered_clauses
13971 (as_a <gomp_ordered *> (stmt)),
13972 OMP_CLAUSE_DEPEND))
13973 /* #pragma omp ordered depend is also just a stand-alone
13974 directive. */
13975 region = NULL;
13976 /* ..., this directive becomes the parent for a new region. */
13977 if (region)
13978 parent = region;
13982 if (single_tree && !parent)
13983 return;
13985 for (son = first_dom_son (CDI_DOMINATORS, bb);
13986 son;
13987 son = next_dom_son (CDI_DOMINATORS, son))
13988 build_omp_regions_1 (son, parent, single_tree);
13991 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13992 root_omp_region. */
13994 static void
13995 build_omp_regions_root (basic_block root)
13997 gcc_assert (root_omp_region == NULL);
13998 build_omp_regions_1 (root, NULL, true);
13999 gcc_assert (root_omp_region != NULL);
14002 /* Expands omp construct (and its subconstructs) starting in HEAD. */
14004 void
14005 omp_expand_local (basic_block head)
14007 build_omp_regions_root (head);
14008 if (dump_file && (dump_flags & TDF_DETAILS))
14010 fprintf (dump_file, "\nOMP region tree\n\n");
14011 dump_omp_region (dump_file, root_omp_region, 0);
14012 fprintf (dump_file, "\n");
14015 remove_exit_barriers (root_omp_region);
14016 expand_omp (root_omp_region);
14018 free_omp_regions ();
14021 /* Scan the CFG and build a tree of OMP regions. Return the root of
14022 the OMP region tree. */
14024 static void
14025 build_omp_regions (void)
14027 gcc_assert (root_omp_region == NULL);
14028 calculate_dominance_info (CDI_DOMINATORS);
14029 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14032 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14034 static unsigned int
14035 execute_expand_omp (void)
14037 build_omp_regions ();
14039 if (!root_omp_region)
14040 return 0;
14042 if (dump_file)
14044 fprintf (dump_file, "\nOMP region tree\n\n");
14045 dump_omp_region (dump_file, root_omp_region, 0);
14046 fprintf (dump_file, "\n");
14049 remove_exit_barriers (root_omp_region);
14051 expand_omp (root_omp_region);
14053 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14054 verify_loop_structure ();
14055 cleanup_tree_cfg ();
14057 free_omp_regions ();
14059 return 0;
14062 /* OMP expansion -- the default pass, run before creation of SSA form. */
14064 namespace {
14066 const pass_data pass_data_expand_omp =
14068 GIMPLE_PASS, /* type */
14069 "ompexp", /* name */
14070 OPTGROUP_NONE, /* optinfo_flags */
14071 TV_NONE, /* tv_id */
14072 PROP_gimple_any, /* properties_required */
14073 PROP_gimple_eomp, /* properties_provided */
14074 0, /* properties_destroyed */
14075 0, /* todo_flags_start */
14076 0, /* todo_flags_finish */
14079 class pass_expand_omp : public gimple_opt_pass
14081 public:
14082 pass_expand_omp (gcc::context *ctxt)
14083 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14086 /* opt_pass methods: */
14087 virtual unsigned int execute (function *)
14089 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14090 || flag_openmp_simd != 0)
14091 && !seen_error ());
14093 /* This pass always runs, to provide PROP_gimple_eomp.
14094 But often, there is nothing to do. */
14095 if (!gate)
14096 return 0;
14098 return execute_expand_omp ();
14101 }; // class pass_expand_omp
14103 } // anon namespace
14105 gimple_opt_pass *
14106 make_pass_expand_omp (gcc::context *ctxt)
14108 return new pass_expand_omp (ctxt);
14111 namespace {
14113 const pass_data pass_data_expand_omp_ssa =
14115 GIMPLE_PASS, /* type */
14116 "ompexpssa", /* name */
14117 OPTGROUP_NONE, /* optinfo_flags */
14118 TV_NONE, /* tv_id */
14119 PROP_cfg | PROP_ssa, /* properties_required */
14120 PROP_gimple_eomp, /* properties_provided */
14121 0, /* properties_destroyed */
14122 0, /* todo_flags_start */
14123 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14126 class pass_expand_omp_ssa : public gimple_opt_pass
14128 public:
14129 pass_expand_omp_ssa (gcc::context *ctxt)
14130 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14133 /* opt_pass methods: */
14134 virtual bool gate (function *fun)
14136 return !(fun->curr_properties & PROP_gimple_eomp);
14138 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14139 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14141 }; // class pass_expand_omp_ssa
14143 } // anon namespace
14145 gimple_opt_pass *
14146 make_pass_expand_omp_ssa (gcc::context *ctxt)
14148 return new pass_expand_omp_ssa (ctxt);
14151 /* Routines to lower OMP directives into OMP-GIMPLE. */
14153 /* If ctx is a worksharing context inside of a cancellable parallel
14154 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14155 and conditional branch to parallel's cancel_label to handle
14156 cancellation in the implicit barrier. */
14158 static void
14159 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14161 gimple *omp_return = gimple_seq_last_stmt (*body);
14162 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14163 if (gimple_omp_return_nowait_p (omp_return))
14164 return;
14165 if (ctx->outer
14166 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14167 && ctx->outer->cancellable)
14169 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14170 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14171 tree lhs = create_tmp_var (c_bool_type);
14172 gimple_omp_return_set_lhs (omp_return, lhs);
14173 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14174 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14175 fold_convert (c_bool_type,
14176 boolean_false_node),
14177 ctx->outer->cancel_label, fallthru_label);
14178 gimple_seq_add_stmt (body, g);
14179 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14183 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14184 CTX is the enclosing OMP context for the current statement. */
14186 static void
14187 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14189 tree block, control;
14190 gimple_stmt_iterator tgsi;
14191 gomp_sections *stmt;
14192 gimple *t;
14193 gbind *new_stmt, *bind;
14194 gimple_seq ilist, dlist, olist, new_body;
14196 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14198 push_gimplify_context ();
14200 dlist = NULL;
14201 ilist = NULL;
14202 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14203 &ilist, &dlist, ctx, NULL);
14205 new_body = gimple_omp_body (stmt);
14206 gimple_omp_set_body (stmt, NULL);
14207 tgsi = gsi_start (new_body);
14208 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14210 omp_context *sctx;
14211 gimple *sec_start;
14213 sec_start = gsi_stmt (tgsi);
14214 sctx = maybe_lookup_ctx (sec_start);
14215 gcc_assert (sctx);
14217 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14218 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14219 GSI_CONTINUE_LINKING);
14220 gimple_omp_set_body (sec_start, NULL);
14222 if (gsi_one_before_end_p (tgsi))
14224 gimple_seq l = NULL;
14225 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14226 &l, ctx);
14227 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14228 gimple_omp_section_set_last (sec_start);
14231 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14232 GSI_CONTINUE_LINKING);
14235 block = make_node (BLOCK);
14236 bind = gimple_build_bind (NULL, new_body, block);
14238 olist = NULL;
14239 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14241 block = make_node (BLOCK);
14242 new_stmt = gimple_build_bind (NULL, NULL, block);
14243 gsi_replace (gsi_p, new_stmt, true);
14245 pop_gimplify_context (new_stmt);
14246 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14247 BLOCK_VARS (block) = gimple_bind_vars (bind);
14248 if (BLOCK_VARS (block))
14249 TREE_USED (block) = 1;
14251 new_body = NULL;
14252 gimple_seq_add_seq (&new_body, ilist);
14253 gimple_seq_add_stmt (&new_body, stmt);
14254 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14255 gimple_seq_add_stmt (&new_body, bind);
14257 control = create_tmp_var (unsigned_type_node, ".section");
14258 t = gimple_build_omp_continue (control, control);
14259 gimple_omp_sections_set_control (stmt, control);
14260 gimple_seq_add_stmt (&new_body, t);
14262 gimple_seq_add_seq (&new_body, olist);
14263 if (ctx->cancellable)
14264 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14265 gimple_seq_add_seq (&new_body, dlist);
14267 new_body = maybe_catch_exception (new_body);
14269 t = gimple_build_omp_return
14270 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14271 OMP_CLAUSE_NOWAIT));
14272 gimple_seq_add_stmt (&new_body, t);
14273 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14275 gimple_bind_set_body (new_stmt, new_body);
14279 /* A subroutine of lower_omp_single. Expand the simple form of
14280 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14282 if (GOMP_single_start ())
14283 BODY;
14284 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14286 FIXME. It may be better to delay expanding the logic of this until
14287 pass_expand_omp. The expanded logic may make the job more difficult
14288 to a synchronization analysis pass. */
14290 static void
14291 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14293 location_t loc = gimple_location (single_stmt);
14294 tree tlabel = create_artificial_label (loc);
14295 tree flabel = create_artificial_label (loc);
14296 gimple *call, *cond;
14297 tree lhs, decl;
14299 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14300 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14301 call = gimple_build_call (decl, 0);
14302 gimple_call_set_lhs (call, lhs);
14303 gimple_seq_add_stmt (pre_p, call);
14305 cond = gimple_build_cond (EQ_EXPR, lhs,
14306 fold_convert_loc (loc, TREE_TYPE (lhs),
14307 boolean_true_node),
14308 tlabel, flabel);
14309 gimple_seq_add_stmt (pre_p, cond);
14310 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14311 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14312 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14316 /* A subroutine of lower_omp_single. Expand the simple form of
14317 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14319 #pragma omp single copyprivate (a, b, c)
14321 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14324 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14326 BODY;
14327 copyout.a = a;
14328 copyout.b = b;
14329 copyout.c = c;
14330 GOMP_single_copy_end (&copyout);
14332 else
14334 a = copyout_p->a;
14335 b = copyout_p->b;
14336 c = copyout_p->c;
14338 GOMP_barrier ();
14341 FIXME. It may be better to delay expanding the logic of this until
14342 pass_expand_omp. The expanded logic may make the job more difficult
14343 to a synchronization analysis pass. */
14345 static void
14346 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14347 omp_context *ctx)
14349 tree ptr_type, t, l0, l1, l2, bfn_decl;
14350 gimple_seq copyin_seq;
14351 location_t loc = gimple_location (single_stmt);
14353 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14355 ptr_type = build_pointer_type (ctx->record_type);
14356 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14358 l0 = create_artificial_label (loc);
14359 l1 = create_artificial_label (loc);
14360 l2 = create_artificial_label (loc);
14362 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14363 t = build_call_expr_loc (loc, bfn_decl, 0);
14364 t = fold_convert_loc (loc, ptr_type, t);
14365 gimplify_assign (ctx->receiver_decl, t, pre_p);
14367 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14368 build_int_cst (ptr_type, 0));
14369 t = build3 (COND_EXPR, void_type_node, t,
14370 build_and_jump (&l0), build_and_jump (&l1));
14371 gimplify_and_add (t, pre_p);
14373 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14375 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14377 copyin_seq = NULL;
14378 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14379 &copyin_seq, ctx);
14381 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14382 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14383 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14384 gimplify_and_add (t, pre_p);
14386 t = build_and_jump (&l2);
14387 gimplify_and_add (t, pre_p);
14389 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14391 gimple_seq_add_seq (pre_p, copyin_seq);
14393 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14397 /* Expand code for an OpenMP single directive. */
14399 static void
14400 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14402 tree block;
14403 gimple *t;
14404 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14405 gbind *bind;
14406 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14408 push_gimplify_context ();
14410 block = make_node (BLOCK);
14411 bind = gimple_build_bind (NULL, NULL, block);
14412 gsi_replace (gsi_p, bind, true);
14413 bind_body = NULL;
14414 dlist = NULL;
14415 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14416 &bind_body, &dlist, ctx, NULL);
14417 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14419 gimple_seq_add_stmt (&bind_body, single_stmt);
14421 if (ctx->record_type)
14422 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14423 else
14424 lower_omp_single_simple (single_stmt, &bind_body);
14426 gimple_omp_set_body (single_stmt, NULL);
14428 gimple_seq_add_seq (&bind_body, dlist);
14430 bind_body = maybe_catch_exception (bind_body);
14432 t = gimple_build_omp_return
14433 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14434 OMP_CLAUSE_NOWAIT));
14435 gimple_seq_add_stmt (&bind_body_tail, t);
14436 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14437 if (ctx->record_type)
14439 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14440 tree clobber = build_constructor (ctx->record_type, NULL);
14441 TREE_THIS_VOLATILE (clobber) = 1;
14442 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14443 clobber), GSI_SAME_STMT);
14445 gimple_seq_add_seq (&bind_body, bind_body_tail);
14446 gimple_bind_set_body (bind, bind_body);
14448 pop_gimplify_context (bind);
14450 gimple_bind_append_vars (bind, ctx->block_vars);
14451 BLOCK_VARS (block) = ctx->block_vars;
14452 if (BLOCK_VARS (block))
14453 TREE_USED (block) = 1;
14457 /* Expand code for an OpenMP master directive. */
14459 static void
14460 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14462 tree block, lab = NULL, x, bfn_decl;
14463 gimple *stmt = gsi_stmt (*gsi_p);
14464 gbind *bind;
14465 location_t loc = gimple_location (stmt);
14466 gimple_seq tseq;
14468 push_gimplify_context ();
14470 block = make_node (BLOCK);
14471 bind = gimple_build_bind (NULL, NULL, block);
14472 gsi_replace (gsi_p, bind, true);
14473 gimple_bind_add_stmt (bind, stmt);
14475 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14476 x = build_call_expr_loc (loc, bfn_decl, 0);
14477 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14478 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14479 tseq = NULL;
14480 gimplify_and_add (x, &tseq);
14481 gimple_bind_add_seq (bind, tseq);
14483 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14484 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14485 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14486 gimple_omp_set_body (stmt, NULL);
14488 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14490 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14492 pop_gimplify_context (bind);
14494 gimple_bind_append_vars (bind, ctx->block_vars);
14495 BLOCK_VARS (block) = ctx->block_vars;
14499 /* Expand code for an OpenMP taskgroup directive. */
14501 static void
14502 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14504 gimple *stmt = gsi_stmt (*gsi_p);
14505 gcall *x;
14506 gbind *bind;
14507 tree block = make_node (BLOCK);
14509 bind = gimple_build_bind (NULL, NULL, block);
14510 gsi_replace (gsi_p, bind, true);
14511 gimple_bind_add_stmt (bind, stmt);
14513 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14515 gimple_bind_add_stmt (bind, x);
14517 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14518 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14519 gimple_omp_set_body (stmt, NULL);
14521 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14523 gimple_bind_append_vars (bind, ctx->block_vars);
14524 BLOCK_VARS (block) = ctx->block_vars;
14528 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14530 static void
14531 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14532 omp_context *ctx)
14534 struct omp_for_data fd;
14535 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14536 return;
14538 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14539 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14540 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14541 if (!fd.ordered)
14542 return;
14544 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14545 tree c = gimple_omp_ordered_clauses (ord_stmt);
14546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14547 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14549 /* Merge depend clauses from multiple adjacent
14550 #pragma omp ordered depend(sink:...) constructs
14551 into one #pragma omp ordered depend(sink:...), so that
14552 we can optimize them together. */
14553 gimple_stmt_iterator gsi = *gsi_p;
14554 gsi_next (&gsi);
14555 while (!gsi_end_p (gsi))
14557 gimple *stmt = gsi_stmt (gsi);
14558 if (is_gimple_debug (stmt)
14559 || gimple_code (stmt) == GIMPLE_NOP)
14561 gsi_next (&gsi);
14562 continue;
14564 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14565 break;
14566 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14567 c = gimple_omp_ordered_clauses (ord_stmt2);
14568 if (c == NULL_TREE
14569 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14570 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14571 break;
14572 while (*list_p)
14573 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14574 *list_p = c;
14575 gsi_remove (&gsi, true);
14579 /* Canonicalize sink dependence clauses into one folded clause if
14580 possible.
14582 The basic algorithm is to create a sink vector whose first
14583 element is the GCD of all the first elements, and whose remaining
14584 elements are the minimum of the subsequent columns.
14586 We ignore dependence vectors whose first element is zero because
14587 such dependencies are known to be executed by the same thread.
14589 We take into account the direction of the loop, so a minimum
14590 becomes a maximum if the loop is iterating forwards. We also
14591 ignore sink clauses where the loop direction is unknown, or where
14592 the offsets are clearly invalid because they are not a multiple
14593 of the loop increment.
14595 For example:
14597 #pragma omp for ordered(2)
14598 for (i=0; i < N; ++i)
14599 for (j=0; j < M; ++j)
14601 #pragma omp ordered \
14602 depend(sink:i-8,j-2) \
14603 depend(sink:i,j-1) \ // Completely ignored because i+0.
14604 depend(sink:i-4,j-3) \
14605 depend(sink:i-6,j-4)
14606 #pragma omp ordered depend(source)
14609 Folded clause is:
14611 depend(sink:-gcd(8,4,6),-min(2,3,4))
14612 -or-
14613 depend(sink:-2,-2)
14616 /* FIXME: Computing GCD's where the first element is zero is
14617 non-trivial in the presence of collapsed loops. Do this later. */
14618 if (fd.collapse > 1)
14619 return;
14621 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14622 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14623 tree folded_dep = NULL_TREE;
14624 /* TRUE if the first dimension's offset is negative. */
14625 bool neg_offset_p = false;
14627 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14628 unsigned int i;
14629 while ((c = *list_p) != NULL)
14631 bool remove = false;
14633 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14634 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14635 goto next_ordered_clause;
14637 tree vec;
14638 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14639 vec && TREE_CODE (vec) == TREE_LIST;
14640 vec = TREE_CHAIN (vec), ++i)
14642 gcc_assert (i < len);
14644 /* extract_omp_for_data has canonicalized the condition. */
14645 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14646 || fd.loops[i].cond_code == GT_EXPR);
14647 bool forward = fd.loops[i].cond_code == LT_EXPR;
14648 bool maybe_lexically_later = true;
14650 /* While the committee makes up its mind, bail if we have any
14651 non-constant steps. */
14652 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14653 goto lower_omp_ordered_ret;
14655 tree itype = TREE_TYPE (TREE_VALUE (vec));
14656 if (POINTER_TYPE_P (itype))
14657 itype = sizetype;
14658 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14659 TYPE_PRECISION (itype),
14660 TYPE_SIGN (itype));
14662 /* Ignore invalid offsets that are not multiples of the step. */
14663 if (!wi::multiple_of_p
14664 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14665 UNSIGNED))
14667 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14668 "ignoring sink clause with offset that is not "
14669 "a multiple of the loop step");
14670 remove = true;
14671 goto next_ordered_clause;
14674 /* Calculate the first dimension. The first dimension of
14675 the folded dependency vector is the GCD of the first
14676 elements, while ignoring any first elements whose offset
14677 is 0. */
14678 if (i == 0)
14680 /* Ignore dependence vectors whose first dimension is 0. */
14681 if (offset == 0)
14683 remove = true;
14684 goto next_ordered_clause;
14686 else
14688 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14690 error_at (OMP_CLAUSE_LOCATION (c),
14691 "first offset must be in opposite direction "
14692 "of loop iterations");
14693 goto lower_omp_ordered_ret;
14695 if (forward)
14696 offset = -offset;
14697 neg_offset_p = forward;
14698 /* Initialize the first time around. */
14699 if (folded_dep == NULL_TREE)
14701 folded_dep = c;
14702 folded_deps[0] = offset;
14704 else
14705 folded_deps[0] = wi::gcd (folded_deps[0],
14706 offset, UNSIGNED);
14709 /* Calculate minimum for the remaining dimensions. */
14710 else
14712 folded_deps[len + i - 1] = offset;
14713 if (folded_dep == c)
14714 folded_deps[i] = offset;
14715 else if (maybe_lexically_later
14716 && !wi::eq_p (folded_deps[i], offset))
14718 if (forward ^ wi::gts_p (folded_deps[i], offset))
14720 unsigned int j;
14721 folded_dep = c;
14722 for (j = 1; j <= i; j++)
14723 folded_deps[j] = folded_deps[len + j - 1];
14725 else
14726 maybe_lexically_later = false;
14730 gcc_assert (i == len);
14732 remove = true;
14734 next_ordered_clause:
14735 if (remove)
14736 *list_p = OMP_CLAUSE_CHAIN (c);
14737 else
14738 list_p = &OMP_CLAUSE_CHAIN (c);
14741 if (folded_dep)
14743 if (neg_offset_p)
14744 folded_deps[0] = -folded_deps[0];
14746 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14747 if (POINTER_TYPE_P (itype))
14748 itype = sizetype;
14750 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14751 = wide_int_to_tree (itype, folded_deps[0]);
14752 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14753 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14756 lower_omp_ordered_ret:
14758 /* Ordered without clauses is #pragma omp threads, while we want
14759 a nop instead if we remove all clauses. */
14760 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14761 gsi_replace (gsi_p, gimple_build_nop (), true);
14765 /* Expand code for an OpenMP ordered directive. */
14767 static void
14768 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14770 tree block;
14771 gimple *stmt = gsi_stmt (*gsi_p);
14772 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14773 gcall *x;
14774 gbind *bind;
14775 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14776 OMP_CLAUSE_SIMD);
14777 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14778 OMP_CLAUSE_THREADS);
14780 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14781 OMP_CLAUSE_DEPEND))
14783 /* FIXME: This is needs to be moved to the expansion to verify various
14784 conditions only testable on cfg with dominators computed, and also
14785 all the depend clauses to be merged still might need to be available
14786 for the runtime checks. */
14787 if (0)
14788 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14789 return;
14792 push_gimplify_context ();
14794 block = make_node (BLOCK);
14795 bind = gimple_build_bind (NULL, NULL, block);
14796 gsi_replace (gsi_p, bind, true);
14797 gimple_bind_add_stmt (bind, stmt);
14799 if (simd)
14801 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14802 build_int_cst (NULL_TREE, threads));
14803 cfun->has_simduid_loops = true;
14805 else
14806 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14808 gimple_bind_add_stmt (bind, x);
14810 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14811 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14812 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14813 gimple_omp_set_body (stmt, NULL);
14815 if (simd)
14816 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14817 build_int_cst (NULL_TREE, threads));
14818 else
14819 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14821 gimple_bind_add_stmt (bind, x);
14823 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14825 pop_gimplify_context (bind);
14827 gimple_bind_append_vars (bind, ctx->block_vars);
14828 BLOCK_VARS (block) = gimple_bind_vars (bind);
14832 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14833 substitution of a couple of function calls. But in the NAMED case,
14834 requires that languages coordinate a symbol name. It is therefore
14835 best put here in common code. */
14837 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14839 static void
14840 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14842 tree block;
14843 tree name, lock, unlock;
14844 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14845 gbind *bind;
14846 location_t loc = gimple_location (stmt);
14847 gimple_seq tbody;
14849 name = gimple_omp_critical_name (stmt);
14850 if (name)
14852 tree decl;
14854 if (!critical_name_mutexes)
14855 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14857 tree *n = critical_name_mutexes->get (name);
14858 if (n == NULL)
14860 char *new_str;
14862 decl = create_tmp_var_raw (ptr_type_node);
14864 new_str = ACONCAT ((".gomp_critical_user_",
14865 IDENTIFIER_POINTER (name), NULL));
14866 DECL_NAME (decl) = get_identifier (new_str);
14867 TREE_PUBLIC (decl) = 1;
14868 TREE_STATIC (decl) = 1;
14869 DECL_COMMON (decl) = 1;
14870 DECL_ARTIFICIAL (decl) = 1;
14871 DECL_IGNORED_P (decl) = 1;
14873 varpool_node::finalize_decl (decl);
14875 critical_name_mutexes->put (name, decl);
14877 else
14878 decl = *n;
14880 /* If '#pragma omp critical' is inside offloaded region or
14881 inside function marked as offloadable, the symbol must be
14882 marked as offloadable too. */
14883 omp_context *octx;
14884 if (cgraph_node::get (current_function_decl)->offloadable)
14885 varpool_node::get_create (decl)->offloadable = 1;
14886 else
14887 for (octx = ctx->outer; octx; octx = octx->outer)
14888 if (is_gimple_omp_offloaded (octx->stmt))
14890 varpool_node::get_create (decl)->offloadable = 1;
14891 break;
14894 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14895 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14897 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14898 unlock = build_call_expr_loc (loc, unlock, 1,
14899 build_fold_addr_expr_loc (loc, decl));
14901 else
14903 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14904 lock = build_call_expr_loc (loc, lock, 0);
14906 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14907 unlock = build_call_expr_loc (loc, unlock, 0);
14910 push_gimplify_context ();
14912 block = make_node (BLOCK);
14913 bind = gimple_build_bind (NULL, NULL, block);
14914 gsi_replace (gsi_p, bind, true);
14915 gimple_bind_add_stmt (bind, stmt);
14917 tbody = gimple_bind_body (bind);
14918 gimplify_and_add (lock, &tbody);
14919 gimple_bind_set_body (bind, tbody);
14921 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14922 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14923 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14924 gimple_omp_set_body (stmt, NULL);
14926 tbody = gimple_bind_body (bind);
14927 gimplify_and_add (unlock, &tbody);
14928 gimple_bind_set_body (bind, tbody);
14930 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14932 pop_gimplify_context (bind);
14933 gimple_bind_append_vars (bind, ctx->block_vars);
14934 BLOCK_VARS (block) = gimple_bind_vars (bind);
14938 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14939 for a lastprivate clause. Given a loop control predicate of (V
14940 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14941 is appended to *DLIST, iterator initialization is appended to
14942 *BODY_P. */
14944 static void
14945 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14946 gimple_seq *dlist, struct omp_context *ctx)
14948 tree clauses, cond, vinit;
14949 enum tree_code cond_code;
14950 gimple_seq stmts;
14952 cond_code = fd->loop.cond_code;
14953 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14955 /* When possible, use a strict equality expression. This can let VRP
14956 type optimizations deduce the value and remove a copy. */
14957 if (tree_fits_shwi_p (fd->loop.step))
14959 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14960 if (step == 1 || step == -1)
14961 cond_code = EQ_EXPR;
14964 tree n2 = fd->loop.n2;
14965 if (fd->collapse > 1
14966 && TREE_CODE (n2) != INTEGER_CST
14967 && gimple_omp_for_combined_into_p (fd->for_stmt))
14969 struct omp_context *taskreg_ctx = NULL;
14970 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14972 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14973 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14974 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14976 if (gimple_omp_for_combined_into_p (gfor))
14978 gcc_assert (ctx->outer->outer
14979 && is_parallel_ctx (ctx->outer->outer));
14980 taskreg_ctx = ctx->outer->outer;
14982 else
14984 struct omp_for_data outer_fd;
14985 extract_omp_for_data (gfor, &outer_fd, NULL);
14986 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14989 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14990 taskreg_ctx = ctx->outer->outer;
14992 else if (is_taskreg_ctx (ctx->outer))
14993 taskreg_ctx = ctx->outer;
14994 if (taskreg_ctx)
14996 int i;
14997 tree innerc
14998 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14999 OMP_CLAUSE__LOOPTEMP_);
15000 gcc_assert (innerc);
15001 for (i = 0; i < fd->collapse; i++)
15003 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15004 OMP_CLAUSE__LOOPTEMP_);
15005 gcc_assert (innerc);
15007 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15008 OMP_CLAUSE__LOOPTEMP_);
15009 if (innerc)
15010 n2 = fold_convert (TREE_TYPE (n2),
15011 lookup_decl (OMP_CLAUSE_DECL (innerc),
15012 taskreg_ctx));
15015 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
15017 clauses = gimple_omp_for_clauses (fd->for_stmt);
15018 stmts = NULL;
15019 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15020 if (!gimple_seq_empty_p (stmts))
15022 gimple_seq_add_seq (&stmts, *dlist);
15023 *dlist = stmts;
15025 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15026 vinit = fd->loop.n1;
15027 if (cond_code == EQ_EXPR
15028 && tree_fits_shwi_p (fd->loop.n2)
15029 && ! integer_zerop (fd->loop.n2))
15030 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15031 else
15032 vinit = unshare_expr (vinit);
15034 /* Initialize the iterator variable, so that threads that don't execute
15035 any iterations don't execute the lastprivate clauses by accident. */
15036 gimplify_assign (fd->loop.v, vinit, body_p);
15041 /* Lower code for an OMP loop directive. */
15043 static void
15044 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15046 tree *rhs_p, block;
15047 struct omp_for_data fd, *fdp = NULL;
15048 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15049 gbind *new_stmt;
15050 gimple_seq omp_for_body, body, dlist;
15051 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15052 size_t i;
15054 push_gimplify_context ();
15056 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15058 block = make_node (BLOCK);
15059 new_stmt = gimple_build_bind (NULL, NULL, block);
15060 /* Replace at gsi right away, so that 'stmt' is no member
15061 of a sequence anymore as we're going to add to a different
15062 one below. */
15063 gsi_replace (gsi_p, new_stmt, true);
15065 /* Move declaration of temporaries in the loop body before we make
15066 it go away. */
15067 omp_for_body = gimple_omp_body (stmt);
15068 if (!gimple_seq_empty_p (omp_for_body)
15069 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15071 gbind *inner_bind
15072 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15073 tree vars = gimple_bind_vars (inner_bind);
15074 gimple_bind_append_vars (new_stmt, vars);
15075 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15076 keep them on the inner_bind and it's block. */
15077 gimple_bind_set_vars (inner_bind, NULL_TREE);
15078 if (gimple_bind_block (inner_bind))
15079 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15082 if (gimple_omp_for_combined_into_p (stmt))
15084 extract_omp_for_data (stmt, &fd, NULL);
15085 fdp = &fd;
15087 /* We need two temporaries with fd.loop.v type (istart/iend)
15088 and then (fd.collapse - 1) temporaries with the same
15089 type for count2 ... countN-1 vars if not constant. */
15090 size_t count = 2;
15091 tree type = fd.iter_type;
15092 if (fd.collapse > 1
15093 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15094 count += fd.collapse - 1;
15095 bool taskreg_for
15096 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15097 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15098 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15099 tree clauses = *pc;
15100 if (taskreg_for)
15101 outerc
15102 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15103 OMP_CLAUSE__LOOPTEMP_);
15104 for (i = 0; i < count; i++)
15106 tree temp;
15107 if (taskreg_for)
15109 gcc_assert (outerc);
15110 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15111 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15112 OMP_CLAUSE__LOOPTEMP_);
15114 else
15116 temp = create_tmp_var (type);
15117 insert_decl_map (&ctx->outer->cb, temp, temp);
15119 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15120 OMP_CLAUSE_DECL (*pc) = temp;
15121 pc = &OMP_CLAUSE_CHAIN (*pc);
15123 *pc = clauses;
15126 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15127 dlist = NULL;
15128 body = NULL;
15129 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15130 fdp);
15131 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15133 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15135 /* Lower the header expressions. At this point, we can assume that
15136 the header is of the form:
15138 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15140 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15141 using the .omp_data_s mapping, if needed. */
15142 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15144 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15145 if (!is_gimple_min_invariant (*rhs_p))
15146 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15148 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15149 if (!is_gimple_min_invariant (*rhs_p))
15150 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15152 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15153 if (!is_gimple_min_invariant (*rhs_p))
15154 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15157 /* Once lowered, extract the bounds and clauses. */
15158 extract_omp_for_data (stmt, &fd, NULL);
15160 if (is_gimple_omp_oacc (ctx->stmt)
15161 && !ctx_in_oacc_kernels_region (ctx))
15162 lower_oacc_head_tail (gimple_location (stmt),
15163 gimple_omp_for_clauses (stmt),
15164 &oacc_head, &oacc_tail, ctx);
15166 /* Add OpenACC partitioning and reduction markers just before the loop */
15167 if (oacc_head)
15168 gimple_seq_add_seq (&body, oacc_head);
15170 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15172 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15173 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15174 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15175 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15177 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15178 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15179 OMP_CLAUSE_LINEAR_STEP (c)
15180 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15181 ctx);
15184 if (!gimple_omp_for_grid_phony (stmt))
15185 gimple_seq_add_stmt (&body, stmt);
15186 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15188 if (!gimple_omp_for_grid_phony (stmt))
15189 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15190 fd.loop.v));
15192 /* After the loop, add exit clauses. */
15193 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15195 if (ctx->cancellable)
15196 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15198 gimple_seq_add_seq (&body, dlist);
15200 body = maybe_catch_exception (body);
15202 if (!gimple_omp_for_grid_phony (stmt))
15204 /* Region exit marker goes at the end of the loop body. */
15205 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15206 maybe_add_implicit_barrier_cancel (ctx, &body);
15209 /* Add OpenACC joining and reduction markers just after the loop. */
15210 if (oacc_tail)
15211 gimple_seq_add_seq (&body, oacc_tail);
15213 pop_gimplify_context (new_stmt);
15215 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15216 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15217 if (BLOCK_VARS (block))
15218 TREE_USED (block) = 1;
15220 gimple_bind_set_body (new_stmt, body);
15221 gimple_omp_set_body (stmt, NULL);
15222 gimple_omp_for_set_pre_body (stmt, NULL);
15225 /* Callback for walk_stmts. Check if the current statement only contains
15226 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15228 static tree
15229 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15230 bool *handled_ops_p,
15231 struct walk_stmt_info *wi)
15233 int *info = (int *) wi->info;
15234 gimple *stmt = gsi_stmt (*gsi_p);
15236 *handled_ops_p = true;
15237 switch (gimple_code (stmt))
15239 WALK_SUBSTMTS;
15241 case GIMPLE_OMP_FOR:
15242 case GIMPLE_OMP_SECTIONS:
15243 *info = *info == 0 ? 1 : -1;
15244 break;
15245 default:
15246 *info = -1;
15247 break;
15249 return NULL;
15252 struct omp_taskcopy_context
15254 /* This field must be at the beginning, as we do "inheritance": Some
15255 callback functions for tree-inline.c (e.g., omp_copy_decl)
15256 receive a copy_body_data pointer that is up-casted to an
15257 omp_context pointer. */
15258 copy_body_data cb;
15259 omp_context *ctx;
15262 static tree
15263 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15265 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15267 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15268 return create_tmp_var (TREE_TYPE (var));
15270 return var;
15273 static tree
15274 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15276 tree name, new_fields = NULL, type, f;
15278 type = lang_hooks.types.make_type (RECORD_TYPE);
15279 name = DECL_NAME (TYPE_NAME (orig_type));
15280 name = build_decl (gimple_location (tcctx->ctx->stmt),
15281 TYPE_DECL, name, type);
15282 TYPE_NAME (type) = name;
15284 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15286 tree new_f = copy_node (f);
15287 DECL_CONTEXT (new_f) = type;
15288 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15289 TREE_CHAIN (new_f) = new_fields;
15290 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15291 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15292 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15293 &tcctx->cb, NULL);
15294 new_fields = new_f;
15295 tcctx->cb.decl_map->put (f, new_f);
15297 TYPE_FIELDS (type) = nreverse (new_fields);
15298 layout_type (type);
15299 return type;
15302 /* Create task copyfn. */
15304 static void
15305 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15307 struct function *child_cfun;
15308 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15309 tree record_type, srecord_type, bind, list;
15310 bool record_needs_remap = false, srecord_needs_remap = false;
15311 splay_tree_node n;
15312 struct omp_taskcopy_context tcctx;
15313 location_t loc = gimple_location (task_stmt);
15315 child_fn = gimple_omp_task_copy_fn (task_stmt);
15316 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15317 gcc_assert (child_cfun->cfg == NULL);
15318 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15320 /* Reset DECL_CONTEXT on function arguments. */
15321 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15322 DECL_CONTEXT (t) = child_fn;
15324 /* Populate the function. */
15325 push_gimplify_context ();
15326 push_cfun (child_cfun);
15328 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15329 TREE_SIDE_EFFECTS (bind) = 1;
15330 list = NULL;
15331 DECL_SAVED_TREE (child_fn) = bind;
15332 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15334 /* Remap src and dst argument types if needed. */
15335 record_type = ctx->record_type;
15336 srecord_type = ctx->srecord_type;
15337 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15338 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15340 record_needs_remap = true;
15341 break;
15343 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15344 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15346 srecord_needs_remap = true;
15347 break;
15350 if (record_needs_remap || srecord_needs_remap)
15352 memset (&tcctx, '\0', sizeof (tcctx));
15353 tcctx.cb.src_fn = ctx->cb.src_fn;
15354 tcctx.cb.dst_fn = child_fn;
15355 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15356 gcc_checking_assert (tcctx.cb.src_node);
15357 tcctx.cb.dst_node = tcctx.cb.src_node;
15358 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15359 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15360 tcctx.cb.eh_lp_nr = 0;
15361 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15362 tcctx.cb.decl_map = new hash_map<tree, tree>;
15363 tcctx.ctx = ctx;
15365 if (record_needs_remap)
15366 record_type = task_copyfn_remap_type (&tcctx, record_type);
15367 if (srecord_needs_remap)
15368 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15370 else
15371 tcctx.cb.decl_map = NULL;
15373 arg = DECL_ARGUMENTS (child_fn);
15374 TREE_TYPE (arg) = build_pointer_type (record_type);
15375 sarg = DECL_CHAIN (arg);
15376 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15378 /* First pass: initialize temporaries used in record_type and srecord_type
15379 sizes and field offsets. */
15380 if (tcctx.cb.decl_map)
15381 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15384 tree *p;
15386 decl = OMP_CLAUSE_DECL (c);
15387 p = tcctx.cb.decl_map->get (decl);
15388 if (p == NULL)
15389 continue;
15390 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15391 sf = (tree) n->value;
15392 sf = *tcctx.cb.decl_map->get (sf);
15393 src = build_simple_mem_ref_loc (loc, sarg);
15394 src = omp_build_component_ref (src, sf);
15395 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15396 append_to_statement_list (t, &list);
15399 /* Second pass: copy shared var pointers and copy construct non-VLA
15400 firstprivate vars. */
15401 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15402 switch (OMP_CLAUSE_CODE (c))
15404 splay_tree_key key;
15405 case OMP_CLAUSE_SHARED:
15406 decl = OMP_CLAUSE_DECL (c);
15407 key = (splay_tree_key) decl;
15408 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15409 key = (splay_tree_key) &DECL_UID (decl);
15410 n = splay_tree_lookup (ctx->field_map, key);
15411 if (n == NULL)
15412 break;
15413 f = (tree) n->value;
15414 if (tcctx.cb.decl_map)
15415 f = *tcctx.cb.decl_map->get (f);
15416 n = splay_tree_lookup (ctx->sfield_map, key);
15417 sf = (tree) n->value;
15418 if (tcctx.cb.decl_map)
15419 sf = *tcctx.cb.decl_map->get (sf);
15420 src = build_simple_mem_ref_loc (loc, sarg);
15421 src = omp_build_component_ref (src, sf);
15422 dst = build_simple_mem_ref_loc (loc, arg);
15423 dst = omp_build_component_ref (dst, f);
15424 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15425 append_to_statement_list (t, &list);
15426 break;
15427 case OMP_CLAUSE_FIRSTPRIVATE:
15428 decl = OMP_CLAUSE_DECL (c);
15429 if (is_variable_sized (decl))
15430 break;
15431 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15432 if (n == NULL)
15433 break;
15434 f = (tree) n->value;
15435 if (tcctx.cb.decl_map)
15436 f = *tcctx.cb.decl_map->get (f);
15437 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15438 if (n != NULL)
15440 sf = (tree) n->value;
15441 if (tcctx.cb.decl_map)
15442 sf = *tcctx.cb.decl_map->get (sf);
15443 src = build_simple_mem_ref_loc (loc, sarg);
15444 src = omp_build_component_ref (src, sf);
15445 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15446 src = build_simple_mem_ref_loc (loc, src);
15448 else
15449 src = decl;
15450 dst = build_simple_mem_ref_loc (loc, arg);
15451 dst = omp_build_component_ref (dst, f);
15452 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15453 append_to_statement_list (t, &list);
15454 break;
15455 case OMP_CLAUSE_PRIVATE:
15456 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15457 break;
15458 decl = OMP_CLAUSE_DECL (c);
15459 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15460 f = (tree) n->value;
15461 if (tcctx.cb.decl_map)
15462 f = *tcctx.cb.decl_map->get (f);
15463 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15464 if (n != NULL)
15466 sf = (tree) n->value;
15467 if (tcctx.cb.decl_map)
15468 sf = *tcctx.cb.decl_map->get (sf);
15469 src = build_simple_mem_ref_loc (loc, sarg);
15470 src = omp_build_component_ref (src, sf);
15471 if (use_pointer_for_field (decl, NULL))
15472 src = build_simple_mem_ref_loc (loc, src);
15474 else
15475 src = decl;
15476 dst = build_simple_mem_ref_loc (loc, arg);
15477 dst = omp_build_component_ref (dst, f);
15478 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15479 append_to_statement_list (t, &list);
15480 break;
15481 default:
15482 break;
15485 /* Last pass: handle VLA firstprivates. */
15486 if (tcctx.cb.decl_map)
15487 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15488 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15490 tree ind, ptr, df;
15492 decl = OMP_CLAUSE_DECL (c);
15493 if (!is_variable_sized (decl))
15494 continue;
15495 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15496 if (n == NULL)
15497 continue;
15498 f = (tree) n->value;
15499 f = *tcctx.cb.decl_map->get (f);
15500 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15501 ind = DECL_VALUE_EXPR (decl);
15502 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15503 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15504 n = splay_tree_lookup (ctx->sfield_map,
15505 (splay_tree_key) TREE_OPERAND (ind, 0));
15506 sf = (tree) n->value;
15507 sf = *tcctx.cb.decl_map->get (sf);
15508 src = build_simple_mem_ref_loc (loc, sarg);
15509 src = omp_build_component_ref (src, sf);
15510 src = build_simple_mem_ref_loc (loc, src);
15511 dst = build_simple_mem_ref_loc (loc, arg);
15512 dst = omp_build_component_ref (dst, f);
15513 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15514 append_to_statement_list (t, &list);
15515 n = splay_tree_lookup (ctx->field_map,
15516 (splay_tree_key) TREE_OPERAND (ind, 0));
15517 df = (tree) n->value;
15518 df = *tcctx.cb.decl_map->get (df);
15519 ptr = build_simple_mem_ref_loc (loc, arg);
15520 ptr = omp_build_component_ref (ptr, df);
15521 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15522 build_fold_addr_expr_loc (loc, dst));
15523 append_to_statement_list (t, &list);
15526 t = build1 (RETURN_EXPR, void_type_node, NULL);
15527 append_to_statement_list (t, &list);
15529 if (tcctx.cb.decl_map)
15530 delete tcctx.cb.decl_map;
15531 pop_gimplify_context (NULL);
15532 BIND_EXPR_BODY (bind) = list;
15533 pop_cfun ();
15536 static void
15537 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15539 tree c, clauses;
15540 gimple *g;
15541 size_t n_in = 0, n_out = 0, idx = 2, i;
15543 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15544 gcc_assert (clauses);
15545 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15547 switch (OMP_CLAUSE_DEPEND_KIND (c))
15549 case OMP_CLAUSE_DEPEND_IN:
15550 n_in++;
15551 break;
15552 case OMP_CLAUSE_DEPEND_OUT:
15553 case OMP_CLAUSE_DEPEND_INOUT:
15554 n_out++;
15555 break;
15556 case OMP_CLAUSE_DEPEND_SOURCE:
15557 case OMP_CLAUSE_DEPEND_SINK:
15558 /* FALLTHRU */
15559 default:
15560 gcc_unreachable ();
15562 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15563 tree array = create_tmp_var (type);
15564 TREE_ADDRESSABLE (array) = 1;
15565 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15566 NULL_TREE);
15567 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15568 gimple_seq_add_stmt (iseq, g);
15569 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15570 NULL_TREE);
15571 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15572 gimple_seq_add_stmt (iseq, g);
15573 for (i = 0; i < 2; i++)
15575 if ((i ? n_in : n_out) == 0)
15576 continue;
15577 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15578 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15579 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15581 tree t = OMP_CLAUSE_DECL (c);
15582 t = fold_convert (ptr_type_node, t);
15583 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15584 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15585 NULL_TREE, NULL_TREE);
15586 g = gimple_build_assign (r, t);
15587 gimple_seq_add_stmt (iseq, g);
15590 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15591 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15592 OMP_CLAUSE_CHAIN (c) = *pclauses;
15593 *pclauses = c;
15594 tree clobber = build_constructor (type, NULL);
15595 TREE_THIS_VOLATILE (clobber) = 1;
15596 g = gimple_build_assign (array, clobber);
15597 gimple_seq_add_stmt (oseq, g);
15600 /* Lower the OpenMP parallel or task directive in the current statement
15601 in GSI_P. CTX holds context information for the directive. */
15603 static void
15604 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15606 tree clauses;
15607 tree child_fn, t;
15608 gimple *stmt = gsi_stmt (*gsi_p);
15609 gbind *par_bind, *bind, *dep_bind = NULL;
15610 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15611 location_t loc = gimple_location (stmt);
15613 clauses = gimple_omp_taskreg_clauses (stmt);
15614 par_bind
15615 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15616 par_body = gimple_bind_body (par_bind);
15617 child_fn = ctx->cb.dst_fn;
15618 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15619 && !gimple_omp_parallel_combined_p (stmt))
15621 struct walk_stmt_info wi;
15622 int ws_num = 0;
15624 memset (&wi, 0, sizeof (wi));
15625 wi.info = &ws_num;
15626 wi.val_only = true;
15627 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15628 if (ws_num == 1)
15629 gimple_omp_parallel_set_combined_p (stmt, true);
15631 gimple_seq dep_ilist = NULL;
15632 gimple_seq dep_olist = NULL;
15633 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15634 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15636 push_gimplify_context ();
15637 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15638 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15639 &dep_ilist, &dep_olist);
15642 if (ctx->srecord_type)
15643 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15645 push_gimplify_context ();
15647 par_olist = NULL;
15648 par_ilist = NULL;
15649 par_rlist = NULL;
15650 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15651 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15652 if (phony_construct && ctx->record_type)
15654 gcc_checking_assert (!ctx->receiver_decl);
15655 ctx->receiver_decl = create_tmp_var
15656 (build_reference_type (ctx->record_type), ".omp_rec");
15658 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15659 lower_omp (&par_body, ctx);
15660 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15661 lower_reduction_clauses (clauses, &par_rlist, ctx);
15663 /* Declare all the variables created by mapping and the variables
15664 declared in the scope of the parallel body. */
15665 record_vars_into (ctx->block_vars, child_fn);
15666 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15668 if (ctx->record_type)
15670 ctx->sender_decl
15671 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15672 : ctx->record_type, ".omp_data_o");
15673 DECL_NAMELESS (ctx->sender_decl) = 1;
15674 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15675 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15678 olist = NULL;
15679 ilist = NULL;
15680 lower_send_clauses (clauses, &ilist, &olist, ctx);
15681 lower_send_shared_vars (&ilist, &olist, ctx);
15683 if (ctx->record_type)
15685 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15686 TREE_THIS_VOLATILE (clobber) = 1;
15687 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15688 clobber));
15691 /* Once all the expansions are done, sequence all the different
15692 fragments inside gimple_omp_body. */
15694 new_body = NULL;
15696 if (ctx->record_type)
15698 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15699 /* fixup_child_record_type might have changed receiver_decl's type. */
15700 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15701 gimple_seq_add_stmt (&new_body,
15702 gimple_build_assign (ctx->receiver_decl, t));
15705 gimple_seq_add_seq (&new_body, par_ilist);
15706 gimple_seq_add_seq (&new_body, par_body);
15707 gimple_seq_add_seq (&new_body, par_rlist);
15708 if (ctx->cancellable)
15709 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15710 gimple_seq_add_seq (&new_body, par_olist);
15711 new_body = maybe_catch_exception (new_body);
15712 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15713 gimple_seq_add_stmt (&new_body,
15714 gimple_build_omp_continue (integer_zero_node,
15715 integer_zero_node));
15716 if (!phony_construct)
15718 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15719 gimple_omp_set_body (stmt, new_body);
15722 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15723 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15724 gimple_bind_add_seq (bind, ilist);
15725 if (!phony_construct)
15726 gimple_bind_add_stmt (bind, stmt);
15727 else
15728 gimple_bind_add_seq (bind, new_body);
15729 gimple_bind_add_seq (bind, olist);
15731 pop_gimplify_context (NULL);
15733 if (dep_bind)
15735 gimple_bind_add_seq (dep_bind, dep_ilist);
15736 gimple_bind_add_stmt (dep_bind, bind);
15737 gimple_bind_add_seq (dep_bind, dep_olist);
15738 pop_gimplify_context (dep_bind);
15742 /* Lower the GIMPLE_OMP_TARGET in the current statement
15743 in GSI_P. CTX holds context information for the directive. */
15745 static void
15746 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15748 tree clauses;
15749 tree child_fn, t, c;
15750 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15751 gbind *tgt_bind, *bind, *dep_bind = NULL;
15752 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15753 location_t loc = gimple_location (stmt);
15754 bool offloaded, data_region;
15755 unsigned int map_cnt = 0;
15757 offloaded = is_gimple_omp_offloaded (stmt);
15758 switch (gimple_omp_target_kind (stmt))
15760 case GF_OMP_TARGET_KIND_REGION:
15761 case GF_OMP_TARGET_KIND_UPDATE:
15762 case GF_OMP_TARGET_KIND_ENTER_DATA:
15763 case GF_OMP_TARGET_KIND_EXIT_DATA:
15764 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15765 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15766 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15767 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15768 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15769 data_region = false;
15770 break;
15771 case GF_OMP_TARGET_KIND_DATA:
15772 case GF_OMP_TARGET_KIND_OACC_DATA:
15773 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15774 data_region = true;
15775 break;
15776 default:
15777 gcc_unreachable ();
15780 clauses = gimple_omp_target_clauses (stmt);
15782 gimple_seq dep_ilist = NULL;
15783 gimple_seq dep_olist = NULL;
15784 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15786 push_gimplify_context ();
15787 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15788 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15789 &dep_ilist, &dep_olist);
15792 tgt_bind = NULL;
15793 tgt_body = NULL;
15794 if (offloaded)
15796 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15797 tgt_body = gimple_bind_body (tgt_bind);
15799 else if (data_region)
15800 tgt_body = gimple_omp_body (stmt);
15801 child_fn = ctx->cb.dst_fn;
15803 push_gimplify_context ();
15804 fplist = NULL;
15806 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15807 switch (OMP_CLAUSE_CODE (c))
15809 tree var, x;
15811 default:
15812 break;
15813 case OMP_CLAUSE_MAP:
15814 #if CHECKING_P
15815 /* First check what we're prepared to handle in the following. */
15816 switch (OMP_CLAUSE_MAP_KIND (c))
15818 case GOMP_MAP_ALLOC:
15819 case GOMP_MAP_TO:
15820 case GOMP_MAP_FROM:
15821 case GOMP_MAP_TOFROM:
15822 case GOMP_MAP_POINTER:
15823 case GOMP_MAP_TO_PSET:
15824 case GOMP_MAP_DELETE:
15825 case GOMP_MAP_RELEASE:
15826 case GOMP_MAP_ALWAYS_TO:
15827 case GOMP_MAP_ALWAYS_FROM:
15828 case GOMP_MAP_ALWAYS_TOFROM:
15829 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15830 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15831 case GOMP_MAP_STRUCT:
15832 case GOMP_MAP_ALWAYS_POINTER:
15833 break;
15834 case GOMP_MAP_FORCE_ALLOC:
15835 case GOMP_MAP_FORCE_TO:
15836 case GOMP_MAP_FORCE_FROM:
15837 case GOMP_MAP_FORCE_TOFROM:
15838 case GOMP_MAP_FORCE_PRESENT:
15839 case GOMP_MAP_FORCE_DEVICEPTR:
15840 case GOMP_MAP_DEVICE_RESIDENT:
15841 case GOMP_MAP_LINK:
15842 gcc_assert (is_gimple_omp_oacc (stmt));
15843 break;
15844 default:
15845 gcc_unreachable ();
15847 #endif
15848 /* FALLTHRU */
15849 case OMP_CLAUSE_TO:
15850 case OMP_CLAUSE_FROM:
15851 oacc_firstprivate:
15852 var = OMP_CLAUSE_DECL (c);
15853 if (!DECL_P (var))
15855 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15856 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15857 && (OMP_CLAUSE_MAP_KIND (c)
15858 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15859 map_cnt++;
15860 continue;
15863 if (DECL_SIZE (var)
15864 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15866 tree var2 = DECL_VALUE_EXPR (var);
15867 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15868 var2 = TREE_OPERAND (var2, 0);
15869 gcc_assert (DECL_P (var2));
15870 var = var2;
15873 if (offloaded
15874 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15875 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15876 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15878 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15880 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15881 && varpool_node::get_create (var)->offloadable)
15882 continue;
15884 tree type = build_pointer_type (TREE_TYPE (var));
15885 tree new_var = lookup_decl (var, ctx);
15886 x = create_tmp_var_raw (type, get_name (new_var));
15887 gimple_add_tmp_var (x);
15888 x = build_simple_mem_ref (x);
15889 SET_DECL_VALUE_EXPR (new_var, x);
15890 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15892 continue;
15895 if (!maybe_lookup_field (var, ctx))
15896 continue;
15898 /* Don't remap oacc parallel reduction variables, because the
15899 intermediate result must be local to each gang. */
15900 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15901 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15903 x = build_receiver_ref (var, true, ctx);
15904 tree new_var = lookup_decl (var, ctx);
15906 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15907 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15908 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15909 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15910 x = build_simple_mem_ref (x);
15911 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15913 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15914 if (is_reference (new_var))
15916 /* Create a local object to hold the instance
15917 value. */
15918 tree type = TREE_TYPE (TREE_TYPE (new_var));
15919 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15920 tree inst = create_tmp_var (type, id);
15921 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15922 x = build_fold_addr_expr (inst);
15924 gimplify_assign (new_var, x, &fplist);
15926 else if (DECL_P (new_var))
15928 SET_DECL_VALUE_EXPR (new_var, x);
15929 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15931 else
15932 gcc_unreachable ();
15934 map_cnt++;
15935 break;
15937 case OMP_CLAUSE_FIRSTPRIVATE:
15938 if (is_oacc_parallel (ctx))
15939 goto oacc_firstprivate;
15940 map_cnt++;
15941 var = OMP_CLAUSE_DECL (c);
15942 if (!is_reference (var)
15943 && !is_gimple_reg_type (TREE_TYPE (var)))
15945 tree new_var = lookup_decl (var, ctx);
15946 if (is_variable_sized (var))
15948 tree pvar = DECL_VALUE_EXPR (var);
15949 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15950 pvar = TREE_OPERAND (pvar, 0);
15951 gcc_assert (DECL_P (pvar));
15952 tree new_pvar = lookup_decl (pvar, ctx);
15953 x = build_fold_indirect_ref (new_pvar);
15954 TREE_THIS_NOTRAP (x) = 1;
15956 else
15957 x = build_receiver_ref (var, true, ctx);
15958 SET_DECL_VALUE_EXPR (new_var, x);
15959 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15961 break;
15963 case OMP_CLAUSE_PRIVATE:
15964 if (is_gimple_omp_oacc (ctx->stmt))
15965 break;
15966 var = OMP_CLAUSE_DECL (c);
15967 if (is_variable_sized (var))
15969 tree new_var = lookup_decl (var, ctx);
15970 tree pvar = DECL_VALUE_EXPR (var);
15971 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15972 pvar = TREE_OPERAND (pvar, 0);
15973 gcc_assert (DECL_P (pvar));
15974 tree new_pvar = lookup_decl (pvar, ctx);
15975 x = build_fold_indirect_ref (new_pvar);
15976 TREE_THIS_NOTRAP (x) = 1;
15977 SET_DECL_VALUE_EXPR (new_var, x);
15978 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15980 break;
15982 case OMP_CLAUSE_USE_DEVICE_PTR:
15983 case OMP_CLAUSE_IS_DEVICE_PTR:
15984 var = OMP_CLAUSE_DECL (c);
15985 map_cnt++;
15986 if (is_variable_sized (var))
15988 tree new_var = lookup_decl (var, ctx);
15989 tree pvar = DECL_VALUE_EXPR (var);
15990 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15991 pvar = TREE_OPERAND (pvar, 0);
15992 gcc_assert (DECL_P (pvar));
15993 tree new_pvar = lookup_decl (pvar, ctx);
15994 x = build_fold_indirect_ref (new_pvar);
15995 TREE_THIS_NOTRAP (x) = 1;
15996 SET_DECL_VALUE_EXPR (new_var, x);
15997 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15999 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16001 tree new_var = lookup_decl (var, ctx);
16002 tree type = build_pointer_type (TREE_TYPE (var));
16003 x = create_tmp_var_raw (type, get_name (new_var));
16004 gimple_add_tmp_var (x);
16005 x = build_simple_mem_ref (x);
16006 SET_DECL_VALUE_EXPR (new_var, x);
16007 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16009 else
16011 tree new_var = lookup_decl (var, ctx);
16012 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
16013 gimple_add_tmp_var (x);
16014 SET_DECL_VALUE_EXPR (new_var, x);
16015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16017 break;
16020 if (offloaded)
16022 target_nesting_level++;
16023 lower_omp (&tgt_body, ctx);
16024 target_nesting_level--;
16026 else if (data_region)
16027 lower_omp (&tgt_body, ctx);
16029 if (offloaded)
16031 /* Declare all the variables created by mapping and the variables
16032 declared in the scope of the target body. */
16033 record_vars_into (ctx->block_vars, child_fn);
16034 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16037 olist = NULL;
16038 ilist = NULL;
16039 if (ctx->record_type)
16041 ctx->sender_decl
16042 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16043 DECL_NAMELESS (ctx->sender_decl) = 1;
16044 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16045 t = make_tree_vec (3);
16046 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16047 TREE_VEC_ELT (t, 1)
16048 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16049 ".omp_data_sizes");
16050 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16051 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16052 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16053 tree tkind_type = short_unsigned_type_node;
16054 int talign_shift = 8;
16055 TREE_VEC_ELT (t, 2)
16056 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16057 ".omp_data_kinds");
16058 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16059 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16060 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16061 gimple_omp_target_set_data_arg (stmt, t);
16063 vec<constructor_elt, va_gc> *vsize;
16064 vec<constructor_elt, va_gc> *vkind;
16065 vec_alloc (vsize, map_cnt);
16066 vec_alloc (vkind, map_cnt);
16067 unsigned int map_idx = 0;
16069 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16070 switch (OMP_CLAUSE_CODE (c))
16072 tree ovar, nc, s, purpose, var, x, type;
16073 unsigned int talign;
16075 default:
16076 break;
16078 case OMP_CLAUSE_MAP:
16079 case OMP_CLAUSE_TO:
16080 case OMP_CLAUSE_FROM:
16081 oacc_firstprivate_map:
16082 nc = c;
16083 ovar = OMP_CLAUSE_DECL (c);
16084 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16085 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16086 || (OMP_CLAUSE_MAP_KIND (c)
16087 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16088 break;
16089 if (!DECL_P (ovar))
16091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16092 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16094 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16095 == get_base_address (ovar));
16096 nc = OMP_CLAUSE_CHAIN (c);
16097 ovar = OMP_CLAUSE_DECL (nc);
16099 else
16101 tree x = build_sender_ref (ovar, ctx);
16102 tree v
16103 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16104 gimplify_assign (x, v, &ilist);
16105 nc = NULL_TREE;
16108 else
16110 if (DECL_SIZE (ovar)
16111 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16113 tree ovar2 = DECL_VALUE_EXPR (ovar);
16114 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16115 ovar2 = TREE_OPERAND (ovar2, 0);
16116 gcc_assert (DECL_P (ovar2));
16117 ovar = ovar2;
16119 if (!maybe_lookup_field (ovar, ctx))
16120 continue;
16123 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16124 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16125 talign = DECL_ALIGN_UNIT (ovar);
16126 if (nc)
16128 var = lookup_decl_in_outer_ctx (ovar, ctx);
16129 x = build_sender_ref (ovar, ctx);
16131 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16132 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16133 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16134 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16136 gcc_assert (offloaded);
16137 tree avar
16138 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16139 mark_addressable (avar);
16140 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16141 talign = DECL_ALIGN_UNIT (avar);
16142 avar = build_fold_addr_expr (avar);
16143 gimplify_assign (x, avar, &ilist);
16145 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16147 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16148 if (!is_reference (var))
16150 if (is_gimple_reg (var)
16151 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16152 TREE_NO_WARNING (var) = 1;
16153 var = build_fold_addr_expr (var);
16155 else
16156 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16157 gimplify_assign (x, var, &ilist);
16159 else if (is_gimple_reg (var))
16161 gcc_assert (offloaded);
16162 tree avar = create_tmp_var (TREE_TYPE (var));
16163 mark_addressable (avar);
16164 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16165 if (GOMP_MAP_COPY_TO_P (map_kind)
16166 || map_kind == GOMP_MAP_POINTER
16167 || map_kind == GOMP_MAP_TO_PSET
16168 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16170 /* If we need to initialize a temporary
16171 with VAR because it is not addressable, and
16172 the variable hasn't been initialized yet, then
16173 we'll get a warning for the store to avar.
16174 Don't warn in that case, the mapping might
16175 be implicit. */
16176 TREE_NO_WARNING (var) = 1;
16177 gimplify_assign (avar, var, &ilist);
16179 avar = build_fold_addr_expr (avar);
16180 gimplify_assign (x, avar, &ilist);
16181 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16182 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16183 && !TYPE_READONLY (TREE_TYPE (var)))
16185 x = unshare_expr (x);
16186 x = build_simple_mem_ref (x);
16187 gimplify_assign (var, x, &olist);
16190 else
16192 var = build_fold_addr_expr (var);
16193 gimplify_assign (x, var, &ilist);
16196 s = NULL_TREE;
16197 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16199 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16200 s = TREE_TYPE (ovar);
16201 if (TREE_CODE (s) == REFERENCE_TYPE)
16202 s = TREE_TYPE (s);
16203 s = TYPE_SIZE_UNIT (s);
16205 else
16206 s = OMP_CLAUSE_SIZE (c);
16207 if (s == NULL_TREE)
16208 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16209 s = fold_convert (size_type_node, s);
16210 purpose = size_int (map_idx++);
16211 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16212 if (TREE_CODE (s) != INTEGER_CST)
16213 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16215 unsigned HOST_WIDE_INT tkind, tkind_zero;
16216 switch (OMP_CLAUSE_CODE (c))
16218 case OMP_CLAUSE_MAP:
16219 tkind = OMP_CLAUSE_MAP_KIND (c);
16220 tkind_zero = tkind;
16221 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16222 switch (tkind)
16224 case GOMP_MAP_ALLOC:
16225 case GOMP_MAP_TO:
16226 case GOMP_MAP_FROM:
16227 case GOMP_MAP_TOFROM:
16228 case GOMP_MAP_ALWAYS_TO:
16229 case GOMP_MAP_ALWAYS_FROM:
16230 case GOMP_MAP_ALWAYS_TOFROM:
16231 case GOMP_MAP_RELEASE:
16232 case GOMP_MAP_FORCE_TO:
16233 case GOMP_MAP_FORCE_FROM:
16234 case GOMP_MAP_FORCE_TOFROM:
16235 case GOMP_MAP_FORCE_PRESENT:
16236 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16237 break;
16238 case GOMP_MAP_DELETE:
16239 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16240 default:
16241 break;
16243 if (tkind_zero != tkind)
16245 if (integer_zerop (s))
16246 tkind = tkind_zero;
16247 else if (integer_nonzerop (s))
16248 tkind_zero = tkind;
16250 break;
16251 case OMP_CLAUSE_FIRSTPRIVATE:
16252 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16253 tkind = GOMP_MAP_TO;
16254 tkind_zero = tkind;
16255 break;
16256 case OMP_CLAUSE_TO:
16257 tkind = GOMP_MAP_TO;
16258 tkind_zero = tkind;
16259 break;
16260 case OMP_CLAUSE_FROM:
16261 tkind = GOMP_MAP_FROM;
16262 tkind_zero = tkind;
16263 break;
16264 default:
16265 gcc_unreachable ();
16267 gcc_checking_assert (tkind
16268 < (HOST_WIDE_INT_C (1U) << talign_shift));
16269 gcc_checking_assert (tkind_zero
16270 < (HOST_WIDE_INT_C (1U) << talign_shift));
16271 talign = ceil_log2 (talign);
16272 tkind |= talign << talign_shift;
16273 tkind_zero |= talign << talign_shift;
16274 gcc_checking_assert (tkind
16275 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16276 gcc_checking_assert (tkind_zero
16277 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16278 if (tkind == tkind_zero)
16279 x = build_int_cstu (tkind_type, tkind);
16280 else
16282 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16283 x = build3 (COND_EXPR, tkind_type,
16284 fold_build2 (EQ_EXPR, boolean_type_node,
16285 unshare_expr (s), size_zero_node),
16286 build_int_cstu (tkind_type, tkind_zero),
16287 build_int_cstu (tkind_type, tkind));
16289 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16290 if (nc && nc != c)
16291 c = nc;
16292 break;
16294 case OMP_CLAUSE_FIRSTPRIVATE:
16295 if (is_oacc_parallel (ctx))
16296 goto oacc_firstprivate_map;
16297 ovar = OMP_CLAUSE_DECL (c);
16298 if (is_reference (ovar))
16299 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16300 else
16301 talign = DECL_ALIGN_UNIT (ovar);
16302 var = lookup_decl_in_outer_ctx (ovar, ctx);
16303 x = build_sender_ref (ovar, ctx);
16304 tkind = GOMP_MAP_FIRSTPRIVATE;
16305 type = TREE_TYPE (ovar);
16306 if (is_reference (ovar))
16307 type = TREE_TYPE (type);
16308 if ((INTEGRAL_TYPE_P (type)
16309 && TYPE_PRECISION (type) <= POINTER_SIZE)
16310 || TREE_CODE (type) == POINTER_TYPE)
16312 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16313 tree t = var;
16314 if (is_reference (var))
16315 t = build_simple_mem_ref (var);
16316 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16317 TREE_NO_WARNING (var) = 1;
16318 if (TREE_CODE (type) != POINTER_TYPE)
16319 t = fold_convert (pointer_sized_int_node, t);
16320 t = fold_convert (TREE_TYPE (x), t);
16321 gimplify_assign (x, t, &ilist);
16323 else if (is_reference (var))
16324 gimplify_assign (x, var, &ilist);
16325 else if (is_gimple_reg (var))
16327 tree avar = create_tmp_var (TREE_TYPE (var));
16328 mark_addressable (avar);
16329 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16330 TREE_NO_WARNING (var) = 1;
16331 gimplify_assign (avar, var, &ilist);
16332 avar = build_fold_addr_expr (avar);
16333 gimplify_assign (x, avar, &ilist);
16335 else
16337 var = build_fold_addr_expr (var);
16338 gimplify_assign (x, var, &ilist);
16340 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16341 s = size_int (0);
16342 else if (is_reference (var))
16343 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16344 else
16345 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16346 s = fold_convert (size_type_node, s);
16347 purpose = size_int (map_idx++);
16348 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16349 if (TREE_CODE (s) != INTEGER_CST)
16350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16352 gcc_checking_assert (tkind
16353 < (HOST_WIDE_INT_C (1U) << talign_shift));
16354 talign = ceil_log2 (talign);
16355 tkind |= talign << talign_shift;
16356 gcc_checking_assert (tkind
16357 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16358 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16359 build_int_cstu (tkind_type, tkind));
16360 break;
16362 case OMP_CLAUSE_USE_DEVICE_PTR:
16363 case OMP_CLAUSE_IS_DEVICE_PTR:
16364 ovar = OMP_CLAUSE_DECL (c);
16365 var = lookup_decl_in_outer_ctx (ovar, ctx);
16366 x = build_sender_ref (ovar, ctx);
16367 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16368 tkind = GOMP_MAP_USE_DEVICE_PTR;
16369 else
16370 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16371 type = TREE_TYPE (ovar);
16372 if (TREE_CODE (type) == ARRAY_TYPE)
16373 var = build_fold_addr_expr (var);
16374 else
16376 if (is_reference (ovar))
16378 type = TREE_TYPE (type);
16379 if (TREE_CODE (type) != ARRAY_TYPE)
16380 var = build_simple_mem_ref (var);
16381 var = fold_convert (TREE_TYPE (x), var);
16384 gimplify_assign (x, var, &ilist);
16385 s = size_int (0);
16386 purpose = size_int (map_idx++);
16387 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16388 gcc_checking_assert (tkind
16389 < (HOST_WIDE_INT_C (1U) << talign_shift));
16390 gcc_checking_assert (tkind
16391 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16392 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16393 build_int_cstu (tkind_type, tkind));
16394 break;
16397 gcc_assert (map_idx == map_cnt);
16399 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16400 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16401 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16402 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16403 for (int i = 1; i <= 2; i++)
16404 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16406 gimple_seq initlist = NULL;
16407 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16408 TREE_VEC_ELT (t, i)),
16409 &initlist, true, NULL_TREE);
16410 gimple_seq_add_seq (&ilist, initlist);
16412 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16413 NULL);
16414 TREE_THIS_VOLATILE (clobber) = 1;
16415 gimple_seq_add_stmt (&olist,
16416 gimple_build_assign (TREE_VEC_ELT (t, i),
16417 clobber));
16420 tree clobber = build_constructor (ctx->record_type, NULL);
16421 TREE_THIS_VOLATILE (clobber) = 1;
16422 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16423 clobber));
16426 /* Once all the expansions are done, sequence all the different
16427 fragments inside gimple_omp_body. */
16429 new_body = NULL;
16431 if (offloaded
16432 && ctx->record_type)
16434 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16435 /* fixup_child_record_type might have changed receiver_decl's type. */
16436 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16437 gimple_seq_add_stmt (&new_body,
16438 gimple_build_assign (ctx->receiver_decl, t));
16440 gimple_seq_add_seq (&new_body, fplist);
16442 if (offloaded || data_region)
16444 tree prev = NULL_TREE;
16445 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16446 switch (OMP_CLAUSE_CODE (c))
16448 tree var, x;
16449 default:
16450 break;
16451 case OMP_CLAUSE_FIRSTPRIVATE:
16452 if (is_gimple_omp_oacc (ctx->stmt))
16453 break;
16454 var = OMP_CLAUSE_DECL (c);
16455 if (is_reference (var)
16456 || is_gimple_reg_type (TREE_TYPE (var)))
16458 tree new_var = lookup_decl (var, ctx);
16459 tree type;
16460 type = TREE_TYPE (var);
16461 if (is_reference (var))
16462 type = TREE_TYPE (type);
16463 if ((INTEGRAL_TYPE_P (type)
16464 && TYPE_PRECISION (type) <= POINTER_SIZE)
16465 || TREE_CODE (type) == POINTER_TYPE)
16467 x = build_receiver_ref (var, false, ctx);
16468 if (TREE_CODE (type) != POINTER_TYPE)
16469 x = fold_convert (pointer_sized_int_node, x);
16470 x = fold_convert (type, x);
16471 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16472 fb_rvalue);
16473 if (is_reference (var))
16475 tree v = create_tmp_var_raw (type, get_name (var));
16476 gimple_add_tmp_var (v);
16477 TREE_ADDRESSABLE (v) = 1;
16478 gimple_seq_add_stmt (&new_body,
16479 gimple_build_assign (v, x));
16480 x = build_fold_addr_expr (v);
16482 gimple_seq_add_stmt (&new_body,
16483 gimple_build_assign (new_var, x));
16485 else
16487 x = build_receiver_ref (var, !is_reference (var), ctx);
16488 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16489 fb_rvalue);
16490 gimple_seq_add_stmt (&new_body,
16491 gimple_build_assign (new_var, x));
16494 else if (is_variable_sized (var))
16496 tree pvar = DECL_VALUE_EXPR (var);
16497 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16498 pvar = TREE_OPERAND (pvar, 0);
16499 gcc_assert (DECL_P (pvar));
16500 tree new_var = lookup_decl (pvar, ctx);
16501 x = build_receiver_ref (var, false, ctx);
16502 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16503 gimple_seq_add_stmt (&new_body,
16504 gimple_build_assign (new_var, x));
16506 break;
16507 case OMP_CLAUSE_PRIVATE:
16508 if (is_gimple_omp_oacc (ctx->stmt))
16509 break;
16510 var = OMP_CLAUSE_DECL (c);
16511 if (is_reference (var))
16513 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16514 tree new_var = lookup_decl (var, ctx);
16515 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16516 if (TREE_CONSTANT (x))
16518 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16519 get_name (var));
16520 gimple_add_tmp_var (x);
16521 TREE_ADDRESSABLE (x) = 1;
16522 x = build_fold_addr_expr_loc (clause_loc, x);
16524 else
16525 break;
16527 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16528 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16529 gimple_seq_add_stmt (&new_body,
16530 gimple_build_assign (new_var, x));
16532 break;
16533 case OMP_CLAUSE_USE_DEVICE_PTR:
16534 case OMP_CLAUSE_IS_DEVICE_PTR:
16535 var = OMP_CLAUSE_DECL (c);
16536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16537 x = build_sender_ref (var, ctx);
16538 else
16539 x = build_receiver_ref (var, false, ctx);
16540 if (is_variable_sized (var))
16542 tree pvar = DECL_VALUE_EXPR (var);
16543 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16544 pvar = TREE_OPERAND (pvar, 0);
16545 gcc_assert (DECL_P (pvar));
16546 tree new_var = lookup_decl (pvar, ctx);
16547 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16548 gimple_seq_add_stmt (&new_body,
16549 gimple_build_assign (new_var, x));
16551 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16553 tree new_var = lookup_decl (var, ctx);
16554 new_var = DECL_VALUE_EXPR (new_var);
16555 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16556 new_var = TREE_OPERAND (new_var, 0);
16557 gcc_assert (DECL_P (new_var));
16558 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16559 gimple_seq_add_stmt (&new_body,
16560 gimple_build_assign (new_var, x));
16562 else
16564 tree type = TREE_TYPE (var);
16565 tree new_var = lookup_decl (var, ctx);
16566 if (is_reference (var))
16568 type = TREE_TYPE (type);
16569 if (TREE_CODE (type) != ARRAY_TYPE)
16571 tree v = create_tmp_var_raw (type, get_name (var));
16572 gimple_add_tmp_var (v);
16573 TREE_ADDRESSABLE (v) = 1;
16574 x = fold_convert (type, x);
16575 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16576 fb_rvalue);
16577 gimple_seq_add_stmt (&new_body,
16578 gimple_build_assign (v, x));
16579 x = build_fold_addr_expr (v);
16582 new_var = DECL_VALUE_EXPR (new_var);
16583 x = fold_convert (TREE_TYPE (new_var), x);
16584 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16585 gimple_seq_add_stmt (&new_body,
16586 gimple_build_assign (new_var, x));
16588 break;
16590 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16591 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16592 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16593 or references to VLAs. */
16594 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16595 switch (OMP_CLAUSE_CODE (c))
16597 tree var;
16598 default:
16599 break;
16600 case OMP_CLAUSE_MAP:
16601 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16602 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16604 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16605 HOST_WIDE_INT offset = 0;
16606 gcc_assert (prev);
16607 var = OMP_CLAUSE_DECL (c);
16608 if (DECL_P (var)
16609 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16610 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16611 ctx))
16612 && varpool_node::get_create (var)->offloadable)
16613 break;
16614 if (TREE_CODE (var) == INDIRECT_REF
16615 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16616 var = TREE_OPERAND (var, 0);
16617 if (TREE_CODE (var) == COMPONENT_REF)
16619 var = get_addr_base_and_unit_offset (var, &offset);
16620 gcc_assert (var != NULL_TREE && DECL_P (var));
16622 else if (DECL_SIZE (var)
16623 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16625 tree var2 = DECL_VALUE_EXPR (var);
16626 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16627 var2 = TREE_OPERAND (var2, 0);
16628 gcc_assert (DECL_P (var2));
16629 var = var2;
16631 tree new_var = lookup_decl (var, ctx), x;
16632 tree type = TREE_TYPE (new_var);
16633 bool is_ref;
16634 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16635 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16636 == COMPONENT_REF))
16638 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16639 is_ref = true;
16640 new_var = build2 (MEM_REF, type,
16641 build_fold_addr_expr (new_var),
16642 build_int_cst (build_pointer_type (type),
16643 offset));
16645 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16647 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16648 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16649 new_var = build2 (MEM_REF, type,
16650 build_fold_addr_expr (new_var),
16651 build_int_cst (build_pointer_type (type),
16652 offset));
16654 else
16655 is_ref = is_reference (var);
16656 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16657 is_ref = false;
16658 bool ref_to_array = false;
16659 if (is_ref)
16661 type = TREE_TYPE (type);
16662 if (TREE_CODE (type) == ARRAY_TYPE)
16664 type = build_pointer_type (type);
16665 ref_to_array = true;
16668 else if (TREE_CODE (type) == ARRAY_TYPE)
16670 tree decl2 = DECL_VALUE_EXPR (new_var);
16671 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16672 decl2 = TREE_OPERAND (decl2, 0);
16673 gcc_assert (DECL_P (decl2));
16674 new_var = decl2;
16675 type = TREE_TYPE (new_var);
16677 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16678 x = fold_convert_loc (clause_loc, type, x);
16679 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16681 tree bias = OMP_CLAUSE_SIZE (c);
16682 if (DECL_P (bias))
16683 bias = lookup_decl (bias, ctx);
16684 bias = fold_convert_loc (clause_loc, sizetype, bias);
16685 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16686 bias);
16687 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16688 TREE_TYPE (x), x, bias);
16690 if (ref_to_array)
16691 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16692 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16693 if (is_ref && !ref_to_array)
16695 tree t = create_tmp_var_raw (type, get_name (var));
16696 gimple_add_tmp_var (t);
16697 TREE_ADDRESSABLE (t) = 1;
16698 gimple_seq_add_stmt (&new_body,
16699 gimple_build_assign (t, x));
16700 x = build_fold_addr_expr_loc (clause_loc, t);
16702 gimple_seq_add_stmt (&new_body,
16703 gimple_build_assign (new_var, x));
16704 prev = NULL_TREE;
16706 else if (OMP_CLAUSE_CHAIN (c)
16707 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16708 == OMP_CLAUSE_MAP
16709 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16710 == GOMP_MAP_FIRSTPRIVATE_POINTER
16711 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16712 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16713 prev = c;
16714 break;
16715 case OMP_CLAUSE_PRIVATE:
16716 var = OMP_CLAUSE_DECL (c);
16717 if (is_variable_sized (var))
16719 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16720 tree new_var = lookup_decl (var, ctx);
16721 tree pvar = DECL_VALUE_EXPR (var);
16722 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16723 pvar = TREE_OPERAND (pvar, 0);
16724 gcc_assert (DECL_P (pvar));
16725 tree new_pvar = lookup_decl (pvar, ctx);
16726 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16727 tree al = size_int (DECL_ALIGN (var));
16728 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16729 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16730 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16731 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16732 gimple_seq_add_stmt (&new_body,
16733 gimple_build_assign (new_pvar, x));
16735 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16737 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16738 tree new_var = lookup_decl (var, ctx);
16739 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16740 if (TREE_CONSTANT (x))
16741 break;
16742 else
16744 tree atmp
16745 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16746 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16747 tree al = size_int (TYPE_ALIGN (rtype));
16748 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16751 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16752 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16753 gimple_seq_add_stmt (&new_body,
16754 gimple_build_assign (new_var, x));
16756 break;
16759 gimple_seq fork_seq = NULL;
16760 gimple_seq join_seq = NULL;
16762 if (is_oacc_parallel (ctx))
16764 /* If there are reductions on the offloaded region itself, treat
16765 them as a dummy GANG loop. */
16766 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16768 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16769 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16772 gimple_seq_add_seq (&new_body, fork_seq);
16773 gimple_seq_add_seq (&new_body, tgt_body);
16774 gimple_seq_add_seq (&new_body, join_seq);
16776 if (offloaded)
16777 new_body = maybe_catch_exception (new_body);
16779 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16780 gimple_omp_set_body (stmt, new_body);
16783 bind = gimple_build_bind (NULL, NULL,
16784 tgt_bind ? gimple_bind_block (tgt_bind)
16785 : NULL_TREE);
16786 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16787 gimple_bind_add_seq (bind, ilist);
16788 gimple_bind_add_stmt (bind, stmt);
16789 gimple_bind_add_seq (bind, olist);
16791 pop_gimplify_context (NULL);
16793 if (dep_bind)
16795 gimple_bind_add_seq (dep_bind, dep_ilist);
16796 gimple_bind_add_stmt (dep_bind, bind);
16797 gimple_bind_add_seq (dep_bind, dep_olist);
16798 pop_gimplify_context (dep_bind);
16802 /* Expand code for an OpenMP teams directive. */
16804 static void
16805 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16807 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16808 push_gimplify_context ();
16810 tree block = make_node (BLOCK);
16811 gbind *bind = gimple_build_bind (NULL, NULL, block);
16812 gsi_replace (gsi_p, bind, true);
16813 gimple_seq bind_body = NULL;
16814 gimple_seq dlist = NULL;
16815 gimple_seq olist = NULL;
16817 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16818 OMP_CLAUSE_NUM_TEAMS);
16819 if (num_teams == NULL_TREE)
16820 num_teams = build_int_cst (unsigned_type_node, 0);
16821 else
16823 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16824 num_teams = fold_convert (unsigned_type_node, num_teams);
16825 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16827 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16828 OMP_CLAUSE_THREAD_LIMIT);
16829 if (thread_limit == NULL_TREE)
16830 thread_limit = build_int_cst (unsigned_type_node, 0);
16831 else
16833 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16834 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16835 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16836 fb_rvalue);
16839 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16840 &bind_body, &dlist, ctx, NULL);
16841 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16842 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16843 if (!gimple_omp_teams_grid_phony (teams_stmt))
16845 gimple_seq_add_stmt (&bind_body, teams_stmt);
16846 location_t loc = gimple_location (teams_stmt);
16847 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16848 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16849 gimple_set_location (call, loc);
16850 gimple_seq_add_stmt (&bind_body, call);
16853 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16854 gimple_omp_set_body (teams_stmt, NULL);
16855 gimple_seq_add_seq (&bind_body, olist);
16856 gimple_seq_add_seq (&bind_body, dlist);
16857 if (!gimple_omp_teams_grid_phony (teams_stmt))
16858 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16859 gimple_bind_set_body (bind, bind_body);
16861 pop_gimplify_context (bind);
16863 gimple_bind_append_vars (bind, ctx->block_vars);
16864 BLOCK_VARS (block) = ctx->block_vars;
16865 if (BLOCK_VARS (block))
16866 TREE_USED (block) = 1;
16869 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16871 static void
16872 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16874 gimple *stmt = gsi_stmt (*gsi_p);
16875 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16876 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16877 gimple_build_omp_return (false));
16881 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16882 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16883 of OMP context, but with task_shared_vars set. */
16885 static tree
16886 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16887 void *data)
16889 tree t = *tp;
16891 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16892 if (VAR_P (t) && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16893 return t;
16895 if (task_shared_vars
16896 && DECL_P (t)
16897 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16898 return t;
16900 /* If a global variable has been privatized, TREE_CONSTANT on
16901 ADDR_EXPR might be wrong. */
16902 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16903 recompute_tree_invariant_for_addr_expr (t);
16905 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16906 return NULL_TREE;
16909 /* Data to be communicated between lower_omp_regimplify_operands and
16910 lower_omp_regimplify_operands_p. */
16912 struct lower_omp_regimplify_operands_data
16914 omp_context *ctx;
16915 vec<tree> *decls;
16918 /* Helper function for lower_omp_regimplify_operands. Find
16919 omp_member_access_dummy_var vars and adjust temporarily their
16920 DECL_VALUE_EXPRs if needed. */
16922 static tree
16923 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16924 void *data)
16926 tree t = omp_member_access_dummy_var (*tp);
16927 if (t)
16929 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16930 lower_omp_regimplify_operands_data *ldata
16931 = (lower_omp_regimplify_operands_data *) wi->info;
16932 tree o = maybe_lookup_decl (t, ldata->ctx);
16933 if (o != t)
16935 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16936 ldata->decls->safe_push (*tp);
16937 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16938 SET_DECL_VALUE_EXPR (*tp, v);
16941 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16942 return NULL_TREE;
16945 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16946 of omp_member_access_dummy_var vars during regimplification. */
16948 static void
16949 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16950 gimple_stmt_iterator *gsi_p)
16952 auto_vec<tree, 10> decls;
16953 if (ctx)
16955 struct walk_stmt_info wi;
16956 memset (&wi, '\0', sizeof (wi));
16957 struct lower_omp_regimplify_operands_data data;
16958 data.ctx = ctx;
16959 data.decls = &decls;
16960 wi.info = &data;
16961 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16963 gimple_regimplify_operands (stmt, gsi_p);
16964 while (!decls.is_empty ())
16966 tree t = decls.pop ();
16967 tree v = decls.pop ();
16968 SET_DECL_VALUE_EXPR (t, v);
16972 static void
16973 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16975 gimple *stmt = gsi_stmt (*gsi_p);
16976 struct walk_stmt_info wi;
16977 gcall *call_stmt;
16979 if (gimple_has_location (stmt))
16980 input_location = gimple_location (stmt);
16982 if (task_shared_vars)
16983 memset (&wi, '\0', sizeof (wi));
16985 /* If we have issued syntax errors, avoid doing any heavy lifting.
16986 Just replace the OMP directives with a NOP to avoid
16987 confusing RTL expansion. */
16988 if (seen_error () && is_gimple_omp (stmt))
16990 gsi_replace (gsi_p, gimple_build_nop (), true);
16991 return;
16994 switch (gimple_code (stmt))
16996 case GIMPLE_COND:
16998 gcond *cond_stmt = as_a <gcond *> (stmt);
16999 if ((ctx || task_shared_vars)
17000 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
17001 lower_omp_regimplify_p,
17002 ctx ? NULL : &wi, NULL)
17003 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
17004 lower_omp_regimplify_p,
17005 ctx ? NULL : &wi, NULL)))
17006 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
17008 break;
17009 case GIMPLE_CATCH:
17010 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
17011 break;
17012 case GIMPLE_EH_FILTER:
17013 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
17014 break;
17015 case GIMPLE_TRY:
17016 lower_omp (gimple_try_eval_ptr (stmt), ctx);
17017 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
17018 break;
17019 case GIMPLE_TRANSACTION:
17020 lower_omp (gimple_transaction_body_ptr (
17021 as_a <gtransaction *> (stmt)),
17022 ctx);
17023 break;
17024 case GIMPLE_BIND:
17025 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17026 break;
17027 case GIMPLE_OMP_PARALLEL:
17028 case GIMPLE_OMP_TASK:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 if (ctx->cancellable)
17032 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17033 lower_omp_taskreg (gsi_p, ctx);
17034 break;
17035 case GIMPLE_OMP_FOR:
17036 ctx = maybe_lookup_ctx (stmt);
17037 gcc_assert (ctx);
17038 if (ctx->cancellable)
17039 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17040 lower_omp_for (gsi_p, ctx);
17041 break;
17042 case GIMPLE_OMP_SECTIONS:
17043 ctx = maybe_lookup_ctx (stmt);
17044 gcc_assert (ctx);
17045 if (ctx->cancellable)
17046 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17047 lower_omp_sections (gsi_p, ctx);
17048 break;
17049 case GIMPLE_OMP_SINGLE:
17050 ctx = maybe_lookup_ctx (stmt);
17051 gcc_assert (ctx);
17052 lower_omp_single (gsi_p, ctx);
17053 break;
17054 case GIMPLE_OMP_MASTER:
17055 ctx = maybe_lookup_ctx (stmt);
17056 gcc_assert (ctx);
17057 lower_omp_master (gsi_p, ctx);
17058 break;
17059 case GIMPLE_OMP_TASKGROUP:
17060 ctx = maybe_lookup_ctx (stmt);
17061 gcc_assert (ctx);
17062 lower_omp_taskgroup (gsi_p, ctx);
17063 break;
17064 case GIMPLE_OMP_ORDERED:
17065 ctx = maybe_lookup_ctx (stmt);
17066 gcc_assert (ctx);
17067 lower_omp_ordered (gsi_p, ctx);
17068 break;
17069 case GIMPLE_OMP_CRITICAL:
17070 ctx = maybe_lookup_ctx (stmt);
17071 gcc_assert (ctx);
17072 lower_omp_critical (gsi_p, ctx);
17073 break;
17074 case GIMPLE_OMP_ATOMIC_LOAD:
17075 if ((ctx || task_shared_vars)
17076 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17077 as_a <gomp_atomic_load *> (stmt)),
17078 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17079 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17080 break;
17081 case GIMPLE_OMP_TARGET:
17082 ctx = maybe_lookup_ctx (stmt);
17083 gcc_assert (ctx);
17084 lower_omp_target (gsi_p, ctx);
17085 break;
17086 case GIMPLE_OMP_TEAMS:
17087 ctx = maybe_lookup_ctx (stmt);
17088 gcc_assert (ctx);
17089 lower_omp_teams (gsi_p, ctx);
17090 break;
17091 case GIMPLE_OMP_GRID_BODY:
17092 ctx = maybe_lookup_ctx (stmt);
17093 gcc_assert (ctx);
17094 lower_omp_grid_body (gsi_p, ctx);
17095 break;
17096 case GIMPLE_CALL:
17097 tree fndecl;
17098 call_stmt = as_a <gcall *> (stmt);
17099 fndecl = gimple_call_fndecl (call_stmt);
17100 if (fndecl
17101 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17102 switch (DECL_FUNCTION_CODE (fndecl))
17104 case BUILT_IN_GOMP_BARRIER:
17105 if (ctx == NULL)
17106 break;
17107 /* FALLTHRU */
17108 case BUILT_IN_GOMP_CANCEL:
17109 case BUILT_IN_GOMP_CANCELLATION_POINT:
17110 omp_context *cctx;
17111 cctx = ctx;
17112 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17113 cctx = cctx->outer;
17114 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17115 if (!cctx->cancellable)
17117 if (DECL_FUNCTION_CODE (fndecl)
17118 == BUILT_IN_GOMP_CANCELLATION_POINT)
17120 stmt = gimple_build_nop ();
17121 gsi_replace (gsi_p, stmt, false);
17123 break;
17125 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17127 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17128 gimple_call_set_fndecl (call_stmt, fndecl);
17129 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17131 tree lhs;
17132 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17133 gimple_call_set_lhs (call_stmt, lhs);
17134 tree fallthru_label;
17135 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17136 gimple *g;
17137 g = gimple_build_label (fallthru_label);
17138 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17139 g = gimple_build_cond (NE_EXPR, lhs,
17140 fold_convert (TREE_TYPE (lhs),
17141 boolean_false_node),
17142 cctx->cancel_label, fallthru_label);
17143 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17144 break;
17145 default:
17146 break;
17148 /* FALLTHRU */
17149 default:
17150 if ((ctx || task_shared_vars)
17151 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17152 ctx ? NULL : &wi))
17154 /* Just remove clobbers, this should happen only if we have
17155 "privatized" local addressable variables in SIMD regions,
17156 the clobber isn't needed in that case and gimplifying address
17157 of the ARRAY_REF into a pointer and creating MEM_REF based
17158 clobber would create worse code than we get with the clobber
17159 dropped. */
17160 if (gimple_clobber_p (stmt))
17162 gsi_replace (gsi_p, gimple_build_nop (), true);
17163 break;
17165 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17167 break;
17171 static void
17172 lower_omp (gimple_seq *body, omp_context *ctx)
17174 location_t saved_location = input_location;
17175 gimple_stmt_iterator gsi;
17176 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17177 lower_omp_1 (&gsi, ctx);
17178 /* During gimplification, we haven't folded statments inside offloading
17179 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17180 if (target_nesting_level || taskreg_nesting_level)
17181 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17182 fold_stmt (&gsi);
17183 input_location = saved_location;
17186 /* Returen true if STMT is an assignment of a register-type into a local
17187 VAR_DECL. */
17189 static bool
17190 grid_reg_assignment_to_local_var_p (gimple *stmt)
17192 gassign *assign = dyn_cast <gassign *> (stmt);
17193 if (!assign)
17194 return false;
17195 tree lhs = gimple_assign_lhs (assign);
17196 if (!VAR_P (lhs)
17197 || !is_gimple_reg_type (TREE_TYPE (lhs))
17198 || is_global_var (lhs))
17199 return false;
17200 return true;
17203 /* Return true if all statements in SEQ are assignments to local register-type
17204 variables. */
17206 static bool
17207 grid_seq_only_contains_local_assignments (gimple_seq seq)
17209 if (!seq)
17210 return true;
17212 gimple_stmt_iterator gsi;
17213 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17214 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17215 return false;
17216 return true;
17219 /* Scan statements in SEQ and call itself recursively on any bind. If during
17220 whole search only assignments to register-type local variables and one
17221 single OMP statement is encountered, return true, otherwise return false.
17222 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17223 are used for dumping a note about a failure. */
17225 static bool
17226 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17227 const char *name, gimple **ret)
17229 gimple_stmt_iterator gsi;
17230 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17232 gimple *stmt = gsi_stmt (gsi);
17234 if (grid_reg_assignment_to_local_var_p (stmt))
17235 continue;
17236 if (gbind *bind = dyn_cast <gbind *> (stmt))
17238 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17239 target_loc, name, ret))
17240 return false;
17242 else if (is_gimple_omp (stmt))
17244 if (*ret)
17246 if (dump_enabled_p ())
17247 dump_printf_loc (MSG_NOTE, target_loc,
17248 "Will not turn target construct into a simple "
17249 "GPGPU kernel because %s construct contains "
17250 "multiple OpenMP constructs\n", name);
17251 return false;
17253 *ret = stmt;
17255 else
17257 if (dump_enabled_p ())
17258 dump_printf_loc (MSG_NOTE, target_loc,
17259 "Will not turn target construct into a simple "
17260 "GPGPU kernel because %s construct contains "
17261 "a complex statement\n", name);
17262 return false;
17265 return true;
17268 /* Scan statements in SEQ and make sure that it and any binds in it contain
17269 only assignments to local register-type variables and one OMP construct. If
17270 so, return that construct, otherwise return NULL. If dumping is enabled and
17271 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17272 failure. */
17274 static gimple *
17275 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17276 const char *name)
17278 if (!seq)
17280 if (dump_enabled_p ())
17281 dump_printf_loc (MSG_NOTE, target_loc,
17282 "Will not turn target construct into a simple "
17283 "GPGPU kernel because %s construct has empty "
17284 "body\n",
17285 name);
17286 return NULL;
17289 gimple *ret = NULL;
17290 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17292 if (!ret && dump_enabled_p ())
17293 dump_printf_loc (MSG_NOTE, target_loc,
17294 "Will not turn target construct into a simple "
17295 "GPGPU kernel because %s construct does not contain"
17296 "any other OpenMP construct\n", name);
17297 return ret;
17299 else
17300 return NULL;
17303 /* Walker function looking for statements there is no point gridifying (and for
17304 noreturn function calls which we cannot do). Return non-NULL if such a
17305 function is found. */
17307 static tree
17308 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17309 bool *handled_ops_p,
17310 struct walk_stmt_info *wi)
17312 *handled_ops_p = false;
17313 gimple *stmt = gsi_stmt (*gsi);
17314 switch (gimple_code (stmt))
17316 case GIMPLE_CALL:
17317 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17319 *handled_ops_p = true;
17320 wi->info = stmt;
17321 return error_mark_node;
17323 break;
17325 /* We may reduce the following list if we find a way to implement the
17326 clauses, but now there is no point trying further. */
17327 case GIMPLE_OMP_CRITICAL:
17328 case GIMPLE_OMP_TASKGROUP:
17329 case GIMPLE_OMP_TASK:
17330 case GIMPLE_OMP_SECTION:
17331 case GIMPLE_OMP_SECTIONS:
17332 case GIMPLE_OMP_SECTIONS_SWITCH:
17333 case GIMPLE_OMP_TARGET:
17334 case GIMPLE_OMP_ORDERED:
17335 *handled_ops_p = true;
17336 wi->info = stmt;
17337 return error_mark_node;
17339 case GIMPLE_OMP_FOR:
17340 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17341 && gimple_omp_for_combined_into_p (stmt))
17343 *handled_ops_p = true;
17344 wi->info = stmt;
17345 return error_mark_node;
17347 break;
17349 default:
17350 break;
17352 return NULL;
17356 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17357 kernel, return true, otherwise return false. In the case of success, also
17358 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17359 none. */
17361 static bool
17362 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17364 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17365 return false;
17367 location_t tloc = gimple_location (target);
17368 gimple *stmt
17369 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17370 tloc, "target");
17371 if (!stmt)
17372 return false;
17373 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17374 tree group_size = NULL;
17375 if (!teams)
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a simple "
17379 "GPGPU kernel because it does not have a sole teams "
17380 "construct in it.\n");
17381 return false;
17384 tree clauses = gimple_omp_teams_clauses (teams);
17385 while (clauses)
17387 switch (OMP_CLAUSE_CODE (clauses))
17389 case OMP_CLAUSE_NUM_TEAMS:
17390 if (dump_enabled_p ())
17391 dump_printf_loc (MSG_NOTE, tloc,
17392 "Will not turn target construct into a "
17393 "gridified GPGPU kernel because we cannot "
17394 "handle num_teams clause of teams "
17395 "construct\n ");
17396 return false;
17398 case OMP_CLAUSE_REDUCTION:
17399 if (dump_enabled_p ())
17400 dump_printf_loc (MSG_NOTE, tloc,
17401 "Will not turn target construct into a "
17402 "gridified GPGPU kernel because a reduction "
17403 "clause is present\n ");
17404 return false;
17406 case OMP_CLAUSE_LASTPRIVATE:
17407 if (dump_enabled_p ())
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a "
17410 "gridified GPGPU kernel because a lastprivate "
17411 "clause is present\n ");
17412 return false;
17414 case OMP_CLAUSE_THREAD_LIMIT:
17415 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17416 break;
17418 default:
17419 break;
17421 clauses = OMP_CLAUSE_CHAIN (clauses);
17424 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17425 "teams");
17426 if (!stmt)
17427 return false;
17428 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17429 if (!dist)
17431 dump_printf_loc (MSG_NOTE, tloc,
17432 "Will not turn target construct into a simple "
17433 "GPGPU kernel because the teams construct does not have "
17434 "a sole distribute construct in it.\n");
17435 return false;
17438 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17439 if (!gimple_omp_for_combined_p (dist))
17441 if (dump_enabled_p ())
17442 dump_printf_loc (MSG_NOTE, tloc,
17443 "Will not turn target construct into a gridified GPGPU "
17444 "kernel because we cannot handle a standalone "
17445 "distribute construct\n ");
17446 return false;
17448 if (dist->collapse > 1)
17450 if (dump_enabled_p ())
17451 dump_printf_loc (MSG_NOTE, tloc,
17452 "Will not turn target construct into a gridified GPGPU "
17453 "kernel because the distribute construct contains "
17454 "collapse clause\n");
17455 return false;
17457 struct omp_for_data fd;
17458 extract_omp_for_data (dist, &fd, NULL);
17459 if (fd.chunk_size)
17461 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17463 if (dump_enabled_p ())
17464 dump_printf_loc (MSG_NOTE, tloc,
17465 "Will not turn target construct into a "
17466 "gridified GPGPU kernel because the teams "
17467 "thread limit is different from distribute "
17468 "schedule chunk\n");
17469 return false;
17471 group_size = fd.chunk_size;
17473 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17474 "distribute");
17475 gomp_parallel *par;
17476 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17477 return false;
17479 clauses = gimple_omp_parallel_clauses (par);
17480 while (clauses)
17482 switch (OMP_CLAUSE_CODE (clauses))
17484 case OMP_CLAUSE_NUM_THREADS:
17485 if (dump_enabled_p ())
17486 dump_printf_loc (MSG_NOTE, tloc,
17487 "Will not turn target construct into a gridified"
17488 "GPGPU kernel because there is a num_threads "
17489 "clause of the parallel construct\n");
17490 return false;
17492 case OMP_CLAUSE_REDUCTION:
17493 if (dump_enabled_p ())
17494 dump_printf_loc (MSG_NOTE, tloc,
17495 "Will not turn target construct into a "
17496 "gridified GPGPU kernel because a reduction "
17497 "clause is present\n ");
17498 return false;
17500 case OMP_CLAUSE_LASTPRIVATE:
17501 if (dump_enabled_p ())
17502 dump_printf_loc (MSG_NOTE, tloc,
17503 "Will not turn target construct into a "
17504 "gridified GPGPU kernel because a lastprivate "
17505 "clause is present\n ");
17506 return false;
17508 default:
17509 break;
17511 clauses = OMP_CLAUSE_CHAIN (clauses);
17514 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17515 "parallel");
17516 gomp_for *gfor;
17517 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17518 return false;
17520 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17522 if (dump_enabled_p ())
17523 dump_printf_loc (MSG_NOTE, tloc,
17524 "Will not turn target construct into a gridified GPGPU "
17525 "kernel because the inner loop is not a simple for "
17526 "loop\n");
17527 return false;
17529 if (gfor->collapse > 1)
17531 if (dump_enabled_p ())
17532 dump_printf_loc (MSG_NOTE, tloc,
17533 "Will not turn target construct into a gridified GPGPU "
17534 "kernel because the inner loop contains collapse "
17535 "clause\n");
17536 return false;
17539 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a gridified GPGPU "
17544 "kernel because the inner loop pre_body contains"
17545 "a complex instruction\n");
17546 return false;
17549 clauses = gimple_omp_for_clauses (gfor);
17550 while (clauses)
17552 switch (OMP_CLAUSE_CODE (clauses))
17554 case OMP_CLAUSE_SCHEDULE:
17555 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17557 if (dump_enabled_p ())
17558 dump_printf_loc (MSG_NOTE, tloc,
17559 "Will not turn target construct into a "
17560 "gridified GPGPU kernel because the inner "
17561 "loop has a non-automatic scheduling clause\n");
17562 return false;
17564 break;
17566 case OMP_CLAUSE_REDUCTION:
17567 if (dump_enabled_p ())
17568 dump_printf_loc (MSG_NOTE, tloc,
17569 "Will not turn target construct into a "
17570 "gridified GPGPU kernel because a reduction "
17571 "clause is present\n ");
17572 return false;
17574 case OMP_CLAUSE_LASTPRIVATE:
17575 if (dump_enabled_p ())
17576 dump_printf_loc (MSG_NOTE, tloc,
17577 "Will not turn target construct into a "
17578 "gridified GPGPU kernel because a lastprivate "
17579 "clause is present\n ");
17580 return false;
17582 default:
17583 break;
17585 clauses = OMP_CLAUSE_CHAIN (clauses);
17588 struct walk_stmt_info wi;
17589 memset (&wi, 0, sizeof (wi));
17590 if (walk_gimple_seq (gimple_omp_body (gfor),
17591 grid_find_ungridifiable_statement,
17592 NULL, &wi))
17594 gimple *bad = (gimple *) wi.info;
17595 if (dump_enabled_p ())
17597 if (is_gimple_call (bad))
17598 dump_printf_loc (MSG_NOTE, tloc,
17599 "Will not turn target construct into a gridified "
17600 " GPGPU kernel because the inner loop contains "
17601 "call to a noreturn function\n");
17602 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17603 dump_printf_loc (MSG_NOTE, tloc,
17604 "Will not turn target construct into a gridified "
17605 " GPGPU kernel because the inner loop contains "
17606 "a simd construct\n");
17607 else
17608 dump_printf_loc (MSG_NOTE, tloc,
17609 "Will not turn target construct into a gridified "
17610 "GPGPU kernel because the inner loop contains "
17611 "statement %s which cannot be transformed\n",
17612 gimple_code_name[(int) gimple_code (bad)]);
17614 return false;
17617 *group_size_p = group_size;
17618 return true;
17621 /* Operand walker, used to remap pre-body declarations according to a hash map
17622 provided in DATA. */
17624 static tree
17625 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17627 tree t = *tp;
17629 if (DECL_P (t) || TYPE_P (t))
17630 *walk_subtrees = 0;
17631 else
17632 *walk_subtrees = 1;
17634 if (VAR_P (t))
17636 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17637 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17638 tree *repl = declmap->get (t);
17639 if (repl)
17640 *tp = *repl;
17642 return NULL_TREE;
17645 /* Copy leading register-type assignments to local variables in SRC to just
17646 before DST, Creating temporaries, adjusting mapping of operands in WI and
17647 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17648 Return the first statement that does not conform to
17649 grid_reg_assignment_to_local_var_p or NULL. */
17651 static gimple *
17652 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17653 gbind *tgt_bind, struct walk_stmt_info *wi)
17655 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17656 gimple_stmt_iterator gsi;
17657 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17659 gimple *stmt = gsi_stmt (gsi);
17660 if (gbind *bind = dyn_cast <gbind *> (stmt))
17662 gimple *r = grid_copy_leading_local_assignments
17663 (gimple_bind_body (bind), dst, tgt_bind, wi);
17664 if (r)
17665 return r;
17666 else
17667 continue;
17669 if (!grid_reg_assignment_to_local_var_p (stmt))
17670 return stmt;
17671 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17672 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17673 TREE_TYPE (lhs));
17674 DECL_CONTEXT (repl) = current_function_decl;
17675 gimple_bind_append_vars (tgt_bind, repl);
17677 declmap->put (lhs, repl);
17678 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17679 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17680 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17682 return NULL;
17685 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17686 components, mark them as part of kernel and return the inner loop, and copy
17687 assignment leading to them just before DST, remapping them using WI and
17688 adding new temporaries to TGT_BIND. */
17690 static gomp_for *
17691 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17692 gbind *tgt_bind, struct walk_stmt_info *wi)
17694 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17695 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17696 gcc_assert (teams);
17697 gimple_omp_teams_set_grid_phony (teams, true);
17698 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17699 tgt_bind, wi);
17700 gcc_checking_assert (stmt);
17701 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17702 gcc_assert (dist);
17703 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17704 if (prebody)
17705 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17706 gimple_omp_for_set_grid_phony (dist, true);
17707 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17708 tgt_bind, wi);
17709 gcc_checking_assert (stmt);
17711 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17712 gimple_omp_parallel_set_grid_phony (parallel, true);
17713 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17714 tgt_bind, wi);
17715 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17716 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17717 prebody = gimple_omp_for_pre_body (inner_loop);
17718 if (prebody)
17719 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17721 return inner_loop;
17724 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17725 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17726 is the bind into which temporaries inserted before TARGET should be
17727 added. */
17729 static void
17730 grid_attempt_target_gridification (gomp_target *target,
17731 gimple_stmt_iterator *gsi,
17732 gbind *tgt_bind)
17734 tree group_size;
17735 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17736 return;
17738 location_t loc = gimple_location (target);
17739 if (dump_enabled_p ())
17740 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17741 "Target construct will be turned into a gridified GPGPU "
17742 "kernel\n");
17744 /* Copy target body to a GPUKERNEL construct: */
17745 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17746 (gimple_omp_body (target));
17748 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17749 struct walk_stmt_info wi;
17750 memset (&wi, 0, sizeof (struct walk_stmt_info));
17751 wi.info = declmap;
17753 /* Copy assignments in between OMP statements before target, mark OMP
17754 statements within copy appropriatly. */
17755 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17756 tgt_bind, &wi);
17758 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17759 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17760 tree new_block = gimple_bind_block (new_bind);
17761 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17762 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17763 BLOCK_SUBBLOCKS (enc_block) = new_block;
17764 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17765 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17766 gimple_seq_add_stmt
17767 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17768 gpukernel);
17770 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17771 push_gimplify_context ();
17772 size_t collapse = gimple_omp_for_collapse (inner_loop);
17773 for (size_t i = 0; i < collapse; i++)
17775 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17776 if (POINTER_TYPE_P (type))
17777 itype = signed_type_for (type);
17778 else
17779 itype = type;
17781 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17782 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17783 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17784 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17785 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17786 adjust_for_condition (loc, &cond_code, &n2);
17787 tree step;
17788 step = get_omp_for_step_from_incr (loc,
17789 gimple_omp_for_incr (inner_loop, i));
17790 gimple_seq tmpseq = NULL;
17791 n1 = fold_convert (itype, n1);
17792 n2 = fold_convert (itype, n2);
17793 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17794 t = fold_build2 (PLUS_EXPR, itype, step, t);
17795 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17796 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17797 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17798 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17799 fold_build1 (NEGATE_EXPR, itype, t),
17800 fold_build1 (NEGATE_EXPR, itype, step));
17801 else
17802 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17803 tree gs = fold_convert (uint32_type_node, t);
17804 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17805 if (!gimple_seq_empty_p (tmpseq))
17806 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17808 tree ws;
17809 if (i == 0 && group_size)
17811 ws = fold_convert (uint32_type_node, group_size);
17812 tmpseq = NULL;
17813 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17814 if (!gimple_seq_empty_p (tmpseq))
17815 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17817 else
17818 ws = build_zero_cst (uint32_type_node);
17820 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17821 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17822 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17823 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17824 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17825 gimple_omp_target_set_clauses (target, c);
17827 pop_gimplify_context (tgt_bind);
17828 delete declmap;
17829 return;
17832 /* Walker function doing all the work for create_target_kernels. */
17834 static tree
17835 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17836 bool *handled_ops_p,
17837 struct walk_stmt_info *incoming)
17839 *handled_ops_p = false;
17841 gimple *stmt = gsi_stmt (*gsi);
17842 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17843 if (target)
17845 gbind *tgt_bind = (gbind *) incoming->info;
17846 gcc_checking_assert (tgt_bind);
17847 grid_attempt_target_gridification (target, gsi, tgt_bind);
17848 return NULL_TREE;
17850 gbind *bind = dyn_cast <gbind *> (stmt);
17851 if (bind)
17853 *handled_ops_p = true;
17854 struct walk_stmt_info wi;
17855 memset (&wi, 0, sizeof (wi));
17856 wi.info = bind;
17857 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17858 grid_gridify_all_targets_stmt, NULL, &wi);
17860 return NULL_TREE;
17863 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17864 have their bodies duplicated, with the new copy being put into a
17865 gimple_omp_grid_body statement. All kernel-related construct within the
17866 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17867 re-structuring is often needed, such as copying pre-bodies before the target
17868 construct so that kernel grid sizes can be computed. */
17870 static void
17871 grid_gridify_all_targets (gimple_seq *body_p)
17873 struct walk_stmt_info wi;
17874 memset (&wi, 0, sizeof (wi));
17875 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17879 /* Main entry point. */
17881 static unsigned int
17882 execute_lower_omp (void)
17884 gimple_seq body;
17885 int i;
17886 omp_context *ctx;
17888 /* This pass always runs, to provide PROP_gimple_lomp.
17889 But often, there is nothing to do. */
17890 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17891 && flag_openmp_simd == 0)
17892 return 0;
17894 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17895 delete_omp_context);
17897 body = gimple_body (current_function_decl);
17899 if (hsa_gen_requested_p ())
17900 grid_gridify_all_targets (&body);
17902 scan_omp (&body, NULL);
17903 gcc_assert (taskreg_nesting_level == 0);
17904 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17905 finish_taskreg_scan (ctx);
17906 taskreg_contexts.release ();
17908 if (all_contexts->root)
17910 if (task_shared_vars)
17911 push_gimplify_context ();
17912 lower_omp (&body, NULL);
17913 if (task_shared_vars)
17914 pop_gimplify_context (NULL);
17917 if (all_contexts)
17919 splay_tree_delete (all_contexts);
17920 all_contexts = NULL;
17922 BITMAP_FREE (task_shared_vars);
17923 return 0;
17926 namespace {
17928 const pass_data pass_data_lower_omp =
17930 GIMPLE_PASS, /* type */
17931 "omplower", /* name */
17932 OPTGROUP_NONE, /* optinfo_flags */
17933 TV_NONE, /* tv_id */
17934 PROP_gimple_any, /* properties_required */
17935 PROP_gimple_lomp, /* properties_provided */
17936 0, /* properties_destroyed */
17937 0, /* todo_flags_start */
17938 0, /* todo_flags_finish */
17941 class pass_lower_omp : public gimple_opt_pass
17943 public:
17944 pass_lower_omp (gcc::context *ctxt)
17945 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17948 /* opt_pass methods: */
17949 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17951 }; // class pass_lower_omp
17953 } // anon namespace
17955 gimple_opt_pass *
17956 make_pass_lower_omp (gcc::context *ctxt)
17958 return new pass_lower_omp (ctxt);
17961 /* The following is a utility to diagnose structured block violations.
17962 It is not part of the "omplower" pass, as that's invoked too late. It
17963 should be invoked by the respective front ends after gimplification. */
17965 static splay_tree all_labels;
17967 /* Check for mismatched contexts and generate an error if needed. Return
17968 true if an error is detected. */
17970 static bool
17971 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17972 gimple *branch_ctx, gimple *label_ctx)
17974 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17975 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17977 if (label_ctx == branch_ctx)
17978 return false;
17980 const char* kind = NULL;
17982 if (flag_cilkplus)
17984 if ((branch_ctx
17985 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17986 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17987 || (label_ctx
17988 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17989 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17990 kind = "Cilk Plus";
17992 if (flag_openacc)
17994 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17995 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17997 gcc_checking_assert (kind == NULL);
17998 kind = "OpenACC";
18001 if (kind == NULL)
18003 gcc_checking_assert (flag_openmp);
18004 kind = "OpenMP";
18008 Previously we kept track of the label's entire context in diagnose_sb_[12]
18009 so we could traverse it and issue a correct "exit" or "enter" error
18010 message upon a structured block violation.
18012 We built the context by building a list with tree_cons'ing, but there is
18013 no easy counterpart in gimple tuples. It seems like far too much work
18014 for issuing exit/enter error messages. If someone really misses the
18015 distinct error message... patches welcome.
18018 #if 0
18019 /* Try to avoid confusing the user by producing and error message
18020 with correct "exit" or "enter" verbiage. We prefer "exit"
18021 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
18022 if (branch_ctx == NULL)
18023 exit_p = false;
18024 else
18026 while (label_ctx)
18028 if (TREE_VALUE (label_ctx) == branch_ctx)
18030 exit_p = false;
18031 break;
18033 label_ctx = TREE_CHAIN (label_ctx);
18037 if (exit_p)
18038 error ("invalid exit from %s structured block", kind);
18039 else
18040 error ("invalid entry to %s structured block", kind);
18041 #endif
18043 /* If it's obvious we have an invalid entry, be specific about the error. */
18044 if (branch_ctx == NULL)
18045 error ("invalid entry to %s structured block", kind);
18046 else
18048 /* Otherwise, be vague and lazy, but efficient. */
18049 error ("invalid branch to/from %s structured block", kind);
18052 gsi_replace (gsi_p, gimple_build_nop (), false);
18053 return true;
18056 /* Pass 1: Create a minimal tree of structured blocks, and record
18057 where each label is found. */
18059 static tree
18060 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18061 struct walk_stmt_info *wi)
18063 gimple *context = (gimple *) wi->info;
18064 gimple *inner_context;
18065 gimple *stmt = gsi_stmt (*gsi_p);
18067 *handled_ops_p = true;
18069 switch (gimple_code (stmt))
18071 WALK_SUBSTMTS;
18073 case GIMPLE_OMP_PARALLEL:
18074 case GIMPLE_OMP_TASK:
18075 case GIMPLE_OMP_SECTIONS:
18076 case GIMPLE_OMP_SINGLE:
18077 case GIMPLE_OMP_SECTION:
18078 case GIMPLE_OMP_MASTER:
18079 case GIMPLE_OMP_ORDERED:
18080 case GIMPLE_OMP_CRITICAL:
18081 case GIMPLE_OMP_TARGET:
18082 case GIMPLE_OMP_TEAMS:
18083 case GIMPLE_OMP_TASKGROUP:
18084 /* The minimal context here is just the current OMP construct. */
18085 inner_context = stmt;
18086 wi->info = inner_context;
18087 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18088 wi->info = context;
18089 break;
18091 case GIMPLE_OMP_FOR:
18092 inner_context = stmt;
18093 wi->info = inner_context;
18094 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18095 walk them. */
18096 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18097 diagnose_sb_1, NULL, wi);
18098 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18099 wi->info = context;
18100 break;
18102 case GIMPLE_LABEL:
18103 splay_tree_insert (all_labels,
18104 (splay_tree_key) gimple_label_label (
18105 as_a <glabel *> (stmt)),
18106 (splay_tree_value) context);
18107 break;
18109 default:
18110 break;
18113 return NULL_TREE;
18116 /* Pass 2: Check each branch and see if its context differs from that of
18117 the destination label's context. */
18119 static tree
18120 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18121 struct walk_stmt_info *wi)
18123 gimple *context = (gimple *) wi->info;
18124 splay_tree_node n;
18125 gimple *stmt = gsi_stmt (*gsi_p);
18127 *handled_ops_p = true;
18129 switch (gimple_code (stmt))
18131 WALK_SUBSTMTS;
18133 case GIMPLE_OMP_PARALLEL:
18134 case GIMPLE_OMP_TASK:
18135 case GIMPLE_OMP_SECTIONS:
18136 case GIMPLE_OMP_SINGLE:
18137 case GIMPLE_OMP_SECTION:
18138 case GIMPLE_OMP_MASTER:
18139 case GIMPLE_OMP_ORDERED:
18140 case GIMPLE_OMP_CRITICAL:
18141 case GIMPLE_OMP_TARGET:
18142 case GIMPLE_OMP_TEAMS:
18143 case GIMPLE_OMP_TASKGROUP:
18144 wi->info = stmt;
18145 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18146 wi->info = context;
18147 break;
18149 case GIMPLE_OMP_FOR:
18150 wi->info = stmt;
18151 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18152 walk them. */
18153 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18154 diagnose_sb_2, NULL, wi);
18155 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18156 wi->info = context;
18157 break;
18159 case GIMPLE_COND:
18161 gcond *cond_stmt = as_a <gcond *> (stmt);
18162 tree lab = gimple_cond_true_label (cond_stmt);
18163 if (lab)
18165 n = splay_tree_lookup (all_labels,
18166 (splay_tree_key) lab);
18167 diagnose_sb_0 (gsi_p, context,
18168 n ? (gimple *) n->value : NULL);
18170 lab = gimple_cond_false_label (cond_stmt);
18171 if (lab)
18173 n = splay_tree_lookup (all_labels,
18174 (splay_tree_key) lab);
18175 diagnose_sb_0 (gsi_p, context,
18176 n ? (gimple *) n->value : NULL);
18179 break;
18181 case GIMPLE_GOTO:
18183 tree lab = gimple_goto_dest (stmt);
18184 if (TREE_CODE (lab) != LABEL_DECL)
18185 break;
18187 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18188 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18190 break;
18192 case GIMPLE_SWITCH:
18194 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18195 unsigned int i;
18196 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18198 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18199 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18200 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18201 break;
18204 break;
18206 case GIMPLE_RETURN:
18207 diagnose_sb_0 (gsi_p, context, NULL);
18208 break;
18210 default:
18211 break;
18214 return NULL_TREE;
18217 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18218 GIMPLE_* codes. */
18219 bool
18220 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18221 int *region_idx)
18223 gimple *last = last_stmt (bb);
18224 enum gimple_code code = gimple_code (last);
18225 struct omp_region *cur_region = *region;
18226 bool fallthru = false;
18228 switch (code)
18230 case GIMPLE_OMP_PARALLEL:
18231 case GIMPLE_OMP_TASK:
18232 case GIMPLE_OMP_FOR:
18233 case GIMPLE_OMP_SINGLE:
18234 case GIMPLE_OMP_TEAMS:
18235 case GIMPLE_OMP_MASTER:
18236 case GIMPLE_OMP_TASKGROUP:
18237 case GIMPLE_OMP_CRITICAL:
18238 case GIMPLE_OMP_SECTION:
18239 case GIMPLE_OMP_GRID_BODY:
18240 cur_region = new_omp_region (bb, code, cur_region);
18241 fallthru = true;
18242 break;
18244 case GIMPLE_OMP_ORDERED:
18245 cur_region = new_omp_region (bb, code, cur_region);
18246 fallthru = true;
18247 if (find_omp_clause (gimple_omp_ordered_clauses
18248 (as_a <gomp_ordered *> (last)),
18249 OMP_CLAUSE_DEPEND))
18250 cur_region = cur_region->outer;
18251 break;
18253 case GIMPLE_OMP_TARGET:
18254 cur_region = new_omp_region (bb, code, cur_region);
18255 fallthru = true;
18256 switch (gimple_omp_target_kind (last))
18258 case GF_OMP_TARGET_KIND_REGION:
18259 case GF_OMP_TARGET_KIND_DATA:
18260 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18261 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18262 case GF_OMP_TARGET_KIND_OACC_DATA:
18263 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18264 break;
18265 case GF_OMP_TARGET_KIND_UPDATE:
18266 case GF_OMP_TARGET_KIND_ENTER_DATA:
18267 case GF_OMP_TARGET_KIND_EXIT_DATA:
18268 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18269 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18270 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18271 cur_region = cur_region->outer;
18272 break;
18273 default:
18274 gcc_unreachable ();
18276 break;
18278 case GIMPLE_OMP_SECTIONS:
18279 cur_region = new_omp_region (bb, code, cur_region);
18280 fallthru = true;
18281 break;
18283 case GIMPLE_OMP_SECTIONS_SWITCH:
18284 fallthru = false;
18285 break;
18287 case GIMPLE_OMP_ATOMIC_LOAD:
18288 case GIMPLE_OMP_ATOMIC_STORE:
18289 fallthru = true;
18290 break;
18292 case GIMPLE_OMP_RETURN:
18293 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18294 somewhere other than the next block. This will be
18295 created later. */
18296 cur_region->exit = bb;
18297 if (cur_region->type == GIMPLE_OMP_TASK)
18298 /* Add an edge corresponding to not scheduling the task
18299 immediately. */
18300 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18301 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18302 cur_region = cur_region->outer;
18303 break;
18305 case GIMPLE_OMP_CONTINUE:
18306 cur_region->cont = bb;
18307 switch (cur_region->type)
18309 case GIMPLE_OMP_FOR:
18310 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18311 succs edges as abnormal to prevent splitting
18312 them. */
18313 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18314 /* Make the loopback edge. */
18315 make_edge (bb, single_succ (cur_region->entry),
18316 EDGE_ABNORMAL);
18318 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18319 corresponds to the case that the body of the loop
18320 is not executed at all. */
18321 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18322 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18323 fallthru = false;
18324 break;
18326 case GIMPLE_OMP_SECTIONS:
18327 /* Wire up the edges into and out of the nested sections. */
18329 basic_block switch_bb = single_succ (cur_region->entry);
18331 struct omp_region *i;
18332 for (i = cur_region->inner; i ; i = i->next)
18334 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18335 make_edge (switch_bb, i->entry, 0);
18336 make_edge (i->exit, bb, EDGE_FALLTHRU);
18339 /* Make the loopback edge to the block with
18340 GIMPLE_OMP_SECTIONS_SWITCH. */
18341 make_edge (bb, switch_bb, 0);
18343 /* Make the edge from the switch to exit. */
18344 make_edge (switch_bb, bb->next_bb, 0);
18345 fallthru = false;
18347 break;
18349 case GIMPLE_OMP_TASK:
18350 fallthru = true;
18351 break;
18353 default:
18354 gcc_unreachable ();
18356 break;
18358 default:
18359 gcc_unreachable ();
18362 if (*region != cur_region)
18364 *region = cur_region;
18365 if (cur_region)
18366 *region_idx = cur_region->entry->index;
18367 else
18368 *region_idx = 0;
18371 return fallthru;
18374 static unsigned int
18375 diagnose_omp_structured_block_errors (void)
18377 struct walk_stmt_info wi;
18378 gimple_seq body = gimple_body (current_function_decl);
18380 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18382 memset (&wi, 0, sizeof (wi));
18383 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18385 memset (&wi, 0, sizeof (wi));
18386 wi.want_locations = true;
18387 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18389 gimple_set_body (current_function_decl, body);
18391 splay_tree_delete (all_labels);
18392 all_labels = NULL;
18394 return 0;
18397 namespace {
18399 const pass_data pass_data_diagnose_omp_blocks =
18401 GIMPLE_PASS, /* type */
18402 "*diagnose_omp_blocks", /* name */
18403 OPTGROUP_NONE, /* optinfo_flags */
18404 TV_NONE, /* tv_id */
18405 PROP_gimple_any, /* properties_required */
18406 0, /* properties_provided */
18407 0, /* properties_destroyed */
18408 0, /* todo_flags_start */
18409 0, /* todo_flags_finish */
18412 class pass_diagnose_omp_blocks : public gimple_opt_pass
18414 public:
18415 pass_diagnose_omp_blocks (gcc::context *ctxt)
18416 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18419 /* opt_pass methods: */
18420 virtual bool gate (function *)
18422 return flag_cilkplus || flag_openacc || flag_openmp;
18424 virtual unsigned int execute (function *)
18426 return diagnose_omp_structured_block_errors ();
18429 }; // class pass_diagnose_omp_blocks
18431 } // anon namespace
18433 gimple_opt_pass *
18434 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18436 return new pass_diagnose_omp_blocks (ctxt);
18439 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18440 adds their addresses and sizes to constructor-vector V_CTOR. */
18441 static void
18442 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18443 vec<constructor_elt, va_gc> *v_ctor)
18445 unsigned len = vec_safe_length (v_decls);
18446 for (unsigned i = 0; i < len; i++)
18448 tree it = (*v_decls)[i];
18449 bool is_var = VAR_P (it);
18450 bool is_link_var
18451 = is_var
18452 #ifdef ACCEL_COMPILER
18453 && DECL_HAS_VALUE_EXPR_P (it)
18454 #endif
18455 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18457 tree size = NULL_TREE;
18458 if (is_var)
18459 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18461 tree addr;
18462 if (!is_link_var)
18463 addr = build_fold_addr_expr (it);
18464 else
18466 #ifdef ACCEL_COMPILER
18467 /* For "omp declare target link" vars add address of the pointer to
18468 the target table, instead of address of the var. */
18469 tree value_expr = DECL_VALUE_EXPR (it);
18470 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18471 varpool_node::finalize_decl (link_ptr_decl);
18472 addr = build_fold_addr_expr (link_ptr_decl);
18473 #else
18474 addr = build_fold_addr_expr (it);
18475 #endif
18477 /* Most significant bit of the size marks "omp declare target link"
18478 vars in host and target tables. */
18479 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18480 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18481 * BITS_PER_UNIT - 1);
18482 size = wide_int_to_tree (const_ptr_type_node, isize);
18485 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18486 if (is_var)
18487 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18491 /* Create new symbols containing (address, size) pairs for global variables,
18492 marked with "omp declare target" attribute, as well as addresses for the
18493 functions, which are outlined offloading regions. */
18494 void
18495 omp_finish_file (void)
18497 unsigned num_funcs = vec_safe_length (offload_funcs);
18498 unsigned num_vars = vec_safe_length (offload_vars);
18500 if (num_funcs == 0 && num_vars == 0)
18501 return;
18503 if (targetm_common.have_named_sections)
18505 vec<constructor_elt, va_gc> *v_f, *v_v;
18506 vec_alloc (v_f, num_funcs);
18507 vec_alloc (v_v, num_vars * 2);
18509 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18510 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18512 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18513 num_vars * 2);
18514 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18515 num_funcs);
18516 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18517 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18518 tree ctor_v = build_constructor (vars_decl_type, v_v);
18519 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18520 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18521 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18522 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18523 get_identifier (".offload_func_table"),
18524 funcs_decl_type);
18525 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18526 get_identifier (".offload_var_table"),
18527 vars_decl_type);
18528 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18529 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18530 otherwise a joint table in a binary will contain padding between
18531 tables from multiple object files. */
18532 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18533 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18534 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18535 DECL_INITIAL (funcs_decl) = ctor_f;
18536 DECL_INITIAL (vars_decl) = ctor_v;
18537 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18538 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18540 varpool_node::finalize_decl (vars_decl);
18541 varpool_node::finalize_decl (funcs_decl);
18543 else
18545 for (unsigned i = 0; i < num_funcs; i++)
18547 tree it = (*offload_funcs)[i];
18548 targetm.record_offload_symbol (it);
18550 for (unsigned i = 0; i < num_vars; i++)
18552 tree it = (*offload_vars)[i];
18553 targetm.record_offload_symbol (it);
18558 /* Find the number of threads (POS = false), or thread number (POS =
18559 true) for an OpenACC region partitioned as MASK. Setup code
18560 required for the calculation is added to SEQ. */
18562 static tree
18563 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18565 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18566 unsigned ix;
18568 /* Start at gang level, and examine relevant dimension indices. */
18569 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18570 if (GOMP_DIM_MASK (ix) & mask)
18572 tree arg = build_int_cst (unsigned_type_node, ix);
18574 if (res)
18576 /* We had an outer index, so scale that by the size of
18577 this dimension. */
18578 tree n = create_tmp_var (integer_type_node);
18579 gimple *call
18580 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18582 gimple_call_set_lhs (call, n);
18583 gimple_seq_add_stmt (seq, call);
18584 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18586 if (pos)
18588 /* Determine index in this dimension. */
18589 tree id = create_tmp_var (integer_type_node);
18590 gimple *call = gimple_build_call_internal
18591 (IFN_GOACC_DIM_POS, 1, arg);
18593 gimple_call_set_lhs (call, id);
18594 gimple_seq_add_stmt (seq, call);
18595 if (res)
18596 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18597 else
18598 res = id;
18602 if (res == NULL_TREE)
18603 res = integer_zero_node;
18605 return res;
18608 /* Transform IFN_GOACC_LOOP calls to actual code. See
18609 expand_oacc_for for where these are generated. At the vector
18610 level, we stride loops, such that each member of a warp will
18611 operate on adjacent iterations. At the worker and gang level,
18612 each gang/warp executes a set of contiguous iterations. Chunking
18613 can override this such that each iteration engine executes a
18614 contiguous chunk, and then moves on to stride to the next chunk. */
18616 static void
18617 oacc_xform_loop (gcall *call)
18619 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18620 enum ifn_goacc_loop_kind code
18621 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18622 tree dir = gimple_call_arg (call, 1);
18623 tree range = gimple_call_arg (call, 2);
18624 tree step = gimple_call_arg (call, 3);
18625 tree chunk_size = NULL_TREE;
18626 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18627 tree lhs = gimple_call_lhs (call);
18628 tree type = TREE_TYPE (lhs);
18629 tree diff_type = TREE_TYPE (range);
18630 tree r = NULL_TREE;
18631 gimple_seq seq = NULL;
18632 bool chunking = false, striding = true;
18633 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18634 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18636 #ifdef ACCEL_COMPILER
18637 chunk_size = gimple_call_arg (call, 4);
18638 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18639 || integer_zerop (chunk_size)) /* Default (also static). */
18641 /* If we're at the gang level, we want each to execute a
18642 contiguous run of iterations. Otherwise we want each element
18643 to stride. */
18644 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18645 chunking = false;
18647 else
18649 /* Chunk of size 1 is striding. */
18650 striding = integer_onep (chunk_size);
18651 chunking = !striding;
18653 #endif
18655 /* striding=true, chunking=true
18656 -> invalid.
18657 striding=true, chunking=false
18658 -> chunks=1
18659 striding=false,chunking=true
18660 -> chunks=ceil (range/(chunksize*threads*step))
18661 striding=false,chunking=false
18662 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18663 push_gimplify_context (true);
18665 switch (code)
18667 default: gcc_unreachable ();
18669 case IFN_GOACC_LOOP_CHUNKS:
18670 if (!chunking)
18671 r = build_int_cst (type, 1);
18672 else
18674 /* chunk_max
18675 = (range - dir) / (chunks * step * num_threads) + dir */
18676 tree per = oacc_thread_numbers (false, mask, &seq);
18677 per = fold_convert (type, per);
18678 chunk_size = fold_convert (type, chunk_size);
18679 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18680 per = fold_build2 (MULT_EXPR, type, per, step);
18681 r = build2 (MINUS_EXPR, type, range, dir);
18682 r = build2 (PLUS_EXPR, type, r, per);
18683 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18685 break;
18687 case IFN_GOACC_LOOP_STEP:
18689 /* If striding, step by the entire compute volume, otherwise
18690 step by the inner volume. */
18691 unsigned volume = striding ? mask : inner_mask;
18693 r = oacc_thread_numbers (false, volume, &seq);
18694 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18696 break;
18698 case IFN_GOACC_LOOP_OFFSET:
18699 if (striding)
18701 r = oacc_thread_numbers (true, mask, &seq);
18702 r = fold_convert (diff_type, r);
18704 else
18706 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18707 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18708 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18709 inner_size, outer_size);
18711 volume = fold_convert (diff_type, volume);
18712 if (chunking)
18713 chunk_size = fold_convert (diff_type, chunk_size);
18714 else
18716 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18718 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18719 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18720 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18723 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18724 fold_convert (diff_type, inner_size));
18725 r = oacc_thread_numbers (true, outer_mask, &seq);
18726 r = fold_convert (diff_type, r);
18727 r = build2 (MULT_EXPR, diff_type, r, span);
18729 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18730 inner = fold_convert (diff_type, inner);
18731 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18733 if (chunking)
18735 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18736 tree per
18737 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18738 per = build2 (MULT_EXPR, diff_type, per, chunk);
18740 r = build2 (PLUS_EXPR, diff_type, r, per);
18743 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18744 if (type != diff_type)
18745 r = fold_convert (type, r);
18746 break;
18748 case IFN_GOACC_LOOP_BOUND:
18749 if (striding)
18750 r = range;
18751 else
18753 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18754 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18755 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18756 inner_size, outer_size);
18758 volume = fold_convert (diff_type, volume);
18759 if (chunking)
18760 chunk_size = fold_convert (diff_type, chunk_size);
18761 else
18763 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18765 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18766 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18767 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18770 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18771 fold_convert (diff_type, inner_size));
18773 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18775 tree offset = gimple_call_arg (call, 6);
18776 r = build2 (PLUS_EXPR, diff_type, r,
18777 fold_convert (diff_type, offset));
18778 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18779 diff_type, r, range);
18781 if (diff_type != type)
18782 r = fold_convert (type, r);
18783 break;
18786 gimplify_assign (lhs, r, &seq);
18788 pop_gimplify_context (NULL);
18790 gsi_replace_with_seq (&gsi, seq, true);
18793 /* Default partitioned and minimum partitioned dimensions. */
18795 static int oacc_default_dims[GOMP_DIM_MAX];
18796 static int oacc_min_dims[GOMP_DIM_MAX];
18798 /* Parse the default dimension parameter. This is a set of
18799 :-separated optional compute dimensions. Each specified dimension
18800 is a positive integer. When device type support is added, it is
18801 planned to be a comma separated list of such compute dimensions,
18802 with all but the first prefixed by the colon-terminated device
18803 type. */
18805 static void
18806 oacc_parse_default_dims (const char *dims)
18808 int ix;
18810 for (ix = GOMP_DIM_MAX; ix--;)
18812 oacc_default_dims[ix] = -1;
18813 oacc_min_dims[ix] = 1;
18816 #ifndef ACCEL_COMPILER
18817 /* Cannot be overridden on the host. */
18818 dims = NULL;
18819 #endif
18820 if (dims)
18822 const char *pos = dims;
18824 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18826 if (ix)
18828 if (*pos != ':')
18829 goto malformed;
18830 pos++;
18833 if (*pos != ':')
18835 long val;
18836 const char *eptr;
18838 errno = 0;
18839 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18840 if (errno || val <= 0 || (int) val != val)
18841 goto malformed;
18842 pos = eptr;
18843 oacc_default_dims[ix] = (int) val;
18846 if (*pos)
18848 malformed:
18849 error_at (UNKNOWN_LOCATION,
18850 "-fopenacc-dim operand is malformed at '%s'", pos);
18854 /* Allow the backend to validate the dimensions. */
18855 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18856 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18859 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18860 raw attribute. DIMS is an array of dimensions, which is filled in.
18861 LEVEL is the partitioning level of a routine, or -1 for an offload
18862 region itself. USED is the mask of partitioned execution in the
18863 function. */
18865 static void
18866 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18868 tree purpose[GOMP_DIM_MAX];
18869 unsigned ix;
18870 tree pos = TREE_VALUE (attrs);
18871 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18873 /* Make sure the attribute creator attached the dimension
18874 information. */
18875 gcc_assert (pos);
18877 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18879 purpose[ix] = TREE_PURPOSE (pos);
18880 tree val = TREE_VALUE (pos);
18881 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18882 pos = TREE_CHAIN (pos);
18885 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18887 /* Default anything left to 1 or a partitioned default. */
18888 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18889 if (dims[ix] < 0)
18891 /* The OpenACC spec says 'If the [num_gangs] clause is not
18892 specified, an implementation-defined default will be used;
18893 the default may depend on the code within the construct.'
18894 (2.5.6). Thus an implementation is free to choose
18895 non-unity default for a parallel region that doesn't have
18896 any gang-partitioned loops. However, it appears that there
18897 is a sufficient body of user code that expects non-gang
18898 partitioned regions to not execute in gang-redundant mode.
18899 So we (a) don't warn about the non-portability and (b) pick
18900 the minimum permissible dimension size when there is no
18901 partitioned execution. Otherwise we pick the global
18902 default for the dimension, which the user can control. The
18903 same wording and logic applies to num_workers and
18904 vector_length, however the worker- or vector- single
18905 execution doesn't have the same impact as gang-redundant
18906 execution. (If the minimum gang-level partioning is not 1,
18907 the target is probably too confusing.) */
18908 dims[ix] = (used & GOMP_DIM_MASK (ix)
18909 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18910 changed = true;
18913 if (changed)
18915 /* Replace the attribute with new values. */
18916 pos = NULL_TREE;
18917 for (ix = GOMP_DIM_MAX; ix--;)
18919 pos = tree_cons (purpose[ix],
18920 build_int_cst (integer_type_node, dims[ix]),
18921 pos);
18922 if (is_kernel)
18923 TREE_PUBLIC (pos) = 1;
18925 replace_oacc_fn_attrib (fn, pos);
18929 /* Create an empty OpenACC loop structure at LOC. */
18931 static oacc_loop *
18932 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18934 oacc_loop *loop = XCNEW (oacc_loop);
18936 loop->parent = parent;
18937 loop->child = loop->sibling = NULL;
18939 if (parent)
18941 loop->sibling = parent->child;
18942 parent->child = loop;
18945 loop->loc = loc;
18946 loop->marker = NULL;
18947 memset (loop->heads, 0, sizeof (loop->heads));
18948 memset (loop->tails, 0, sizeof (loop->tails));
18949 loop->routine = NULL_TREE;
18951 loop->mask = loop->flags = loop->inner = 0;
18952 loop->ifns = 0;
18953 loop->chunk_size = 0;
18954 loop->head_end = NULL;
18956 return loop;
18959 /* Create an outermost, dummy OpenACC loop for offloaded function
18960 DECL. */
18962 static oacc_loop *
18963 new_oacc_loop_outer (tree decl)
18965 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18968 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18969 Link into PARENT loop. Return the new loop. */
18971 static oacc_loop *
18972 new_oacc_loop (oacc_loop *parent, gcall *marker)
18974 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18976 loop->marker = marker;
18978 /* TODO: This is where device_type flattening would occur for the loop
18979 flags. */
18981 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18983 tree chunk_size = integer_zero_node;
18984 if (loop->flags & OLF_GANG_STATIC)
18985 chunk_size = gimple_call_arg (marker, 4);
18986 loop->chunk_size = chunk_size;
18988 return loop;
18991 /* Create a dummy loop encompassing a call to a openACC routine.
18992 Extract the routine's partitioning requirements. */
18994 static void
18995 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18997 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18998 int level = oacc_fn_attrib_level (attrs);
19000 gcc_assert (level >= 0);
19002 loop->marker = call;
19003 loop->routine = decl;
19004 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19005 ^ (GOMP_DIM_MASK (level) - 1));
19008 /* Finish off the current OpenACC loop ending at tail marker TAIL.
19009 Return the parent loop. */
19011 static oacc_loop *
19012 finish_oacc_loop (oacc_loop *loop)
19014 /* If the loop has been collapsed, don't partition it. */
19015 if (!loop->ifns)
19016 loop->mask = loop->flags = 0;
19017 return loop->parent;
19020 /* Free all OpenACC loop structures within LOOP (inclusive). */
19022 static void
19023 free_oacc_loop (oacc_loop *loop)
19025 if (loop->sibling)
19026 free_oacc_loop (loop->sibling);
19027 if (loop->child)
19028 free_oacc_loop (loop->child);
19030 free (loop);
19033 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19035 static void
19036 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19037 const char *title, int level)
19039 enum ifn_unique_kind kind
19040 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19042 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19043 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19045 gimple *stmt = gsi_stmt (gsi);
19047 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19049 enum ifn_unique_kind k
19050 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19051 (gimple_call_arg (stmt, 0)));
19053 if (k == kind && stmt != from)
19054 break;
19056 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19058 gsi_next (&gsi);
19059 while (gsi_end_p (gsi))
19060 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19064 /* Dump OpenACC loops LOOP, its siblings and its children. */
19066 static void
19067 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19069 int ix;
19071 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19072 loop->flags, loop->mask,
19073 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19075 if (loop->marker)
19076 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19078 if (loop->routine)
19079 fprintf (file, "%*sRoutine %s:%u:%s\n",
19080 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19081 DECL_SOURCE_LINE (loop->routine),
19082 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19084 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19085 if (loop->heads[ix])
19086 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19087 for (ix = GOMP_DIM_MAX; ix--;)
19088 if (loop->tails[ix])
19089 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19091 if (loop->child)
19092 dump_oacc_loop (file, loop->child, depth + 1);
19093 if (loop->sibling)
19094 dump_oacc_loop (file, loop->sibling, depth);
19097 void debug_oacc_loop (oacc_loop *);
19099 /* Dump loops to stderr. */
19101 DEBUG_FUNCTION void
19102 debug_oacc_loop (oacc_loop *loop)
19104 dump_oacc_loop (stderr, loop, 0);
19107 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19108 structures as we go. By construction these loops are properly
19109 nested. */
19111 static void
19112 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19114 int marker = 0;
19115 int remaining = 0;
19117 if (bb->flags & BB_VISITED)
19118 return;
19120 follow:
19121 bb->flags |= BB_VISITED;
19123 /* Scan for loop markers. */
19124 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19125 gsi_next (&gsi))
19127 gimple *stmt = gsi_stmt (gsi);
19129 if (!is_gimple_call (stmt))
19130 continue;
19132 gcall *call = as_a <gcall *> (stmt);
19134 /* If this is a routine, make a dummy loop for it. */
19135 if (tree decl = gimple_call_fndecl (call))
19136 if (tree attrs = get_oacc_fn_attrib (decl))
19138 gcc_assert (!marker);
19139 new_oacc_loop_routine (loop, call, decl, attrs);
19142 if (!gimple_call_internal_p (call))
19143 continue;
19145 switch (gimple_call_internal_fn (call))
19147 default:
19148 break;
19150 case IFN_GOACC_LOOP:
19151 /* Count the goacc loop abstraction fns, to determine if the
19152 loop was collapsed already. */
19153 loop->ifns++;
19154 break;
19156 case IFN_UNIQUE:
19157 enum ifn_unique_kind kind
19158 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19159 (gimple_call_arg (call, 0)));
19160 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19161 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19163 if (gimple_call_num_args (call) == 2)
19165 gcc_assert (marker && !remaining);
19166 marker = 0;
19167 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19168 loop = finish_oacc_loop (loop);
19169 else
19170 loop->head_end = call;
19172 else
19174 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19176 if (!marker)
19178 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19179 loop = new_oacc_loop (loop, call);
19180 remaining = count;
19182 gcc_assert (count == remaining);
19183 if (remaining)
19185 remaining--;
19186 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19187 loop->heads[marker] = call;
19188 else
19189 loop->tails[remaining] = call;
19191 marker++;
19196 if (remaining || marker)
19198 bb = single_succ (bb);
19199 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19200 goto follow;
19203 /* Walk successor blocks. */
19204 edge e;
19205 edge_iterator ei;
19207 FOR_EACH_EDGE (e, ei, bb->succs)
19208 oacc_loop_discover_walk (loop, e->dest);
19211 /* LOOP is the first sibling. Reverse the order in place and return
19212 the new first sibling. Recurse to child loops. */
19214 static oacc_loop *
19215 oacc_loop_sibling_nreverse (oacc_loop *loop)
19217 oacc_loop *last = NULL;
19220 if (loop->child)
19221 loop->child = oacc_loop_sibling_nreverse (loop->child);
19223 oacc_loop *next = loop->sibling;
19224 loop->sibling = last;
19225 last = loop;
19226 loop = next;
19228 while (loop);
19230 return last;
19233 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19234 the current function. */
19236 static oacc_loop *
19237 oacc_loop_discovery ()
19239 /* Clear basic block flags, in particular BB_VISITED which we're going to use
19240 in the following. */
19241 clear_bb_flags ();
19243 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19244 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19246 /* The siblings were constructed in reverse order, reverse them so
19247 that diagnostics come out in an unsurprising order. */
19248 top = oacc_loop_sibling_nreverse (top);
19250 return top;
19253 /* Transform the abstract internal function markers starting at FROM
19254 to be for partitioning level LEVEL. Stop when we meet another HEAD
19255 or TAIL marker. */
19257 static void
19258 oacc_loop_xform_head_tail (gcall *from, int level)
19260 enum ifn_unique_kind kind
19261 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19262 tree replacement = build_int_cst (unsigned_type_node, level);
19264 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19266 gimple *stmt = gsi_stmt (gsi);
19268 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19270 enum ifn_unique_kind k
19271 = ((enum ifn_unique_kind)
19272 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19274 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19275 *gimple_call_arg_ptr (stmt, 2) = replacement;
19276 else if (k == kind && stmt != from)
19277 break;
19279 else if (gimple_call_internal_p (stmt, IFN_GOACC_REDUCTION))
19280 *gimple_call_arg_ptr (stmt, 3) = replacement;
19282 gsi_next (&gsi);
19283 while (gsi_end_p (gsi))
19284 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19288 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19289 determined partitioning mask and chunking argument. END_MARKER
19290 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19291 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19292 the replacement partitioning mask and CHUNK_ARG is the replacement
19293 chunking arg. */
19295 static void
19296 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19297 tree mask_arg, tree chunk_arg)
19299 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19301 gcc_checking_assert (ifns);
19302 for (;;)
19304 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19306 gimple *stmt = gsi_stmt (gsi);
19308 if (!is_gimple_call (stmt))
19309 continue;
19311 gcall *call = as_a <gcall *> (stmt);
19313 if (!gimple_call_internal_p (call))
19314 continue;
19316 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19317 continue;
19319 *gimple_call_arg_ptr (call, 5) = mask_arg;
19320 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19321 ifns--;
19322 if (!ifns)
19323 return;
19326 /* The LOOP_BOUND ifn could be in the single successor
19327 block. */
19328 basic_block bb = single_succ (gsi_bb (gsi));
19329 gsi = gsi_start_bb (bb);
19333 /* Process the discovered OpenACC loops, setting the correct
19334 partitioning level etc. */
19336 static void
19337 oacc_loop_process (oacc_loop *loop)
19339 if (loop->child)
19340 oacc_loop_process (loop->child);
19342 if (loop->mask && !loop->routine)
19344 int ix;
19345 unsigned mask = loop->mask;
19346 unsigned dim = GOMP_DIM_GANG;
19347 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19348 tree chunk_arg = loop->chunk_size;
19350 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19352 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19354 while (!(GOMP_DIM_MASK (dim) & mask))
19355 dim++;
19357 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19358 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19360 mask ^= GOMP_DIM_MASK (dim);
19364 if (loop->sibling)
19365 oacc_loop_process (loop->sibling);
19368 /* Walk the OpenACC loop heirarchy checking and assigning the
19369 programmer-specified partitionings. OUTER_MASK is the partitioning
19370 this loop is contained within. Return mask of partitioning
19371 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19372 bit. */
19374 static unsigned
19375 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19377 unsigned this_mask = loop->mask;
19378 unsigned mask_all = 0;
19379 bool noisy = true;
19381 #ifdef ACCEL_COMPILER
19382 /* When device_type is supported, we want the device compiler to be
19383 noisy, if the loop parameters are device_type-specific. */
19384 noisy = false;
19385 #endif
19387 if (!loop->routine)
19389 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19390 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19392 this_mask = ((loop->flags >> OLF_DIM_BASE)
19393 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19395 if ((this_mask != 0) + auto_par + seq_par > 1)
19397 if (noisy)
19398 error_at (loop->loc,
19399 seq_par
19400 ? "%<seq%> overrides other OpenACC loop specifiers"
19401 : "%<auto%> conflicts with other OpenACC loop specifiers");
19402 auto_par = false;
19403 loop->flags &= ~OLF_AUTO;
19404 if (seq_par)
19406 loop->flags &=
19407 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19408 this_mask = 0;
19411 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19412 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19415 if (this_mask & outer_mask)
19417 const oacc_loop *outer;
19418 for (outer = loop->parent; outer; outer = outer->parent)
19419 if (outer->mask & this_mask)
19420 break;
19422 if (noisy)
19424 if (outer)
19426 error_at (loop->loc,
19427 "%s uses same OpenACC parallelism as containing loop",
19428 loop->routine ? "routine call" : "inner loop");
19429 inform (outer->loc, "containing loop here");
19431 else
19432 error_at (loop->loc,
19433 "%s uses OpenACC parallelism disallowed by containing routine",
19434 loop->routine ? "routine call" : "loop");
19436 if (loop->routine)
19437 inform (DECL_SOURCE_LOCATION (loop->routine),
19438 "routine %qD declared here", loop->routine);
19440 this_mask &= ~outer_mask;
19442 else
19444 unsigned outermost = least_bit_hwi (this_mask);
19446 if (outermost && outermost <= outer_mask)
19448 if (noisy)
19450 error_at (loop->loc,
19451 "incorrectly nested OpenACC loop parallelism");
19453 const oacc_loop *outer;
19454 for (outer = loop->parent;
19455 outer->flags && outer->flags < outermost;
19456 outer = outer->parent)
19457 continue;
19458 inform (outer->loc, "containing loop here");
19461 this_mask &= ~outermost;
19465 loop->mask = this_mask;
19466 mask_all |= this_mask;
19468 if (loop->child)
19470 loop->inner = oacc_loop_fixed_partitions (loop->child,
19471 outer_mask | this_mask);
19472 mask_all |= loop->inner;
19475 if (loop->sibling)
19476 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19478 return mask_all;
19481 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19482 OUTER_MASK is the partitioning this loop is contained within.
19483 Return the cumulative partitioning used by this loop, siblings and
19484 children. */
19486 static unsigned
19487 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19489 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19490 bool noisy = true;
19492 #ifdef ACCEL_COMPILER
19493 /* When device_type is supported, we want the device compiler to be
19494 noisy, if the loop parameters are device_type-specific. */
19495 noisy = false;
19496 #endif
19498 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19500 /* Allocate the outermost loop at the outermost available
19501 level. */
19502 unsigned this_mask = outer_mask + 1;
19504 if (!(this_mask & loop->inner))
19505 loop->mask = this_mask;
19508 if (loop->child)
19510 unsigned child_mask = outer_mask | loop->mask;
19512 if (loop->mask || assign)
19513 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19515 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19518 if (assign && !loop->mask)
19520 /* Allocate the loop at the innermost available level. */
19521 unsigned this_mask = 0;
19523 /* Determine the outermost partitioning used within this loop. */
19524 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19525 this_mask = least_bit_hwi (this_mask);
19527 /* Pick the partitioning just inside that one. */
19528 this_mask >>= 1;
19530 /* And avoid picking one use by an outer loop. */
19531 this_mask &= ~outer_mask;
19533 if (!this_mask && noisy)
19534 warning_at (loop->loc, 0,
19535 "insufficient partitioning available to parallelize loop");
19537 loop->mask = this_mask;
19540 if (assign && dump_file)
19541 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19542 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19543 loop->mask);
19545 unsigned inner_mask = 0;
19547 if (loop->sibling)
19548 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19550 inner_mask |= loop->inner | loop->mask;
19552 return inner_mask;
19555 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19556 axes. Return mask of partitioning. */
19558 static unsigned
19559 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19561 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19563 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19565 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19566 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19568 return mask_all;
19571 /* Default fork/join early expander. Delete the function calls if
19572 there is no RTL expander. */
19574 bool
19575 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19576 const int *ARG_UNUSED (dims), bool is_fork)
19578 if (is_fork)
19579 return targetm.have_oacc_fork ();
19580 else
19581 return targetm.have_oacc_join ();
19584 /* Default goacc.reduction early expander.
19586 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19587 If RES_PTR is not integer-zerop:
19588 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19589 TEARDOWN - emit '*RES_PTR = VAR'
19590 If LHS is not NULL
19591 emit 'LHS = VAR' */
19593 void
19594 default_goacc_reduction (gcall *call)
19596 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19597 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19598 tree lhs = gimple_call_lhs (call);
19599 tree var = gimple_call_arg (call, 2);
19600 gimple_seq seq = NULL;
19602 if (code == IFN_GOACC_REDUCTION_SETUP
19603 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19605 /* Setup and Teardown need to copy from/to the receiver object,
19606 if there is one. */
19607 tree ref_to_res = gimple_call_arg (call, 1);
19609 if (!integer_zerop (ref_to_res))
19611 tree dst = build_simple_mem_ref (ref_to_res);
19612 tree src = var;
19614 if (code == IFN_GOACC_REDUCTION_SETUP)
19616 src = dst;
19617 dst = lhs;
19618 lhs = NULL;
19620 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19624 /* Copy VAR to LHS, if there is an LHS. */
19625 if (lhs)
19626 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19628 gsi_replace_with_seq (&gsi, seq, true);
19631 /* Main entry point for oacc transformations which run on the device
19632 compiler after LTO, so we know what the target device is at this
19633 point (including the host fallback). */
19635 static unsigned int
19636 execute_oacc_device_lower ()
19638 tree attrs = get_oacc_fn_attrib (current_function_decl);
19640 if (!attrs)
19641 /* Not an offloaded function. */
19642 return 0;
19644 /* Parse the default dim argument exactly once. */
19645 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19647 oacc_parse_default_dims (flag_openacc_dims);
19648 flag_openacc_dims = (char *)&flag_openacc_dims;
19651 /* Discover, partition and process the loops. */
19652 oacc_loop *loops = oacc_loop_discovery ();
19653 int fn_level = oacc_fn_attrib_level (attrs);
19655 if (dump_file)
19656 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19657 ? "Function is kernels offload\n"
19658 : fn_level < 0 ? "Function is parallel offload\n"
19659 : "Function is routine level %d\n", fn_level);
19661 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19662 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19663 int dims[GOMP_DIM_MAX];
19665 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19667 if (dump_file)
19669 const char *comma = "Compute dimensions [";
19670 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19671 fprintf (dump_file, "%s%d", comma, dims[ix]);
19672 fprintf (dump_file, "]\n");
19675 oacc_loop_process (loops);
19676 if (dump_file)
19678 fprintf (dump_file, "OpenACC loops\n");
19679 dump_oacc_loop (dump_file, loops, 0);
19680 fprintf (dump_file, "\n");
19683 /* Offloaded targets may introduce new basic blocks, which require
19684 dominance information to update SSA. */
19685 calculate_dominance_info (CDI_DOMINATORS);
19687 /* Now lower internal loop functions to target-specific code
19688 sequences. */
19689 basic_block bb;
19690 FOR_ALL_BB_FN (bb, cfun)
19691 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19693 gimple *stmt = gsi_stmt (gsi);
19694 if (!is_gimple_call (stmt))
19696 gsi_next (&gsi);
19697 continue;
19700 gcall *call = as_a <gcall *> (stmt);
19701 if (!gimple_call_internal_p (call))
19703 gsi_next (&gsi);
19704 continue;
19707 /* Rewind to allow rescan. */
19708 gsi_prev (&gsi);
19709 bool rescan = false, remove = false;
19710 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19712 switch (ifn_code)
19714 default: break;
19716 case IFN_GOACC_LOOP:
19717 oacc_xform_loop (call);
19718 rescan = true;
19719 break;
19721 case IFN_GOACC_REDUCTION:
19722 /* Mark the function for SSA renaming. */
19723 mark_virtual_operands_for_renaming (cfun);
19725 /* If the level is -1, this ended up being an unused
19726 axis. Handle as a default. */
19727 if (integer_minus_onep (gimple_call_arg (call, 3)))
19728 default_goacc_reduction (call);
19729 else
19730 targetm.goacc.reduction (call);
19731 rescan = true;
19732 break;
19734 case IFN_UNIQUE:
19736 enum ifn_unique_kind kind
19737 = ((enum ifn_unique_kind)
19738 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19740 switch (kind)
19742 default:
19743 gcc_unreachable ();
19745 case IFN_UNIQUE_OACC_FORK:
19746 case IFN_UNIQUE_OACC_JOIN:
19747 if (integer_minus_onep (gimple_call_arg (call, 2)))
19748 remove = true;
19749 else if (!targetm.goacc.fork_join
19750 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19751 remove = true;
19752 break;
19754 case IFN_UNIQUE_OACC_HEAD_MARK:
19755 case IFN_UNIQUE_OACC_TAIL_MARK:
19756 remove = true;
19757 break;
19759 break;
19763 if (gsi_end_p (gsi))
19764 /* We rewound past the beginning of the BB. */
19765 gsi = gsi_start_bb (bb);
19766 else
19767 /* Undo the rewind. */
19768 gsi_next (&gsi);
19770 if (remove)
19772 if (gimple_vdef (call))
19773 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19774 if (gimple_call_lhs (call))
19776 /* Propagate the data dependency var. */
19777 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19778 gimple_call_arg (call, 1));
19779 gsi_replace (&gsi, ass, false);
19781 else
19782 gsi_remove (&gsi, true);
19784 else if (!rescan)
19785 /* If not rescanning, advance over the call. */
19786 gsi_next (&gsi);
19789 free_oacc_loop (loops);
19791 return 0;
19794 /* Default launch dimension validator. Force everything to 1. A
19795 backend that wants to provide larger dimensions must override this
19796 hook. */
19798 bool
19799 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19800 int ARG_UNUSED (fn_level))
19802 bool changed = false;
19804 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19806 if (dims[ix] != 1)
19808 dims[ix] = 1;
19809 changed = true;
19813 return changed;
19816 /* Default dimension bound is unknown on accelerator and 1 on host. */
19819 default_goacc_dim_limit (int ARG_UNUSED (axis))
19821 #ifdef ACCEL_COMPILER
19822 return 0;
19823 #else
19824 return 1;
19825 #endif
19828 namespace {
19830 const pass_data pass_data_oacc_device_lower =
19832 GIMPLE_PASS, /* type */
19833 "oaccdevlow", /* name */
19834 OPTGROUP_NONE, /* optinfo_flags */
19835 TV_NONE, /* tv_id */
19836 PROP_cfg, /* properties_required */
19837 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19838 0, /* properties_destroyed */
19839 0, /* todo_flags_start */
19840 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19843 class pass_oacc_device_lower : public gimple_opt_pass
19845 public:
19846 pass_oacc_device_lower (gcc::context *ctxt)
19847 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19850 /* opt_pass methods: */
19851 virtual bool gate (function *) { return flag_openacc; };
19853 virtual unsigned int execute (function *)
19855 return execute_oacc_device_lower ();
19858 }; // class pass_oacc_device_lower
19860 } // anon namespace
19862 gimple_opt_pass *
19863 make_pass_oacc_device_lower (gcc::context *ctxt)
19865 return new pass_oacc_device_lower (ctxt);
19868 /* "omp declare target link" handling pass. */
19870 namespace {
19872 const pass_data pass_data_omp_target_link =
19874 GIMPLE_PASS, /* type */
19875 "omptargetlink", /* name */
19876 OPTGROUP_NONE, /* optinfo_flags */
19877 TV_NONE, /* tv_id */
19878 PROP_ssa, /* properties_required */
19879 0, /* properties_provided */
19880 0, /* properties_destroyed */
19881 0, /* todo_flags_start */
19882 TODO_update_ssa, /* todo_flags_finish */
19885 class pass_omp_target_link : public gimple_opt_pass
19887 public:
19888 pass_omp_target_link (gcc::context *ctxt)
19889 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19892 /* opt_pass methods: */
19893 virtual bool gate (function *fun)
19895 #ifdef ACCEL_COMPILER
19896 tree attrs = DECL_ATTRIBUTES (fun->decl);
19897 return lookup_attribute ("omp declare target", attrs)
19898 || lookup_attribute ("omp target entrypoint", attrs);
19899 #else
19900 (void) fun;
19901 return false;
19902 #endif
19905 virtual unsigned execute (function *);
19908 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19910 static tree
19911 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19913 tree t = *tp;
19915 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t)
19916 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19918 *walk_subtrees = 0;
19919 return t;
19922 return NULL_TREE;
19925 unsigned
19926 pass_omp_target_link::execute (function *fun)
19928 basic_block bb;
19929 FOR_EACH_BB_FN (bb, fun)
19931 gimple_stmt_iterator gsi;
19932 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19933 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19934 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19937 return 0;
19940 } // anon namespace
19942 gimple_opt_pass *
19943 make_pass_omp_target_link (gcc::context *ctxt)
19945 return new pass_omp_target_link (ctxt);
19948 #include "gt-omp-low.h"