ifcvt-4.c: Add hppa*64*-*-* to skip list.
[official-gcc.git] / gcc / omp-low.c
blob82dec9d09b4d00737968552eadfaa5fa7d172dce
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83 #include "symbol-summary.h"
84 #include "hsa.h"
85 #include "params.h"
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
92 expressions.
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
102 struct omp_region
104 /* The enclosing region. */
105 struct omp_region *outer;
107 /* First child region. */
108 struct omp_region *inner;
110 /* Next peer region. */
111 struct omp_region *next;
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 basic_block exit;
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 basic_block cont;
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind;
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple *stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
201 struct omp_for_data_loop
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
207 /* A structure describing the main elements of a parallel loop. */
209 struct omp_for_data
211 struct omp_for_data_loop loop;
212 tree chunk_size;
213 gomp_for *for_stmt;
214 tree pre, iter_type;
215 int collapse;
216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
218 unsigned char sched_modifiers;
219 enum omp_clause_schedule_kind sched_kind;
220 struct omp_for_data_loop *loops;
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
226 struct oacc_loop
228 oacc_loop *parent; /* Containing loop. */
230 oacc_loop *child; /* First inner loop. */
232 oacc_loop *sibling; /* Next loop within same parent. */
234 location_t loc; /* Location of the loop start. */
236 gcall *marker; /* Initial head marker. */
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
241 tree routine; /* Pseudo-loop enclosing a routine. */
243 unsigned mask; /* Partitioning mask. */
244 unsigned flags; /* Partitioning flags. */
245 unsigned ifns; /* Contained loop abstraction functions. */
246 tree chunk_size; /* Chunk size. */
247 gcall *head_end; /* Final marker of head sequence. */
250 /* Flags for an OpenACC loop. */
252 enum oacc_loop_flags {
253 OLF_SEQ = 1u << 0, /* Explicitly sequential */
254 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
255 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
256 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
258 /* Explicitly specified loop axes. */
259 OLF_DIM_BASE = 4,
260 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
261 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
262 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
264 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
268 static splay_tree all_contexts;
269 static int taskreg_nesting_level;
270 static int target_nesting_level;
271 static struct omp_region *root_omp_region;
272 static bitmap task_shared_vars;
273 static vec<omp_context *> taskreg_contexts;
274 static bool omp_any_child_fn_dumped;
276 static void scan_omp (gimple_seq *, omp_context *);
277 static tree scan_omp_1_op (tree *, int *, void *);
278 static gphi *find_phi_with_arg_on_edge (tree, edge);
280 #define WALK_SUBSTMTS \
281 case GIMPLE_BIND: \
282 case GIMPLE_TRY: \
283 case GIMPLE_CATCH: \
284 case GIMPLE_EH_FILTER: \
285 case GIMPLE_TRANSACTION: \
286 /* The sub-statements for these should be walked. */ \
287 *handled_ops_p = false; \
288 break;
290 /* Return true if CTX corresponds to an oacc parallel region. */
292 static bool
293 is_oacc_parallel (omp_context *ctx)
295 enum gimple_code outer_type = gimple_code (ctx->stmt);
296 return ((outer_type == GIMPLE_OMP_TARGET)
297 && (gimple_omp_target_kind (ctx->stmt)
298 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
301 /* Return true if CTX corresponds to an oacc kernels region. */
303 static bool
304 is_oacc_kernels (omp_context *ctx)
306 enum gimple_code outer_type = gimple_code (ctx->stmt);
307 return ((outer_type == GIMPLE_OMP_TARGET)
308 && (gimple_omp_target_kind (ctx->stmt)
309 == GF_OMP_TARGET_KIND_OACC_KERNELS));
312 /* If DECL is the artificial dummy VAR_DECL created for non-static
313 data member privatization, return the underlying "this" parameter,
314 otherwise return NULL. */
316 tree
317 omp_member_access_dummy_var (tree decl)
319 if (!VAR_P (decl)
320 || !DECL_ARTIFICIAL (decl)
321 || !DECL_IGNORED_P (decl)
322 || !DECL_HAS_VALUE_EXPR_P (decl)
323 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
324 return NULL_TREE;
326 tree v = DECL_VALUE_EXPR (decl);
327 if (TREE_CODE (v) != COMPONENT_REF)
328 return NULL_TREE;
330 while (1)
331 switch (TREE_CODE (v))
333 case COMPONENT_REF:
334 case MEM_REF:
335 case INDIRECT_REF:
336 CASE_CONVERT:
337 case POINTER_PLUS_EXPR:
338 v = TREE_OPERAND (v, 0);
339 continue;
340 case PARM_DECL:
341 if (DECL_CONTEXT (v) == current_function_decl
342 && DECL_ARTIFICIAL (v)
343 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
344 return v;
345 return NULL_TREE;
346 default:
347 return NULL_TREE;
351 /* Helper for unshare_and_remap, called through walk_tree. */
353 static tree
354 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
356 tree *pair = (tree *) data;
357 if (*tp == pair[0])
359 *tp = unshare_expr (pair[1]);
360 *walk_subtrees = 0;
362 else if (IS_TYPE_OR_DECL_P (*tp))
363 *walk_subtrees = 0;
364 return NULL_TREE;
367 /* Return unshare_expr (X) with all occurrences of FROM
368 replaced with TO. */
370 static tree
371 unshare_and_remap (tree x, tree from, tree to)
373 tree pair[2] = { from, to };
374 x = unshare_expr (x);
375 walk_tree (&x, unshare_and_remap_1, pair, NULL);
376 return x;
379 /* Holds offload tables with decls. */
380 vec<tree, va_gc> *offload_funcs, *offload_vars;
382 /* Convenience function for calling scan_omp_1_op on tree operands. */
384 static inline tree
385 scan_omp_op (tree *tp, omp_context *ctx)
387 struct walk_stmt_info wi;
389 memset (&wi, 0, sizeof (wi));
390 wi.info = ctx;
391 wi.want_locations = true;
393 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
396 static void lower_omp (gimple_seq *, omp_context *);
397 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
398 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
400 /* Find an OMP clause of type KIND within CLAUSES. */
402 tree
403 find_omp_clause (tree clauses, enum omp_clause_code kind)
405 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
406 if (OMP_CLAUSE_CODE (clauses) == kind)
407 return clauses;
409 return NULL_TREE;
412 /* Return true if CTX is for an omp parallel. */
414 static inline bool
415 is_parallel_ctx (omp_context *ctx)
417 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
421 /* Return true if CTX is for an omp task. */
423 static inline bool
424 is_task_ctx (omp_context *ctx)
426 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
430 /* Return true if CTX is for an omp taskloop. */
432 static inline bool
433 is_taskloop_ctx (omp_context *ctx)
435 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
436 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
440 /* Return true if CTX is for an omp parallel or omp task. */
442 static inline bool
443 is_taskreg_ctx (omp_context *ctx)
445 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
449 /* Return true if REGION is a combined parallel+workshare region. */
451 static inline bool
452 is_combined_parallel (struct omp_region *region)
454 return region->is_combined_parallel;
457 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
458 GT_EXPR. */
460 static void
461 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
463 switch (*cond_code)
465 case LT_EXPR:
466 case GT_EXPR:
467 case NE_EXPR:
468 break;
469 case LE_EXPR:
470 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
471 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
472 else
473 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
474 build_int_cst (TREE_TYPE (*n2), 1));
475 *cond_code = LT_EXPR;
476 break;
477 case GE_EXPR:
478 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
479 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
480 else
481 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
482 build_int_cst (TREE_TYPE (*n2), 1));
483 *cond_code = GT_EXPR;
484 break;
485 default:
486 gcc_unreachable ();
490 /* Return the looping step from INCR, extracted from the step of a gimple omp
491 for statement. */
493 static tree
494 get_omp_for_step_from_incr (location_t loc, tree incr)
496 tree step;
497 switch (TREE_CODE (incr))
499 case PLUS_EXPR:
500 step = TREE_OPERAND (incr, 1);
501 break;
502 case POINTER_PLUS_EXPR:
503 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
504 break;
505 case MINUS_EXPR:
506 step = TREE_OPERAND (incr, 1);
507 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
508 break;
509 default:
510 gcc_unreachable ();
512 return step;
515 /* Extract the header elements of parallel loop FOR_STMT and store
516 them into *FD. */
518 static void
519 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
520 struct omp_for_data_loop *loops)
522 tree t, var, *collapse_iter, *collapse_count;
523 tree count = NULL_TREE, iter_type = long_integer_type_node;
524 struct omp_for_data_loop *loop;
525 int i;
526 struct omp_for_data_loop dummy_loop;
527 location_t loc = gimple_location (for_stmt);
528 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
529 bool distribute = gimple_omp_for_kind (for_stmt)
530 == GF_OMP_FOR_KIND_DISTRIBUTE;
531 bool taskloop = gimple_omp_for_kind (for_stmt)
532 == GF_OMP_FOR_KIND_TASKLOOP;
533 tree iterv, countv;
535 fd->for_stmt = for_stmt;
536 fd->pre = NULL;
537 if (gimple_omp_for_collapse (for_stmt) > 1)
538 fd->loops = loops;
539 else
540 fd->loops = &fd->loop;
542 fd->have_nowait = distribute || simd;
543 fd->have_ordered = false;
544 fd->collapse = 1;
545 fd->ordered = 0;
546 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
547 fd->sched_modifiers = 0;
548 fd->chunk_size = NULL_TREE;
549 fd->simd_schedule = false;
550 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
551 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
552 collapse_iter = NULL;
553 collapse_count = NULL;
555 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
556 switch (OMP_CLAUSE_CODE (t))
558 case OMP_CLAUSE_NOWAIT:
559 fd->have_nowait = true;
560 break;
561 case OMP_CLAUSE_ORDERED:
562 fd->have_ordered = true;
563 if (OMP_CLAUSE_ORDERED_EXPR (t))
564 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
565 break;
566 case OMP_CLAUSE_SCHEDULE:
567 gcc_assert (!distribute && !taskloop);
568 fd->sched_kind
569 = (enum omp_clause_schedule_kind)
570 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
571 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
572 & ~OMP_CLAUSE_SCHEDULE_MASK);
573 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
574 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
575 break;
576 case OMP_CLAUSE_DIST_SCHEDULE:
577 gcc_assert (distribute);
578 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
579 break;
580 case OMP_CLAUSE_COLLAPSE:
581 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
582 if (fd->collapse > 1)
584 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
585 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
587 break;
588 default:
589 break;
591 if (fd->ordered && fd->collapse == 1 && loops != NULL)
593 fd->loops = loops;
594 iterv = NULL_TREE;
595 countv = NULL_TREE;
596 collapse_iter = &iterv;
597 collapse_count = &countv;
600 /* FIXME: for now map schedule(auto) to schedule(static).
601 There should be analysis to determine whether all iterations
602 are approximately the same amount of work (then schedule(static)
603 is best) or if it varies (then schedule(dynamic,N) is better). */
604 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
606 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
607 gcc_assert (fd->chunk_size == NULL);
609 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
610 if (taskloop)
611 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
612 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
613 gcc_assert (fd->chunk_size == NULL);
614 else if (fd->chunk_size == NULL)
616 /* We only need to compute a default chunk size for ordered
617 static loops and dynamic loops. */
618 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
619 || fd->have_ordered)
620 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
621 ? integer_zero_node : integer_one_node;
624 int cnt = fd->ordered ? fd->ordered : fd->collapse;
625 for (i = 0; i < cnt; i++)
627 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
628 loop = &fd->loop;
629 else if (loops != NULL)
630 loop = loops + i;
631 else
632 loop = &dummy_loop;
634 loop->v = gimple_omp_for_index (for_stmt, i);
635 gcc_assert (SSA_VAR_P (loop->v));
636 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
637 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
638 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
639 loop->n1 = gimple_omp_for_initial (for_stmt, i);
641 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
642 loop->n2 = gimple_omp_for_final (for_stmt, i);
643 gcc_assert (loop->cond_code != NE_EXPR
644 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
646 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
648 t = gimple_omp_for_incr (for_stmt, i);
649 gcc_assert (TREE_OPERAND (t, 0) == var);
650 loop->step = get_omp_for_step_from_incr (loc, t);
652 if (simd
653 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
654 && !fd->have_ordered))
656 if (fd->collapse == 1)
657 iter_type = TREE_TYPE (loop->v);
658 else if (i == 0
659 || TYPE_PRECISION (iter_type)
660 < TYPE_PRECISION (TREE_TYPE (loop->v)))
661 iter_type
662 = build_nonstandard_integer_type
663 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
665 else if (iter_type != long_long_unsigned_type_node)
667 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
668 iter_type = long_long_unsigned_type_node;
669 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
670 && TYPE_PRECISION (TREE_TYPE (loop->v))
671 >= TYPE_PRECISION (iter_type))
673 tree n;
675 if (loop->cond_code == LT_EXPR)
676 n = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
678 loop->n2, loop->step);
679 else
680 n = loop->n1;
681 if (TREE_CODE (n) != INTEGER_CST
682 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
683 iter_type = long_long_unsigned_type_node;
685 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
686 > TYPE_PRECISION (iter_type))
688 tree n1, n2;
690 if (loop->cond_code == LT_EXPR)
692 n1 = loop->n1;
693 n2 = fold_build2_loc (loc,
694 PLUS_EXPR, TREE_TYPE (loop->v),
695 loop->n2, loop->step);
697 else
699 n1 = fold_build2_loc (loc,
700 MINUS_EXPR, TREE_TYPE (loop->v),
701 loop->n2, loop->step);
702 n2 = loop->n1;
704 if (TREE_CODE (n1) != INTEGER_CST
705 || TREE_CODE (n2) != INTEGER_CST
706 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
707 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
708 iter_type = long_long_unsigned_type_node;
712 if (i >= fd->collapse)
713 continue;
715 if (collapse_count && *collapse_count == NULL)
717 t = fold_binary (loop->cond_code, boolean_type_node,
718 fold_convert (TREE_TYPE (loop->v), loop->n1),
719 fold_convert (TREE_TYPE (loop->v), loop->n2));
720 if (t && integer_zerop (t))
721 count = build_zero_cst (long_long_unsigned_type_node);
722 else if ((i == 0 || count != NULL_TREE)
723 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
724 && TREE_CONSTANT (loop->n1)
725 && TREE_CONSTANT (loop->n2)
726 && TREE_CODE (loop->step) == INTEGER_CST)
728 tree itype = TREE_TYPE (loop->v);
730 if (POINTER_TYPE_P (itype))
731 itype = signed_type_for (itype);
732 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
733 t = fold_build2_loc (loc,
734 PLUS_EXPR, itype,
735 fold_convert_loc (loc, itype, loop->step), t);
736 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
737 fold_convert_loc (loc, itype, loop->n2));
738 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
739 fold_convert_loc (loc, itype, loop->n1));
740 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
741 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
742 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
743 fold_build1_loc (loc, NEGATE_EXPR, itype,
744 fold_convert_loc (loc, itype,
745 loop->step)));
746 else
747 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
748 fold_convert_loc (loc, itype, loop->step));
749 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
750 if (count != NULL_TREE)
751 count = fold_build2_loc (loc,
752 MULT_EXPR, long_long_unsigned_type_node,
753 count, t);
754 else
755 count = t;
756 if (TREE_CODE (count) != INTEGER_CST)
757 count = NULL_TREE;
759 else if (count && !integer_zerop (count))
760 count = NULL_TREE;
764 if (count
765 && !simd
766 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
767 || fd->have_ordered))
769 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
770 iter_type = long_long_unsigned_type_node;
771 else
772 iter_type = long_integer_type_node;
774 else if (collapse_iter && *collapse_iter != NULL)
775 iter_type = TREE_TYPE (*collapse_iter);
776 fd->iter_type = iter_type;
777 if (collapse_iter && *collapse_iter == NULL)
778 *collapse_iter = create_tmp_var (iter_type, ".iter");
779 if (collapse_count && *collapse_count == NULL)
781 if (count)
782 *collapse_count = fold_convert_loc (loc, iter_type, count);
783 else
784 *collapse_count = create_tmp_var (iter_type, ".count");
787 if (fd->collapse > 1 || (fd->ordered && loops))
789 fd->loop.v = *collapse_iter;
790 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
791 fd->loop.n2 = *collapse_count;
792 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
793 fd->loop.cond_code = LT_EXPR;
795 else if (loops)
796 loops[0] = fd->loop;
800 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
801 is the immediate dominator of PAR_ENTRY_BB, return true if there
802 are no data dependencies that would prevent expanding the parallel
803 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
805 When expanding a combined parallel+workshare region, the call to
806 the child function may need additional arguments in the case of
807 GIMPLE_OMP_FOR regions. In some cases, these arguments are
808 computed out of variables passed in from the parent to the child
809 via 'struct .omp_data_s'. For instance:
811 #pragma omp parallel for schedule (guided, i * 4)
812 for (j ...)
814 Is lowered into:
816 # BLOCK 2 (PAR_ENTRY_BB)
817 .omp_data_o.i = i;
818 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
820 # BLOCK 3 (WS_ENTRY_BB)
821 .omp_data_i = &.omp_data_o;
822 D.1667 = .omp_data_i->i;
823 D.1598 = D.1667 * 4;
824 #pragma omp for schedule (guided, D.1598)
826 When we outline the parallel region, the call to the child function
827 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
828 that value is computed *after* the call site. So, in principle we
829 cannot do the transformation.
831 To see whether the code in WS_ENTRY_BB blocks the combined
832 parallel+workshare call, we collect all the variables used in the
833 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
834 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
835 call.
837 FIXME. If we had the SSA form built at this point, we could merely
838 hoist the code in block 3 into block 2 and be done with it. But at
839 this point we don't have dataflow information and though we could
840 hack something up here, it is really not worth the aggravation. */
842 static bool
843 workshare_safe_to_combine_p (basic_block ws_entry_bb)
845 struct omp_for_data fd;
846 gimple *ws_stmt = last_stmt (ws_entry_bb);
848 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
849 return true;
851 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
853 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
855 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
856 return false;
857 if (fd.iter_type != long_integer_type_node)
858 return false;
860 /* FIXME. We give up too easily here. If any of these arguments
861 are not constants, they will likely involve variables that have
862 been mapped into fields of .omp_data_s for sharing with the child
863 function. With appropriate data flow, it would be possible to
864 see through this. */
865 if (!is_gimple_min_invariant (fd.loop.n1)
866 || !is_gimple_min_invariant (fd.loop.n2)
867 || !is_gimple_min_invariant (fd.loop.step)
868 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
869 return false;
871 return true;
875 static int omp_max_vf (void);
877 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
878 presence (SIMD_SCHEDULE). */
880 static tree
881 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
883 if (!simd_schedule)
884 return chunk_size;
886 int vf = omp_max_vf ();
887 if (vf == 1)
888 return chunk_size;
890 tree type = TREE_TYPE (chunk_size);
891 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
892 build_int_cst (type, vf - 1));
893 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
894 build_int_cst (type, -vf));
898 /* Collect additional arguments needed to emit a combined
899 parallel+workshare call. WS_STMT is the workshare directive being
900 expanded. */
902 static vec<tree, va_gc> *
903 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
905 tree t;
906 location_t loc = gimple_location (ws_stmt);
907 vec<tree, va_gc> *ws_args;
909 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
911 struct omp_for_data fd;
912 tree n1, n2;
914 extract_omp_for_data (for_stmt, &fd, NULL);
915 n1 = fd.loop.n1;
916 n2 = fd.loop.n2;
918 if (gimple_omp_for_combined_into_p (for_stmt))
920 tree innerc
921 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
922 OMP_CLAUSE__LOOPTEMP_);
923 gcc_assert (innerc);
924 n1 = OMP_CLAUSE_DECL (innerc);
925 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
926 OMP_CLAUSE__LOOPTEMP_);
927 gcc_assert (innerc);
928 n2 = OMP_CLAUSE_DECL (innerc);
931 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
933 t = fold_convert_loc (loc, long_integer_type_node, n1);
934 ws_args->quick_push (t);
936 t = fold_convert_loc (loc, long_integer_type_node, n2);
937 ws_args->quick_push (t);
939 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
940 ws_args->quick_push (t);
942 if (fd.chunk_size)
944 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
945 t = omp_adjust_chunk_size (t, fd.simd_schedule);
946 ws_args->quick_push (t);
949 return ws_args;
951 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
953 /* Number of sections is equal to the number of edges from the
954 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
955 the exit of the sections region. */
956 basic_block bb = single_succ (gimple_bb (ws_stmt));
957 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
958 vec_alloc (ws_args, 1);
959 ws_args->quick_push (t);
960 return ws_args;
963 gcc_unreachable ();
967 /* Discover whether REGION is a combined parallel+workshare region. */
969 static void
970 determine_parallel_type (struct omp_region *region)
972 basic_block par_entry_bb, par_exit_bb;
973 basic_block ws_entry_bb, ws_exit_bb;
975 if (region == NULL || region->inner == NULL
976 || region->exit == NULL || region->inner->exit == NULL
977 || region->inner->cont == NULL)
978 return;
980 /* We only support parallel+for and parallel+sections. */
981 if (region->type != GIMPLE_OMP_PARALLEL
982 || (region->inner->type != GIMPLE_OMP_FOR
983 && region->inner->type != GIMPLE_OMP_SECTIONS))
984 return;
986 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
987 WS_EXIT_BB -> PAR_EXIT_BB. */
988 par_entry_bb = region->entry;
989 par_exit_bb = region->exit;
990 ws_entry_bb = region->inner->entry;
991 ws_exit_bb = region->inner->exit;
993 if (single_succ (par_entry_bb) == ws_entry_bb
994 && single_succ (ws_exit_bb) == par_exit_bb
995 && workshare_safe_to_combine_p (ws_entry_bb)
996 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
997 || (last_and_only_stmt (ws_entry_bb)
998 && last_and_only_stmt (par_exit_bb))))
1000 gimple *par_stmt = last_stmt (par_entry_bb);
1001 gimple *ws_stmt = last_stmt (ws_entry_bb);
1003 if (region->inner->type == GIMPLE_OMP_FOR)
1005 /* If this is a combined parallel loop, we need to determine
1006 whether or not to use the combined library calls. There
1007 are two cases where we do not apply the transformation:
1008 static loops and any kind of ordered loop. In the first
1009 case, we already open code the loop so there is no need
1010 to do anything else. In the latter case, the combined
1011 parallel loop call would still need extra synchronization
1012 to implement ordered semantics, so there would not be any
1013 gain in using the combined call. */
1014 tree clauses = gimple_omp_for_clauses (ws_stmt);
1015 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1016 if (c == NULL
1017 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1018 == OMP_CLAUSE_SCHEDULE_STATIC)
1019 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1021 region->is_combined_parallel = false;
1022 region->inner->is_combined_parallel = false;
1023 return;
1027 region->is_combined_parallel = true;
1028 region->inner->is_combined_parallel = true;
1029 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1034 /* Return true if EXPR is variable sized. */
1036 static inline bool
1037 is_variable_sized (const_tree expr)
1039 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1042 /* Return true if DECL is a reference type. */
1044 static inline bool
1045 is_reference (tree decl)
1047 return lang_hooks.decls.omp_privatize_by_reference (decl);
1050 /* Return the type of a decl. If the decl is reference type,
1051 return its base type. */
1052 static inline tree
1053 get_base_type (tree decl)
1055 tree type = TREE_TYPE (decl);
1056 if (is_reference (decl))
1057 type = TREE_TYPE (type);
1058 return type;
1061 /* Lookup variables. The "maybe" form
1062 allows for the variable form to not have been entered, otherwise we
1063 assert that the variable must have been entered. */
1065 static inline tree
1066 lookup_decl (tree var, omp_context *ctx)
1068 tree *n = ctx->cb.decl_map->get (var);
1069 return *n;
1072 static inline tree
1073 maybe_lookup_decl (const_tree var, omp_context *ctx)
1075 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1076 return n ? *n : NULL_TREE;
1079 static inline tree
1080 lookup_field (tree var, omp_context *ctx)
1082 splay_tree_node n;
1083 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1084 return (tree) n->value;
1087 static inline tree
1088 lookup_sfield (splay_tree_key key, omp_context *ctx)
1090 splay_tree_node n;
1091 n = splay_tree_lookup (ctx->sfield_map
1092 ? ctx->sfield_map : ctx->field_map, key);
1093 return (tree) n->value;
1096 static inline tree
1097 lookup_sfield (tree var, omp_context *ctx)
1099 return lookup_sfield ((splay_tree_key) var, ctx);
1102 static inline tree
1103 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1105 splay_tree_node n;
1106 n = splay_tree_lookup (ctx->field_map, key);
1107 return n ? (tree) n->value : NULL_TREE;
1110 static inline tree
1111 maybe_lookup_field (tree var, omp_context *ctx)
1113 return maybe_lookup_field ((splay_tree_key) var, ctx);
1116 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1117 the parallel context if DECL is to be shared. */
1119 static bool
1120 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1122 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1123 return true;
1125 /* We can only use copy-in/copy-out semantics for shared variables
1126 when we know the value is not accessible from an outer scope. */
1127 if (shared_ctx)
1129 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1131 /* ??? Trivially accessible from anywhere. But why would we even
1132 be passing an address in this case? Should we simply assert
1133 this to be false, or should we have a cleanup pass that removes
1134 these from the list of mappings? */
1135 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1136 return true;
1138 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1139 without analyzing the expression whether or not its location
1140 is accessible to anyone else. In the case of nested parallel
1141 regions it certainly may be. */
1142 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1143 return true;
1145 /* Do not use copy-in/copy-out for variables that have their
1146 address taken. */
1147 if (TREE_ADDRESSABLE (decl))
1148 return true;
1150 /* lower_send_shared_vars only uses copy-in, but not copy-out
1151 for these. */
1152 if (TREE_READONLY (decl)
1153 || ((TREE_CODE (decl) == RESULT_DECL
1154 || TREE_CODE (decl) == PARM_DECL)
1155 && DECL_BY_REFERENCE (decl)))
1156 return false;
1158 /* Disallow copy-in/out in nested parallel if
1159 decl is shared in outer parallel, otherwise
1160 each thread could store the shared variable
1161 in its own copy-in location, making the
1162 variable no longer really shared. */
1163 if (shared_ctx->is_nested)
1165 omp_context *up;
1167 for (up = shared_ctx->outer; up; up = up->outer)
1168 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1169 break;
1171 if (up)
1173 tree c;
1175 for (c = gimple_omp_taskreg_clauses (up->stmt);
1176 c; c = OMP_CLAUSE_CHAIN (c))
1177 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1178 && OMP_CLAUSE_DECL (c) == decl)
1179 break;
1181 if (c)
1182 goto maybe_mark_addressable_and_ret;
1186 /* For tasks avoid using copy-in/out. As tasks can be
1187 deferred or executed in different thread, when GOMP_task
1188 returns, the task hasn't necessarily terminated. */
1189 if (is_task_ctx (shared_ctx))
1191 tree outer;
1192 maybe_mark_addressable_and_ret:
1193 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1194 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1196 /* Taking address of OUTER in lower_send_shared_vars
1197 might need regimplification of everything that uses the
1198 variable. */
1199 if (!task_shared_vars)
1200 task_shared_vars = BITMAP_ALLOC (NULL);
1201 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1202 TREE_ADDRESSABLE (outer) = 1;
1204 return true;
1208 return false;
1211 /* Construct a new automatic decl similar to VAR. */
1213 static tree
1214 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1216 tree copy = copy_var_decl (var, name, type);
1218 DECL_CONTEXT (copy) = current_function_decl;
1219 DECL_CHAIN (copy) = ctx->block_vars;
1220 /* If VAR is listed in task_shared_vars, it means it wasn't
1221 originally addressable and is just because task needs to take
1222 it's address. But we don't need to take address of privatizations
1223 from that var. */
1224 if (TREE_ADDRESSABLE (var)
1225 && task_shared_vars
1226 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1227 TREE_ADDRESSABLE (copy) = 0;
1228 ctx->block_vars = copy;
1230 return copy;
1233 static tree
1234 omp_copy_decl_1 (tree var, omp_context *ctx)
1236 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1239 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1240 as appropriate. */
1241 static tree
1242 omp_build_component_ref (tree obj, tree field)
1244 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1245 if (TREE_THIS_VOLATILE (field))
1246 TREE_THIS_VOLATILE (ret) |= 1;
1247 if (TREE_READONLY (field))
1248 TREE_READONLY (ret) |= 1;
1249 return ret;
1252 /* Build tree nodes to access the field for VAR on the receiver side. */
1254 static tree
1255 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1257 tree x, field = lookup_field (var, ctx);
1259 /* If the receiver record type was remapped in the child function,
1260 remap the field into the new record type. */
1261 x = maybe_lookup_field (field, ctx);
1262 if (x != NULL)
1263 field = x;
1265 x = build_simple_mem_ref (ctx->receiver_decl);
1266 TREE_THIS_NOTRAP (x) = 1;
1267 x = omp_build_component_ref (x, field);
1268 if (by_ref)
1270 x = build_simple_mem_ref (x);
1271 TREE_THIS_NOTRAP (x) = 1;
1274 return x;
1277 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1278 of a parallel, this is a component reference; for workshare constructs
1279 this is some variable. */
1281 static tree
1282 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1284 tree x;
1286 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1287 x = var;
1288 else if (is_variable_sized (var))
1290 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1291 x = build_outer_var_ref (x, ctx, lastprivate);
1292 x = build_simple_mem_ref (x);
1294 else if (is_taskreg_ctx (ctx))
1296 bool by_ref = use_pointer_for_field (var, NULL);
1297 x = build_receiver_ref (var, by_ref, ctx);
1299 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1300 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1302 /* #pragma omp simd isn't a worksharing construct, and can reference even
1303 private vars in its linear etc. clauses. */
1304 x = NULL_TREE;
1305 if (ctx->outer && is_taskreg_ctx (ctx))
1306 x = lookup_decl (var, ctx->outer);
1307 else if (ctx->outer)
1308 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1309 if (x == NULL_TREE)
1310 x = var;
1312 else if (lastprivate && is_taskloop_ctx (ctx))
1314 gcc_assert (ctx->outer);
1315 splay_tree_node n
1316 = splay_tree_lookup (ctx->outer->field_map,
1317 (splay_tree_key) &DECL_UID (var));
1318 if (n == NULL)
1320 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1321 x = var;
1322 else
1323 x = lookup_decl (var, ctx->outer);
1325 else
1327 tree field = (tree) n->value;
1328 /* If the receiver record type was remapped in the child function,
1329 remap the field into the new record type. */
1330 x = maybe_lookup_field (field, ctx->outer);
1331 if (x != NULL)
1332 field = x;
1334 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1335 x = omp_build_component_ref (x, field);
1336 if (use_pointer_for_field (var, ctx->outer))
1337 x = build_simple_mem_ref (x);
1340 else if (ctx->outer)
1342 omp_context *outer = ctx->outer;
1343 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1345 outer = outer->outer;
1346 gcc_assert (outer
1347 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1349 x = lookup_decl (var, outer);
1351 else if (is_reference (var))
1352 /* This can happen with orphaned constructs. If var is reference, it is
1353 possible it is shared and as such valid. */
1354 x = var;
1355 else if (omp_member_access_dummy_var (var))
1356 x = var;
1357 else
1358 gcc_unreachable ();
1360 if (x == var)
1362 tree t = omp_member_access_dummy_var (var);
1363 if (t)
1365 x = DECL_VALUE_EXPR (var);
1366 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1367 if (o != t)
1368 x = unshare_and_remap (x, t, o);
1369 else
1370 x = unshare_expr (x);
1374 if (is_reference (var))
1375 x = build_simple_mem_ref (x);
1377 return x;
1380 /* Build tree nodes to access the field for VAR on the sender side. */
1382 static tree
1383 build_sender_ref (splay_tree_key key, omp_context *ctx)
1385 tree field = lookup_sfield (key, ctx);
1386 return omp_build_component_ref (ctx->sender_decl, field);
1389 static tree
1390 build_sender_ref (tree var, omp_context *ctx)
1392 return build_sender_ref ((splay_tree_key) var, ctx);
1395 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1396 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1398 static void
1399 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1400 bool base_pointers_restrict = false)
1402 tree field, type, sfield = NULL_TREE;
1403 splay_tree_key key = (splay_tree_key) var;
1405 if ((mask & 8) != 0)
1407 key = (splay_tree_key) &DECL_UID (var);
1408 gcc_checking_assert (key != (splay_tree_key) var);
1410 gcc_assert ((mask & 1) == 0
1411 || !splay_tree_lookup (ctx->field_map, key));
1412 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1413 || !splay_tree_lookup (ctx->sfield_map, key));
1414 gcc_assert ((mask & 3) == 3
1415 || !is_gimple_omp_oacc (ctx->stmt));
1417 type = TREE_TYPE (var);
1418 /* Prevent redeclaring the var in the split-off function with a restrict
1419 pointer type. Note that we only clear type itself, restrict qualifiers in
1420 the pointed-to type will be ignored by points-to analysis. */
1421 if (POINTER_TYPE_P (type)
1422 && TYPE_RESTRICT (type))
1423 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1425 if (mask & 4)
1427 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1428 type = build_pointer_type (build_pointer_type (type));
1430 else if (by_ref)
1432 type = build_pointer_type (type);
1433 if (base_pointers_restrict)
1434 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1436 else if ((mask & 3) == 1 && is_reference (var))
1437 type = TREE_TYPE (type);
1439 field = build_decl (DECL_SOURCE_LOCATION (var),
1440 FIELD_DECL, DECL_NAME (var), type);
1442 /* Remember what variable this field was created for. This does have a
1443 side effect of making dwarf2out ignore this member, so for helpful
1444 debugging we clear it later in delete_omp_context. */
1445 DECL_ABSTRACT_ORIGIN (field) = var;
1446 if (type == TREE_TYPE (var))
1448 DECL_ALIGN (field) = DECL_ALIGN (var);
1449 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1450 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1452 else
1453 DECL_ALIGN (field) = TYPE_ALIGN (type);
1455 if ((mask & 3) == 3)
1457 insert_field_into_struct (ctx->record_type, field);
1458 if (ctx->srecord_type)
1460 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1461 FIELD_DECL, DECL_NAME (var), type);
1462 DECL_ABSTRACT_ORIGIN (sfield) = var;
1463 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1464 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1465 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1466 insert_field_into_struct (ctx->srecord_type, sfield);
1469 else
1471 if (ctx->srecord_type == NULL_TREE)
1473 tree t;
1475 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1476 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1477 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1479 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1480 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1481 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1482 insert_field_into_struct (ctx->srecord_type, sfield);
1483 splay_tree_insert (ctx->sfield_map,
1484 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1485 (splay_tree_value) sfield);
1488 sfield = field;
1489 insert_field_into_struct ((mask & 1) ? ctx->record_type
1490 : ctx->srecord_type, field);
1493 if (mask & 1)
1494 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1495 if ((mask & 2) && ctx->sfield_map)
1496 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1499 static tree
1500 install_var_local (tree var, omp_context *ctx)
1502 tree new_var = omp_copy_decl_1 (var, ctx);
1503 insert_decl_map (&ctx->cb, var, new_var);
1504 return new_var;
1507 /* Adjust the replacement for DECL in CTX for the new context. This means
1508 copying the DECL_VALUE_EXPR, and fixing up the type. */
1510 static void
1511 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1513 tree new_decl, size;
1515 new_decl = lookup_decl (decl, ctx);
1517 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1519 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1520 && DECL_HAS_VALUE_EXPR_P (decl))
1522 tree ve = DECL_VALUE_EXPR (decl);
1523 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1524 SET_DECL_VALUE_EXPR (new_decl, ve);
1525 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1528 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1530 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1531 if (size == error_mark_node)
1532 size = TYPE_SIZE (TREE_TYPE (new_decl));
1533 DECL_SIZE (new_decl) = size;
1535 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1536 if (size == error_mark_node)
1537 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1538 DECL_SIZE_UNIT (new_decl) = size;
1542 /* The callback for remap_decl. Search all containing contexts for a
1543 mapping of the variable; this avoids having to duplicate the splay
1544 tree ahead of time. We know a mapping doesn't already exist in the
1545 given context. Create new mappings to implement default semantics. */
1547 static tree
1548 omp_copy_decl (tree var, copy_body_data *cb)
1550 omp_context *ctx = (omp_context *) cb;
1551 tree new_var;
1553 if (TREE_CODE (var) == LABEL_DECL)
1555 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1556 DECL_CONTEXT (new_var) = current_function_decl;
1557 insert_decl_map (&ctx->cb, var, new_var);
1558 return new_var;
1561 while (!is_taskreg_ctx (ctx))
1563 ctx = ctx->outer;
1564 if (ctx == NULL)
1565 return var;
1566 new_var = maybe_lookup_decl (var, ctx);
1567 if (new_var)
1568 return new_var;
1571 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1572 return var;
1574 return error_mark_node;
1578 /* Debugging dumps for parallel regions. */
1579 void dump_omp_region (FILE *, struct omp_region *, int);
1580 void debug_omp_region (struct omp_region *);
1581 void debug_all_omp_regions (void);
1583 /* Dump the parallel region tree rooted at REGION. */
1585 void
1586 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1588 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1589 gimple_code_name[region->type]);
1591 if (region->inner)
1592 dump_omp_region (file, region->inner, indent + 4);
1594 if (region->cont)
1596 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1597 region->cont->index);
1600 if (region->exit)
1601 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1602 region->exit->index);
1603 else
1604 fprintf (file, "%*s[no exit marker]\n", indent, "");
1606 if (region->next)
1607 dump_omp_region (file, region->next, indent);
1610 DEBUG_FUNCTION void
1611 debug_omp_region (struct omp_region *region)
1613 dump_omp_region (stderr, region, 0);
1616 DEBUG_FUNCTION void
1617 debug_all_omp_regions (void)
1619 dump_omp_region (stderr, root_omp_region, 0);
1623 /* Create a new parallel region starting at STMT inside region PARENT. */
1625 static struct omp_region *
1626 new_omp_region (basic_block bb, enum gimple_code type,
1627 struct omp_region *parent)
1629 struct omp_region *region = XCNEW (struct omp_region);
1631 region->outer = parent;
1632 region->entry = bb;
1633 region->type = type;
1635 if (parent)
1637 /* This is a nested region. Add it to the list of inner
1638 regions in PARENT. */
1639 region->next = parent->inner;
1640 parent->inner = region;
1642 else
1644 /* This is a toplevel region. Add it to the list of toplevel
1645 regions in ROOT_OMP_REGION. */
1646 region->next = root_omp_region;
1647 root_omp_region = region;
1650 return region;
1653 /* Release the memory associated with the region tree rooted at REGION. */
1655 static void
1656 free_omp_region_1 (struct omp_region *region)
1658 struct omp_region *i, *n;
1660 for (i = region->inner; i ; i = n)
1662 n = i->next;
1663 free_omp_region_1 (i);
1666 free (region);
1669 /* Release the memory for the entire omp region tree. */
1671 void
1672 free_omp_regions (void)
1674 struct omp_region *r, *n;
1675 for (r = root_omp_region; r ; r = n)
1677 n = r->next;
1678 free_omp_region_1 (r);
1680 root_omp_region = NULL;
1684 /* Create a new context, with OUTER_CTX being the surrounding context. */
1686 static omp_context *
1687 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1689 omp_context *ctx = XCNEW (omp_context);
1691 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1692 (splay_tree_value) ctx);
1693 ctx->stmt = stmt;
1695 if (outer_ctx)
1697 ctx->outer = outer_ctx;
1698 ctx->cb = outer_ctx->cb;
1699 ctx->cb.block = NULL;
1700 ctx->depth = outer_ctx->depth + 1;
1702 else
1704 ctx->cb.src_fn = current_function_decl;
1705 ctx->cb.dst_fn = current_function_decl;
1706 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1707 gcc_checking_assert (ctx->cb.src_node);
1708 ctx->cb.dst_node = ctx->cb.src_node;
1709 ctx->cb.src_cfun = cfun;
1710 ctx->cb.copy_decl = omp_copy_decl;
1711 ctx->cb.eh_lp_nr = 0;
1712 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1713 ctx->depth = 1;
1716 ctx->cb.decl_map = new hash_map<tree, tree>;
1718 return ctx;
1721 static gimple_seq maybe_catch_exception (gimple_seq);
1723 /* Finalize task copyfn. */
1725 static void
1726 finalize_task_copyfn (gomp_task *task_stmt)
1728 struct function *child_cfun;
1729 tree child_fn;
1730 gimple_seq seq = NULL, new_seq;
1731 gbind *bind;
1733 child_fn = gimple_omp_task_copy_fn (task_stmt);
1734 if (child_fn == NULL_TREE)
1735 return;
1737 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1738 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1740 push_cfun (child_cfun);
1741 bind = gimplify_body (child_fn, false);
1742 gimple_seq_add_stmt (&seq, bind);
1743 new_seq = maybe_catch_exception (seq);
1744 if (new_seq != seq)
1746 bind = gimple_build_bind (NULL, new_seq, NULL);
1747 seq = NULL;
1748 gimple_seq_add_stmt (&seq, bind);
1750 gimple_set_body (child_fn, seq);
1751 pop_cfun ();
1753 /* Inform the callgraph about the new function. */
1754 cgraph_node *node = cgraph_node::get_create (child_fn);
1755 node->parallelized_function = 1;
1756 cgraph_node::add_new_function (child_fn, false);
1759 /* Destroy a omp_context data structures. Called through the splay tree
1760 value delete callback. */
1762 static void
1763 delete_omp_context (splay_tree_value value)
1765 omp_context *ctx = (omp_context *) value;
1767 delete ctx->cb.decl_map;
1769 if (ctx->field_map)
1770 splay_tree_delete (ctx->field_map);
1771 if (ctx->sfield_map)
1772 splay_tree_delete (ctx->sfield_map);
1774 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1775 it produces corrupt debug information. */
1776 if (ctx->record_type)
1778 tree t;
1779 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1780 DECL_ABSTRACT_ORIGIN (t) = NULL;
1782 if (ctx->srecord_type)
1784 tree t;
1785 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1786 DECL_ABSTRACT_ORIGIN (t) = NULL;
1789 if (is_task_ctx (ctx))
1790 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1792 XDELETE (ctx);
1795 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1796 context. */
1798 static void
1799 fixup_child_record_type (omp_context *ctx)
1801 tree f, type = ctx->record_type;
1803 if (!ctx->receiver_decl)
1804 return;
1805 /* ??? It isn't sufficient to just call remap_type here, because
1806 variably_modified_type_p doesn't work the way we expect for
1807 record types. Testing each field for whether it needs remapping
1808 and creating a new record by hand works, however. */
1809 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1810 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1811 break;
1812 if (f)
1814 tree name, new_fields = NULL;
1816 type = lang_hooks.types.make_type (RECORD_TYPE);
1817 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1818 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1819 TYPE_DECL, name, type);
1820 TYPE_NAME (type) = name;
1822 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1824 tree new_f = copy_node (f);
1825 DECL_CONTEXT (new_f) = type;
1826 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1827 DECL_CHAIN (new_f) = new_fields;
1828 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1829 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1830 &ctx->cb, NULL);
1831 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1832 &ctx->cb, NULL);
1833 new_fields = new_f;
1835 /* Arrange to be able to look up the receiver field
1836 given the sender field. */
1837 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1838 (splay_tree_value) new_f);
1840 TYPE_FIELDS (type) = nreverse (new_fields);
1841 layout_type (type);
1844 /* In a target region we never modify any of the pointers in *.omp_data_i,
1845 so attempt to help the optimizers. */
1846 if (is_gimple_omp_offloaded (ctx->stmt))
1847 type = build_qualified_type (type, TYPE_QUAL_CONST);
1849 TREE_TYPE (ctx->receiver_decl)
1850 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1853 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1854 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1855 restrict. */
1857 static void
1858 scan_sharing_clauses (tree clauses, omp_context *ctx,
1859 bool base_pointers_restrict = false)
1861 tree c, decl;
1862 bool scan_array_reductions = false;
1864 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1866 bool by_ref;
1868 switch (OMP_CLAUSE_CODE (c))
1870 case OMP_CLAUSE_PRIVATE:
1871 decl = OMP_CLAUSE_DECL (c);
1872 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1873 goto do_private;
1874 else if (!is_variable_sized (decl))
1875 install_var_local (decl, ctx);
1876 break;
1878 case OMP_CLAUSE_SHARED:
1879 decl = OMP_CLAUSE_DECL (c);
1880 /* Ignore shared directives in teams construct. */
1881 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1883 /* Global variables don't need to be copied,
1884 the receiver side will use them directly. */
1885 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1886 if (is_global_var (odecl))
1887 break;
1888 insert_decl_map (&ctx->cb, decl, odecl);
1889 break;
1891 gcc_assert (is_taskreg_ctx (ctx));
1892 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1893 || !is_variable_sized (decl));
1894 /* Global variables don't need to be copied,
1895 the receiver side will use them directly. */
1896 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1897 break;
1898 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1900 use_pointer_for_field (decl, ctx);
1901 break;
1903 by_ref = use_pointer_for_field (decl, NULL);
1904 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1905 || TREE_ADDRESSABLE (decl)
1906 || by_ref
1907 || is_reference (decl))
1909 by_ref = use_pointer_for_field (decl, ctx);
1910 install_var_field (decl, by_ref, 3, ctx);
1911 install_var_local (decl, ctx);
1912 break;
1914 /* We don't need to copy const scalar vars back. */
1915 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1916 goto do_private;
1918 case OMP_CLAUSE_REDUCTION:
1919 decl = OMP_CLAUSE_DECL (c);
1920 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1921 && TREE_CODE (decl) == MEM_REF)
1923 tree t = TREE_OPERAND (decl, 0);
1924 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1925 t = TREE_OPERAND (t, 0);
1926 if (TREE_CODE (t) == INDIRECT_REF
1927 || TREE_CODE (t) == ADDR_EXPR)
1928 t = TREE_OPERAND (t, 0);
1929 install_var_local (t, ctx);
1930 if (is_taskreg_ctx (ctx)
1931 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1932 && !is_variable_sized (t))
1934 by_ref = use_pointer_for_field (t, ctx);
1935 install_var_field (t, by_ref, 3, ctx);
1937 break;
1939 goto do_private;
1941 case OMP_CLAUSE_LASTPRIVATE:
1942 /* Let the corresponding firstprivate clause create
1943 the variable. */
1944 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1945 break;
1946 /* FALLTHRU */
1948 case OMP_CLAUSE_FIRSTPRIVATE:
1949 case OMP_CLAUSE_LINEAR:
1950 decl = OMP_CLAUSE_DECL (c);
1951 do_private:
1952 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1953 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1954 && is_gimple_omp_offloaded (ctx->stmt))
1956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1957 install_var_field (decl, !is_reference (decl), 3, ctx);
1958 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1959 install_var_field (decl, true, 3, ctx);
1960 else
1961 install_var_field (decl, false, 3, ctx);
1963 if (is_variable_sized (decl))
1965 if (is_task_ctx (ctx))
1966 install_var_field (decl, false, 1, ctx);
1967 break;
1969 else if (is_taskreg_ctx (ctx))
1971 bool global
1972 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1973 by_ref = use_pointer_for_field (decl, NULL);
1975 if (is_task_ctx (ctx)
1976 && (global || by_ref || is_reference (decl)))
1978 install_var_field (decl, false, 1, ctx);
1979 if (!global)
1980 install_var_field (decl, by_ref, 2, ctx);
1982 else if (!global)
1983 install_var_field (decl, by_ref, 3, ctx);
1985 install_var_local (decl, ctx);
1986 break;
1988 case OMP_CLAUSE_USE_DEVICE_PTR:
1989 decl = OMP_CLAUSE_DECL (c);
1990 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1991 install_var_field (decl, true, 3, ctx);
1992 else
1993 install_var_field (decl, false, 3, ctx);
1994 if (DECL_SIZE (decl)
1995 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1997 tree decl2 = DECL_VALUE_EXPR (decl);
1998 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1999 decl2 = TREE_OPERAND (decl2, 0);
2000 gcc_assert (DECL_P (decl2));
2001 install_var_local (decl2, ctx);
2003 install_var_local (decl, ctx);
2004 break;
2006 case OMP_CLAUSE_IS_DEVICE_PTR:
2007 decl = OMP_CLAUSE_DECL (c);
2008 goto do_private;
2010 case OMP_CLAUSE__LOOPTEMP_:
2011 gcc_assert (is_taskreg_ctx (ctx));
2012 decl = OMP_CLAUSE_DECL (c);
2013 install_var_field (decl, false, 3, ctx);
2014 install_var_local (decl, ctx);
2015 break;
2017 case OMP_CLAUSE_COPYPRIVATE:
2018 case OMP_CLAUSE_COPYIN:
2019 decl = OMP_CLAUSE_DECL (c);
2020 by_ref = use_pointer_for_field (decl, NULL);
2021 install_var_field (decl, by_ref, 3, ctx);
2022 break;
2024 case OMP_CLAUSE_DEFAULT:
2025 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2026 break;
2028 case OMP_CLAUSE_FINAL:
2029 case OMP_CLAUSE_IF:
2030 case OMP_CLAUSE_NUM_THREADS:
2031 case OMP_CLAUSE_NUM_TEAMS:
2032 case OMP_CLAUSE_THREAD_LIMIT:
2033 case OMP_CLAUSE_DEVICE:
2034 case OMP_CLAUSE_SCHEDULE:
2035 case OMP_CLAUSE_DIST_SCHEDULE:
2036 case OMP_CLAUSE_DEPEND:
2037 case OMP_CLAUSE_PRIORITY:
2038 case OMP_CLAUSE_GRAINSIZE:
2039 case OMP_CLAUSE_NUM_TASKS:
2040 case OMP_CLAUSE__CILK_FOR_COUNT_:
2041 case OMP_CLAUSE_NUM_GANGS:
2042 case OMP_CLAUSE_NUM_WORKERS:
2043 case OMP_CLAUSE_VECTOR_LENGTH:
2044 if (ctx->outer)
2045 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2046 break;
2048 case OMP_CLAUSE_TO:
2049 case OMP_CLAUSE_FROM:
2050 case OMP_CLAUSE_MAP:
2051 if (ctx->outer)
2052 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2053 decl = OMP_CLAUSE_DECL (c);
2054 /* Global variables with "omp declare target" attribute
2055 don't need to be copied, the receiver side will use them
2056 directly. However, global variables with "omp declare target link"
2057 attribute need to be copied. */
2058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2059 && DECL_P (decl)
2060 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2061 && (OMP_CLAUSE_MAP_KIND (c)
2062 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2063 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2064 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2065 && varpool_node::get_create (decl)->offloadable
2066 && !lookup_attribute ("omp declare target link",
2067 DECL_ATTRIBUTES (decl)))
2068 break;
2069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2070 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2072 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2073 not offloaded; there is nothing to map for those. */
2074 if (!is_gimple_omp_offloaded (ctx->stmt)
2075 && !POINTER_TYPE_P (TREE_TYPE (decl))
2076 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2077 break;
2079 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2080 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2081 || (OMP_CLAUSE_MAP_KIND (c)
2082 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2084 if (TREE_CODE (decl) == COMPONENT_REF
2085 || (TREE_CODE (decl) == INDIRECT_REF
2086 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2087 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2088 == REFERENCE_TYPE)))
2089 break;
2090 if (DECL_SIZE (decl)
2091 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2093 tree decl2 = DECL_VALUE_EXPR (decl);
2094 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2095 decl2 = TREE_OPERAND (decl2, 0);
2096 gcc_assert (DECL_P (decl2));
2097 install_var_local (decl2, ctx);
2099 install_var_local (decl, ctx);
2100 break;
2102 if (DECL_P (decl))
2104 if (DECL_SIZE (decl)
2105 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2107 tree decl2 = DECL_VALUE_EXPR (decl);
2108 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2109 decl2 = TREE_OPERAND (decl2, 0);
2110 gcc_assert (DECL_P (decl2));
2111 install_var_field (decl2, true, 3, ctx);
2112 install_var_local (decl2, ctx);
2113 install_var_local (decl, ctx);
2115 else
2117 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2118 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2119 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2120 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2121 install_var_field (decl, true, 7, ctx);
2122 else
2123 install_var_field (decl, true, 3, ctx,
2124 base_pointers_restrict);
2125 if (is_gimple_omp_offloaded (ctx->stmt))
2126 install_var_local (decl, ctx);
2129 else
2131 tree base = get_base_address (decl);
2132 tree nc = OMP_CLAUSE_CHAIN (c);
2133 if (DECL_P (base)
2134 && nc != NULL_TREE
2135 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2136 && OMP_CLAUSE_DECL (nc) == base
2137 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2138 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2140 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2141 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2143 else
2145 if (ctx->outer)
2147 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2148 decl = OMP_CLAUSE_DECL (c);
2150 gcc_assert (!splay_tree_lookup (ctx->field_map,
2151 (splay_tree_key) decl));
2152 tree field
2153 = build_decl (OMP_CLAUSE_LOCATION (c),
2154 FIELD_DECL, NULL_TREE, ptr_type_node);
2155 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2156 insert_field_into_struct (ctx->record_type, field);
2157 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2158 (splay_tree_value) field);
2161 break;
2163 case OMP_CLAUSE__GRIDDIM_:
2164 if (ctx->outer)
2166 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2167 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2169 break;
2171 case OMP_CLAUSE_NOWAIT:
2172 case OMP_CLAUSE_ORDERED:
2173 case OMP_CLAUSE_COLLAPSE:
2174 case OMP_CLAUSE_UNTIED:
2175 case OMP_CLAUSE_MERGEABLE:
2176 case OMP_CLAUSE_PROC_BIND:
2177 case OMP_CLAUSE_SAFELEN:
2178 case OMP_CLAUSE_SIMDLEN:
2179 case OMP_CLAUSE_THREADS:
2180 case OMP_CLAUSE_SIMD:
2181 case OMP_CLAUSE_NOGROUP:
2182 case OMP_CLAUSE_DEFAULTMAP:
2183 case OMP_CLAUSE_ASYNC:
2184 case OMP_CLAUSE_WAIT:
2185 case OMP_CLAUSE_GANG:
2186 case OMP_CLAUSE_WORKER:
2187 case OMP_CLAUSE_VECTOR:
2188 case OMP_CLAUSE_TILE:
2189 case OMP_CLAUSE_INDEPENDENT:
2190 case OMP_CLAUSE_AUTO:
2191 case OMP_CLAUSE_SEQ:
2192 break;
2194 case OMP_CLAUSE_ALIGNED:
2195 decl = OMP_CLAUSE_DECL (c);
2196 if (is_global_var (decl)
2197 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2198 install_var_local (decl, ctx);
2199 break;
2201 case OMP_CLAUSE_DEVICE_RESIDENT:
2202 case OMP_CLAUSE__CACHE_:
2203 sorry ("Clause not supported yet");
2204 break;
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_TILE:
2363 case OMP_CLAUSE_INDEPENDENT:
2364 case OMP_CLAUSE_AUTO:
2365 case OMP_CLAUSE_SEQ:
2366 case OMP_CLAUSE__GRIDDIM_:
2367 break;
2369 case OMP_CLAUSE_DEVICE_RESIDENT:
2370 case OMP_CLAUSE__CACHE_:
2371 sorry ("Clause not supported yet");
2372 break;
2374 default:
2375 gcc_unreachable ();
2379 gcc_checking_assert (!scan_array_reductions
2380 || !is_gimple_omp_oacc (ctx->stmt));
2381 if (scan_array_reductions)
2382 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2383 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2384 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2386 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2387 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2389 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2390 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2391 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2392 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2393 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2394 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2397 /* Create a new name for omp child function. Returns an identifier. If
2398 IS_CILK_FOR is true then the suffix for the child function is
2399 "_cilk_for_fn." */
2401 static tree
2402 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2404 if (is_cilk_for)
2405 return clone_function_name (current_function_decl, "_cilk_for_fn");
2406 return clone_function_name (current_function_decl,
2407 task_copy ? "_omp_cpyfn" : "_omp_fn");
2410 /* Returns the type of the induction variable for the child function for
2411 _Cilk_for and the types for _high and _low variables based on TYPE. */
2413 static tree
2414 cilk_for_check_loop_diff_type (tree type)
2416 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2418 if (TYPE_UNSIGNED (type))
2419 return uint32_type_node;
2420 else
2421 return integer_type_node;
2423 else
2425 if (TYPE_UNSIGNED (type))
2426 return uint64_type_node;
2427 else
2428 return long_long_integer_type_node;
2432 /* Build a decl for the omp child function. It'll not contain a body
2433 yet, just the bare decl. */
2435 static void
2436 create_omp_child_function (omp_context *ctx, bool task_copy)
2438 tree decl, type, name, t;
2440 tree cilk_for_count
2441 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2442 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2443 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2444 tree cilk_var_type = NULL_TREE;
2446 name = create_omp_child_function_name (task_copy,
2447 cilk_for_count != NULL_TREE);
2448 if (task_copy)
2449 type = build_function_type_list (void_type_node, ptr_type_node,
2450 ptr_type_node, NULL_TREE);
2451 else if (cilk_for_count)
2453 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2454 cilk_var_type = cilk_for_check_loop_diff_type (type);
2455 type = build_function_type_list (void_type_node, ptr_type_node,
2456 cilk_var_type, cilk_var_type, NULL_TREE);
2458 else
2459 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2461 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2463 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2464 || !task_copy);
2465 if (!task_copy)
2466 ctx->cb.dst_fn = decl;
2467 else
2468 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2470 TREE_STATIC (decl) = 1;
2471 TREE_USED (decl) = 1;
2472 DECL_ARTIFICIAL (decl) = 1;
2473 DECL_IGNORED_P (decl) = 0;
2474 TREE_PUBLIC (decl) = 0;
2475 DECL_UNINLINABLE (decl) = 1;
2476 DECL_EXTERNAL (decl) = 0;
2477 DECL_CONTEXT (decl) = NULL_TREE;
2478 DECL_INITIAL (decl) = make_node (BLOCK);
2479 if (cgraph_node::get (current_function_decl)->offloadable)
2480 cgraph_node::get_create (decl)->offloadable = 1;
2481 else
2483 omp_context *octx;
2484 for (octx = ctx; octx; octx = octx->outer)
2485 if (is_gimple_omp_offloaded (octx->stmt))
2487 cgraph_node::get_create (decl)->offloadable = 1;
2488 if (ENABLE_OFFLOADING)
2489 g->have_offload = true;
2491 break;
2495 if (cgraph_node::get_create (decl)->offloadable
2496 && !lookup_attribute ("omp declare target",
2497 DECL_ATTRIBUTES (current_function_decl)))
2498 DECL_ATTRIBUTES (decl)
2499 = tree_cons (get_identifier ("omp target entrypoint"),
2500 NULL_TREE, DECL_ATTRIBUTES (decl));
2502 t = build_decl (DECL_SOURCE_LOCATION (decl),
2503 RESULT_DECL, NULL_TREE, void_type_node);
2504 DECL_ARTIFICIAL (t) = 1;
2505 DECL_IGNORED_P (t) = 1;
2506 DECL_CONTEXT (t) = decl;
2507 DECL_RESULT (decl) = t;
2509 /* _Cilk_for's child function requires two extra parameters called
2510 __low and __high that are set the by Cilk runtime when it calls this
2511 function. */
2512 if (cilk_for_count)
2514 t = build_decl (DECL_SOURCE_LOCATION (decl),
2515 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2516 DECL_ARTIFICIAL (t) = 1;
2517 DECL_NAMELESS (t) = 1;
2518 DECL_ARG_TYPE (t) = ptr_type_node;
2519 DECL_CONTEXT (t) = current_function_decl;
2520 TREE_USED (t) = 1;
2521 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2522 DECL_ARGUMENTS (decl) = t;
2524 t = build_decl (DECL_SOURCE_LOCATION (decl),
2525 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2526 DECL_ARTIFICIAL (t) = 1;
2527 DECL_NAMELESS (t) = 1;
2528 DECL_ARG_TYPE (t) = ptr_type_node;
2529 DECL_CONTEXT (t) = current_function_decl;
2530 TREE_USED (t) = 1;
2531 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2532 DECL_ARGUMENTS (decl) = t;
2535 tree data_name = get_identifier (".omp_data_i");
2536 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2537 ptr_type_node);
2538 DECL_ARTIFICIAL (t) = 1;
2539 DECL_NAMELESS (t) = 1;
2540 DECL_ARG_TYPE (t) = ptr_type_node;
2541 DECL_CONTEXT (t) = current_function_decl;
2542 TREE_USED (t) = 1;
2543 TREE_READONLY (t) = 1;
2544 if (cilk_for_count)
2545 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2546 DECL_ARGUMENTS (decl) = t;
2547 if (!task_copy)
2548 ctx->receiver_decl = t;
2549 else
2551 t = build_decl (DECL_SOURCE_LOCATION (decl),
2552 PARM_DECL, get_identifier (".omp_data_o"),
2553 ptr_type_node);
2554 DECL_ARTIFICIAL (t) = 1;
2555 DECL_NAMELESS (t) = 1;
2556 DECL_ARG_TYPE (t) = ptr_type_node;
2557 DECL_CONTEXT (t) = current_function_decl;
2558 TREE_USED (t) = 1;
2559 TREE_ADDRESSABLE (t) = 1;
2560 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2561 DECL_ARGUMENTS (decl) = t;
2564 /* Allocate memory for the function structure. The call to
2565 allocate_struct_function clobbers CFUN, so we need to restore
2566 it afterward. */
2567 push_struct_function (decl);
2568 cfun->function_end_locus = gimple_location (ctx->stmt);
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 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2805 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2806 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 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2814 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2815 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 && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4307 max_vf = 1;
4308 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4309 max_vf) == -1)
4310 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4312 if (max_vf > 1)
4314 idx = create_tmp_var (unsigned_type_node);
4315 lane = create_tmp_var (unsigned_type_node);
4318 if (max_vf == 1)
4319 return false;
4321 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4322 tree avar = create_tmp_var_raw (atype);
4323 if (TREE_ADDRESSABLE (new_var))
4324 TREE_ADDRESSABLE (avar) = 1;
4325 DECL_ATTRIBUTES (avar)
4326 = tree_cons (get_identifier ("omp simd array"), NULL,
4327 DECL_ATTRIBUTES (avar));
4328 gimple_add_tmp_var (avar);
4329 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4330 NULL_TREE, NULL_TREE);
4331 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4332 NULL_TREE, NULL_TREE);
4333 if (DECL_P (new_var))
4335 SET_DECL_VALUE_EXPR (new_var, lvar);
4336 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4338 return true;
4341 /* Helper function of lower_rec_input_clauses. For a reference
4342 in simd reduction, add an underlying variable it will reference. */
4344 static void
4345 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4347 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4348 if (TREE_CONSTANT (z))
4350 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4351 get_name (new_vard));
4352 gimple_add_tmp_var (z);
4353 TREE_ADDRESSABLE (z) = 1;
4354 z = build_fold_addr_expr_loc (loc, z);
4355 gimplify_assign (new_vard, z, ilist);
4359 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4360 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4361 private variables. Initialization statements go in ILIST, while calls
4362 to destructors go in DLIST. */
4364 static void
4365 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4366 omp_context *ctx, struct omp_for_data *fd)
4368 tree c, dtor, copyin_seq, x, ptr;
4369 bool copyin_by_ref = false;
4370 bool lastprivate_firstprivate = false;
4371 bool reduction_omp_orig_ref = false;
4372 int pass;
4373 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4374 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4375 int max_vf = 0;
4376 tree lane = NULL_TREE, idx = NULL_TREE;
4377 tree ivar = NULL_TREE, lvar = NULL_TREE;
4378 gimple_seq llist[2] = { NULL, NULL };
4380 copyin_seq = NULL;
4382 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4383 with data sharing clauses referencing variable sized vars. That
4384 is unnecessarily hard to support and very unlikely to result in
4385 vectorized code anyway. */
4386 if (is_simd)
4387 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4388 switch (OMP_CLAUSE_CODE (c))
4390 case OMP_CLAUSE_LINEAR:
4391 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4392 max_vf = 1;
4393 /* FALLTHRU */
4394 case OMP_CLAUSE_PRIVATE:
4395 case OMP_CLAUSE_FIRSTPRIVATE:
4396 case OMP_CLAUSE_LASTPRIVATE:
4397 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4398 max_vf = 1;
4399 break;
4400 case OMP_CLAUSE_REDUCTION:
4401 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4402 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4403 max_vf = 1;
4404 break;
4405 default:
4406 continue;
4409 /* Do all the fixed sized types in the first pass, and the variable sized
4410 types in the second pass. This makes sure that the scalar arguments to
4411 the variable sized types are processed before we use them in the
4412 variable sized operations. */
4413 for (pass = 0; pass < 2; ++pass)
4415 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4417 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4418 tree var, new_var;
4419 bool by_ref;
4420 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4422 switch (c_kind)
4424 case OMP_CLAUSE_PRIVATE:
4425 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4426 continue;
4427 break;
4428 case OMP_CLAUSE_SHARED:
4429 /* Ignore shared directives in teams construct. */
4430 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4431 continue;
4432 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4434 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4435 || is_global_var (OMP_CLAUSE_DECL (c)));
4436 continue;
4438 case OMP_CLAUSE_FIRSTPRIVATE:
4439 case OMP_CLAUSE_COPYIN:
4440 break;
4441 case OMP_CLAUSE_LINEAR:
4442 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4443 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4444 lastprivate_firstprivate = true;
4445 break;
4446 case OMP_CLAUSE_REDUCTION:
4447 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4448 reduction_omp_orig_ref = true;
4449 break;
4450 case OMP_CLAUSE__LOOPTEMP_:
4451 /* Handle _looptemp_ clauses only on parallel/task. */
4452 if (fd)
4453 continue;
4454 break;
4455 case OMP_CLAUSE_LASTPRIVATE:
4456 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4458 lastprivate_firstprivate = true;
4459 if (pass != 0 || is_taskloop_ctx (ctx))
4460 continue;
4462 /* Even without corresponding firstprivate, if
4463 decl is Fortran allocatable, it needs outer var
4464 reference. */
4465 else if (pass == 0
4466 && lang_hooks.decls.omp_private_outer_ref
4467 (OMP_CLAUSE_DECL (c)))
4468 lastprivate_firstprivate = true;
4469 break;
4470 case OMP_CLAUSE_ALIGNED:
4471 if (pass == 0)
4472 continue;
4473 var = OMP_CLAUSE_DECL (c);
4474 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4475 && !is_global_var (var))
4477 new_var = maybe_lookup_decl (var, ctx);
4478 if (new_var == NULL_TREE)
4479 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4480 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4481 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4482 omp_clause_aligned_alignment (c));
4483 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4484 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4485 gimplify_and_add (x, ilist);
4487 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4488 && is_global_var (var))
4490 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4491 new_var = lookup_decl (var, ctx);
4492 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4493 t = build_fold_addr_expr_loc (clause_loc, t);
4494 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4495 t = build_call_expr_loc (clause_loc, t2, 2, t,
4496 omp_clause_aligned_alignment (c));
4497 t = fold_convert_loc (clause_loc, ptype, t);
4498 x = create_tmp_var (ptype);
4499 t = build2 (MODIFY_EXPR, ptype, x, t);
4500 gimplify_and_add (t, ilist);
4501 t = build_simple_mem_ref_loc (clause_loc, x);
4502 SET_DECL_VALUE_EXPR (new_var, t);
4503 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4505 continue;
4506 default:
4507 continue;
4510 new_var = var = OMP_CLAUSE_DECL (c);
4511 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4513 var = TREE_OPERAND (var, 0);
4514 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4515 var = TREE_OPERAND (var, 0);
4516 if (TREE_CODE (var) == INDIRECT_REF
4517 || TREE_CODE (var) == ADDR_EXPR)
4518 var = TREE_OPERAND (var, 0);
4519 if (is_variable_sized (var))
4521 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4522 var = DECL_VALUE_EXPR (var);
4523 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4524 var = TREE_OPERAND (var, 0);
4525 gcc_assert (DECL_P (var));
4527 new_var = var;
4529 if (c_kind != OMP_CLAUSE_COPYIN)
4530 new_var = lookup_decl (var, ctx);
4532 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4534 if (pass != 0)
4535 continue;
4537 /* C/C++ array section reductions. */
4538 else if (c_kind == OMP_CLAUSE_REDUCTION
4539 && var != OMP_CLAUSE_DECL (c))
4541 if (pass == 0)
4542 continue;
4544 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4545 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4546 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4548 tree b = TREE_OPERAND (orig_var, 1);
4549 b = maybe_lookup_decl (b, ctx);
4550 if (b == NULL)
4552 b = TREE_OPERAND (orig_var, 1);
4553 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4555 if (integer_zerop (bias))
4556 bias = b;
4557 else
4559 bias = fold_convert_loc (clause_loc,
4560 TREE_TYPE (b), bias);
4561 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4562 TREE_TYPE (b), b, bias);
4564 orig_var = TREE_OPERAND (orig_var, 0);
4566 if (TREE_CODE (orig_var) == INDIRECT_REF
4567 || TREE_CODE (orig_var) == ADDR_EXPR)
4568 orig_var = TREE_OPERAND (orig_var, 0);
4569 tree d = OMP_CLAUSE_DECL (c);
4570 tree type = TREE_TYPE (d);
4571 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4572 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4573 const char *name = get_name (orig_var);
4574 if (TREE_CONSTANT (v))
4576 x = create_tmp_var_raw (type, name);
4577 gimple_add_tmp_var (x);
4578 TREE_ADDRESSABLE (x) = 1;
4579 x = build_fold_addr_expr_loc (clause_loc, x);
4581 else
4583 tree atmp
4584 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4585 tree t = maybe_lookup_decl (v, ctx);
4586 if (t)
4587 v = t;
4588 else
4589 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4590 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4591 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4592 TREE_TYPE (v), v,
4593 build_int_cst (TREE_TYPE (v), 1));
4594 t = fold_build2_loc (clause_loc, MULT_EXPR,
4595 TREE_TYPE (v), t,
4596 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4597 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4598 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4601 tree ptype = build_pointer_type (TREE_TYPE (type));
4602 x = fold_convert_loc (clause_loc, ptype, x);
4603 tree y = create_tmp_var (ptype, name);
4604 gimplify_assign (y, x, ilist);
4605 x = y;
4606 tree yb = y;
4608 if (!integer_zerop (bias))
4610 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4611 bias);
4612 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4614 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4615 pointer_sized_int_node, yb, bias);
4616 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4617 yb = create_tmp_var (ptype, name);
4618 gimplify_assign (yb, x, ilist);
4619 x = yb;
4622 d = TREE_OPERAND (d, 0);
4623 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4624 d = TREE_OPERAND (d, 0);
4625 if (TREE_CODE (d) == ADDR_EXPR)
4627 if (orig_var != var)
4629 gcc_assert (is_variable_sized (orig_var));
4630 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4632 gimplify_assign (new_var, x, ilist);
4633 tree new_orig_var = lookup_decl (orig_var, ctx);
4634 tree t = build_fold_indirect_ref (new_var);
4635 DECL_IGNORED_P (new_var) = 0;
4636 TREE_THIS_NOTRAP (t);
4637 SET_DECL_VALUE_EXPR (new_orig_var, t);
4638 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4640 else
4642 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4643 build_int_cst (ptype, 0));
4644 SET_DECL_VALUE_EXPR (new_var, x);
4645 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4648 else
4650 gcc_assert (orig_var == var);
4651 if (TREE_CODE (d) == INDIRECT_REF)
4653 x = create_tmp_var (ptype, name);
4654 TREE_ADDRESSABLE (x) = 1;
4655 gimplify_assign (x, yb, ilist);
4656 x = build_fold_addr_expr_loc (clause_loc, x);
4658 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4659 gimplify_assign (new_var, x, ilist);
4661 tree y1 = create_tmp_var (ptype, NULL);
4662 gimplify_assign (y1, y, ilist);
4663 tree i2 = NULL_TREE, y2 = NULL_TREE;
4664 tree body2 = NULL_TREE, end2 = NULL_TREE;
4665 tree y3 = NULL_TREE, y4 = NULL_TREE;
4666 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4668 y2 = create_tmp_var (ptype, NULL);
4669 gimplify_assign (y2, y, ilist);
4670 tree ref = build_outer_var_ref (var, ctx);
4671 /* For ref build_outer_var_ref already performs this. */
4672 if (TREE_CODE (d) == INDIRECT_REF)
4673 gcc_assert (is_reference (var));
4674 else if (TREE_CODE (d) == ADDR_EXPR)
4675 ref = build_fold_addr_expr (ref);
4676 else if (is_reference (var))
4677 ref = build_fold_addr_expr (ref);
4678 ref = fold_convert_loc (clause_loc, ptype, ref);
4679 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4680 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4682 y3 = create_tmp_var (ptype, NULL);
4683 gimplify_assign (y3, unshare_expr (ref), ilist);
4685 if (is_simd)
4687 y4 = create_tmp_var (ptype, NULL);
4688 gimplify_assign (y4, ref, dlist);
4691 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4692 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4693 tree body = create_artificial_label (UNKNOWN_LOCATION);
4694 tree end = create_artificial_label (UNKNOWN_LOCATION);
4695 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4696 if (y2)
4698 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4699 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4700 body2 = create_artificial_label (UNKNOWN_LOCATION);
4701 end2 = create_artificial_label (UNKNOWN_LOCATION);
4702 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4704 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4706 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4707 tree decl_placeholder
4708 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4709 SET_DECL_VALUE_EXPR (decl_placeholder,
4710 build_simple_mem_ref (y1));
4711 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4712 SET_DECL_VALUE_EXPR (placeholder,
4713 y3 ? build_simple_mem_ref (y3)
4714 : error_mark_node);
4715 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4716 x = lang_hooks.decls.omp_clause_default_ctor
4717 (c, build_simple_mem_ref (y1),
4718 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4719 if (x)
4720 gimplify_and_add (x, ilist);
4721 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4723 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4724 lower_omp (&tseq, ctx);
4725 gimple_seq_add_seq (ilist, tseq);
4727 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4728 if (is_simd)
4730 SET_DECL_VALUE_EXPR (decl_placeholder,
4731 build_simple_mem_ref (y2));
4732 SET_DECL_VALUE_EXPR (placeholder,
4733 build_simple_mem_ref (y4));
4734 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4735 lower_omp (&tseq, ctx);
4736 gimple_seq_add_seq (dlist, tseq);
4737 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4739 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4740 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4741 x = lang_hooks.decls.omp_clause_dtor
4742 (c, build_simple_mem_ref (y2));
4743 if (x)
4745 gimple_seq tseq = NULL;
4746 dtor = x;
4747 gimplify_stmt (&dtor, &tseq);
4748 gimple_seq_add_seq (dlist, tseq);
4751 else
4753 x = omp_reduction_init (c, TREE_TYPE (type));
4754 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4756 /* reduction(-:var) sums up the partial results, so it
4757 acts identically to reduction(+:var). */
4758 if (code == MINUS_EXPR)
4759 code = PLUS_EXPR;
4761 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4762 if (is_simd)
4764 x = build2 (code, TREE_TYPE (type),
4765 build_simple_mem_ref (y4),
4766 build_simple_mem_ref (y2));
4767 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4770 gimple *g
4771 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4772 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4773 gimple_seq_add_stmt (ilist, g);
4774 if (y3)
4776 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4777 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4778 gimple_seq_add_stmt (ilist, g);
4780 g = gimple_build_assign (i, PLUS_EXPR, i,
4781 build_int_cst (TREE_TYPE (i), 1));
4782 gimple_seq_add_stmt (ilist, g);
4783 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4784 gimple_seq_add_stmt (ilist, g);
4785 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4786 if (y2)
4788 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4789 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4790 gimple_seq_add_stmt (dlist, g);
4791 if (y4)
4793 g = gimple_build_assign
4794 (y4, POINTER_PLUS_EXPR, y4,
4795 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4796 gimple_seq_add_stmt (dlist, g);
4798 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4799 build_int_cst (TREE_TYPE (i2), 1));
4800 gimple_seq_add_stmt (dlist, g);
4801 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4802 gimple_seq_add_stmt (dlist, g);
4803 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4805 continue;
4807 else if (is_variable_sized (var))
4809 /* For variable sized types, we need to allocate the
4810 actual storage here. Call alloca and store the
4811 result in the pointer decl that we created elsewhere. */
4812 if (pass == 0)
4813 continue;
4815 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4817 gcall *stmt;
4818 tree tmp, atmp;
4820 ptr = DECL_VALUE_EXPR (new_var);
4821 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4822 ptr = TREE_OPERAND (ptr, 0);
4823 gcc_assert (DECL_P (ptr));
4824 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4826 /* void *tmp = __builtin_alloca */
4827 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4828 stmt = gimple_build_call (atmp, 2, x,
4829 size_int (DECL_ALIGN (var)));
4830 tmp = create_tmp_var_raw (ptr_type_node);
4831 gimple_add_tmp_var (tmp);
4832 gimple_call_set_lhs (stmt, tmp);
4834 gimple_seq_add_stmt (ilist, stmt);
4836 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4837 gimplify_assign (ptr, x, ilist);
4840 else if (is_reference (var) && !is_oacc_parallel (ctx))
4842 /* For references that are being privatized for Fortran,
4843 allocate new backing storage for the new pointer
4844 variable. This allows us to avoid changing all the
4845 code that expects a pointer to something that expects
4846 a direct variable. */
4847 if (pass == 0)
4848 continue;
4850 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4851 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4853 x = build_receiver_ref (var, false, ctx);
4854 x = build_fold_addr_expr_loc (clause_loc, x);
4856 else if (TREE_CONSTANT (x))
4858 /* For reduction in SIMD loop, defer adding the
4859 initialization of the reference, because if we decide
4860 to use SIMD array for it, the initilization could cause
4861 expansion ICE. */
4862 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4863 x = NULL_TREE;
4864 else
4866 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4867 get_name (var));
4868 gimple_add_tmp_var (x);
4869 TREE_ADDRESSABLE (x) = 1;
4870 x = build_fold_addr_expr_loc (clause_loc, x);
4873 else
4875 tree atmp
4876 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4877 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4878 tree al = size_int (TYPE_ALIGN (rtype));
4879 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4882 if (x)
4884 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4885 gimplify_assign (new_var, x, ilist);
4888 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4890 else if (c_kind == OMP_CLAUSE_REDUCTION
4891 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4893 if (pass == 0)
4894 continue;
4896 else if (pass != 0)
4897 continue;
4899 switch (OMP_CLAUSE_CODE (c))
4901 case OMP_CLAUSE_SHARED:
4902 /* Ignore shared directives in teams construct. */
4903 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4904 continue;
4905 /* Shared global vars are just accessed directly. */
4906 if (is_global_var (new_var))
4907 break;
4908 /* For taskloop firstprivate/lastprivate, represented
4909 as firstprivate and shared clause on the task, new_var
4910 is the firstprivate var. */
4911 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4912 break;
4913 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4914 needs to be delayed until after fixup_child_record_type so
4915 that we get the correct type during the dereference. */
4916 by_ref = use_pointer_for_field (var, ctx);
4917 x = build_receiver_ref (var, by_ref, ctx);
4918 SET_DECL_VALUE_EXPR (new_var, x);
4919 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4921 /* ??? If VAR is not passed by reference, and the variable
4922 hasn't been initialized yet, then we'll get a warning for
4923 the store into the omp_data_s structure. Ideally, we'd be
4924 able to notice this and not store anything at all, but
4925 we're generating code too early. Suppress the warning. */
4926 if (!by_ref)
4927 TREE_NO_WARNING (var) = 1;
4928 break;
4930 case OMP_CLAUSE_LASTPRIVATE:
4931 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4932 break;
4933 /* FALLTHRU */
4935 case OMP_CLAUSE_PRIVATE:
4936 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4937 x = build_outer_var_ref (var, ctx);
4938 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4940 if (is_task_ctx (ctx))
4941 x = build_receiver_ref (var, false, ctx);
4942 else
4943 x = build_outer_var_ref (var, ctx);
4945 else
4946 x = NULL;
4947 do_private:
4948 tree nx;
4949 nx = lang_hooks.decls.omp_clause_default_ctor
4950 (c, unshare_expr (new_var), x);
4951 if (is_simd)
4953 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4954 if ((TREE_ADDRESSABLE (new_var) || nx || y
4955 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4956 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4957 idx, lane, ivar, lvar))
4959 if (nx)
4960 x = lang_hooks.decls.omp_clause_default_ctor
4961 (c, unshare_expr (ivar), x);
4962 if (nx && x)
4963 gimplify_and_add (x, &llist[0]);
4964 if (y)
4966 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4967 if (y)
4969 gimple_seq tseq = NULL;
4971 dtor = y;
4972 gimplify_stmt (&dtor, &tseq);
4973 gimple_seq_add_seq (&llist[1], tseq);
4976 break;
4979 if (nx)
4980 gimplify_and_add (nx, ilist);
4981 /* FALLTHRU */
4983 do_dtor:
4984 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4985 if (x)
4987 gimple_seq tseq = NULL;
4989 dtor = x;
4990 gimplify_stmt (&dtor, &tseq);
4991 gimple_seq_add_seq (dlist, tseq);
4993 break;
4995 case OMP_CLAUSE_LINEAR:
4996 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4997 goto do_firstprivate;
4998 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4999 x = NULL;
5000 else
5001 x = build_outer_var_ref (var, ctx);
5002 goto do_private;
5004 case OMP_CLAUSE_FIRSTPRIVATE:
5005 if (is_task_ctx (ctx))
5007 if (is_reference (var) || is_variable_sized (var))
5008 goto do_dtor;
5009 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5010 ctx))
5011 || use_pointer_for_field (var, NULL))
5013 x = build_receiver_ref (var, false, ctx);
5014 SET_DECL_VALUE_EXPR (new_var, x);
5015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5016 goto do_dtor;
5019 do_firstprivate:
5020 x = build_outer_var_ref (var, ctx);
5021 if (is_simd)
5023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5024 && gimple_omp_for_combined_into_p (ctx->stmt))
5026 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5027 tree stept = TREE_TYPE (t);
5028 tree ct = find_omp_clause (clauses,
5029 OMP_CLAUSE__LOOPTEMP_);
5030 gcc_assert (ct);
5031 tree l = OMP_CLAUSE_DECL (ct);
5032 tree n1 = fd->loop.n1;
5033 tree step = fd->loop.step;
5034 tree itype = TREE_TYPE (l);
5035 if (POINTER_TYPE_P (itype))
5036 itype = signed_type_for (itype);
5037 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5038 if (TYPE_UNSIGNED (itype)
5039 && fd->loop.cond_code == GT_EXPR)
5040 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5041 fold_build1 (NEGATE_EXPR, itype, l),
5042 fold_build1 (NEGATE_EXPR,
5043 itype, step));
5044 else
5045 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5046 t = fold_build2 (MULT_EXPR, stept,
5047 fold_convert (stept, l), t);
5049 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5051 x = lang_hooks.decls.omp_clause_linear_ctor
5052 (c, new_var, x, t);
5053 gimplify_and_add (x, ilist);
5054 goto do_dtor;
5057 if (POINTER_TYPE_P (TREE_TYPE (x)))
5058 x = fold_build2 (POINTER_PLUS_EXPR,
5059 TREE_TYPE (x), x, t);
5060 else
5061 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5064 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5065 || TREE_ADDRESSABLE (new_var))
5066 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5067 idx, lane, ivar, lvar))
5069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5071 tree iv = create_tmp_var (TREE_TYPE (new_var));
5072 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5073 gimplify_and_add (x, ilist);
5074 gimple_stmt_iterator gsi
5075 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5076 gassign *g
5077 = gimple_build_assign (unshare_expr (lvar), iv);
5078 gsi_insert_before_without_update (&gsi, g,
5079 GSI_SAME_STMT);
5080 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5081 enum tree_code code = PLUS_EXPR;
5082 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5083 code = POINTER_PLUS_EXPR;
5084 g = gimple_build_assign (iv, code, iv, t);
5085 gsi_insert_before_without_update (&gsi, g,
5086 GSI_SAME_STMT);
5087 break;
5089 x = lang_hooks.decls.omp_clause_copy_ctor
5090 (c, unshare_expr (ivar), x);
5091 gimplify_and_add (x, &llist[0]);
5092 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5093 if (x)
5095 gimple_seq tseq = NULL;
5097 dtor = x;
5098 gimplify_stmt (&dtor, &tseq);
5099 gimple_seq_add_seq (&llist[1], tseq);
5101 break;
5104 x = lang_hooks.decls.omp_clause_copy_ctor
5105 (c, unshare_expr (new_var), x);
5106 gimplify_and_add (x, ilist);
5107 goto do_dtor;
5109 case OMP_CLAUSE__LOOPTEMP_:
5110 gcc_assert (is_taskreg_ctx (ctx));
5111 x = build_outer_var_ref (var, ctx);
5112 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5113 gimplify_and_add (x, ilist);
5114 break;
5116 case OMP_CLAUSE_COPYIN:
5117 by_ref = use_pointer_for_field (var, NULL);
5118 x = build_receiver_ref (var, by_ref, ctx);
5119 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5120 append_to_statement_list (x, &copyin_seq);
5121 copyin_by_ref |= by_ref;
5122 break;
5124 case OMP_CLAUSE_REDUCTION:
5125 /* OpenACC reductions are initialized using the
5126 GOACC_REDUCTION internal function. */
5127 if (is_gimple_omp_oacc (ctx->stmt))
5128 break;
5129 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5131 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5132 gimple *tseq;
5133 x = build_outer_var_ref (var, ctx);
5135 if (is_reference (var)
5136 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5137 TREE_TYPE (x)))
5138 x = build_fold_addr_expr_loc (clause_loc, x);
5139 SET_DECL_VALUE_EXPR (placeholder, x);
5140 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5141 tree new_vard = new_var;
5142 if (is_reference (var))
5144 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5145 new_vard = TREE_OPERAND (new_var, 0);
5146 gcc_assert (DECL_P (new_vard));
5148 if (is_simd
5149 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5150 idx, lane, ivar, lvar))
5152 if (new_vard == new_var)
5154 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5155 SET_DECL_VALUE_EXPR (new_var, ivar);
5157 else
5159 SET_DECL_VALUE_EXPR (new_vard,
5160 build_fold_addr_expr (ivar));
5161 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5163 x = lang_hooks.decls.omp_clause_default_ctor
5164 (c, unshare_expr (ivar),
5165 build_outer_var_ref (var, ctx));
5166 if (x)
5167 gimplify_and_add (x, &llist[0]);
5168 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5170 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5171 lower_omp (&tseq, ctx);
5172 gimple_seq_add_seq (&llist[0], tseq);
5174 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5175 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5176 lower_omp (&tseq, ctx);
5177 gimple_seq_add_seq (&llist[1], tseq);
5178 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5179 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5180 if (new_vard == new_var)
5181 SET_DECL_VALUE_EXPR (new_var, lvar);
5182 else
5183 SET_DECL_VALUE_EXPR (new_vard,
5184 build_fold_addr_expr (lvar));
5185 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5186 if (x)
5188 tseq = NULL;
5189 dtor = x;
5190 gimplify_stmt (&dtor, &tseq);
5191 gimple_seq_add_seq (&llist[1], tseq);
5193 break;
5195 /* If this is a reference to constant size reduction var
5196 with placeholder, we haven't emitted the initializer
5197 for it because it is undesirable if SIMD arrays are used.
5198 But if they aren't used, we need to emit the deferred
5199 initialization now. */
5200 else if (is_reference (var) && is_simd)
5201 handle_simd_reference (clause_loc, new_vard, ilist);
5202 x = lang_hooks.decls.omp_clause_default_ctor
5203 (c, unshare_expr (new_var),
5204 build_outer_var_ref (var, ctx));
5205 if (x)
5206 gimplify_and_add (x, ilist);
5207 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5209 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5210 lower_omp (&tseq, ctx);
5211 gimple_seq_add_seq (ilist, tseq);
5213 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5214 if (is_simd)
5216 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5217 lower_omp (&tseq, ctx);
5218 gimple_seq_add_seq (dlist, tseq);
5219 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5221 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5222 goto do_dtor;
5224 else
5226 x = omp_reduction_init (c, TREE_TYPE (new_var));
5227 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5228 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5230 /* reduction(-:var) sums up the partial results, so it
5231 acts identically to reduction(+:var). */
5232 if (code == MINUS_EXPR)
5233 code = PLUS_EXPR;
5235 tree new_vard = new_var;
5236 if (is_simd && is_reference (var))
5238 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5239 new_vard = TREE_OPERAND (new_var, 0);
5240 gcc_assert (DECL_P (new_vard));
5242 if (is_simd
5243 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5244 idx, lane, ivar, lvar))
5246 tree ref = build_outer_var_ref (var, ctx);
5248 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5250 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5251 ref = build_outer_var_ref (var, ctx);
5252 gimplify_assign (ref, x, &llist[1]);
5254 if (new_vard != new_var)
5256 SET_DECL_VALUE_EXPR (new_vard,
5257 build_fold_addr_expr (lvar));
5258 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5261 else
5263 if (is_reference (var) && is_simd)
5264 handle_simd_reference (clause_loc, new_vard, ilist);
5265 gimplify_assign (new_var, x, ilist);
5266 if (is_simd)
5268 tree ref = build_outer_var_ref (var, ctx);
5270 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5271 ref = build_outer_var_ref (var, ctx);
5272 gimplify_assign (ref, x, dlist);
5276 break;
5278 default:
5279 gcc_unreachable ();
5284 if (lane)
5286 tree uid = create_tmp_var (ptr_type_node, "simduid");
5287 /* Don't want uninit warnings on simduid, it is always uninitialized,
5288 but we use it not for the value, but for the DECL_UID only. */
5289 TREE_NO_WARNING (uid) = 1;
5290 gimple *g
5291 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5292 gimple_call_set_lhs (g, lane);
5293 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5294 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5295 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5296 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5297 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5298 gimple_omp_for_set_clauses (ctx->stmt, c);
5299 g = gimple_build_assign (lane, INTEGER_CST,
5300 build_int_cst (unsigned_type_node, 0));
5301 gimple_seq_add_stmt (ilist, g);
5302 for (int i = 0; i < 2; i++)
5303 if (llist[i])
5305 tree vf = create_tmp_var (unsigned_type_node);
5306 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5307 gimple_call_set_lhs (g, vf);
5308 gimple_seq *seq = i == 0 ? ilist : dlist;
5309 gimple_seq_add_stmt (seq, g);
5310 tree t = build_int_cst (unsigned_type_node, 0);
5311 g = gimple_build_assign (idx, INTEGER_CST, t);
5312 gimple_seq_add_stmt (seq, g);
5313 tree body = create_artificial_label (UNKNOWN_LOCATION);
5314 tree header = create_artificial_label (UNKNOWN_LOCATION);
5315 tree end = create_artificial_label (UNKNOWN_LOCATION);
5316 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5317 gimple_seq_add_stmt (seq, gimple_build_label (body));
5318 gimple_seq_add_seq (seq, llist[i]);
5319 t = build_int_cst (unsigned_type_node, 1);
5320 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5321 gimple_seq_add_stmt (seq, g);
5322 gimple_seq_add_stmt (seq, gimple_build_label (header));
5323 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5324 gimple_seq_add_stmt (seq, g);
5325 gimple_seq_add_stmt (seq, gimple_build_label (end));
5329 /* The copyin sequence is not to be executed by the main thread, since
5330 that would result in self-copies. Perhaps not visible to scalars,
5331 but it certainly is to C++ operator=. */
5332 if (copyin_seq)
5334 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5336 x = build2 (NE_EXPR, boolean_type_node, x,
5337 build_int_cst (TREE_TYPE (x), 0));
5338 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5339 gimplify_and_add (x, ilist);
5342 /* If any copyin variable is passed by reference, we must ensure the
5343 master thread doesn't modify it before it is copied over in all
5344 threads. Similarly for variables in both firstprivate and
5345 lastprivate clauses we need to ensure the lastprivate copying
5346 happens after firstprivate copying in all threads. And similarly
5347 for UDRs if initializer expression refers to omp_orig. */
5348 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5350 /* Don't add any barrier for #pragma omp simd or
5351 #pragma omp distribute. */
5352 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5353 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5354 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5357 /* If max_vf is non-zero, then we can use only a vectorization factor
5358 up to the max_vf we chose. So stick it into the safelen clause. */
5359 if (max_vf)
5361 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5362 OMP_CLAUSE_SAFELEN);
5363 if (c == NULL_TREE
5364 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5365 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5366 max_vf) == 1))
5368 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5369 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5370 max_vf);
5371 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5372 gimple_omp_for_set_clauses (ctx->stmt, c);
5378 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5379 both parallel and workshare constructs. PREDICATE may be NULL if it's
5380 always true. */
5382 static void
5383 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5384 omp_context *ctx)
5386 tree x, c, label = NULL, orig_clauses = clauses;
5387 bool par_clauses = false;
5388 tree simduid = NULL, lastlane = NULL;
5390 /* Early exit if there are no lastprivate or linear clauses. */
5391 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5392 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5393 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5394 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5395 break;
5396 if (clauses == NULL)
5398 /* If this was a workshare clause, see if it had been combined
5399 with its parallel. In that case, look for the clauses on the
5400 parallel statement itself. */
5401 if (is_parallel_ctx (ctx))
5402 return;
5404 ctx = ctx->outer;
5405 if (ctx == NULL || !is_parallel_ctx (ctx))
5406 return;
5408 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5409 OMP_CLAUSE_LASTPRIVATE);
5410 if (clauses == NULL)
5411 return;
5412 par_clauses = true;
5415 if (predicate)
5417 gcond *stmt;
5418 tree label_true, arm1, arm2;
5420 label = create_artificial_label (UNKNOWN_LOCATION);
5421 label_true = create_artificial_label (UNKNOWN_LOCATION);
5422 arm1 = TREE_OPERAND (predicate, 0);
5423 arm2 = TREE_OPERAND (predicate, 1);
5424 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5425 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5426 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5427 label_true, label);
5428 gimple_seq_add_stmt (stmt_list, stmt);
5429 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5432 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5433 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5435 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5436 if (simduid)
5437 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5440 for (c = clauses; c ;)
5442 tree var, new_var;
5443 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5445 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5446 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5447 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5449 var = OMP_CLAUSE_DECL (c);
5450 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5451 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5452 && is_taskloop_ctx (ctx))
5454 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5455 new_var = lookup_decl (var, ctx->outer);
5457 else
5458 new_var = lookup_decl (var, ctx);
5460 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5462 tree val = DECL_VALUE_EXPR (new_var);
5463 if (TREE_CODE (val) == ARRAY_REF
5464 && VAR_P (TREE_OPERAND (val, 0))
5465 && lookup_attribute ("omp simd array",
5466 DECL_ATTRIBUTES (TREE_OPERAND (val,
5467 0))))
5469 if (lastlane == NULL)
5471 lastlane = create_tmp_var (unsigned_type_node);
5472 gcall *g
5473 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5474 2, simduid,
5475 TREE_OPERAND (val, 1));
5476 gimple_call_set_lhs (g, lastlane);
5477 gimple_seq_add_stmt (stmt_list, g);
5479 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5480 TREE_OPERAND (val, 0), lastlane,
5481 NULL_TREE, NULL_TREE);
5485 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5486 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5488 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5489 gimple_seq_add_seq (stmt_list,
5490 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5491 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5493 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5494 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5496 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5497 gimple_seq_add_seq (stmt_list,
5498 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5499 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5502 x = NULL_TREE;
5503 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5504 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5506 gcc_checking_assert (is_taskloop_ctx (ctx));
5507 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5508 ctx->outer->outer);
5509 if (is_global_var (ovar))
5510 x = ovar;
5512 if (!x)
5513 x = build_outer_var_ref (var, ctx, true);
5514 if (is_reference (var))
5515 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5516 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5517 gimplify_and_add (x, stmt_list);
5519 c = OMP_CLAUSE_CHAIN (c);
5520 if (c == NULL && !par_clauses)
5522 /* If this was a workshare clause, see if it had been combined
5523 with its parallel. In that case, continue looking for the
5524 clauses also on the parallel statement itself. */
5525 if (is_parallel_ctx (ctx))
5526 break;
5528 ctx = ctx->outer;
5529 if (ctx == NULL || !is_parallel_ctx (ctx))
5530 break;
5532 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5533 OMP_CLAUSE_LASTPRIVATE);
5534 par_clauses = true;
5538 if (label)
5539 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5542 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5543 (which might be a placeholder). INNER is true if this is an inner
5544 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5545 join markers. Generate the before-loop forking sequence in
5546 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5547 general form of these sequences is
5549 GOACC_REDUCTION_SETUP
5550 GOACC_FORK
5551 GOACC_REDUCTION_INIT
5553 GOACC_REDUCTION_FINI
5554 GOACC_JOIN
5555 GOACC_REDUCTION_TEARDOWN. */
5557 static void
5558 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5559 gcall *fork, gcall *join, gimple_seq *fork_seq,
5560 gimple_seq *join_seq, omp_context *ctx)
5562 gimple_seq before_fork = NULL;
5563 gimple_seq after_fork = NULL;
5564 gimple_seq before_join = NULL;
5565 gimple_seq after_join = NULL;
5566 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5567 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5568 unsigned offset = 0;
5570 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5571 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5573 tree orig = OMP_CLAUSE_DECL (c);
5574 tree var = maybe_lookup_decl (orig, ctx);
5575 tree ref_to_res = NULL_TREE;
5576 tree incoming, outgoing;
5578 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5579 if (rcode == MINUS_EXPR)
5580 rcode = PLUS_EXPR;
5581 else if (rcode == TRUTH_ANDIF_EXPR)
5582 rcode = BIT_AND_EXPR;
5583 else if (rcode == TRUTH_ORIF_EXPR)
5584 rcode = BIT_IOR_EXPR;
5585 tree op = build_int_cst (unsigned_type_node, rcode);
5587 if (!var)
5588 var = orig;
5589 gcc_assert (!is_reference (var));
5591 incoming = outgoing = var;
5593 if (!inner)
5595 /* See if an outer construct also reduces this variable. */
5596 omp_context *outer = ctx;
5598 while (omp_context *probe = outer->outer)
5600 enum gimple_code type = gimple_code (probe->stmt);
5601 tree cls;
5603 switch (type)
5605 case GIMPLE_OMP_FOR:
5606 cls = gimple_omp_for_clauses (probe->stmt);
5607 break;
5609 case GIMPLE_OMP_TARGET:
5610 if (gimple_omp_target_kind (probe->stmt)
5611 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5612 goto do_lookup;
5614 cls = gimple_omp_target_clauses (probe->stmt);
5615 break;
5617 default:
5618 goto do_lookup;
5621 outer = probe;
5622 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5623 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5624 && orig == OMP_CLAUSE_DECL (cls))
5625 goto has_outer_reduction;
5628 do_lookup:
5629 /* This is the outermost construct with this reduction,
5630 see if there's a mapping for it. */
5631 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5632 && maybe_lookup_field (orig, outer))
5634 ref_to_res = build_receiver_ref (orig, false, outer);
5635 if (is_reference (orig))
5636 ref_to_res = build_simple_mem_ref (ref_to_res);
5638 outgoing = var;
5639 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5641 else
5642 incoming = outgoing = orig;
5644 has_outer_reduction:;
5647 if (!ref_to_res)
5648 ref_to_res = integer_zero_node;
5650 /* Determine position in reduction buffer, which may be used
5651 by target. */
5652 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5653 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5654 offset = (offset + align - 1) & ~(align - 1);
5655 tree off = build_int_cst (sizetype, offset);
5656 offset += GET_MODE_SIZE (mode);
5658 if (!init_code)
5660 init_code = build_int_cst (integer_type_node,
5661 IFN_GOACC_REDUCTION_INIT);
5662 fini_code = build_int_cst (integer_type_node,
5663 IFN_GOACC_REDUCTION_FINI);
5664 setup_code = build_int_cst (integer_type_node,
5665 IFN_GOACC_REDUCTION_SETUP);
5666 teardown_code = build_int_cst (integer_type_node,
5667 IFN_GOACC_REDUCTION_TEARDOWN);
5670 tree setup_call
5671 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5672 TREE_TYPE (var), 6, setup_code,
5673 unshare_expr (ref_to_res),
5674 incoming, level, op, off);
5675 tree init_call
5676 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5677 TREE_TYPE (var), 6, init_code,
5678 unshare_expr (ref_to_res),
5679 var, level, op, off);
5680 tree fini_call
5681 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5682 TREE_TYPE (var), 6, fini_code,
5683 unshare_expr (ref_to_res),
5684 var, level, op, off);
5685 tree teardown_call
5686 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5687 TREE_TYPE (var), 6, teardown_code,
5688 ref_to_res, var, level, op, off);
5690 gimplify_assign (var, setup_call, &before_fork);
5691 gimplify_assign (var, init_call, &after_fork);
5692 gimplify_assign (var, fini_call, &before_join);
5693 gimplify_assign (outgoing, teardown_call, &after_join);
5696 /* Now stitch things together. */
5697 gimple_seq_add_seq (fork_seq, before_fork);
5698 if (fork)
5699 gimple_seq_add_stmt (fork_seq, fork);
5700 gimple_seq_add_seq (fork_seq, after_fork);
5702 gimple_seq_add_seq (join_seq, before_join);
5703 if (join)
5704 gimple_seq_add_stmt (join_seq, join);
5705 gimple_seq_add_seq (join_seq, after_join);
5708 /* Generate code to implement the REDUCTION clauses. */
5710 static void
5711 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5713 gimple_seq sub_seq = NULL;
5714 gimple *stmt;
5715 tree x, c;
5716 int count = 0;
5718 /* OpenACC loop reductions are handled elsewhere. */
5719 if (is_gimple_omp_oacc (ctx->stmt))
5720 return;
5722 /* SIMD reductions are handled in lower_rec_input_clauses. */
5723 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5724 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5725 return;
5727 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5728 update in that case, otherwise use a lock. */
5729 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5730 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5732 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5733 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5735 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5736 count = -1;
5737 break;
5739 count++;
5742 if (count == 0)
5743 return;
5745 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5747 tree var, ref, new_var, orig_var;
5748 enum tree_code code;
5749 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5751 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5752 continue;
5754 orig_var = var = OMP_CLAUSE_DECL (c);
5755 if (TREE_CODE (var) == MEM_REF)
5757 var = TREE_OPERAND (var, 0);
5758 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5759 var = TREE_OPERAND (var, 0);
5760 if (TREE_CODE (var) == INDIRECT_REF
5761 || TREE_CODE (var) == ADDR_EXPR)
5762 var = TREE_OPERAND (var, 0);
5763 orig_var = var;
5764 if (is_variable_sized (var))
5766 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5767 var = DECL_VALUE_EXPR (var);
5768 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5769 var = TREE_OPERAND (var, 0);
5770 gcc_assert (DECL_P (var));
5773 new_var = lookup_decl (var, ctx);
5774 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5775 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5776 ref = build_outer_var_ref (var, ctx);
5777 code = OMP_CLAUSE_REDUCTION_CODE (c);
5779 /* reduction(-:var) sums up the partial results, so it acts
5780 identically to reduction(+:var). */
5781 if (code == MINUS_EXPR)
5782 code = PLUS_EXPR;
5784 if (count == 1)
5786 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5788 addr = save_expr (addr);
5789 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5790 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5791 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5792 gimplify_and_add (x, stmt_seqp);
5793 return;
5795 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5797 tree d = OMP_CLAUSE_DECL (c);
5798 tree type = TREE_TYPE (d);
5799 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5800 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5801 tree ptype = build_pointer_type (TREE_TYPE (type));
5802 tree bias = TREE_OPERAND (d, 1);
5803 d = TREE_OPERAND (d, 0);
5804 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5806 tree b = TREE_OPERAND (d, 1);
5807 b = maybe_lookup_decl (b, ctx);
5808 if (b == NULL)
5810 b = TREE_OPERAND (d, 1);
5811 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5813 if (integer_zerop (bias))
5814 bias = b;
5815 else
5817 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5818 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5819 TREE_TYPE (b), b, bias);
5821 d = TREE_OPERAND (d, 0);
5823 /* For ref build_outer_var_ref already performs this, so
5824 only new_var needs a dereference. */
5825 if (TREE_CODE (d) == INDIRECT_REF)
5827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5828 gcc_assert (is_reference (var) && var == orig_var);
5830 else if (TREE_CODE (d) == ADDR_EXPR)
5832 if (orig_var == var)
5834 new_var = build_fold_addr_expr (new_var);
5835 ref = build_fold_addr_expr (ref);
5838 else
5840 gcc_assert (orig_var == var);
5841 if (is_reference (var))
5842 ref = build_fold_addr_expr (ref);
5844 if (DECL_P (v))
5846 tree t = maybe_lookup_decl (v, ctx);
5847 if (t)
5848 v = t;
5849 else
5850 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5851 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5853 if (!integer_zerop (bias))
5855 bias = fold_convert_loc (clause_loc, sizetype, bias);
5856 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5857 TREE_TYPE (new_var), new_var,
5858 unshare_expr (bias));
5859 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5860 TREE_TYPE (ref), ref, bias);
5862 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5863 ref = fold_convert_loc (clause_loc, ptype, ref);
5864 tree m = create_tmp_var (ptype, NULL);
5865 gimplify_assign (m, new_var, stmt_seqp);
5866 new_var = m;
5867 m = create_tmp_var (ptype, NULL);
5868 gimplify_assign (m, ref, stmt_seqp);
5869 ref = m;
5870 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5871 tree body = create_artificial_label (UNKNOWN_LOCATION);
5872 tree end = create_artificial_label (UNKNOWN_LOCATION);
5873 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5874 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5875 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5876 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5878 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5879 tree decl_placeholder
5880 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5881 SET_DECL_VALUE_EXPR (placeholder, out);
5882 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5883 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5884 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5885 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5886 gimple_seq_add_seq (&sub_seq,
5887 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5888 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5889 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5890 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5892 else
5894 x = build2 (code, TREE_TYPE (out), out, priv);
5895 out = unshare_expr (out);
5896 gimplify_assign (out, x, &sub_seq);
5898 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5899 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5900 gimple_seq_add_stmt (&sub_seq, g);
5901 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5902 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5903 gimple_seq_add_stmt (&sub_seq, g);
5904 g = gimple_build_assign (i, PLUS_EXPR, i,
5905 build_int_cst (TREE_TYPE (i), 1));
5906 gimple_seq_add_stmt (&sub_seq, g);
5907 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5908 gimple_seq_add_stmt (&sub_seq, g);
5909 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5911 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5913 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5915 if (is_reference (var)
5916 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5917 TREE_TYPE (ref)))
5918 ref = build_fold_addr_expr_loc (clause_loc, ref);
5919 SET_DECL_VALUE_EXPR (placeholder, ref);
5920 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5921 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5922 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5923 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5924 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5926 else
5928 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5929 ref = build_outer_var_ref (var, ctx);
5930 gimplify_assign (ref, x, &sub_seq);
5934 if (is_gimple_omp_oacc (ctx->stmt))
5935 return;
5937 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5939 gimple_seq_add_stmt (stmt_seqp, stmt);
5941 gimple_seq_add_seq (stmt_seqp, sub_seq);
5943 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5945 gimple_seq_add_stmt (stmt_seqp, stmt);
5949 /* Generate code to implement the COPYPRIVATE clauses. */
5951 static void
5952 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5953 omp_context *ctx)
5955 tree c;
5957 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5959 tree var, new_var, ref, x;
5960 bool by_ref;
5961 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5963 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5964 continue;
5966 var = OMP_CLAUSE_DECL (c);
5967 by_ref = use_pointer_for_field (var, NULL);
5969 ref = build_sender_ref (var, ctx);
5970 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5971 if (by_ref)
5973 x = build_fold_addr_expr_loc (clause_loc, new_var);
5974 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5976 gimplify_assign (ref, x, slist);
5978 ref = build_receiver_ref (var, false, ctx);
5979 if (by_ref)
5981 ref = fold_convert_loc (clause_loc,
5982 build_pointer_type (TREE_TYPE (new_var)),
5983 ref);
5984 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5986 if (is_reference (var))
5988 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5989 ref = build_simple_mem_ref_loc (clause_loc, ref);
5990 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5992 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5993 gimplify_and_add (x, rlist);
5998 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5999 and REDUCTION from the sender (aka parent) side. */
6001 static void
6002 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6003 omp_context *ctx)
6005 tree c, t;
6006 int ignored_looptemp = 0;
6007 bool is_taskloop = false;
6009 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6010 by GOMP_taskloop. */
6011 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6013 ignored_looptemp = 2;
6014 is_taskloop = true;
6017 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6019 tree val, ref, x, var;
6020 bool by_ref, do_in = false, do_out = false;
6021 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6023 switch (OMP_CLAUSE_CODE (c))
6025 case OMP_CLAUSE_PRIVATE:
6026 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6027 break;
6028 continue;
6029 case OMP_CLAUSE_FIRSTPRIVATE:
6030 case OMP_CLAUSE_COPYIN:
6031 case OMP_CLAUSE_LASTPRIVATE:
6032 case OMP_CLAUSE_REDUCTION:
6033 break;
6034 case OMP_CLAUSE_SHARED:
6035 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6036 break;
6037 continue;
6038 case OMP_CLAUSE__LOOPTEMP_:
6039 if (ignored_looptemp)
6041 ignored_looptemp--;
6042 continue;
6044 break;
6045 default:
6046 continue;
6049 val = OMP_CLAUSE_DECL (c);
6050 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6051 && TREE_CODE (val) == MEM_REF)
6053 val = TREE_OPERAND (val, 0);
6054 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6055 val = TREE_OPERAND (val, 0);
6056 if (TREE_CODE (val) == INDIRECT_REF
6057 || TREE_CODE (val) == ADDR_EXPR)
6058 val = TREE_OPERAND (val, 0);
6059 if (is_variable_sized (val))
6060 continue;
6063 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6064 outer taskloop region. */
6065 omp_context *ctx_for_o = ctx;
6066 if (is_taskloop
6067 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6068 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6069 ctx_for_o = ctx->outer;
6071 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6073 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6074 && is_global_var (var))
6075 continue;
6077 t = omp_member_access_dummy_var (var);
6078 if (t)
6080 var = DECL_VALUE_EXPR (var);
6081 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6082 if (o != t)
6083 var = unshare_and_remap (var, t, o);
6084 else
6085 var = unshare_expr (var);
6088 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6090 /* Handle taskloop firstprivate/lastprivate, where the
6091 lastprivate on GIMPLE_OMP_TASK is represented as
6092 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6093 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6094 x = omp_build_component_ref (ctx->sender_decl, f);
6095 if (use_pointer_for_field (val, ctx))
6096 var = build_fold_addr_expr (var);
6097 gimplify_assign (x, var, ilist);
6098 DECL_ABSTRACT_ORIGIN (f) = NULL;
6099 continue;
6102 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6103 || val == OMP_CLAUSE_DECL (c))
6104 && is_variable_sized (val))
6105 continue;
6106 by_ref = use_pointer_for_field (val, NULL);
6108 switch (OMP_CLAUSE_CODE (c))
6110 case OMP_CLAUSE_PRIVATE:
6111 case OMP_CLAUSE_FIRSTPRIVATE:
6112 case OMP_CLAUSE_COPYIN:
6113 case OMP_CLAUSE__LOOPTEMP_:
6114 do_in = true;
6115 break;
6117 case OMP_CLAUSE_LASTPRIVATE:
6118 if (by_ref || is_reference (val))
6120 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6121 continue;
6122 do_in = true;
6124 else
6126 do_out = true;
6127 if (lang_hooks.decls.omp_private_outer_ref (val))
6128 do_in = true;
6130 break;
6132 case OMP_CLAUSE_REDUCTION:
6133 do_in = true;
6134 if (val == OMP_CLAUSE_DECL (c))
6135 do_out = !(by_ref || is_reference (val));
6136 else
6137 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6138 break;
6140 default:
6141 gcc_unreachable ();
6144 if (do_in)
6146 ref = build_sender_ref (val, ctx);
6147 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6148 gimplify_assign (ref, x, ilist);
6149 if (is_task_ctx (ctx))
6150 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6153 if (do_out)
6155 ref = build_sender_ref (val, ctx);
6156 gimplify_assign (var, ref, olist);
6161 /* Generate code to implement SHARED from the sender (aka parent)
6162 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6163 list things that got automatically shared. */
6165 static void
6166 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6168 tree var, ovar, nvar, t, f, x, record_type;
6170 if (ctx->record_type == NULL)
6171 return;
6173 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6174 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6176 ovar = DECL_ABSTRACT_ORIGIN (f);
6177 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6178 continue;
6180 nvar = maybe_lookup_decl (ovar, ctx);
6181 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6182 continue;
6184 /* If CTX is a nested parallel directive. Find the immediately
6185 enclosing parallel or workshare construct that contains a
6186 mapping for OVAR. */
6187 var = lookup_decl_in_outer_ctx (ovar, ctx);
6189 t = omp_member_access_dummy_var (var);
6190 if (t)
6192 var = DECL_VALUE_EXPR (var);
6193 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6194 if (o != t)
6195 var = unshare_and_remap (var, t, o);
6196 else
6197 var = unshare_expr (var);
6200 if (use_pointer_for_field (ovar, ctx))
6202 x = build_sender_ref (ovar, ctx);
6203 var = build_fold_addr_expr (var);
6204 gimplify_assign (x, var, ilist);
6206 else
6208 x = build_sender_ref (ovar, ctx);
6209 gimplify_assign (x, var, ilist);
6211 if (!TREE_READONLY (var)
6212 /* We don't need to receive a new reference to a result
6213 or parm decl. In fact we may not store to it as we will
6214 invalidate any pending RSO and generate wrong gimple
6215 during inlining. */
6216 && !((TREE_CODE (var) == RESULT_DECL
6217 || TREE_CODE (var) == PARM_DECL)
6218 && DECL_BY_REFERENCE (var)))
6220 x = build_sender_ref (ovar, ctx);
6221 gimplify_assign (var, x, olist);
6227 /* Emit an OpenACC head marker call, encapulating the partitioning and
6228 other information that must be processed by the target compiler.
6229 Return the maximum number of dimensions the associated loop might
6230 be partitioned over. */
6232 static unsigned
6233 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6234 gimple_seq *seq, omp_context *ctx)
6236 unsigned levels = 0;
6237 unsigned tag = 0;
6238 tree gang_static = NULL_TREE;
6239 auto_vec<tree, 5> args;
6241 args.quick_push (build_int_cst
6242 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6243 args.quick_push (ddvar);
6244 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6246 switch (OMP_CLAUSE_CODE (c))
6248 case OMP_CLAUSE_GANG:
6249 tag |= OLF_DIM_GANG;
6250 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6251 /* static:* is represented by -1, and we can ignore it, as
6252 scheduling is always static. */
6253 if (gang_static && integer_minus_onep (gang_static))
6254 gang_static = NULL_TREE;
6255 levels++;
6256 break;
6258 case OMP_CLAUSE_WORKER:
6259 tag |= OLF_DIM_WORKER;
6260 levels++;
6261 break;
6263 case OMP_CLAUSE_VECTOR:
6264 tag |= OLF_DIM_VECTOR;
6265 levels++;
6266 break;
6268 case OMP_CLAUSE_SEQ:
6269 tag |= OLF_SEQ;
6270 break;
6272 case OMP_CLAUSE_AUTO:
6273 tag |= OLF_AUTO;
6274 break;
6276 case OMP_CLAUSE_INDEPENDENT:
6277 tag |= OLF_INDEPENDENT;
6278 break;
6280 default:
6281 continue;
6285 if (gang_static)
6287 if (DECL_P (gang_static))
6288 gang_static = build_outer_var_ref (gang_static, ctx);
6289 tag |= OLF_GANG_STATIC;
6292 /* In a parallel region, loops are implicitly INDEPENDENT. */
6293 omp_context *tgt = enclosing_target_ctx (ctx);
6294 if (!tgt || is_oacc_parallel (tgt))
6295 tag |= OLF_INDEPENDENT;
6297 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6298 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6299 | OLF_SEQ)))
6300 tag |= OLF_AUTO;
6302 /* Ensure at least one level. */
6303 if (!levels)
6304 levels++;
6306 args.quick_push (build_int_cst (integer_type_node, levels));
6307 args.quick_push (build_int_cst (integer_type_node, tag));
6308 if (gang_static)
6309 args.quick_push (gang_static);
6311 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6312 gimple_set_location (call, loc);
6313 gimple_set_lhs (call, ddvar);
6314 gimple_seq_add_stmt (seq, call);
6316 return levels;
6319 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6320 partitioning level of the enclosed region. */
6322 static void
6323 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6324 tree tofollow, gimple_seq *seq)
6326 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6327 : IFN_UNIQUE_OACC_TAIL_MARK);
6328 tree marker = build_int_cst (integer_type_node, marker_kind);
6329 int nargs = 2 + (tofollow != NULL_TREE);
6330 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6331 marker, ddvar, tofollow);
6332 gimple_set_location (call, loc);
6333 gimple_set_lhs (call, ddvar);
6334 gimple_seq_add_stmt (seq, call);
6337 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6338 the loop clauses, from which we extract reductions. Initialize
6339 HEAD and TAIL. */
6341 static void
6342 lower_oacc_head_tail (location_t loc, tree clauses,
6343 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6345 bool inner = false;
6346 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6347 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6349 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6350 if (!count)
6351 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6353 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6354 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6356 for (unsigned done = 1; count; count--, done++)
6358 gimple_seq fork_seq = NULL;
6359 gimple_seq join_seq = NULL;
6361 tree place = build_int_cst (integer_type_node, -1);
6362 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6363 fork_kind, ddvar, place);
6364 gimple_set_location (fork, loc);
6365 gimple_set_lhs (fork, ddvar);
6367 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6368 join_kind, ddvar, place);
6369 gimple_set_location (join, loc);
6370 gimple_set_lhs (join, ddvar);
6372 /* Mark the beginning of this level sequence. */
6373 if (inner)
6374 lower_oacc_loop_marker (loc, ddvar, true,
6375 build_int_cst (integer_type_node, count),
6376 &fork_seq);
6377 lower_oacc_loop_marker (loc, ddvar, false,
6378 build_int_cst (integer_type_node, done),
6379 &join_seq);
6381 lower_oacc_reductions (loc, clauses, place, inner,
6382 fork, join, &fork_seq, &join_seq, ctx);
6384 /* Append this level to head. */
6385 gimple_seq_add_seq (head, fork_seq);
6386 /* Prepend it to tail. */
6387 gimple_seq_add_seq (&join_seq, *tail);
6388 *tail = join_seq;
6390 inner = true;
6393 /* Mark the end of the sequence. */
6394 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6395 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6398 /* A convenience function to build an empty GIMPLE_COND with just the
6399 condition. */
6401 static gcond *
6402 gimple_build_cond_empty (tree cond)
6404 enum tree_code pred_code;
6405 tree lhs, rhs;
6407 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6408 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6411 /* Return true if a parallel REGION is within a declare target function or
6412 within a target region and is not a part of a gridified target. */
6414 static bool
6415 parallel_needs_hsa_kernel_p (struct omp_region *region)
6417 bool indirect = false;
6418 for (region = region->outer; region; region = region->outer)
6420 if (region->type == GIMPLE_OMP_PARALLEL)
6421 indirect = true;
6422 else if (region->type == GIMPLE_OMP_TARGET)
6424 gomp_target *tgt_stmt
6425 = as_a <gomp_target *> (last_stmt (region->entry));
6427 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6428 OMP_CLAUSE__GRIDDIM_))
6429 return indirect;
6430 else
6431 return true;
6435 if (lookup_attribute ("omp declare target",
6436 DECL_ATTRIBUTES (current_function_decl)))
6437 return true;
6439 return false;
6442 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6443 bool = false);
6445 /* Build the function calls to GOMP_parallel_start etc to actually
6446 generate the parallel operation. REGION is the parallel region
6447 being expanded. BB is the block where to insert the code. WS_ARGS
6448 will be set if this is a call to a combined parallel+workshare
6449 construct, it contains the list of additional arguments needed by
6450 the workshare construct. */
6452 static void
6453 expand_parallel_call (struct omp_region *region, basic_block bb,
6454 gomp_parallel *entry_stmt,
6455 vec<tree, va_gc> *ws_args)
6457 tree t, t1, t2, val, cond, c, clauses, flags;
6458 gimple_stmt_iterator gsi;
6459 gimple *stmt;
6460 enum built_in_function start_ix;
6461 int start_ix2;
6462 location_t clause_loc;
6463 vec<tree, va_gc> *args;
6465 clauses = gimple_omp_parallel_clauses (entry_stmt);
6467 /* Determine what flavor of GOMP_parallel we will be
6468 emitting. */
6469 start_ix = BUILT_IN_GOMP_PARALLEL;
6470 if (is_combined_parallel (region))
6472 switch (region->inner->type)
6474 case GIMPLE_OMP_FOR:
6475 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6476 switch (region->inner->sched_kind)
6478 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6479 start_ix2 = 3;
6480 break;
6481 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6482 case OMP_CLAUSE_SCHEDULE_GUIDED:
6483 if (region->inner->sched_modifiers
6484 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6486 start_ix2 = 3 + region->inner->sched_kind;
6487 break;
6489 /* FALLTHRU */
6490 default:
6491 start_ix2 = region->inner->sched_kind;
6492 break;
6494 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6495 start_ix = (enum built_in_function) start_ix2;
6496 break;
6497 case GIMPLE_OMP_SECTIONS:
6498 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6499 break;
6500 default:
6501 gcc_unreachable ();
6505 /* By default, the value of NUM_THREADS is zero (selected at run time)
6506 and there is no conditional. */
6507 cond = NULL_TREE;
6508 val = build_int_cst (unsigned_type_node, 0);
6509 flags = build_int_cst (unsigned_type_node, 0);
6511 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6512 if (c)
6513 cond = OMP_CLAUSE_IF_EXPR (c);
6515 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6516 if (c)
6518 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6519 clause_loc = OMP_CLAUSE_LOCATION (c);
6521 else
6522 clause_loc = gimple_location (entry_stmt);
6524 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6525 if (c)
6526 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6528 /* Ensure 'val' is of the correct type. */
6529 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6531 /* If we found the clause 'if (cond)', build either
6532 (cond != 0) or (cond ? val : 1u). */
6533 if (cond)
6535 cond = gimple_boolify (cond);
6537 if (integer_zerop (val))
6538 val = fold_build2_loc (clause_loc,
6539 EQ_EXPR, unsigned_type_node, cond,
6540 build_int_cst (TREE_TYPE (cond), 0));
6541 else
6543 basic_block cond_bb, then_bb, else_bb;
6544 edge e, e_then, e_else;
6545 tree tmp_then, tmp_else, tmp_join, tmp_var;
6547 tmp_var = create_tmp_var (TREE_TYPE (val));
6548 if (gimple_in_ssa_p (cfun))
6550 tmp_then = make_ssa_name (tmp_var);
6551 tmp_else = make_ssa_name (tmp_var);
6552 tmp_join = make_ssa_name (tmp_var);
6554 else
6556 tmp_then = tmp_var;
6557 tmp_else = tmp_var;
6558 tmp_join = tmp_var;
6561 e = split_block_after_labels (bb);
6562 cond_bb = e->src;
6563 bb = e->dest;
6564 remove_edge (e);
6566 then_bb = create_empty_bb (cond_bb);
6567 else_bb = create_empty_bb (then_bb);
6568 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6569 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6571 stmt = gimple_build_cond_empty (cond);
6572 gsi = gsi_start_bb (cond_bb);
6573 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6575 gsi = gsi_start_bb (then_bb);
6576 expand_omp_build_assign (&gsi, tmp_then, val, true);
6578 gsi = gsi_start_bb (else_bb);
6579 expand_omp_build_assign (&gsi, tmp_else,
6580 build_int_cst (unsigned_type_node, 1),
6581 true);
6583 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6584 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6585 add_bb_to_loop (then_bb, cond_bb->loop_father);
6586 add_bb_to_loop (else_bb, cond_bb->loop_father);
6587 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6588 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6590 if (gimple_in_ssa_p (cfun))
6592 gphi *phi = create_phi_node (tmp_join, bb);
6593 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6594 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6597 val = tmp_join;
6600 gsi = gsi_start_bb (bb);
6601 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6602 false, GSI_CONTINUE_LINKING);
6605 gsi = gsi_last_bb (bb);
6606 t = gimple_omp_parallel_data_arg (entry_stmt);
6607 if (t == NULL)
6608 t1 = null_pointer_node;
6609 else
6610 t1 = build_fold_addr_expr (t);
6611 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6612 t2 = build_fold_addr_expr (child_fndecl);
6614 vec_alloc (args, 4 + vec_safe_length (ws_args));
6615 args->quick_push (t2);
6616 args->quick_push (t1);
6617 args->quick_push (val);
6618 if (ws_args)
6619 args->splice (*ws_args);
6620 args->quick_push (flags);
6622 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6623 builtin_decl_explicit (start_ix), args);
6625 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6626 false, GSI_CONTINUE_LINKING);
6628 if (hsa_gen_requested_p ()
6629 && parallel_needs_hsa_kernel_p (region))
6631 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6632 hsa_register_kernel (child_cnode);
6636 /* Insert a function call whose name is FUNC_NAME with the information from
6637 ENTRY_STMT into the basic_block BB. */
6639 static void
6640 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6641 vec <tree, va_gc> *ws_args)
6643 tree t, t1, t2;
6644 gimple_stmt_iterator gsi;
6645 vec <tree, va_gc> *args;
6647 gcc_assert (vec_safe_length (ws_args) == 2);
6648 tree func_name = (*ws_args)[0];
6649 tree grain = (*ws_args)[1];
6651 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6652 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6653 gcc_assert (count != NULL_TREE);
6654 count = OMP_CLAUSE_OPERAND (count, 0);
6656 gsi = gsi_last_bb (bb);
6657 t = gimple_omp_parallel_data_arg (entry_stmt);
6658 if (t == NULL)
6659 t1 = null_pointer_node;
6660 else
6661 t1 = build_fold_addr_expr (t);
6662 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6664 vec_alloc (args, 4);
6665 args->quick_push (t2);
6666 args->quick_push (t1);
6667 args->quick_push (count);
6668 args->quick_push (grain);
6669 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6671 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6672 GSI_CONTINUE_LINKING);
6675 /* Build the function call to GOMP_task to actually
6676 generate the task operation. BB is the block where to insert the code. */
6678 static void
6679 expand_task_call (struct omp_region *region, basic_block bb,
6680 gomp_task *entry_stmt)
6682 tree t1, t2, t3;
6683 gimple_stmt_iterator gsi;
6684 location_t loc = gimple_location (entry_stmt);
6686 tree clauses = gimple_omp_task_clauses (entry_stmt);
6688 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6689 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6690 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6691 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6692 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6693 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6695 unsigned int iflags
6696 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6697 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6698 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6700 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6701 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6702 tree num_tasks = NULL_TREE;
6703 bool ull = false;
6704 if (taskloop_p)
6706 gimple *g = last_stmt (region->outer->entry);
6707 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6708 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6709 struct omp_for_data fd;
6710 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6711 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6712 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6713 OMP_CLAUSE__LOOPTEMP_);
6714 startvar = OMP_CLAUSE_DECL (startvar);
6715 endvar = OMP_CLAUSE_DECL (endvar);
6716 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6717 if (fd.loop.cond_code == LT_EXPR)
6718 iflags |= GOMP_TASK_FLAG_UP;
6719 tree tclauses = gimple_omp_for_clauses (g);
6720 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6721 if (num_tasks)
6722 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6723 else
6725 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6726 if (num_tasks)
6728 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6729 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6731 else
6732 num_tasks = integer_zero_node;
6734 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6735 if (ifc == NULL_TREE)
6736 iflags |= GOMP_TASK_FLAG_IF;
6737 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6738 iflags |= GOMP_TASK_FLAG_NOGROUP;
6739 ull = fd.iter_type == long_long_unsigned_type_node;
6741 else if (priority)
6742 iflags |= GOMP_TASK_FLAG_PRIORITY;
6744 tree flags = build_int_cst (unsigned_type_node, iflags);
6746 tree cond = boolean_true_node;
6747 if (ifc)
6749 if (taskloop_p)
6751 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6752 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6753 build_int_cst (unsigned_type_node,
6754 GOMP_TASK_FLAG_IF),
6755 build_int_cst (unsigned_type_node, 0));
6756 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6757 flags, t);
6759 else
6760 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6763 if (finalc)
6765 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6766 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6767 build_int_cst (unsigned_type_node,
6768 GOMP_TASK_FLAG_FINAL),
6769 build_int_cst (unsigned_type_node, 0));
6770 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6772 if (depend)
6773 depend = OMP_CLAUSE_DECL (depend);
6774 else
6775 depend = build_int_cst (ptr_type_node, 0);
6776 if (priority)
6777 priority = fold_convert (integer_type_node,
6778 OMP_CLAUSE_PRIORITY_EXPR (priority));
6779 else
6780 priority = integer_zero_node;
6782 gsi = gsi_last_bb (bb);
6783 tree t = gimple_omp_task_data_arg (entry_stmt);
6784 if (t == NULL)
6785 t2 = null_pointer_node;
6786 else
6787 t2 = build_fold_addr_expr_loc (loc, t);
6788 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6789 t = gimple_omp_task_copy_fn (entry_stmt);
6790 if (t == NULL)
6791 t3 = null_pointer_node;
6792 else
6793 t3 = build_fold_addr_expr_loc (loc, t);
6795 if (taskloop_p)
6796 t = build_call_expr (ull
6797 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6798 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6799 11, t1, t2, t3,
6800 gimple_omp_task_arg_size (entry_stmt),
6801 gimple_omp_task_arg_align (entry_stmt), flags,
6802 num_tasks, priority, startvar, endvar, step);
6803 else
6804 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6805 9, t1, t2, t3,
6806 gimple_omp_task_arg_size (entry_stmt),
6807 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6808 depend, priority);
6810 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6811 false, GSI_CONTINUE_LINKING);
6815 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6816 catch handler and return it. This prevents programs from violating the
6817 structured block semantics with throws. */
6819 static gimple_seq
6820 maybe_catch_exception (gimple_seq body)
6822 gimple *g;
6823 tree decl;
6825 if (!flag_exceptions)
6826 return body;
6828 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6829 decl = lang_hooks.eh_protect_cleanup_actions ();
6830 else
6831 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6833 g = gimple_build_eh_must_not_throw (decl);
6834 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6835 GIMPLE_TRY_CATCH);
6837 return gimple_seq_alloc_with_stmt (g);
6840 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6842 static tree
6843 vec2chain (vec<tree, va_gc> *v)
6845 tree chain = NULL_TREE, t;
6846 unsigned ix;
6848 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6850 DECL_CHAIN (t) = chain;
6851 chain = t;
6854 return chain;
6858 /* Remove barriers in REGION->EXIT's block. Note that this is only
6859 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6860 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6861 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6862 removed. */
6864 static void
6865 remove_exit_barrier (struct omp_region *region)
6867 gimple_stmt_iterator gsi;
6868 basic_block exit_bb;
6869 edge_iterator ei;
6870 edge e;
6871 gimple *stmt;
6872 int any_addressable_vars = -1;
6874 exit_bb = region->exit;
6876 /* If the parallel region doesn't return, we don't have REGION->EXIT
6877 block at all. */
6878 if (! exit_bb)
6879 return;
6881 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6882 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6883 statements that can appear in between are extremely limited -- no
6884 memory operations at all. Here, we allow nothing at all, so the
6885 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6886 gsi = gsi_last_bb (exit_bb);
6887 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6888 gsi_prev (&gsi);
6889 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6890 return;
6892 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6894 gsi = gsi_last_bb (e->src);
6895 if (gsi_end_p (gsi))
6896 continue;
6897 stmt = gsi_stmt (gsi);
6898 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6899 && !gimple_omp_return_nowait_p (stmt))
6901 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6902 in many cases. If there could be tasks queued, the barrier
6903 might be needed to let the tasks run before some local
6904 variable of the parallel that the task uses as shared
6905 runs out of scope. The task can be spawned either
6906 from within current function (this would be easy to check)
6907 or from some function it calls and gets passed an address
6908 of such a variable. */
6909 if (any_addressable_vars < 0)
6911 gomp_parallel *parallel_stmt
6912 = as_a <gomp_parallel *> (last_stmt (region->entry));
6913 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6914 tree local_decls, block, decl;
6915 unsigned ix;
6917 any_addressable_vars = 0;
6918 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6919 if (TREE_ADDRESSABLE (decl))
6921 any_addressable_vars = 1;
6922 break;
6924 for (block = gimple_block (stmt);
6925 !any_addressable_vars
6926 && block
6927 && TREE_CODE (block) == BLOCK;
6928 block = BLOCK_SUPERCONTEXT (block))
6930 for (local_decls = BLOCK_VARS (block);
6931 local_decls;
6932 local_decls = DECL_CHAIN (local_decls))
6933 if (TREE_ADDRESSABLE (local_decls))
6935 any_addressable_vars = 1;
6936 break;
6938 if (block == gimple_block (parallel_stmt))
6939 break;
6942 if (!any_addressable_vars)
6943 gimple_omp_return_set_nowait (stmt);
6948 static void
6949 remove_exit_barriers (struct omp_region *region)
6951 if (region->type == GIMPLE_OMP_PARALLEL)
6952 remove_exit_barrier (region);
6954 if (region->inner)
6956 region = region->inner;
6957 remove_exit_barriers (region);
6958 while (region->next)
6960 region = region->next;
6961 remove_exit_barriers (region);
6966 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6967 calls. These can't be declared as const functions, but
6968 within one parallel body they are constant, so they can be
6969 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6970 which are declared const. Similarly for task body, except
6971 that in untied task omp_get_thread_num () can change at any task
6972 scheduling point. */
6974 static void
6975 optimize_omp_library_calls (gimple *entry_stmt)
6977 basic_block bb;
6978 gimple_stmt_iterator gsi;
6979 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6980 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6981 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6982 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6983 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6984 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6985 OMP_CLAUSE_UNTIED) != NULL);
6987 FOR_EACH_BB_FN (bb, cfun)
6988 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6990 gimple *call = gsi_stmt (gsi);
6991 tree decl;
6993 if (is_gimple_call (call)
6994 && (decl = gimple_call_fndecl (call))
6995 && DECL_EXTERNAL (decl)
6996 && TREE_PUBLIC (decl)
6997 && DECL_INITIAL (decl) == NULL)
6999 tree built_in;
7001 if (DECL_NAME (decl) == thr_num_id)
7003 /* In #pragma omp task untied omp_get_thread_num () can change
7004 during the execution of the task region. */
7005 if (untied_task)
7006 continue;
7007 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7009 else if (DECL_NAME (decl) == num_thr_id)
7010 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7011 else
7012 continue;
7014 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7015 || gimple_call_num_args (call) != 0)
7016 continue;
7018 if (flag_exceptions && !TREE_NOTHROW (decl))
7019 continue;
7021 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7022 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7023 TREE_TYPE (TREE_TYPE (built_in))))
7024 continue;
7026 gimple_call_set_fndecl (call, built_in);
7031 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7032 regimplified. */
7034 static tree
7035 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7037 tree t = *tp;
7039 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7040 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7041 return t;
7043 if (TREE_CODE (t) == ADDR_EXPR)
7044 recompute_tree_invariant_for_addr_expr (t);
7046 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7047 return NULL_TREE;
7050 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7052 static void
7053 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7054 bool after)
7056 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7057 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7058 !after, after ? GSI_CONTINUE_LINKING
7059 : GSI_SAME_STMT);
7060 gimple *stmt = gimple_build_assign (to, from);
7061 if (after)
7062 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7063 else
7064 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7065 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7066 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7068 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7069 gimple_regimplify_operands (stmt, &gsi);
7073 /* Expand the OpenMP parallel or task directive starting at REGION. */
7075 static void
7076 expand_omp_taskreg (struct omp_region *region)
7078 basic_block entry_bb, exit_bb, new_bb;
7079 struct function *child_cfun;
7080 tree child_fn, block, t;
7081 gimple_stmt_iterator gsi;
7082 gimple *entry_stmt, *stmt;
7083 edge e;
7084 vec<tree, va_gc> *ws_args;
7086 entry_stmt = last_stmt (region->entry);
7087 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7088 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7090 entry_bb = region->entry;
7091 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7092 exit_bb = region->cont;
7093 else
7094 exit_bb = region->exit;
7096 bool is_cilk_for
7097 = (flag_cilkplus
7098 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7099 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7100 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7102 if (is_cilk_for)
7103 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7104 and the inner statement contains the name of the built-in function
7105 and grain. */
7106 ws_args = region->inner->ws_args;
7107 else if (is_combined_parallel (region))
7108 ws_args = region->ws_args;
7109 else
7110 ws_args = NULL;
7112 if (child_cfun->cfg)
7114 /* Due to inlining, it may happen that we have already outlined
7115 the region, in which case all we need to do is make the
7116 sub-graph unreachable and emit the parallel call. */
7117 edge entry_succ_e, exit_succ_e;
7119 entry_succ_e = single_succ_edge (entry_bb);
7121 gsi = gsi_last_bb (entry_bb);
7122 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7123 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7124 gsi_remove (&gsi, true);
7126 new_bb = entry_bb;
7127 if (exit_bb)
7129 exit_succ_e = single_succ_edge (exit_bb);
7130 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7132 remove_edge_and_dominated_blocks (entry_succ_e);
7134 else
7136 unsigned srcidx, dstidx, num;
7138 /* If the parallel region needs data sent from the parent
7139 function, then the very first statement (except possible
7140 tree profile counter updates) of the parallel body
7141 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7142 &.OMP_DATA_O is passed as an argument to the child function,
7143 we need to replace it with the argument as seen by the child
7144 function.
7146 In most cases, this will end up being the identity assignment
7147 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7148 a function call that has been inlined, the original PARM_DECL
7149 .OMP_DATA_I may have been converted into a different local
7150 variable. In which case, we need to keep the assignment. */
7151 if (gimple_omp_taskreg_data_arg (entry_stmt))
7153 basic_block entry_succ_bb
7154 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7155 : FALLTHRU_EDGE (entry_bb)->dest;
7156 tree arg;
7157 gimple *parcopy_stmt = NULL;
7159 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7161 gimple *stmt;
7163 gcc_assert (!gsi_end_p (gsi));
7164 stmt = gsi_stmt (gsi);
7165 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7166 continue;
7168 if (gimple_num_ops (stmt) == 2)
7170 tree arg = gimple_assign_rhs1 (stmt);
7172 /* We're ignore the subcode because we're
7173 effectively doing a STRIP_NOPS. */
7175 if (TREE_CODE (arg) == ADDR_EXPR
7176 && TREE_OPERAND (arg, 0)
7177 == gimple_omp_taskreg_data_arg (entry_stmt))
7179 parcopy_stmt = stmt;
7180 break;
7185 gcc_assert (parcopy_stmt != NULL);
7186 arg = DECL_ARGUMENTS (child_fn);
7188 if (!gimple_in_ssa_p (cfun))
7190 if (gimple_assign_lhs (parcopy_stmt) == arg)
7191 gsi_remove (&gsi, true);
7192 else
7194 /* ?? Is setting the subcode really necessary ?? */
7195 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7196 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7199 else
7201 tree lhs = gimple_assign_lhs (parcopy_stmt);
7202 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7203 /* We'd like to set the rhs to the default def in the child_fn,
7204 but it's too early to create ssa names in the child_fn.
7205 Instead, we set the rhs to the parm. In
7206 move_sese_region_to_fn, we introduce a default def for the
7207 parm, map the parm to it's default def, and once we encounter
7208 this stmt, replace the parm with the default def. */
7209 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7210 update_stmt (parcopy_stmt);
7214 /* Declare local variables needed in CHILD_CFUN. */
7215 block = DECL_INITIAL (child_fn);
7216 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7217 /* The gimplifier could record temporaries in parallel/task block
7218 rather than in containing function's local_decls chain,
7219 which would mean cgraph missed finalizing them. Do it now. */
7220 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7221 if (TREE_CODE (t) == VAR_DECL
7222 && TREE_STATIC (t)
7223 && !DECL_EXTERNAL (t))
7224 varpool_node::finalize_decl (t);
7225 DECL_SAVED_TREE (child_fn) = NULL;
7226 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7227 gimple_set_body (child_fn, NULL);
7228 TREE_USED (block) = 1;
7230 /* Reset DECL_CONTEXT on function arguments. */
7231 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7232 DECL_CONTEXT (t) = child_fn;
7234 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7235 so that it can be moved to the child function. */
7236 gsi = gsi_last_bb (entry_bb);
7237 stmt = gsi_stmt (gsi);
7238 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7239 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7240 e = split_block (entry_bb, stmt);
7241 gsi_remove (&gsi, true);
7242 entry_bb = e->dest;
7243 edge e2 = NULL;
7244 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7245 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7246 else
7248 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7249 gcc_assert (e2->dest == region->exit);
7250 remove_edge (BRANCH_EDGE (entry_bb));
7251 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7252 gsi = gsi_last_bb (region->exit);
7253 gcc_assert (!gsi_end_p (gsi)
7254 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7255 gsi_remove (&gsi, true);
7258 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7259 if (exit_bb)
7261 gsi = gsi_last_bb (exit_bb);
7262 gcc_assert (!gsi_end_p (gsi)
7263 && (gimple_code (gsi_stmt (gsi))
7264 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7265 stmt = gimple_build_return (NULL);
7266 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7267 gsi_remove (&gsi, true);
7270 /* Move the parallel region into CHILD_CFUN. */
7272 if (gimple_in_ssa_p (cfun))
7274 init_tree_ssa (child_cfun);
7275 init_ssa_operands (child_cfun);
7276 child_cfun->gimple_df->in_ssa_p = true;
7277 block = NULL_TREE;
7279 else
7280 block = gimple_block (entry_stmt);
7282 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7283 if (exit_bb)
7284 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7285 if (e2)
7287 basic_block dest_bb = e2->dest;
7288 if (!exit_bb)
7289 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7290 remove_edge (e2);
7291 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7293 /* When the OMP expansion process cannot guarantee an up-to-date
7294 loop tree arrange for the child function to fixup loops. */
7295 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7296 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7298 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7299 num = vec_safe_length (child_cfun->local_decls);
7300 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7302 t = (*child_cfun->local_decls)[srcidx];
7303 if (DECL_CONTEXT (t) == cfun->decl)
7304 continue;
7305 if (srcidx != dstidx)
7306 (*child_cfun->local_decls)[dstidx] = t;
7307 dstidx++;
7309 if (dstidx != num)
7310 vec_safe_truncate (child_cfun->local_decls, dstidx);
7312 /* Inform the callgraph about the new function. */
7313 child_cfun->curr_properties = cfun->curr_properties;
7314 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7315 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7316 cgraph_node *node = cgraph_node::get_create (child_fn);
7317 node->parallelized_function = 1;
7318 cgraph_node::add_new_function (child_fn, true);
7320 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7321 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7323 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7324 fixed in a following pass. */
7325 push_cfun (child_cfun);
7326 if (need_asm)
7327 assign_assembler_name_if_neeeded (child_fn);
7329 if (optimize)
7330 optimize_omp_library_calls (entry_stmt);
7331 cgraph_edge::rebuild_edges ();
7333 /* Some EH regions might become dead, see PR34608. If
7334 pass_cleanup_cfg isn't the first pass to happen with the
7335 new child, these dead EH edges might cause problems.
7336 Clean them up now. */
7337 if (flag_exceptions)
7339 basic_block bb;
7340 bool changed = false;
7342 FOR_EACH_BB_FN (bb, cfun)
7343 changed |= gimple_purge_dead_eh_edges (bb);
7344 if (changed)
7345 cleanup_tree_cfg ();
7347 if (gimple_in_ssa_p (cfun))
7348 update_ssa (TODO_update_ssa);
7349 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7350 verify_loop_structure ();
7351 pop_cfun ();
7353 if (dump_file && !gimple_in_ssa_p (cfun))
7355 omp_any_child_fn_dumped = true;
7356 dump_function_header (dump_file, child_fn, dump_flags);
7357 dump_function_to_file (child_fn, dump_file, dump_flags);
7361 /* Emit a library call to launch the children threads. */
7362 if (is_cilk_for)
7363 expand_cilk_for_call (new_bb,
7364 as_a <gomp_parallel *> (entry_stmt), ws_args);
7365 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7366 expand_parallel_call (region, new_bb,
7367 as_a <gomp_parallel *> (entry_stmt), ws_args);
7368 else
7369 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7370 if (gimple_in_ssa_p (cfun))
7371 update_ssa (TODO_update_ssa_only_virtuals);
7374 /* Information about members of an OpenACC collapsed loop nest. */
7376 struct oacc_collapse
7378 tree base; /* Base value. */
7379 tree iters; /* Number of steps. */
7380 tree step; /* step size. */
7383 /* Helper for expand_oacc_for. Determine collapsed loop information.
7384 Fill in COUNTS array. Emit any initialization code before GSI.
7385 Return the calculated outer loop bound of BOUND_TYPE. */
7387 static tree
7388 expand_oacc_collapse_init (const struct omp_for_data *fd,
7389 gimple_stmt_iterator *gsi,
7390 oacc_collapse *counts, tree bound_type)
7392 tree total = build_int_cst (bound_type, 1);
7393 int ix;
7395 gcc_assert (integer_onep (fd->loop.step));
7396 gcc_assert (integer_zerop (fd->loop.n1));
7398 for (ix = 0; ix != fd->collapse; ix++)
7400 const omp_for_data_loop *loop = &fd->loops[ix];
7402 tree iter_type = TREE_TYPE (loop->v);
7403 tree diff_type = iter_type;
7404 tree plus_type = iter_type;
7406 gcc_assert (loop->cond_code == fd->loop.cond_code);
7408 if (POINTER_TYPE_P (iter_type))
7409 plus_type = sizetype;
7410 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7411 diff_type = signed_type_for (diff_type);
7413 tree b = loop->n1;
7414 tree e = loop->n2;
7415 tree s = loop->step;
7416 bool up = loop->cond_code == LT_EXPR;
7417 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7418 bool negating;
7419 tree expr;
7421 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7422 true, GSI_SAME_STMT);
7423 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7424 true, GSI_SAME_STMT);
7426 /* Convert the step, avoiding possible unsigned->signed overflow. */
7427 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7428 if (negating)
7429 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7430 s = fold_convert (diff_type, s);
7431 if (negating)
7432 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7433 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7434 true, GSI_SAME_STMT);
7436 /* Determine the range, avoiding possible unsigned->signed overflow. */
7437 negating = !up && TYPE_UNSIGNED (iter_type);
7438 expr = fold_build2 (MINUS_EXPR, plus_type,
7439 fold_convert (plus_type, negating ? b : e),
7440 fold_convert (plus_type, negating ? e : b));
7441 expr = fold_convert (diff_type, expr);
7442 if (negating)
7443 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7444 tree range = force_gimple_operand_gsi
7445 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7447 /* Determine number of iterations. */
7448 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7449 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7450 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7452 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7453 true, GSI_SAME_STMT);
7455 counts[ix].base = b;
7456 counts[ix].iters = iters;
7457 counts[ix].step = s;
7459 total = fold_build2 (MULT_EXPR, bound_type, total,
7460 fold_convert (bound_type, iters));
7463 return total;
7466 /* Emit initializers for collapsed loop members. IVAR is the outer
7467 loop iteration variable, from which collapsed loop iteration values
7468 are calculated. COUNTS array has been initialized by
7469 expand_oacc_collapse_inits. */
7471 static void
7472 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7473 gimple_stmt_iterator *gsi,
7474 const oacc_collapse *counts, tree ivar)
7476 tree ivar_type = TREE_TYPE (ivar);
7478 /* The most rapidly changing iteration variable is the innermost
7479 one. */
7480 for (int ix = fd->collapse; ix--;)
7482 const omp_for_data_loop *loop = &fd->loops[ix];
7483 const oacc_collapse *collapse = &counts[ix];
7484 tree iter_type = TREE_TYPE (loop->v);
7485 tree diff_type = TREE_TYPE (collapse->step);
7486 tree plus_type = iter_type;
7487 enum tree_code plus_code = PLUS_EXPR;
7488 tree expr;
7490 if (POINTER_TYPE_P (iter_type))
7492 plus_code = POINTER_PLUS_EXPR;
7493 plus_type = sizetype;
7496 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7497 fold_convert (ivar_type, collapse->iters));
7498 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7499 collapse->step);
7500 expr = fold_build2 (plus_code, iter_type, collapse->base,
7501 fold_convert (plus_type, expr));
7502 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7503 true, GSI_SAME_STMT);
7504 gassign *ass = gimple_build_assign (loop->v, expr);
7505 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7507 if (ix)
7509 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7510 fold_convert (ivar_type, collapse->iters));
7511 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7512 true, GSI_SAME_STMT);
7518 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7519 of the combined collapse > 1 loop constructs, generate code like:
7520 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7521 if (cond3 is <)
7522 adj = STEP3 - 1;
7523 else
7524 adj = STEP3 + 1;
7525 count3 = (adj + N32 - N31) / STEP3;
7526 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7527 if (cond2 is <)
7528 adj = STEP2 - 1;
7529 else
7530 adj = STEP2 + 1;
7531 count2 = (adj + N22 - N21) / STEP2;
7532 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7533 if (cond1 is <)
7534 adj = STEP1 - 1;
7535 else
7536 adj = STEP1 + 1;
7537 count1 = (adj + N12 - N11) / STEP1;
7538 count = count1 * count2 * count3;
7539 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7540 count = 0;
7541 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7542 of the combined loop constructs, just initialize COUNTS array
7543 from the _looptemp_ clauses. */
7545 /* NOTE: It *could* be better to moosh all of the BBs together,
7546 creating one larger BB with all the computation and the unexpected
7547 jump at the end. I.e.
7549 bool zero3, zero2, zero1, zero;
7551 zero3 = N32 c3 N31;
7552 count3 = (N32 - N31) /[cl] STEP3;
7553 zero2 = N22 c2 N21;
7554 count2 = (N22 - N21) /[cl] STEP2;
7555 zero1 = N12 c1 N11;
7556 count1 = (N12 - N11) /[cl] STEP1;
7557 zero = zero3 || zero2 || zero1;
7558 count = count1 * count2 * count3;
7559 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7561 After all, we expect the zero=false, and thus we expect to have to
7562 evaluate all of the comparison expressions, so short-circuiting
7563 oughtn't be a win. Since the condition isn't protecting a
7564 denominator, we're not concerned about divide-by-zero, so we can
7565 fully evaluate count even if a numerator turned out to be wrong.
7567 It seems like putting this all together would create much better
7568 scheduling opportunities, and less pressure on the chip's branch
7569 predictor. */
7571 static void
7572 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7573 basic_block &entry_bb, tree *counts,
7574 basic_block &zero_iter1_bb, int &first_zero_iter1,
7575 basic_block &zero_iter2_bb, int &first_zero_iter2,
7576 basic_block &l2_dom_bb)
7578 tree t, type = TREE_TYPE (fd->loop.v);
7579 edge e, ne;
7580 int i;
7582 /* Collapsed loops need work for expansion into SSA form. */
7583 gcc_assert (!gimple_in_ssa_p (cfun));
7585 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7586 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7588 gcc_assert (fd->ordered == 0);
7589 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7590 isn't supposed to be handled, as the inner loop doesn't
7591 use it. */
7592 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7593 OMP_CLAUSE__LOOPTEMP_);
7594 gcc_assert (innerc);
7595 for (i = 0; i < fd->collapse; i++)
7597 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7598 OMP_CLAUSE__LOOPTEMP_);
7599 gcc_assert (innerc);
7600 if (i)
7601 counts[i] = OMP_CLAUSE_DECL (innerc);
7602 else
7603 counts[0] = NULL_TREE;
7605 return;
7608 for (i = fd->collapse; i < fd->ordered; i++)
7610 tree itype = TREE_TYPE (fd->loops[i].v);
7611 counts[i] = NULL_TREE;
7612 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7613 fold_convert (itype, fd->loops[i].n1),
7614 fold_convert (itype, fd->loops[i].n2));
7615 if (t && integer_zerop (t))
7617 for (i = fd->collapse; i < fd->ordered; i++)
7618 counts[i] = build_int_cst (type, 0);
7619 break;
7622 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7624 tree itype = TREE_TYPE (fd->loops[i].v);
7626 if (i >= fd->collapse && counts[i])
7627 continue;
7628 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7629 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7630 fold_convert (itype, fd->loops[i].n1),
7631 fold_convert (itype, fd->loops[i].n2)))
7632 == NULL_TREE || !integer_onep (t)))
7634 gcond *cond_stmt;
7635 tree n1, n2;
7636 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7637 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7638 true, GSI_SAME_STMT);
7639 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7640 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7641 true, GSI_SAME_STMT);
7642 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7643 NULL_TREE, NULL_TREE);
7644 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7645 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7646 expand_omp_regimplify_p, NULL, NULL)
7647 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7648 expand_omp_regimplify_p, NULL, NULL))
7650 *gsi = gsi_for_stmt (cond_stmt);
7651 gimple_regimplify_operands (cond_stmt, gsi);
7653 e = split_block (entry_bb, cond_stmt);
7654 basic_block &zero_iter_bb
7655 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7656 int &first_zero_iter
7657 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7658 if (zero_iter_bb == NULL)
7660 gassign *assign_stmt;
7661 first_zero_iter = i;
7662 zero_iter_bb = create_empty_bb (entry_bb);
7663 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7664 *gsi = gsi_after_labels (zero_iter_bb);
7665 if (i < fd->collapse)
7666 assign_stmt = gimple_build_assign (fd->loop.n2,
7667 build_zero_cst (type));
7668 else
7670 counts[i] = create_tmp_reg (type, ".count");
7671 assign_stmt
7672 = gimple_build_assign (counts[i], build_zero_cst (type));
7674 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7675 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7676 entry_bb);
7678 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7679 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7680 e->flags = EDGE_TRUE_VALUE;
7681 e->probability = REG_BR_PROB_BASE - ne->probability;
7682 if (l2_dom_bb == NULL)
7683 l2_dom_bb = entry_bb;
7684 entry_bb = e->dest;
7685 *gsi = gsi_last_bb (entry_bb);
7688 if (POINTER_TYPE_P (itype))
7689 itype = signed_type_for (itype);
7690 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7691 ? -1 : 1));
7692 t = fold_build2 (PLUS_EXPR, itype,
7693 fold_convert (itype, fd->loops[i].step), t);
7694 t = fold_build2 (PLUS_EXPR, itype, t,
7695 fold_convert (itype, fd->loops[i].n2));
7696 t = fold_build2 (MINUS_EXPR, itype, t,
7697 fold_convert (itype, fd->loops[i].n1));
7698 /* ?? We could probably use CEIL_DIV_EXPR instead of
7699 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7700 generate the same code in the end because generically we
7701 don't know that the values involved must be negative for
7702 GT?? */
7703 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7704 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7705 fold_build1 (NEGATE_EXPR, itype, t),
7706 fold_build1 (NEGATE_EXPR, itype,
7707 fold_convert (itype,
7708 fd->loops[i].step)));
7709 else
7710 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7711 fold_convert (itype, fd->loops[i].step));
7712 t = fold_convert (type, t);
7713 if (TREE_CODE (t) == INTEGER_CST)
7714 counts[i] = t;
7715 else
7717 if (i < fd->collapse || i != first_zero_iter2)
7718 counts[i] = create_tmp_reg (type, ".count");
7719 expand_omp_build_assign (gsi, counts[i], t);
7721 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7723 if (i == 0)
7724 t = counts[0];
7725 else
7726 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7727 expand_omp_build_assign (gsi, fd->loop.n2, t);
7733 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7734 T = V;
7735 V3 = N31 + (T % count3) * STEP3;
7736 T = T / count3;
7737 V2 = N21 + (T % count2) * STEP2;
7738 T = T / count2;
7739 V1 = N11 + T * STEP1;
7740 if this loop doesn't have an inner loop construct combined with it.
7741 If it does have an inner loop construct combined with it and the
7742 iteration count isn't known constant, store values from counts array
7743 into its _looptemp_ temporaries instead. */
7745 static void
7746 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7747 tree *counts, gimple *inner_stmt, tree startvar)
7749 int i;
7750 if (gimple_omp_for_combined_p (fd->for_stmt))
7752 /* If fd->loop.n2 is constant, then no propagation of the counts
7753 is needed, they are constant. */
7754 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7755 return;
7757 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7758 ? gimple_omp_taskreg_clauses (inner_stmt)
7759 : gimple_omp_for_clauses (inner_stmt);
7760 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7761 isn't supposed to be handled, as the inner loop doesn't
7762 use it. */
7763 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7764 gcc_assert (innerc);
7765 for (i = 0; i < fd->collapse; i++)
7767 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7768 OMP_CLAUSE__LOOPTEMP_);
7769 gcc_assert (innerc);
7770 if (i)
7772 tree tem = OMP_CLAUSE_DECL (innerc);
7773 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7774 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7775 false, GSI_CONTINUE_LINKING);
7776 gassign *stmt = gimple_build_assign (tem, t);
7777 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7780 return;
7783 tree type = TREE_TYPE (fd->loop.v);
7784 tree tem = create_tmp_reg (type, ".tem");
7785 gassign *stmt = gimple_build_assign (tem, startvar);
7786 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7788 for (i = fd->collapse - 1; i >= 0; i--)
7790 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7791 itype = vtype;
7792 if (POINTER_TYPE_P (vtype))
7793 itype = signed_type_for (vtype);
7794 if (i != 0)
7795 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7796 else
7797 t = tem;
7798 t = fold_convert (itype, t);
7799 t = fold_build2 (MULT_EXPR, itype, t,
7800 fold_convert (itype, fd->loops[i].step));
7801 if (POINTER_TYPE_P (vtype))
7802 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7803 else
7804 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7805 t = force_gimple_operand_gsi (gsi, t,
7806 DECL_P (fd->loops[i].v)
7807 && TREE_ADDRESSABLE (fd->loops[i].v),
7808 NULL_TREE, false,
7809 GSI_CONTINUE_LINKING);
7810 stmt = gimple_build_assign (fd->loops[i].v, t);
7811 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7812 if (i != 0)
7814 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7815 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7816 false, GSI_CONTINUE_LINKING);
7817 stmt = gimple_build_assign (tem, t);
7818 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7824 /* Helper function for expand_omp_for_*. Generate code like:
7825 L10:
7826 V3 += STEP3;
7827 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7828 L11:
7829 V3 = N31;
7830 V2 += STEP2;
7831 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7832 L12:
7833 V2 = N21;
7834 V1 += STEP1;
7835 goto BODY_BB; */
7837 static basic_block
7838 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7839 basic_block body_bb)
7841 basic_block last_bb, bb, collapse_bb = NULL;
7842 int i;
7843 gimple_stmt_iterator gsi;
7844 edge e;
7845 tree t;
7846 gimple *stmt;
7848 last_bb = cont_bb;
7849 for (i = fd->collapse - 1; i >= 0; i--)
7851 tree vtype = TREE_TYPE (fd->loops[i].v);
7853 bb = create_empty_bb (last_bb);
7854 add_bb_to_loop (bb, last_bb->loop_father);
7855 gsi = gsi_start_bb (bb);
7857 if (i < fd->collapse - 1)
7859 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7860 e->probability = REG_BR_PROB_BASE / 8;
7862 t = fd->loops[i + 1].n1;
7863 t = force_gimple_operand_gsi (&gsi, t,
7864 DECL_P (fd->loops[i + 1].v)
7865 && TREE_ADDRESSABLE (fd->loops[i
7866 + 1].v),
7867 NULL_TREE, false,
7868 GSI_CONTINUE_LINKING);
7869 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7870 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7872 else
7873 collapse_bb = bb;
7875 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7877 if (POINTER_TYPE_P (vtype))
7878 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7879 else
7880 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7881 t = force_gimple_operand_gsi (&gsi, t,
7882 DECL_P (fd->loops[i].v)
7883 && TREE_ADDRESSABLE (fd->loops[i].v),
7884 NULL_TREE, false, GSI_CONTINUE_LINKING);
7885 stmt = gimple_build_assign (fd->loops[i].v, t);
7886 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7888 if (i > 0)
7890 t = fd->loops[i].n2;
7891 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7892 false, GSI_CONTINUE_LINKING);
7893 tree v = fd->loops[i].v;
7894 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7895 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7896 false, GSI_CONTINUE_LINKING);
7897 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7898 stmt = gimple_build_cond_empty (t);
7899 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7900 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7901 e->probability = REG_BR_PROB_BASE * 7 / 8;
7903 else
7904 make_edge (bb, body_bb, EDGE_FALLTHRU);
7905 last_bb = bb;
7908 return collapse_bb;
7912 /* Expand #pragma omp ordered depend(source). */
7914 static void
7915 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7916 tree *counts, location_t loc)
7918 enum built_in_function source_ix
7919 = fd->iter_type == long_integer_type_node
7920 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7921 gimple *g
7922 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7923 build_fold_addr_expr (counts[fd->ordered]));
7924 gimple_set_location (g, loc);
7925 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7928 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7930 static void
7931 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7932 tree *counts, tree c, location_t loc)
7934 auto_vec<tree, 10> args;
7935 enum built_in_function sink_ix
7936 = fd->iter_type == long_integer_type_node
7937 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7938 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7939 int i;
7940 gimple_stmt_iterator gsi2 = *gsi;
7941 bool warned_step = false;
7943 for (i = 0; i < fd->ordered; i++)
7945 off = TREE_PURPOSE (deps);
7946 if (!integer_zerop (off))
7948 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7949 || fd->loops[i].cond_code == GT_EXPR);
7950 bool forward = fd->loops[i].cond_code == LT_EXPR;
7951 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7952 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7953 "lexically later iteration");
7954 break;
7956 deps = TREE_CHAIN (deps);
7958 /* If all offsets corresponding to the collapsed loops are zero,
7959 this depend clause can be ignored. FIXME: but there is still a
7960 flush needed. We need to emit one __sync_synchronize () for it
7961 though (perhaps conditionally)? Solve this together with the
7962 conservative dependence folding optimization.
7963 if (i >= fd->collapse)
7964 return; */
7966 deps = OMP_CLAUSE_DECL (c);
7967 gsi_prev (&gsi2);
7968 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7969 edge e2 = split_block_after_labels (e1->dest);
7971 *gsi = gsi_after_labels (e1->dest);
7972 for (i = 0; i < fd->ordered; i++)
7974 tree itype = TREE_TYPE (fd->loops[i].v);
7975 if (POINTER_TYPE_P (itype))
7976 itype = sizetype;
7977 if (i)
7978 deps = TREE_CHAIN (deps);
7979 off = TREE_PURPOSE (deps);
7980 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7982 if (integer_zerop (off))
7983 t = boolean_true_node;
7984 else
7986 tree a;
7987 tree co = fold_convert_loc (loc, itype, off);
7988 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7990 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7991 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7992 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7993 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7994 co);
7996 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7997 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7998 fd->loops[i].v, co);
7999 else
8000 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8001 fd->loops[i].v, co);
8002 if (fd->loops[i].cond_code == LT_EXPR)
8004 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8005 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8006 fd->loops[i].n1);
8007 else
8008 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8009 fd->loops[i].n2);
8011 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8012 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8013 fd->loops[i].n2);
8014 else
8015 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8016 fd->loops[i].n1);
8018 if (cond)
8019 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8020 else
8021 cond = t;
8023 off = fold_convert_loc (loc, itype, off);
8025 if (fd->loops[i].cond_code == LT_EXPR
8026 ? !integer_onep (fd->loops[i].step)
8027 : !integer_minus_onep (fd->loops[i].step))
8029 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8030 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8031 fold_build1_loc (loc, NEGATE_EXPR, itype,
8032 s));
8033 else
8034 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8035 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8036 build_int_cst (itype, 0));
8037 if (integer_zerop (t) && !warned_step)
8039 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8040 "in the iteration space");
8041 warned_step = true;
8043 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8044 cond, t);
8047 if (i <= fd->collapse - 1 && fd->collapse > 1)
8048 t = fd->loop.v;
8049 else if (counts[i])
8050 t = counts[i];
8051 else
8053 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8054 fd->loops[i].v, fd->loops[i].n1);
8055 t = fold_convert_loc (loc, fd->iter_type, t);
8057 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8058 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8059 fold_build1_loc (loc, NEGATE_EXPR, itype,
8060 s));
8061 else
8062 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8063 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8064 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8065 off = fold_convert_loc (loc, fd->iter_type, off);
8066 if (i <= fd->collapse - 1 && fd->collapse > 1)
8068 if (i)
8069 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8070 off);
8071 if (i < fd->collapse - 1)
8073 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8074 counts[i]);
8075 continue;
8078 off = unshare_expr (off);
8079 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8080 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8081 true, GSI_SAME_STMT);
8082 args.safe_push (t);
8084 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8085 gimple_set_location (g, loc);
8086 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8088 *gsi = gsi_last_bb (e1->src);
8089 cond = unshare_expr (cond);
8090 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8091 GSI_CONTINUE_LINKING);
8092 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8093 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8094 e3->probability = REG_BR_PROB_BASE / 8;
8095 e1->probability = REG_BR_PROB_BASE - e3->probability;
8096 e1->flags = EDGE_TRUE_VALUE;
8097 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8099 *gsi = gsi_after_labels (e2->dest);
8102 /* Expand all #pragma omp ordered depend(source) and
8103 #pragma omp ordered depend(sink:...) constructs in the current
8104 #pragma omp for ordered(n) region. */
8106 static void
8107 expand_omp_ordered_source_sink (struct omp_region *region,
8108 struct omp_for_data *fd, tree *counts,
8109 basic_block cont_bb)
8111 struct omp_region *inner;
8112 int i;
8113 for (i = fd->collapse - 1; i < fd->ordered; i++)
8114 if (i == fd->collapse - 1 && fd->collapse > 1)
8115 counts[i] = NULL_TREE;
8116 else if (i >= fd->collapse && !cont_bb)
8117 counts[i] = build_zero_cst (fd->iter_type);
8118 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8119 && integer_onep (fd->loops[i].step))
8120 counts[i] = NULL_TREE;
8121 else
8122 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8123 tree atype
8124 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8125 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8126 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8128 for (inner = region->inner; inner; inner = inner->next)
8129 if (inner->type == GIMPLE_OMP_ORDERED)
8131 gomp_ordered *ord_stmt = inner->ord_stmt;
8132 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8133 location_t loc = gimple_location (ord_stmt);
8134 tree c;
8135 for (c = gimple_omp_ordered_clauses (ord_stmt);
8136 c; c = OMP_CLAUSE_CHAIN (c))
8137 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8138 break;
8139 if (c)
8140 expand_omp_ordered_source (&gsi, fd, counts, loc);
8141 for (c = gimple_omp_ordered_clauses (ord_stmt);
8142 c; c = OMP_CLAUSE_CHAIN (c))
8143 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8144 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8145 gsi_remove (&gsi, true);
8149 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8150 collapsed. */
8152 static basic_block
8153 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8154 basic_block cont_bb, basic_block body_bb,
8155 bool ordered_lastprivate)
8157 if (fd->ordered == fd->collapse)
8158 return cont_bb;
8160 if (!cont_bb)
8162 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8163 for (int i = fd->collapse; i < fd->ordered; i++)
8165 tree type = TREE_TYPE (fd->loops[i].v);
8166 tree n1 = fold_convert (type, fd->loops[i].n1);
8167 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8168 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8169 size_int (i - fd->collapse + 1),
8170 NULL_TREE, NULL_TREE);
8171 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8173 return NULL;
8176 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8178 tree t, type = TREE_TYPE (fd->loops[i].v);
8179 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8180 expand_omp_build_assign (&gsi, fd->loops[i].v,
8181 fold_convert (type, fd->loops[i].n1));
8182 if (counts[i])
8183 expand_omp_build_assign (&gsi, counts[i],
8184 build_zero_cst (fd->iter_type));
8185 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8186 size_int (i - fd->collapse + 1),
8187 NULL_TREE, NULL_TREE);
8188 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8189 if (!gsi_end_p (gsi))
8190 gsi_prev (&gsi);
8191 else
8192 gsi = gsi_last_bb (body_bb);
8193 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8194 basic_block new_body = e1->dest;
8195 if (body_bb == cont_bb)
8196 cont_bb = new_body;
8197 edge e2 = NULL;
8198 basic_block new_header;
8199 if (EDGE_COUNT (cont_bb->preds) > 0)
8201 gsi = gsi_last_bb (cont_bb);
8202 if (POINTER_TYPE_P (type))
8203 t = fold_build_pointer_plus (fd->loops[i].v,
8204 fold_convert (sizetype,
8205 fd->loops[i].step));
8206 else
8207 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8208 fold_convert (type, fd->loops[i].step));
8209 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8210 if (counts[i])
8212 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8213 build_int_cst (fd->iter_type, 1));
8214 expand_omp_build_assign (&gsi, counts[i], t);
8215 t = counts[i];
8217 else
8219 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8220 fd->loops[i].v, fd->loops[i].n1);
8221 t = fold_convert (fd->iter_type, t);
8222 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8223 true, GSI_SAME_STMT);
8225 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8226 size_int (i - fd->collapse + 1),
8227 NULL_TREE, NULL_TREE);
8228 expand_omp_build_assign (&gsi, aref, t);
8229 gsi_prev (&gsi);
8230 e2 = split_block (cont_bb, gsi_stmt (gsi));
8231 new_header = e2->dest;
8233 else
8234 new_header = cont_bb;
8235 gsi = gsi_after_labels (new_header);
8236 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8237 true, GSI_SAME_STMT);
8238 tree n2
8239 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8240 true, NULL_TREE, true, GSI_SAME_STMT);
8241 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8242 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8243 edge e3 = split_block (new_header, gsi_stmt (gsi));
8244 cont_bb = e3->dest;
8245 remove_edge (e1);
8246 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8247 e3->flags = EDGE_FALSE_VALUE;
8248 e3->probability = REG_BR_PROB_BASE / 8;
8249 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8250 e1->probability = REG_BR_PROB_BASE - e3->probability;
8252 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8253 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8255 if (e2)
8257 struct loop *loop = alloc_loop ();
8258 loop->header = new_header;
8259 loop->latch = e2->src;
8260 add_loop (loop, body_bb->loop_father);
8264 /* If there are any lastprivate clauses and it is possible some loops
8265 might have zero iterations, ensure all the decls are initialized,
8266 otherwise we could crash evaluating C++ class iterators with lastprivate
8267 clauses. */
8268 bool need_inits = false;
8269 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8270 if (need_inits)
8272 tree type = TREE_TYPE (fd->loops[i].v);
8273 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8274 expand_omp_build_assign (&gsi, fd->loops[i].v,
8275 fold_convert (type, fd->loops[i].n1));
8277 else
8279 tree type = TREE_TYPE (fd->loops[i].v);
8280 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8281 boolean_type_node,
8282 fold_convert (type, fd->loops[i].n1),
8283 fold_convert (type, fd->loops[i].n2));
8284 if (!integer_onep (this_cond))
8285 need_inits = true;
8288 return cont_bb;
8292 /* A subroutine of expand_omp_for. Generate code for a parallel
8293 loop with any schedule. Given parameters:
8295 for (V = N1; V cond N2; V += STEP) BODY;
8297 where COND is "<" or ">", we generate pseudocode
8299 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8300 if (more) goto L0; else goto L3;
8302 V = istart0;
8303 iend = iend0;
8305 BODY;
8306 V += STEP;
8307 if (V cond iend) goto L1; else goto L2;
8309 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8312 If this is a combined omp parallel loop, instead of the call to
8313 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8314 If this is gimple_omp_for_combined_p loop, then instead of assigning
8315 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8316 inner GIMPLE_OMP_FOR and V += STEP; and
8317 if (V cond iend) goto L1; else goto L2; are removed.
8319 For collapsed loops, given parameters:
8320 collapse(3)
8321 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8322 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8323 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8324 BODY;
8326 we generate pseudocode
8328 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8329 if (cond3 is <)
8330 adj = STEP3 - 1;
8331 else
8332 adj = STEP3 + 1;
8333 count3 = (adj + N32 - N31) / STEP3;
8334 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8335 if (cond2 is <)
8336 adj = STEP2 - 1;
8337 else
8338 adj = STEP2 + 1;
8339 count2 = (adj + N22 - N21) / STEP2;
8340 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8341 if (cond1 is <)
8342 adj = STEP1 - 1;
8343 else
8344 adj = STEP1 + 1;
8345 count1 = (adj + N12 - N11) / STEP1;
8346 count = count1 * count2 * count3;
8347 goto Z1;
8349 count = 0;
8351 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8352 if (more) goto L0; else goto L3;
8354 V = istart0;
8355 T = V;
8356 V3 = N31 + (T % count3) * STEP3;
8357 T = T / count3;
8358 V2 = N21 + (T % count2) * STEP2;
8359 T = T / count2;
8360 V1 = N11 + T * STEP1;
8361 iend = iend0;
8363 BODY;
8364 V += 1;
8365 if (V < iend) goto L10; else goto L2;
8366 L10:
8367 V3 += STEP3;
8368 if (V3 cond3 N32) goto L1; else goto L11;
8369 L11:
8370 V3 = N31;
8371 V2 += STEP2;
8372 if (V2 cond2 N22) goto L1; else goto L12;
8373 L12:
8374 V2 = N21;
8375 V1 += STEP1;
8376 goto L1;
8378 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8383 static void
8384 expand_omp_for_generic (struct omp_region *region,
8385 struct omp_for_data *fd,
8386 enum built_in_function start_fn,
8387 enum built_in_function next_fn,
8388 gimple *inner_stmt)
8390 tree type, istart0, iend0, iend;
8391 tree t, vmain, vback, bias = NULL_TREE;
8392 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8393 basic_block l2_bb = NULL, l3_bb = NULL;
8394 gimple_stmt_iterator gsi;
8395 gassign *assign_stmt;
8396 bool in_combined_parallel = is_combined_parallel (region);
8397 bool broken_loop = region->cont == NULL;
8398 edge e, ne;
8399 tree *counts = NULL;
8400 int i;
8401 bool ordered_lastprivate = false;
8403 gcc_assert (!broken_loop || !in_combined_parallel);
8404 gcc_assert (fd->iter_type == long_integer_type_node
8405 || !in_combined_parallel);
8407 entry_bb = region->entry;
8408 cont_bb = region->cont;
8409 collapse_bb = NULL;
8410 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8411 gcc_assert (broken_loop
8412 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8413 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8414 l1_bb = single_succ (l0_bb);
8415 if (!broken_loop)
8417 l2_bb = create_empty_bb (cont_bb);
8418 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8419 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8420 == l1_bb));
8421 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8423 else
8424 l2_bb = NULL;
8425 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8426 exit_bb = region->exit;
8428 gsi = gsi_last_bb (entry_bb);
8430 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8431 if (fd->ordered
8432 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8433 OMP_CLAUSE_LASTPRIVATE))
8434 ordered_lastprivate = false;
8435 if (fd->collapse > 1 || fd->ordered)
8437 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8438 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8440 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8441 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8442 zero_iter1_bb, first_zero_iter1,
8443 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8445 if (zero_iter1_bb)
8447 /* Some counts[i] vars might be uninitialized if
8448 some loop has zero iterations. But the body shouldn't
8449 be executed in that case, so just avoid uninit warnings. */
8450 for (i = first_zero_iter1;
8451 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8452 if (SSA_VAR_P (counts[i]))
8453 TREE_NO_WARNING (counts[i]) = 1;
8454 gsi_prev (&gsi);
8455 e = split_block (entry_bb, gsi_stmt (gsi));
8456 entry_bb = e->dest;
8457 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8458 gsi = gsi_last_bb (entry_bb);
8459 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8460 get_immediate_dominator (CDI_DOMINATORS,
8461 zero_iter1_bb));
8463 if (zero_iter2_bb)
8465 /* Some counts[i] vars might be uninitialized if
8466 some loop has zero iterations. But the body shouldn't
8467 be executed in that case, so just avoid uninit warnings. */
8468 for (i = first_zero_iter2; i < fd->ordered; i++)
8469 if (SSA_VAR_P (counts[i]))
8470 TREE_NO_WARNING (counts[i]) = 1;
8471 if (zero_iter1_bb)
8472 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8473 else
8475 gsi_prev (&gsi);
8476 e = split_block (entry_bb, gsi_stmt (gsi));
8477 entry_bb = e->dest;
8478 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8479 gsi = gsi_last_bb (entry_bb);
8480 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8481 get_immediate_dominator
8482 (CDI_DOMINATORS, zero_iter2_bb));
8485 if (fd->collapse == 1)
8487 counts[0] = fd->loop.n2;
8488 fd->loop = fd->loops[0];
8492 type = TREE_TYPE (fd->loop.v);
8493 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8494 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8495 TREE_ADDRESSABLE (istart0) = 1;
8496 TREE_ADDRESSABLE (iend0) = 1;
8498 /* See if we need to bias by LLONG_MIN. */
8499 if (fd->iter_type == long_long_unsigned_type_node
8500 && TREE_CODE (type) == INTEGER_TYPE
8501 && !TYPE_UNSIGNED (type)
8502 && fd->ordered == 0)
8504 tree n1, n2;
8506 if (fd->loop.cond_code == LT_EXPR)
8508 n1 = fd->loop.n1;
8509 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8511 else
8513 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8514 n2 = fd->loop.n1;
8516 if (TREE_CODE (n1) != INTEGER_CST
8517 || TREE_CODE (n2) != INTEGER_CST
8518 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8519 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8522 gimple_stmt_iterator gsif = gsi;
8523 gsi_prev (&gsif);
8525 tree arr = NULL_TREE;
8526 if (in_combined_parallel)
8528 gcc_assert (fd->ordered == 0);
8529 /* In a combined parallel loop, emit a call to
8530 GOMP_loop_foo_next. */
8531 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8532 build_fold_addr_expr (istart0),
8533 build_fold_addr_expr (iend0));
8535 else
8537 tree t0, t1, t2, t3, t4;
8538 /* If this is not a combined parallel loop, emit a call to
8539 GOMP_loop_foo_start in ENTRY_BB. */
8540 t4 = build_fold_addr_expr (iend0);
8541 t3 = build_fold_addr_expr (istart0);
8542 if (fd->ordered)
8544 t0 = build_int_cst (unsigned_type_node,
8545 fd->ordered - fd->collapse + 1);
8546 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8547 fd->ordered
8548 - fd->collapse + 1),
8549 ".omp_counts");
8550 DECL_NAMELESS (arr) = 1;
8551 TREE_ADDRESSABLE (arr) = 1;
8552 TREE_STATIC (arr) = 1;
8553 vec<constructor_elt, va_gc> *v;
8554 vec_alloc (v, fd->ordered - fd->collapse + 1);
8555 int idx;
8557 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8559 tree c;
8560 if (idx == 0 && fd->collapse > 1)
8561 c = fd->loop.n2;
8562 else
8563 c = counts[idx + fd->collapse - 1];
8564 tree purpose = size_int (idx);
8565 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8566 if (TREE_CODE (c) != INTEGER_CST)
8567 TREE_STATIC (arr) = 0;
8570 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8571 if (!TREE_STATIC (arr))
8572 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8573 void_type_node, arr),
8574 true, NULL_TREE, true, GSI_SAME_STMT);
8575 t1 = build_fold_addr_expr (arr);
8576 t2 = NULL_TREE;
8578 else
8580 t2 = fold_convert (fd->iter_type, fd->loop.step);
8581 t1 = fd->loop.n2;
8582 t0 = fd->loop.n1;
8583 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8585 tree innerc
8586 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8587 OMP_CLAUSE__LOOPTEMP_);
8588 gcc_assert (innerc);
8589 t0 = OMP_CLAUSE_DECL (innerc);
8590 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8591 OMP_CLAUSE__LOOPTEMP_);
8592 gcc_assert (innerc);
8593 t1 = OMP_CLAUSE_DECL (innerc);
8595 if (POINTER_TYPE_P (TREE_TYPE (t0))
8596 && TYPE_PRECISION (TREE_TYPE (t0))
8597 != TYPE_PRECISION (fd->iter_type))
8599 /* Avoid casting pointers to integer of a different size. */
8600 tree itype = signed_type_for (type);
8601 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8602 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8604 else
8606 t1 = fold_convert (fd->iter_type, t1);
8607 t0 = fold_convert (fd->iter_type, t0);
8609 if (bias)
8611 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8612 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8615 if (fd->iter_type == long_integer_type_node || fd->ordered)
8617 if (fd->chunk_size)
8619 t = fold_convert (fd->iter_type, fd->chunk_size);
8620 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8621 if (fd->ordered)
8622 t = build_call_expr (builtin_decl_explicit (start_fn),
8623 5, t0, t1, t, t3, t4);
8624 else
8625 t = build_call_expr (builtin_decl_explicit (start_fn),
8626 6, t0, t1, t2, t, t3, t4);
8628 else if (fd->ordered)
8629 t = build_call_expr (builtin_decl_explicit (start_fn),
8630 4, t0, t1, t3, t4);
8631 else
8632 t = build_call_expr (builtin_decl_explicit (start_fn),
8633 5, t0, t1, t2, t3, t4);
8635 else
8637 tree t5;
8638 tree c_bool_type;
8639 tree bfn_decl;
8641 /* The GOMP_loop_ull_*start functions have additional boolean
8642 argument, true for < loops and false for > loops.
8643 In Fortran, the C bool type can be different from
8644 boolean_type_node. */
8645 bfn_decl = builtin_decl_explicit (start_fn);
8646 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8647 t5 = build_int_cst (c_bool_type,
8648 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8649 if (fd->chunk_size)
8651 tree bfn_decl = builtin_decl_explicit (start_fn);
8652 t = fold_convert (fd->iter_type, fd->chunk_size);
8653 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8654 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8656 else
8657 t = build_call_expr (builtin_decl_explicit (start_fn),
8658 6, t5, t0, t1, t2, t3, t4);
8661 if (TREE_TYPE (t) != boolean_type_node)
8662 t = fold_build2 (NE_EXPR, boolean_type_node,
8663 t, build_int_cst (TREE_TYPE (t), 0));
8664 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8665 true, GSI_SAME_STMT);
8666 if (arr && !TREE_STATIC (arr))
8668 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8669 TREE_THIS_VOLATILE (clobber) = 1;
8670 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8671 GSI_SAME_STMT);
8673 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8675 /* Remove the GIMPLE_OMP_FOR statement. */
8676 gsi_remove (&gsi, true);
8678 if (gsi_end_p (gsif))
8679 gsif = gsi_after_labels (gsi_bb (gsif));
8680 gsi_next (&gsif);
8682 /* Iteration setup for sequential loop goes in L0_BB. */
8683 tree startvar = fd->loop.v;
8684 tree endvar = NULL_TREE;
8686 if (gimple_omp_for_combined_p (fd->for_stmt))
8688 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8689 && gimple_omp_for_kind (inner_stmt)
8690 == GF_OMP_FOR_KIND_SIMD);
8691 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8692 OMP_CLAUSE__LOOPTEMP_);
8693 gcc_assert (innerc);
8694 startvar = OMP_CLAUSE_DECL (innerc);
8695 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8696 OMP_CLAUSE__LOOPTEMP_);
8697 gcc_assert (innerc);
8698 endvar = OMP_CLAUSE_DECL (innerc);
8701 gsi = gsi_start_bb (l0_bb);
8702 t = istart0;
8703 if (fd->ordered && fd->collapse == 1)
8704 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8705 fold_convert (fd->iter_type, fd->loop.step));
8706 else if (bias)
8707 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8708 if (fd->ordered && fd->collapse == 1)
8710 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8711 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8712 fd->loop.n1, fold_convert (sizetype, t));
8713 else
8715 t = fold_convert (TREE_TYPE (startvar), t);
8716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8717 fd->loop.n1, t);
8720 else
8722 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8723 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8724 t = fold_convert (TREE_TYPE (startvar), t);
8726 t = force_gimple_operand_gsi (&gsi, t,
8727 DECL_P (startvar)
8728 && TREE_ADDRESSABLE (startvar),
8729 NULL_TREE, false, GSI_CONTINUE_LINKING);
8730 assign_stmt = gimple_build_assign (startvar, t);
8731 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8733 t = iend0;
8734 if (fd->ordered && fd->collapse == 1)
8735 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8736 fold_convert (fd->iter_type, fd->loop.step));
8737 else if (bias)
8738 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8739 if (fd->ordered && fd->collapse == 1)
8741 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8742 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8743 fd->loop.n1, fold_convert (sizetype, t));
8744 else
8746 t = fold_convert (TREE_TYPE (startvar), t);
8747 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8748 fd->loop.n1, t);
8751 else
8753 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8754 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8755 t = fold_convert (TREE_TYPE (startvar), t);
8757 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8758 false, GSI_CONTINUE_LINKING);
8759 if (endvar)
8761 assign_stmt = gimple_build_assign (endvar, iend);
8762 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8763 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8764 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8765 else
8766 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8767 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8769 /* Handle linear clause adjustments. */
8770 tree itercnt = NULL_TREE;
8771 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8772 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8773 c; c = OMP_CLAUSE_CHAIN (c))
8774 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8775 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8777 tree d = OMP_CLAUSE_DECL (c);
8778 bool is_ref = is_reference (d);
8779 tree t = d, a, dest;
8780 if (is_ref)
8781 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8782 tree type = TREE_TYPE (t);
8783 if (POINTER_TYPE_P (type))
8784 type = sizetype;
8785 dest = unshare_expr (t);
8786 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8787 expand_omp_build_assign (&gsif, v, t);
8788 if (itercnt == NULL_TREE)
8790 itercnt = startvar;
8791 tree n1 = fd->loop.n1;
8792 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8794 itercnt
8795 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8796 itercnt);
8797 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8799 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8800 itercnt, n1);
8801 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8802 itercnt, fd->loop.step);
8803 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8804 NULL_TREE, false,
8805 GSI_CONTINUE_LINKING);
8807 a = fold_build2 (MULT_EXPR, type,
8808 fold_convert (type, itercnt),
8809 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8810 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8811 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8812 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8813 false, GSI_CONTINUE_LINKING);
8814 assign_stmt = gimple_build_assign (dest, t);
8815 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8817 if (fd->collapse > 1)
8818 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8820 if (fd->ordered)
8822 /* Until now, counts array contained number of iterations or
8823 variable containing it for ith loop. From now on, we need
8824 those counts only for collapsed loops, and only for the 2nd
8825 till the last collapsed one. Move those one element earlier,
8826 we'll use counts[fd->collapse - 1] for the first source/sink
8827 iteration counter and so on and counts[fd->ordered]
8828 as the array holding the current counter values for
8829 depend(source). */
8830 if (fd->collapse > 1)
8831 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8832 if (broken_loop)
8834 int i;
8835 for (i = fd->collapse; i < fd->ordered; i++)
8837 tree type = TREE_TYPE (fd->loops[i].v);
8838 tree this_cond
8839 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8840 fold_convert (type, fd->loops[i].n1),
8841 fold_convert (type, fd->loops[i].n2));
8842 if (!integer_onep (this_cond))
8843 break;
8845 if (i < fd->ordered)
8847 cont_bb
8848 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8849 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8850 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8851 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8852 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8853 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8854 make_edge (cont_bb, l1_bb, 0);
8855 l2_bb = create_empty_bb (cont_bb);
8856 broken_loop = false;
8859 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8860 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8861 ordered_lastprivate);
8862 if (counts[fd->collapse - 1])
8864 gcc_assert (fd->collapse == 1);
8865 gsi = gsi_last_bb (l0_bb);
8866 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8867 istart0, true);
8868 gsi = gsi_last_bb (cont_bb);
8869 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8870 build_int_cst (fd->iter_type, 1));
8871 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8872 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8873 size_zero_node, NULL_TREE, NULL_TREE);
8874 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8875 t = counts[fd->collapse - 1];
8877 else if (fd->collapse > 1)
8878 t = fd->loop.v;
8879 else
8881 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8882 fd->loops[0].v, fd->loops[0].n1);
8883 t = fold_convert (fd->iter_type, t);
8885 gsi = gsi_last_bb (l0_bb);
8886 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8887 size_zero_node, NULL_TREE, NULL_TREE);
8888 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8889 false, GSI_CONTINUE_LINKING);
8890 expand_omp_build_assign (&gsi, aref, t, true);
8893 if (!broken_loop)
8895 /* Code to control the increment and predicate for the sequential
8896 loop goes in the CONT_BB. */
8897 gsi = gsi_last_bb (cont_bb);
8898 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8899 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8900 vmain = gimple_omp_continue_control_use (cont_stmt);
8901 vback = gimple_omp_continue_control_def (cont_stmt);
8903 if (!gimple_omp_for_combined_p (fd->for_stmt))
8905 if (POINTER_TYPE_P (type))
8906 t = fold_build_pointer_plus (vmain, fd->loop.step);
8907 else
8908 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8909 t = force_gimple_operand_gsi (&gsi, t,
8910 DECL_P (vback)
8911 && TREE_ADDRESSABLE (vback),
8912 NULL_TREE, true, GSI_SAME_STMT);
8913 assign_stmt = gimple_build_assign (vback, t);
8914 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8916 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8918 if (fd->collapse > 1)
8919 t = fd->loop.v;
8920 else
8922 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8923 fd->loops[0].v, fd->loops[0].n1);
8924 t = fold_convert (fd->iter_type, t);
8926 tree aref = build4 (ARRAY_REF, fd->iter_type,
8927 counts[fd->ordered], size_zero_node,
8928 NULL_TREE, NULL_TREE);
8929 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8930 true, GSI_SAME_STMT);
8931 expand_omp_build_assign (&gsi, aref, t);
8934 t = build2 (fd->loop.cond_code, boolean_type_node,
8935 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8936 iend);
8937 gcond *cond_stmt = gimple_build_cond_empty (t);
8938 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8941 /* Remove GIMPLE_OMP_CONTINUE. */
8942 gsi_remove (&gsi, true);
8944 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8945 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8947 /* Emit code to get the next parallel iteration in L2_BB. */
8948 gsi = gsi_start_bb (l2_bb);
8950 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8951 build_fold_addr_expr (istart0),
8952 build_fold_addr_expr (iend0));
8953 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8954 false, GSI_CONTINUE_LINKING);
8955 if (TREE_TYPE (t) != boolean_type_node)
8956 t = fold_build2 (NE_EXPR, boolean_type_node,
8957 t, build_int_cst (TREE_TYPE (t), 0));
8958 gcond *cond_stmt = gimple_build_cond_empty (t);
8959 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8962 /* Add the loop cleanup function. */
8963 gsi = gsi_last_bb (exit_bb);
8964 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8965 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8966 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8967 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8968 else
8969 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8970 gcall *call_stmt = gimple_build_call (t, 0);
8971 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8972 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8973 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8974 if (fd->ordered)
8976 tree arr = counts[fd->ordered];
8977 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8978 TREE_THIS_VOLATILE (clobber) = 1;
8979 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8980 GSI_SAME_STMT);
8982 gsi_remove (&gsi, true);
8984 /* Connect the new blocks. */
8985 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8986 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8988 if (!broken_loop)
8990 gimple_seq phis;
8992 e = find_edge (cont_bb, l3_bb);
8993 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8995 phis = phi_nodes (l3_bb);
8996 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8998 gimple *phi = gsi_stmt (gsi);
8999 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9000 PHI_ARG_DEF_FROM_EDGE (phi, e));
9002 remove_edge (e);
9004 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9005 e = find_edge (cont_bb, l1_bb);
9006 if (e == NULL)
9008 e = BRANCH_EDGE (cont_bb);
9009 gcc_assert (single_succ (e->dest) == l1_bb);
9011 if (gimple_omp_for_combined_p (fd->for_stmt))
9013 remove_edge (e);
9014 e = NULL;
9016 else if (fd->collapse > 1)
9018 remove_edge (e);
9019 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9021 else
9022 e->flags = EDGE_TRUE_VALUE;
9023 if (e)
9025 e->probability = REG_BR_PROB_BASE * 7 / 8;
9026 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9028 else
9030 e = find_edge (cont_bb, l2_bb);
9031 e->flags = EDGE_FALLTHRU;
9033 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9035 if (gimple_in_ssa_p (cfun))
9037 /* Add phis to the outer loop that connect to the phis in the inner,
9038 original loop, and move the loop entry value of the inner phi to
9039 the loop entry value of the outer phi. */
9040 gphi_iterator psi;
9041 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9043 source_location locus;
9044 gphi *nphi;
9045 gphi *exit_phi = psi.phi ();
9047 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9048 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9050 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9051 edge latch_to_l1 = find_edge (latch, l1_bb);
9052 gphi *inner_phi
9053 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9055 tree t = gimple_phi_result (exit_phi);
9056 tree new_res = copy_ssa_name (t, NULL);
9057 nphi = create_phi_node (new_res, l0_bb);
9059 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9060 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9061 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9062 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9063 add_phi_arg (nphi, t, entry_to_l0, locus);
9065 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9066 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9068 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9072 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9073 recompute_dominator (CDI_DOMINATORS, l2_bb));
9074 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9075 recompute_dominator (CDI_DOMINATORS, l3_bb));
9076 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9077 recompute_dominator (CDI_DOMINATORS, l0_bb));
9078 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9079 recompute_dominator (CDI_DOMINATORS, l1_bb));
9081 /* We enter expand_omp_for_generic with a loop. This original loop may
9082 have its own loop struct, or it may be part of an outer loop struct
9083 (which may be the fake loop). */
9084 struct loop *outer_loop = entry_bb->loop_father;
9085 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9087 add_bb_to_loop (l2_bb, outer_loop);
9089 /* We've added a new loop around the original loop. Allocate the
9090 corresponding loop struct. */
9091 struct loop *new_loop = alloc_loop ();
9092 new_loop->header = l0_bb;
9093 new_loop->latch = l2_bb;
9094 add_loop (new_loop, outer_loop);
9096 /* Allocate a loop structure for the original loop unless we already
9097 had one. */
9098 if (!orig_loop_has_loop_struct
9099 && !gimple_omp_for_combined_p (fd->for_stmt))
9101 struct loop *orig_loop = alloc_loop ();
9102 orig_loop->header = l1_bb;
9103 /* The loop may have multiple latches. */
9104 add_loop (orig_loop, new_loop);
9110 /* A subroutine of expand_omp_for. Generate code for a parallel
9111 loop with static schedule and no specified chunk size. Given
9112 parameters:
9114 for (V = N1; V cond N2; V += STEP) BODY;
9116 where COND is "<" or ">", we generate pseudocode
9118 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9119 if (cond is <)
9120 adj = STEP - 1;
9121 else
9122 adj = STEP + 1;
9123 if ((__typeof (V)) -1 > 0 && cond is >)
9124 n = -(adj + N2 - N1) / -STEP;
9125 else
9126 n = (adj + N2 - N1) / STEP;
9127 q = n / nthreads;
9128 tt = n % nthreads;
9129 if (threadid < tt) goto L3; else goto L4;
9131 tt = 0;
9132 q = q + 1;
9134 s0 = q * threadid + tt;
9135 e0 = s0 + q;
9136 V = s0 * STEP + N1;
9137 if (s0 >= e0) goto L2; else goto L0;
9139 e = e0 * STEP + N1;
9141 BODY;
9142 V += STEP;
9143 if (V cond e) goto L1;
9147 static void
9148 expand_omp_for_static_nochunk (struct omp_region *region,
9149 struct omp_for_data *fd,
9150 gimple *inner_stmt)
9152 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9153 tree type, itype, vmain, vback;
9154 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9155 basic_block body_bb, cont_bb, collapse_bb = NULL;
9156 basic_block fin_bb;
9157 gimple_stmt_iterator gsi;
9158 edge ep;
9159 bool broken_loop = region->cont == NULL;
9160 tree *counts = NULL;
9161 tree n1, n2, step;
9163 itype = type = TREE_TYPE (fd->loop.v);
9164 if (POINTER_TYPE_P (type))
9165 itype = signed_type_for (type);
9167 entry_bb = region->entry;
9168 cont_bb = region->cont;
9169 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9170 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9171 gcc_assert (broken_loop
9172 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9173 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9174 body_bb = single_succ (seq_start_bb);
9175 if (!broken_loop)
9177 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9178 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9179 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9181 exit_bb = region->exit;
9183 /* Iteration space partitioning goes in ENTRY_BB. */
9184 gsi = gsi_last_bb (entry_bb);
9185 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9187 if (fd->collapse > 1)
9189 int first_zero_iter = -1, dummy = -1;
9190 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9192 counts = XALLOCAVEC (tree, fd->collapse);
9193 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9194 fin_bb, first_zero_iter,
9195 dummy_bb, dummy, l2_dom_bb);
9196 t = NULL_TREE;
9198 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9199 t = integer_one_node;
9200 else
9201 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9202 fold_convert (type, fd->loop.n1),
9203 fold_convert (type, fd->loop.n2));
9204 if (fd->collapse == 1
9205 && TYPE_UNSIGNED (type)
9206 && (t == NULL_TREE || !integer_onep (t)))
9208 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9209 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9210 true, GSI_SAME_STMT);
9211 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9212 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9213 true, GSI_SAME_STMT);
9214 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9215 NULL_TREE, NULL_TREE);
9216 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9217 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9218 expand_omp_regimplify_p, NULL, NULL)
9219 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9220 expand_omp_regimplify_p, NULL, NULL))
9222 gsi = gsi_for_stmt (cond_stmt);
9223 gimple_regimplify_operands (cond_stmt, &gsi);
9225 ep = split_block (entry_bb, cond_stmt);
9226 ep->flags = EDGE_TRUE_VALUE;
9227 entry_bb = ep->dest;
9228 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9229 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9230 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9231 if (gimple_in_ssa_p (cfun))
9233 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9234 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9235 !gsi_end_p (gpi); gsi_next (&gpi))
9237 gphi *phi = gpi.phi ();
9238 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9239 ep, UNKNOWN_LOCATION);
9242 gsi = gsi_last_bb (entry_bb);
9245 switch (gimple_omp_for_kind (fd->for_stmt))
9247 case GF_OMP_FOR_KIND_FOR:
9248 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9249 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9250 break;
9251 case GF_OMP_FOR_KIND_DISTRIBUTE:
9252 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9253 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9254 break;
9255 default:
9256 gcc_unreachable ();
9258 nthreads = build_call_expr (nthreads, 0);
9259 nthreads = fold_convert (itype, nthreads);
9260 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9261 true, GSI_SAME_STMT);
9262 threadid = build_call_expr (threadid, 0);
9263 threadid = fold_convert (itype, threadid);
9264 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9265 true, GSI_SAME_STMT);
9267 n1 = fd->loop.n1;
9268 n2 = fd->loop.n2;
9269 step = fd->loop.step;
9270 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9272 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9273 OMP_CLAUSE__LOOPTEMP_);
9274 gcc_assert (innerc);
9275 n1 = OMP_CLAUSE_DECL (innerc);
9276 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9277 OMP_CLAUSE__LOOPTEMP_);
9278 gcc_assert (innerc);
9279 n2 = OMP_CLAUSE_DECL (innerc);
9281 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9282 true, NULL_TREE, true, GSI_SAME_STMT);
9283 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9284 true, NULL_TREE, true, GSI_SAME_STMT);
9285 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9286 true, NULL_TREE, true, GSI_SAME_STMT);
9288 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9289 t = fold_build2 (PLUS_EXPR, itype, step, t);
9290 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9291 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9292 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9293 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9294 fold_build1 (NEGATE_EXPR, itype, t),
9295 fold_build1 (NEGATE_EXPR, itype, step));
9296 else
9297 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9298 t = fold_convert (itype, t);
9299 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9301 q = create_tmp_reg (itype, "q");
9302 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9303 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9304 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9306 tt = create_tmp_reg (itype, "tt");
9307 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9308 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9309 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9311 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9312 gcond *cond_stmt = gimple_build_cond_empty (t);
9313 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9315 second_bb = split_block (entry_bb, cond_stmt)->dest;
9316 gsi = gsi_last_bb (second_bb);
9317 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9319 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9320 GSI_SAME_STMT);
9321 gassign *assign_stmt
9322 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9323 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9325 third_bb = split_block (second_bb, assign_stmt)->dest;
9326 gsi = gsi_last_bb (third_bb);
9327 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9329 t = build2 (MULT_EXPR, itype, q, threadid);
9330 t = build2 (PLUS_EXPR, itype, t, tt);
9331 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9333 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9334 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9336 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9337 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9339 /* Remove the GIMPLE_OMP_FOR statement. */
9340 gsi_remove (&gsi, true);
9342 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9343 gsi = gsi_start_bb (seq_start_bb);
9345 tree startvar = fd->loop.v;
9346 tree endvar = NULL_TREE;
9348 if (gimple_omp_for_combined_p (fd->for_stmt))
9350 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9351 ? gimple_omp_parallel_clauses (inner_stmt)
9352 : gimple_omp_for_clauses (inner_stmt);
9353 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9354 gcc_assert (innerc);
9355 startvar = OMP_CLAUSE_DECL (innerc);
9356 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9357 OMP_CLAUSE__LOOPTEMP_);
9358 gcc_assert (innerc);
9359 endvar = OMP_CLAUSE_DECL (innerc);
9360 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9361 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9363 int i;
9364 for (i = 1; i < fd->collapse; i++)
9366 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9367 OMP_CLAUSE__LOOPTEMP_);
9368 gcc_assert (innerc);
9370 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9371 OMP_CLAUSE__LOOPTEMP_);
9372 if (innerc)
9374 /* If needed (distribute parallel for with lastprivate),
9375 propagate down the total number of iterations. */
9376 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9377 fd->loop.n2);
9378 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9379 GSI_CONTINUE_LINKING);
9380 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9381 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9385 t = fold_convert (itype, s0);
9386 t = fold_build2 (MULT_EXPR, itype, t, step);
9387 if (POINTER_TYPE_P (type))
9388 t = fold_build_pointer_plus (n1, t);
9389 else
9390 t = fold_build2 (PLUS_EXPR, type, t, n1);
9391 t = fold_convert (TREE_TYPE (startvar), t);
9392 t = force_gimple_operand_gsi (&gsi, t,
9393 DECL_P (startvar)
9394 && TREE_ADDRESSABLE (startvar),
9395 NULL_TREE, false, GSI_CONTINUE_LINKING);
9396 assign_stmt = gimple_build_assign (startvar, t);
9397 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9399 t = fold_convert (itype, e0);
9400 t = fold_build2 (MULT_EXPR, itype, t, step);
9401 if (POINTER_TYPE_P (type))
9402 t = fold_build_pointer_plus (n1, t);
9403 else
9404 t = fold_build2 (PLUS_EXPR, type, t, n1);
9405 t = fold_convert (TREE_TYPE (startvar), t);
9406 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9407 false, GSI_CONTINUE_LINKING);
9408 if (endvar)
9410 assign_stmt = gimple_build_assign (endvar, e);
9411 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9412 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9413 assign_stmt = gimple_build_assign (fd->loop.v, e);
9414 else
9415 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9416 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9418 /* Handle linear clause adjustments. */
9419 tree itercnt = NULL_TREE;
9420 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9421 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9422 c; c = OMP_CLAUSE_CHAIN (c))
9423 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9424 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9426 tree d = OMP_CLAUSE_DECL (c);
9427 bool is_ref = is_reference (d);
9428 tree t = d, a, dest;
9429 if (is_ref)
9430 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9431 if (itercnt == NULL_TREE)
9433 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9435 itercnt = fold_build2 (MINUS_EXPR, itype,
9436 fold_convert (itype, n1),
9437 fold_convert (itype, fd->loop.n1));
9438 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9439 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9440 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9441 NULL_TREE, false,
9442 GSI_CONTINUE_LINKING);
9444 else
9445 itercnt = s0;
9447 tree type = TREE_TYPE (t);
9448 if (POINTER_TYPE_P (type))
9449 type = sizetype;
9450 a = fold_build2 (MULT_EXPR, type,
9451 fold_convert (type, itercnt),
9452 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9453 dest = unshare_expr (t);
9454 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9455 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9456 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9457 false, GSI_CONTINUE_LINKING);
9458 assign_stmt = gimple_build_assign (dest, t);
9459 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9461 if (fd->collapse > 1)
9462 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9464 if (!broken_loop)
9466 /* The code controlling the sequential loop replaces the
9467 GIMPLE_OMP_CONTINUE. */
9468 gsi = gsi_last_bb (cont_bb);
9469 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9470 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9471 vmain = gimple_omp_continue_control_use (cont_stmt);
9472 vback = gimple_omp_continue_control_def (cont_stmt);
9474 if (!gimple_omp_for_combined_p (fd->for_stmt))
9476 if (POINTER_TYPE_P (type))
9477 t = fold_build_pointer_plus (vmain, step);
9478 else
9479 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9480 t = force_gimple_operand_gsi (&gsi, t,
9481 DECL_P (vback)
9482 && TREE_ADDRESSABLE (vback),
9483 NULL_TREE, true, GSI_SAME_STMT);
9484 assign_stmt = gimple_build_assign (vback, t);
9485 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9487 t = build2 (fd->loop.cond_code, boolean_type_node,
9488 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9489 ? t : vback, e);
9490 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9493 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9494 gsi_remove (&gsi, true);
9496 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9497 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9500 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9501 gsi = gsi_last_bb (exit_bb);
9502 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9504 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9505 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9507 gsi_remove (&gsi, true);
9509 /* Connect all the blocks. */
9510 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9511 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9512 ep = find_edge (entry_bb, second_bb);
9513 ep->flags = EDGE_TRUE_VALUE;
9514 ep->probability = REG_BR_PROB_BASE / 4;
9515 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9516 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9518 if (!broken_loop)
9520 ep = find_edge (cont_bb, body_bb);
9521 if (ep == NULL)
9523 ep = BRANCH_EDGE (cont_bb);
9524 gcc_assert (single_succ (ep->dest) == body_bb);
9526 if (gimple_omp_for_combined_p (fd->for_stmt))
9528 remove_edge (ep);
9529 ep = NULL;
9531 else if (fd->collapse > 1)
9533 remove_edge (ep);
9534 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9536 else
9537 ep->flags = EDGE_TRUE_VALUE;
9538 find_edge (cont_bb, fin_bb)->flags
9539 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9542 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9543 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9544 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9546 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9547 recompute_dominator (CDI_DOMINATORS, body_bb));
9548 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9549 recompute_dominator (CDI_DOMINATORS, fin_bb));
9551 struct loop *loop = body_bb->loop_father;
9552 if (loop != entry_bb->loop_father)
9554 gcc_assert (loop->header == body_bb);
9555 gcc_assert (broken_loop
9556 || loop->latch == region->cont
9557 || single_pred (loop->latch) == region->cont);
9558 return;
9561 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9563 loop = alloc_loop ();
9564 loop->header = body_bb;
9565 if (collapse_bb == NULL)
9566 loop->latch = cont_bb;
9567 add_loop (loop, body_bb->loop_father);
9571 /* Return phi in E->DEST with ARG on edge E. */
9573 static gphi *
9574 find_phi_with_arg_on_edge (tree arg, edge e)
9576 basic_block bb = e->dest;
9578 for (gphi_iterator gpi = gsi_start_phis (bb);
9579 !gsi_end_p (gpi);
9580 gsi_next (&gpi))
9582 gphi *phi = gpi.phi ();
9583 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9584 return phi;
9587 return NULL;
9590 /* A subroutine of expand_omp_for. Generate code for a parallel
9591 loop with static schedule and a specified chunk size. Given
9592 parameters:
9594 for (V = N1; V cond N2; V += STEP) BODY;
9596 where COND is "<" or ">", we generate pseudocode
9598 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9599 if (cond is <)
9600 adj = STEP - 1;
9601 else
9602 adj = STEP + 1;
9603 if ((__typeof (V)) -1 > 0 && cond is >)
9604 n = -(adj + N2 - N1) / -STEP;
9605 else
9606 n = (adj + N2 - N1) / STEP;
9607 trip = 0;
9608 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9609 here so that V is defined
9610 if the loop is not entered
9612 s0 = (trip * nthreads + threadid) * CHUNK;
9613 e0 = min(s0 + CHUNK, n);
9614 if (s0 < n) goto L1; else goto L4;
9616 V = s0 * STEP + N1;
9617 e = e0 * STEP + N1;
9619 BODY;
9620 V += STEP;
9621 if (V cond e) goto L2; else goto L3;
9623 trip += 1;
9624 goto L0;
9628 static void
9629 expand_omp_for_static_chunk (struct omp_region *region,
9630 struct omp_for_data *fd, gimple *inner_stmt)
9632 tree n, s0, e0, e, t;
9633 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9634 tree type, itype, vmain, vback, vextra;
9635 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9636 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9637 gimple_stmt_iterator gsi;
9638 edge se;
9639 bool broken_loop = region->cont == NULL;
9640 tree *counts = NULL;
9641 tree n1, n2, step;
9643 itype = type = TREE_TYPE (fd->loop.v);
9644 if (POINTER_TYPE_P (type))
9645 itype = signed_type_for (type);
9647 entry_bb = region->entry;
9648 se = split_block (entry_bb, last_stmt (entry_bb));
9649 entry_bb = se->src;
9650 iter_part_bb = se->dest;
9651 cont_bb = region->cont;
9652 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9653 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9654 gcc_assert (broken_loop
9655 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9656 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9657 body_bb = single_succ (seq_start_bb);
9658 if (!broken_loop)
9660 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9661 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9662 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9663 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9665 exit_bb = region->exit;
9667 /* Trip and adjustment setup goes in ENTRY_BB. */
9668 gsi = gsi_last_bb (entry_bb);
9669 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9671 if (fd->collapse > 1)
9673 int first_zero_iter = -1, dummy = -1;
9674 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9676 counts = XALLOCAVEC (tree, fd->collapse);
9677 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9678 fin_bb, first_zero_iter,
9679 dummy_bb, dummy, l2_dom_bb);
9680 t = NULL_TREE;
9682 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9683 t = integer_one_node;
9684 else
9685 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9686 fold_convert (type, fd->loop.n1),
9687 fold_convert (type, fd->loop.n2));
9688 if (fd->collapse == 1
9689 && TYPE_UNSIGNED (type)
9690 && (t == NULL_TREE || !integer_onep (t)))
9692 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9693 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9694 true, GSI_SAME_STMT);
9695 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9696 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9697 true, GSI_SAME_STMT);
9698 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9699 NULL_TREE, NULL_TREE);
9700 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9701 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9702 expand_omp_regimplify_p, NULL, NULL)
9703 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9704 expand_omp_regimplify_p, NULL, NULL))
9706 gsi = gsi_for_stmt (cond_stmt);
9707 gimple_regimplify_operands (cond_stmt, &gsi);
9709 se = split_block (entry_bb, cond_stmt);
9710 se->flags = EDGE_TRUE_VALUE;
9711 entry_bb = se->dest;
9712 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9713 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9714 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9715 if (gimple_in_ssa_p (cfun))
9717 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9718 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9719 !gsi_end_p (gpi); gsi_next (&gpi))
9721 gphi *phi = gpi.phi ();
9722 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9723 se, UNKNOWN_LOCATION);
9726 gsi = gsi_last_bb (entry_bb);
9729 switch (gimple_omp_for_kind (fd->for_stmt))
9731 case GF_OMP_FOR_KIND_FOR:
9732 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9733 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9734 break;
9735 case GF_OMP_FOR_KIND_DISTRIBUTE:
9736 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9737 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9738 break;
9739 default:
9740 gcc_unreachable ();
9742 nthreads = build_call_expr (nthreads, 0);
9743 nthreads = fold_convert (itype, nthreads);
9744 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9745 true, GSI_SAME_STMT);
9746 threadid = build_call_expr (threadid, 0);
9747 threadid = fold_convert (itype, threadid);
9748 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9749 true, GSI_SAME_STMT);
9751 n1 = fd->loop.n1;
9752 n2 = fd->loop.n2;
9753 step = fd->loop.step;
9754 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9756 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9757 OMP_CLAUSE__LOOPTEMP_);
9758 gcc_assert (innerc);
9759 n1 = OMP_CLAUSE_DECL (innerc);
9760 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9761 OMP_CLAUSE__LOOPTEMP_);
9762 gcc_assert (innerc);
9763 n2 = OMP_CLAUSE_DECL (innerc);
9765 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9766 true, NULL_TREE, true, GSI_SAME_STMT);
9767 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9768 true, NULL_TREE, true, GSI_SAME_STMT);
9769 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9770 true, NULL_TREE, true, GSI_SAME_STMT);
9771 tree chunk_size = fold_convert (itype, fd->chunk_size);
9772 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9773 chunk_size
9774 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9775 GSI_SAME_STMT);
9777 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9778 t = fold_build2 (PLUS_EXPR, itype, step, t);
9779 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9780 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9781 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9782 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9783 fold_build1 (NEGATE_EXPR, itype, t),
9784 fold_build1 (NEGATE_EXPR, itype, step));
9785 else
9786 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9787 t = fold_convert (itype, t);
9788 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9789 true, GSI_SAME_STMT);
9791 trip_var = create_tmp_reg (itype, ".trip");
9792 if (gimple_in_ssa_p (cfun))
9794 trip_init = make_ssa_name (trip_var);
9795 trip_main = make_ssa_name (trip_var);
9796 trip_back = make_ssa_name (trip_var);
9798 else
9800 trip_init = trip_var;
9801 trip_main = trip_var;
9802 trip_back = trip_var;
9805 gassign *assign_stmt
9806 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9807 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9809 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9810 t = fold_build2 (MULT_EXPR, itype, t, step);
9811 if (POINTER_TYPE_P (type))
9812 t = fold_build_pointer_plus (n1, t);
9813 else
9814 t = fold_build2 (PLUS_EXPR, type, t, n1);
9815 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9816 true, GSI_SAME_STMT);
9818 /* Remove the GIMPLE_OMP_FOR. */
9819 gsi_remove (&gsi, true);
9821 gimple_stmt_iterator gsif = gsi;
9823 /* Iteration space partitioning goes in ITER_PART_BB. */
9824 gsi = gsi_last_bb (iter_part_bb);
9826 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9827 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9828 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9829 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9830 false, GSI_CONTINUE_LINKING);
9832 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9833 t = fold_build2 (MIN_EXPR, itype, t, n);
9834 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9835 false, GSI_CONTINUE_LINKING);
9837 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9838 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9840 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9841 gsi = gsi_start_bb (seq_start_bb);
9843 tree startvar = fd->loop.v;
9844 tree endvar = NULL_TREE;
9846 if (gimple_omp_for_combined_p (fd->for_stmt))
9848 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9849 ? gimple_omp_parallel_clauses (inner_stmt)
9850 : gimple_omp_for_clauses (inner_stmt);
9851 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9852 gcc_assert (innerc);
9853 startvar = OMP_CLAUSE_DECL (innerc);
9854 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9855 OMP_CLAUSE__LOOPTEMP_);
9856 gcc_assert (innerc);
9857 endvar = OMP_CLAUSE_DECL (innerc);
9858 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9859 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9861 int i;
9862 for (i = 1; i < fd->collapse; i++)
9864 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9865 OMP_CLAUSE__LOOPTEMP_);
9866 gcc_assert (innerc);
9868 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9869 OMP_CLAUSE__LOOPTEMP_);
9870 if (innerc)
9872 /* If needed (distribute parallel for with lastprivate),
9873 propagate down the total number of iterations. */
9874 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9875 fd->loop.n2);
9876 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9877 GSI_CONTINUE_LINKING);
9878 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9879 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9884 t = fold_convert (itype, s0);
9885 t = fold_build2 (MULT_EXPR, itype, t, step);
9886 if (POINTER_TYPE_P (type))
9887 t = fold_build_pointer_plus (n1, t);
9888 else
9889 t = fold_build2 (PLUS_EXPR, type, t, n1);
9890 t = fold_convert (TREE_TYPE (startvar), t);
9891 t = force_gimple_operand_gsi (&gsi, t,
9892 DECL_P (startvar)
9893 && TREE_ADDRESSABLE (startvar),
9894 NULL_TREE, false, GSI_CONTINUE_LINKING);
9895 assign_stmt = gimple_build_assign (startvar, t);
9896 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9898 t = fold_convert (itype, e0);
9899 t = fold_build2 (MULT_EXPR, itype, t, step);
9900 if (POINTER_TYPE_P (type))
9901 t = fold_build_pointer_plus (n1, t);
9902 else
9903 t = fold_build2 (PLUS_EXPR, type, t, n1);
9904 t = fold_convert (TREE_TYPE (startvar), t);
9905 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9906 false, GSI_CONTINUE_LINKING);
9907 if (endvar)
9909 assign_stmt = gimple_build_assign (endvar, e);
9910 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9911 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9912 assign_stmt = gimple_build_assign (fd->loop.v, e);
9913 else
9914 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9915 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9917 /* Handle linear clause adjustments. */
9918 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9919 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9920 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9921 c; c = OMP_CLAUSE_CHAIN (c))
9922 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9923 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9925 tree d = OMP_CLAUSE_DECL (c);
9926 bool is_ref = is_reference (d);
9927 tree t = d, a, dest;
9928 if (is_ref)
9929 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9930 tree type = TREE_TYPE (t);
9931 if (POINTER_TYPE_P (type))
9932 type = sizetype;
9933 dest = unshare_expr (t);
9934 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9935 expand_omp_build_assign (&gsif, v, t);
9936 if (itercnt == NULL_TREE)
9938 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9940 itercntbias
9941 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9942 fold_convert (itype, fd->loop.n1));
9943 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9944 itercntbias, step);
9945 itercntbias
9946 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9947 NULL_TREE, true,
9948 GSI_SAME_STMT);
9949 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9950 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9951 NULL_TREE, false,
9952 GSI_CONTINUE_LINKING);
9954 else
9955 itercnt = s0;
9957 a = fold_build2 (MULT_EXPR, type,
9958 fold_convert (type, itercnt),
9959 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9960 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9961 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9962 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9963 false, GSI_CONTINUE_LINKING);
9964 assign_stmt = gimple_build_assign (dest, t);
9965 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9967 if (fd->collapse > 1)
9968 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9970 if (!broken_loop)
9972 /* The code controlling the sequential loop goes in CONT_BB,
9973 replacing the GIMPLE_OMP_CONTINUE. */
9974 gsi = gsi_last_bb (cont_bb);
9975 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9976 vmain = gimple_omp_continue_control_use (cont_stmt);
9977 vback = gimple_omp_continue_control_def (cont_stmt);
9979 if (!gimple_omp_for_combined_p (fd->for_stmt))
9981 if (POINTER_TYPE_P (type))
9982 t = fold_build_pointer_plus (vmain, step);
9983 else
9984 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9985 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9986 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9987 true, GSI_SAME_STMT);
9988 assign_stmt = gimple_build_assign (vback, t);
9989 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9991 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9992 t = build2 (EQ_EXPR, boolean_type_node,
9993 build_int_cst (itype, 0),
9994 build_int_cst (itype, 1));
9995 else
9996 t = build2 (fd->loop.cond_code, boolean_type_node,
9997 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9998 ? t : vback, e);
9999 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10002 /* Remove GIMPLE_OMP_CONTINUE. */
10003 gsi_remove (&gsi, true);
10005 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10006 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10008 /* Trip update code goes into TRIP_UPDATE_BB. */
10009 gsi = gsi_start_bb (trip_update_bb);
10011 t = build_int_cst (itype, 1);
10012 t = build2 (PLUS_EXPR, itype, trip_main, t);
10013 assign_stmt = gimple_build_assign (trip_back, t);
10014 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10017 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10018 gsi = gsi_last_bb (exit_bb);
10019 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10021 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10022 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10024 gsi_remove (&gsi, true);
10026 /* Connect the new blocks. */
10027 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10028 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10030 if (!broken_loop)
10032 se = find_edge (cont_bb, body_bb);
10033 if (se == NULL)
10035 se = BRANCH_EDGE (cont_bb);
10036 gcc_assert (single_succ (se->dest) == body_bb);
10038 if (gimple_omp_for_combined_p (fd->for_stmt))
10040 remove_edge (se);
10041 se = NULL;
10043 else if (fd->collapse > 1)
10045 remove_edge (se);
10046 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10048 else
10049 se->flags = EDGE_TRUE_VALUE;
10050 find_edge (cont_bb, trip_update_bb)->flags
10051 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10053 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10056 if (gimple_in_ssa_p (cfun))
10058 gphi_iterator psi;
10059 gphi *phi;
10060 edge re, ene;
10061 edge_var_map *vm;
10062 size_t i;
10064 gcc_assert (fd->collapse == 1 && !broken_loop);
10066 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10067 remove arguments of the phi nodes in fin_bb. We need to create
10068 appropriate phi nodes in iter_part_bb instead. */
10069 se = find_edge (iter_part_bb, fin_bb);
10070 re = single_succ_edge (trip_update_bb);
10071 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10072 ene = single_succ_edge (entry_bb);
10074 psi = gsi_start_phis (fin_bb);
10075 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10076 gsi_next (&psi), ++i)
10078 gphi *nphi;
10079 source_location locus;
10081 phi = psi.phi ();
10082 t = gimple_phi_result (phi);
10083 gcc_assert (t == redirect_edge_var_map_result (vm));
10085 if (!single_pred_p (fin_bb))
10086 t = copy_ssa_name (t, phi);
10088 nphi = create_phi_node (t, iter_part_bb);
10090 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10091 locus = gimple_phi_arg_location_from_edge (phi, se);
10093 /* A special case -- fd->loop.v is not yet computed in
10094 iter_part_bb, we need to use vextra instead. */
10095 if (t == fd->loop.v)
10096 t = vextra;
10097 add_phi_arg (nphi, t, ene, locus);
10098 locus = redirect_edge_var_map_location (vm);
10099 tree back_arg = redirect_edge_var_map_def (vm);
10100 add_phi_arg (nphi, back_arg, re, locus);
10101 edge ce = find_edge (cont_bb, body_bb);
10102 if (ce == NULL)
10104 ce = BRANCH_EDGE (cont_bb);
10105 gcc_assert (single_succ (ce->dest) == body_bb);
10106 ce = single_succ_edge (ce->dest);
10108 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10109 gcc_assert (inner_loop_phi != NULL);
10110 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10111 find_edge (seq_start_bb, body_bb), locus);
10113 if (!single_pred_p (fin_bb))
10114 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10116 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10117 redirect_edge_var_map_clear (re);
10118 if (single_pred_p (fin_bb))
10119 while (1)
10121 psi = gsi_start_phis (fin_bb);
10122 if (gsi_end_p (psi))
10123 break;
10124 remove_phi_node (&psi, false);
10127 /* Make phi node for trip. */
10128 phi = create_phi_node (trip_main, iter_part_bb);
10129 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10130 UNKNOWN_LOCATION);
10131 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10132 UNKNOWN_LOCATION);
10135 if (!broken_loop)
10136 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10137 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10138 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10139 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10140 recompute_dominator (CDI_DOMINATORS, fin_bb));
10141 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10142 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10143 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10144 recompute_dominator (CDI_DOMINATORS, body_bb));
10146 if (!broken_loop)
10148 struct loop *loop = body_bb->loop_father;
10149 struct loop *trip_loop = alloc_loop ();
10150 trip_loop->header = iter_part_bb;
10151 trip_loop->latch = trip_update_bb;
10152 add_loop (trip_loop, iter_part_bb->loop_father);
10154 if (loop != entry_bb->loop_father)
10156 gcc_assert (loop->header == body_bb);
10157 gcc_assert (loop->latch == region->cont
10158 || single_pred (loop->latch) == region->cont);
10159 trip_loop->inner = loop;
10160 return;
10163 if (!gimple_omp_for_combined_p (fd->for_stmt))
10165 loop = alloc_loop ();
10166 loop->header = body_bb;
10167 if (collapse_bb == NULL)
10168 loop->latch = cont_bb;
10169 add_loop (loop, trip_loop);
10174 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10175 Given parameters:
10176 for (V = N1; V cond N2; V += STEP) BODY;
10178 where COND is "<" or ">" or "!=", we generate pseudocode
10180 for (ind_var = low; ind_var < high; ind_var++)
10182 V = n1 + (ind_var * STEP)
10184 <BODY>
10187 In the above pseudocode, low and high are function parameters of the
10188 child function. In the function below, we are inserting a temp.
10189 variable that will be making a call to two OMP functions that will not be
10190 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10191 with _Cilk_for). These functions are replaced with low and high
10192 by the function that handles taskreg. */
10195 static void
10196 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10198 bool broken_loop = region->cont == NULL;
10199 basic_block entry_bb = region->entry;
10200 basic_block cont_bb = region->cont;
10202 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10203 gcc_assert (broken_loop
10204 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10205 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10206 basic_block l1_bb, l2_bb;
10208 if (!broken_loop)
10210 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10211 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10212 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10213 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10215 else
10217 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10218 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10219 l2_bb = single_succ (l1_bb);
10221 basic_block exit_bb = region->exit;
10222 basic_block l2_dom_bb = NULL;
10224 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10226 /* Below statements until the "tree high_val = ..." are pseudo statements
10227 used to pass information to be used by expand_omp_taskreg.
10228 low_val and high_val will be replaced by the __low and __high
10229 parameter from the child function.
10231 The call_exprs part is a place-holder, it is mainly used
10232 to distinctly identify to the top-level part that this is
10233 where we should put low and high (reasoning given in header
10234 comment). */
10236 tree child_fndecl
10237 = gimple_omp_parallel_child_fn (
10238 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10239 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10240 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10242 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10243 high_val = t;
10244 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10245 low_val = t;
10247 gcc_assert (low_val && high_val);
10249 tree type = TREE_TYPE (low_val);
10250 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10253 /* Not needed in SSA form right now. */
10254 gcc_assert (!gimple_in_ssa_p (cfun));
10255 if (l2_dom_bb == NULL)
10256 l2_dom_bb = l1_bb;
10258 tree n1 = low_val;
10259 tree n2 = high_val;
10261 gimple *stmt = gimple_build_assign (ind_var, n1);
10263 /* Replace the GIMPLE_OMP_FOR statement. */
10264 gsi_replace (&gsi, stmt, true);
10266 if (!broken_loop)
10268 /* Code to control the increment goes in the CONT_BB. */
10269 gsi = gsi_last_bb (cont_bb);
10270 stmt = gsi_stmt (gsi);
10271 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10272 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10273 build_one_cst (type));
10275 /* Replace GIMPLE_OMP_CONTINUE. */
10276 gsi_replace (&gsi, stmt, true);
10279 /* Emit the condition in L1_BB. */
10280 gsi = gsi_after_labels (l1_bb);
10281 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10282 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10283 fd->loop.step);
10284 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10285 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10286 fd->loop.n1, fold_convert (sizetype, t));
10287 else
10288 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10289 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10290 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10291 expand_omp_build_assign (&gsi, fd->loop.v, t);
10293 /* The condition is always '<' since the runtime will fill in the low
10294 and high values. */
10295 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10296 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10298 /* Remove GIMPLE_OMP_RETURN. */
10299 gsi = gsi_last_bb (exit_bb);
10300 gsi_remove (&gsi, true);
10302 /* Connect the new blocks. */
10303 remove_edge (FALLTHRU_EDGE (entry_bb));
10305 edge e, ne;
10306 if (!broken_loop)
10308 remove_edge (BRANCH_EDGE (entry_bb));
10309 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10311 e = BRANCH_EDGE (l1_bb);
10312 ne = FALLTHRU_EDGE (l1_bb);
10313 e->flags = EDGE_TRUE_VALUE;
10315 else
10317 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10319 ne = single_succ_edge (l1_bb);
10320 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10323 ne->flags = EDGE_FALSE_VALUE;
10324 e->probability = REG_BR_PROB_BASE * 7 / 8;
10325 ne->probability = REG_BR_PROB_BASE / 8;
10327 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10328 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10329 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10331 if (!broken_loop)
10333 struct loop *loop = alloc_loop ();
10334 loop->header = l1_bb;
10335 loop->latch = cont_bb;
10336 add_loop (loop, l1_bb->loop_father);
10337 loop->safelen = INT_MAX;
10340 /* Pick the correct library function based on the precision of the
10341 induction variable type. */
10342 tree lib_fun = NULL_TREE;
10343 if (TYPE_PRECISION (type) == 32)
10344 lib_fun = cilk_for_32_fndecl;
10345 else if (TYPE_PRECISION (type) == 64)
10346 lib_fun = cilk_for_64_fndecl;
10347 else
10348 gcc_unreachable ();
10350 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10352 /* WS_ARGS contains the library function flavor to call:
10353 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10354 user-defined grain value. If the user does not define one, then zero
10355 is passed in by the parser. */
10356 vec_alloc (region->ws_args, 2);
10357 region->ws_args->quick_push (lib_fun);
10358 region->ws_args->quick_push (fd->chunk_size);
10361 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10362 loop. Given parameters:
10364 for (V = N1; V cond N2; V += STEP) BODY;
10366 where COND is "<" or ">", we generate pseudocode
10368 V = N1;
10369 goto L1;
10371 BODY;
10372 V += STEP;
10374 if (V cond N2) goto L0; else goto L2;
10377 For collapsed loops, given parameters:
10378 collapse(3)
10379 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10380 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10381 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10382 BODY;
10384 we generate pseudocode
10386 if (cond3 is <)
10387 adj = STEP3 - 1;
10388 else
10389 adj = STEP3 + 1;
10390 count3 = (adj + N32 - N31) / STEP3;
10391 if (cond2 is <)
10392 adj = STEP2 - 1;
10393 else
10394 adj = STEP2 + 1;
10395 count2 = (adj + N22 - N21) / STEP2;
10396 if (cond1 is <)
10397 adj = STEP1 - 1;
10398 else
10399 adj = STEP1 + 1;
10400 count1 = (adj + N12 - N11) / STEP1;
10401 count = count1 * count2 * count3;
10402 V = 0;
10403 V1 = N11;
10404 V2 = N21;
10405 V3 = N31;
10406 goto L1;
10408 BODY;
10409 V += 1;
10410 V3 += STEP3;
10411 V2 += (V3 cond3 N32) ? 0 : STEP2;
10412 V3 = (V3 cond3 N32) ? V3 : N31;
10413 V1 += (V2 cond2 N22) ? 0 : STEP1;
10414 V2 = (V2 cond2 N22) ? V2 : N21;
10416 if (V < count) goto L0; else goto L2;
10421 static void
10422 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10424 tree type, t;
10425 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10426 gimple_stmt_iterator gsi;
10427 gimple *stmt;
10428 gcond *cond_stmt;
10429 bool broken_loop = region->cont == NULL;
10430 edge e, ne;
10431 tree *counts = NULL;
10432 int i;
10433 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10434 OMP_CLAUSE_SAFELEN);
10435 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10436 OMP_CLAUSE__SIMDUID_);
10437 tree n1, n2;
10439 type = TREE_TYPE (fd->loop.v);
10440 entry_bb = region->entry;
10441 cont_bb = region->cont;
10442 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10443 gcc_assert (broken_loop
10444 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10445 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10446 if (!broken_loop)
10448 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10449 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10450 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10451 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10453 else
10455 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10456 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10457 l2_bb = single_succ (l1_bb);
10459 exit_bb = region->exit;
10460 l2_dom_bb = NULL;
10462 gsi = gsi_last_bb (entry_bb);
10464 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10465 /* Not needed in SSA form right now. */
10466 gcc_assert (!gimple_in_ssa_p (cfun));
10467 if (fd->collapse > 1)
10469 int first_zero_iter = -1, dummy = -1;
10470 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10472 counts = XALLOCAVEC (tree, fd->collapse);
10473 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10474 zero_iter_bb, first_zero_iter,
10475 dummy_bb, dummy, l2_dom_bb);
10477 if (l2_dom_bb == NULL)
10478 l2_dom_bb = l1_bb;
10480 n1 = fd->loop.n1;
10481 n2 = fd->loop.n2;
10482 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10484 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10485 OMP_CLAUSE__LOOPTEMP_);
10486 gcc_assert (innerc);
10487 n1 = OMP_CLAUSE_DECL (innerc);
10488 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10489 OMP_CLAUSE__LOOPTEMP_);
10490 gcc_assert (innerc);
10491 n2 = OMP_CLAUSE_DECL (innerc);
10492 expand_omp_build_assign (&gsi, fd->loop.v,
10493 fold_convert (type, n1));
10494 if (fd->collapse > 1)
10496 gsi_prev (&gsi);
10497 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10498 gsi_next (&gsi);
10501 else
10503 expand_omp_build_assign (&gsi, fd->loop.v,
10504 fold_convert (type, fd->loop.n1));
10505 if (fd->collapse > 1)
10506 for (i = 0; i < fd->collapse; i++)
10508 tree itype = TREE_TYPE (fd->loops[i].v);
10509 if (POINTER_TYPE_P (itype))
10510 itype = signed_type_for (itype);
10511 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10512 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10516 /* Remove the GIMPLE_OMP_FOR statement. */
10517 gsi_remove (&gsi, true);
10519 if (!broken_loop)
10521 /* Code to control the increment goes in the CONT_BB. */
10522 gsi = gsi_last_bb (cont_bb);
10523 stmt = gsi_stmt (gsi);
10524 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10526 if (POINTER_TYPE_P (type))
10527 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10528 else
10529 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10530 expand_omp_build_assign (&gsi, fd->loop.v, t);
10532 if (fd->collapse > 1)
10534 i = fd->collapse - 1;
10535 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10537 t = fold_convert (sizetype, fd->loops[i].step);
10538 t = fold_build_pointer_plus (fd->loops[i].v, t);
10540 else
10542 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10543 fd->loops[i].step);
10544 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10545 fd->loops[i].v, t);
10547 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10549 for (i = fd->collapse - 1; i > 0; i--)
10551 tree itype = TREE_TYPE (fd->loops[i].v);
10552 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10553 if (POINTER_TYPE_P (itype2))
10554 itype2 = signed_type_for (itype2);
10555 t = build3 (COND_EXPR, itype2,
10556 build2 (fd->loops[i].cond_code, boolean_type_node,
10557 fd->loops[i].v,
10558 fold_convert (itype, fd->loops[i].n2)),
10559 build_int_cst (itype2, 0),
10560 fold_convert (itype2, fd->loops[i - 1].step));
10561 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10562 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10563 else
10564 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10565 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10567 t = build3 (COND_EXPR, itype,
10568 build2 (fd->loops[i].cond_code, boolean_type_node,
10569 fd->loops[i].v,
10570 fold_convert (itype, fd->loops[i].n2)),
10571 fd->loops[i].v,
10572 fold_convert (itype, fd->loops[i].n1));
10573 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10577 /* Remove GIMPLE_OMP_CONTINUE. */
10578 gsi_remove (&gsi, true);
10581 /* Emit the condition in L1_BB. */
10582 gsi = gsi_start_bb (l1_bb);
10584 t = fold_convert (type, n2);
10585 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10586 false, GSI_CONTINUE_LINKING);
10587 tree v = fd->loop.v;
10588 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10589 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10590 false, GSI_CONTINUE_LINKING);
10591 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10592 cond_stmt = gimple_build_cond_empty (t);
10593 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10594 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10595 NULL, NULL)
10596 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10597 NULL, NULL))
10599 gsi = gsi_for_stmt (cond_stmt);
10600 gimple_regimplify_operands (cond_stmt, &gsi);
10603 /* Remove GIMPLE_OMP_RETURN. */
10604 gsi = gsi_last_bb (exit_bb);
10605 gsi_remove (&gsi, true);
10607 /* Connect the new blocks. */
10608 remove_edge (FALLTHRU_EDGE (entry_bb));
10610 if (!broken_loop)
10612 remove_edge (BRANCH_EDGE (entry_bb));
10613 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10615 e = BRANCH_EDGE (l1_bb);
10616 ne = FALLTHRU_EDGE (l1_bb);
10617 e->flags = EDGE_TRUE_VALUE;
10619 else
10621 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10623 ne = single_succ_edge (l1_bb);
10624 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10627 ne->flags = EDGE_FALSE_VALUE;
10628 e->probability = REG_BR_PROB_BASE * 7 / 8;
10629 ne->probability = REG_BR_PROB_BASE / 8;
10631 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10632 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10633 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10635 if (!broken_loop)
10637 struct loop *loop = alloc_loop ();
10638 loop->header = l1_bb;
10639 loop->latch = cont_bb;
10640 add_loop (loop, l1_bb->loop_father);
10641 if (safelen == NULL_TREE)
10642 loop->safelen = INT_MAX;
10643 else
10645 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10646 if (TREE_CODE (safelen) != INTEGER_CST)
10647 loop->safelen = 0;
10648 else if (!tree_fits_uhwi_p (safelen)
10649 || tree_to_uhwi (safelen) > INT_MAX)
10650 loop->safelen = INT_MAX;
10651 else
10652 loop->safelen = tree_to_uhwi (safelen);
10653 if (loop->safelen == 1)
10654 loop->safelen = 0;
10656 if (simduid)
10658 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10659 cfun->has_simduid_loops = true;
10661 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10662 the loop. */
10663 if ((flag_tree_loop_vectorize
10664 || (!global_options_set.x_flag_tree_loop_vectorize
10665 && !global_options_set.x_flag_tree_vectorize))
10666 && flag_tree_loop_optimize
10667 && loop->safelen > 1)
10669 loop->force_vectorize = true;
10670 cfun->has_force_vectorize_loops = true;
10673 else if (simduid)
10674 cfun->has_simduid_loops = true;
10677 /* Taskloop construct is represented after gimplification with
10678 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10679 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10680 which should just compute all the needed loop temporaries
10681 for GIMPLE_OMP_TASK. */
10683 static void
10684 expand_omp_taskloop_for_outer (struct omp_region *region,
10685 struct omp_for_data *fd,
10686 gimple *inner_stmt)
10688 tree type, bias = NULL_TREE;
10689 basic_block entry_bb, cont_bb, exit_bb;
10690 gimple_stmt_iterator gsi;
10691 gassign *assign_stmt;
10692 tree *counts = NULL;
10693 int i;
10695 gcc_assert (inner_stmt);
10696 gcc_assert (region->cont);
10697 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10698 && gimple_omp_task_taskloop_p (inner_stmt));
10699 type = TREE_TYPE (fd->loop.v);
10701 /* See if we need to bias by LLONG_MIN. */
10702 if (fd->iter_type == long_long_unsigned_type_node
10703 && TREE_CODE (type) == INTEGER_TYPE
10704 && !TYPE_UNSIGNED (type))
10706 tree n1, n2;
10708 if (fd->loop.cond_code == LT_EXPR)
10710 n1 = fd->loop.n1;
10711 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10713 else
10715 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10716 n2 = fd->loop.n1;
10718 if (TREE_CODE (n1) != INTEGER_CST
10719 || TREE_CODE (n2) != INTEGER_CST
10720 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10721 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10724 entry_bb = region->entry;
10725 cont_bb = region->cont;
10726 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10727 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10728 exit_bb = region->exit;
10730 gsi = gsi_last_bb (entry_bb);
10731 gimple *for_stmt = gsi_stmt (gsi);
10732 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10733 if (fd->collapse > 1)
10735 int first_zero_iter = -1, dummy = -1;
10736 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10738 counts = XALLOCAVEC (tree, fd->collapse);
10739 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10740 zero_iter_bb, first_zero_iter,
10741 dummy_bb, dummy, l2_dom_bb);
10743 if (zero_iter_bb)
10745 /* Some counts[i] vars might be uninitialized if
10746 some loop has zero iterations. But the body shouldn't
10747 be executed in that case, so just avoid uninit warnings. */
10748 for (i = first_zero_iter; i < fd->collapse; i++)
10749 if (SSA_VAR_P (counts[i]))
10750 TREE_NO_WARNING (counts[i]) = 1;
10751 gsi_prev (&gsi);
10752 edge e = split_block (entry_bb, gsi_stmt (gsi));
10753 entry_bb = e->dest;
10754 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10755 gsi = gsi_last_bb (entry_bb);
10756 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10757 get_immediate_dominator (CDI_DOMINATORS,
10758 zero_iter_bb));
10762 tree t0, t1;
10763 t1 = fd->loop.n2;
10764 t0 = fd->loop.n1;
10765 if (POINTER_TYPE_P (TREE_TYPE (t0))
10766 && TYPE_PRECISION (TREE_TYPE (t0))
10767 != TYPE_PRECISION (fd->iter_type))
10769 /* Avoid casting pointers to integer of a different size. */
10770 tree itype = signed_type_for (type);
10771 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10772 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10774 else
10776 t1 = fold_convert (fd->iter_type, t1);
10777 t0 = fold_convert (fd->iter_type, t0);
10779 if (bias)
10781 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10782 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10785 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10786 OMP_CLAUSE__LOOPTEMP_);
10787 gcc_assert (innerc);
10788 tree startvar = OMP_CLAUSE_DECL (innerc);
10789 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10790 gcc_assert (innerc);
10791 tree endvar = OMP_CLAUSE_DECL (innerc);
10792 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10794 gcc_assert (innerc);
10795 for (i = 1; i < fd->collapse; i++)
10797 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10798 OMP_CLAUSE__LOOPTEMP_);
10799 gcc_assert (innerc);
10801 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10802 OMP_CLAUSE__LOOPTEMP_);
10803 if (innerc)
10805 /* If needed (inner taskloop has lastprivate clause), propagate
10806 down the total number of iterations. */
10807 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10808 NULL_TREE, false,
10809 GSI_CONTINUE_LINKING);
10810 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10811 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10815 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10816 GSI_CONTINUE_LINKING);
10817 assign_stmt = gimple_build_assign (startvar, t0);
10818 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10820 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10821 GSI_CONTINUE_LINKING);
10822 assign_stmt = gimple_build_assign (endvar, t1);
10823 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10824 if (fd->collapse > 1)
10825 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10827 /* Remove the GIMPLE_OMP_FOR statement. */
10828 gsi = gsi_for_stmt (for_stmt);
10829 gsi_remove (&gsi, true);
10831 gsi = gsi_last_bb (cont_bb);
10832 gsi_remove (&gsi, true);
10834 gsi = gsi_last_bb (exit_bb);
10835 gsi_remove (&gsi, true);
10837 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10838 remove_edge (BRANCH_EDGE (entry_bb));
10839 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10840 remove_edge (BRANCH_EDGE (cont_bb));
10841 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10842 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10843 recompute_dominator (CDI_DOMINATORS, region->entry));
10846 /* Taskloop construct is represented after gimplification with
10847 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10848 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10849 GOMP_taskloop{,_ull} function arranges for each task to be given just
10850 a single range of iterations. */
10852 static void
10853 expand_omp_taskloop_for_inner (struct omp_region *region,
10854 struct omp_for_data *fd,
10855 gimple *inner_stmt)
10857 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10858 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10859 basic_block fin_bb;
10860 gimple_stmt_iterator gsi;
10861 edge ep;
10862 bool broken_loop = region->cont == NULL;
10863 tree *counts = NULL;
10864 tree n1, n2, step;
10866 itype = type = TREE_TYPE (fd->loop.v);
10867 if (POINTER_TYPE_P (type))
10868 itype = signed_type_for (type);
10870 /* See if we need to bias by LLONG_MIN. */
10871 if (fd->iter_type == long_long_unsigned_type_node
10872 && TREE_CODE (type) == INTEGER_TYPE
10873 && !TYPE_UNSIGNED (type))
10875 tree n1, n2;
10877 if (fd->loop.cond_code == LT_EXPR)
10879 n1 = fd->loop.n1;
10880 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10882 else
10884 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10885 n2 = fd->loop.n1;
10887 if (TREE_CODE (n1) != INTEGER_CST
10888 || TREE_CODE (n2) != INTEGER_CST
10889 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10890 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10893 entry_bb = region->entry;
10894 cont_bb = region->cont;
10895 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10896 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10897 gcc_assert (broken_loop
10898 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10899 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10900 if (!broken_loop)
10902 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10903 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10905 exit_bb = region->exit;
10907 /* Iteration space partitioning goes in ENTRY_BB. */
10908 gsi = gsi_last_bb (entry_bb);
10909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10911 if (fd->collapse > 1)
10913 int first_zero_iter = -1, dummy = -1;
10914 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10916 counts = XALLOCAVEC (tree, fd->collapse);
10917 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10918 fin_bb, first_zero_iter,
10919 dummy_bb, dummy, l2_dom_bb);
10920 t = NULL_TREE;
10922 else
10923 t = integer_one_node;
10925 step = fd->loop.step;
10926 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10927 OMP_CLAUSE__LOOPTEMP_);
10928 gcc_assert (innerc);
10929 n1 = OMP_CLAUSE_DECL (innerc);
10930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10931 gcc_assert (innerc);
10932 n2 = OMP_CLAUSE_DECL (innerc);
10933 if (bias)
10935 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10936 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10938 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10939 true, NULL_TREE, true, GSI_SAME_STMT);
10940 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10941 true, NULL_TREE, true, GSI_SAME_STMT);
10942 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10943 true, NULL_TREE, true, GSI_SAME_STMT);
10945 tree startvar = fd->loop.v;
10946 tree endvar = NULL_TREE;
10948 if (gimple_omp_for_combined_p (fd->for_stmt))
10950 tree clauses = gimple_omp_for_clauses (inner_stmt);
10951 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10952 gcc_assert (innerc);
10953 startvar = OMP_CLAUSE_DECL (innerc);
10954 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10955 OMP_CLAUSE__LOOPTEMP_);
10956 gcc_assert (innerc);
10957 endvar = OMP_CLAUSE_DECL (innerc);
10959 t = fold_convert (TREE_TYPE (startvar), n1);
10960 t = force_gimple_operand_gsi (&gsi, t,
10961 DECL_P (startvar)
10962 && TREE_ADDRESSABLE (startvar),
10963 NULL_TREE, false, GSI_CONTINUE_LINKING);
10964 gimple *assign_stmt = gimple_build_assign (startvar, t);
10965 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10967 t = fold_convert (TREE_TYPE (startvar), n2);
10968 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10969 false, GSI_CONTINUE_LINKING);
10970 if (endvar)
10972 assign_stmt = gimple_build_assign (endvar, e);
10973 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10974 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10975 assign_stmt = gimple_build_assign (fd->loop.v, e);
10976 else
10977 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10978 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10980 if (fd->collapse > 1)
10981 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10983 if (!broken_loop)
10985 /* The code controlling the sequential loop replaces the
10986 GIMPLE_OMP_CONTINUE. */
10987 gsi = gsi_last_bb (cont_bb);
10988 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10989 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10990 vmain = gimple_omp_continue_control_use (cont_stmt);
10991 vback = gimple_omp_continue_control_def (cont_stmt);
10993 if (!gimple_omp_for_combined_p (fd->for_stmt))
10995 if (POINTER_TYPE_P (type))
10996 t = fold_build_pointer_plus (vmain, step);
10997 else
10998 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10999 t = force_gimple_operand_gsi (&gsi, t,
11000 DECL_P (vback)
11001 && TREE_ADDRESSABLE (vback),
11002 NULL_TREE, true, GSI_SAME_STMT);
11003 assign_stmt = gimple_build_assign (vback, t);
11004 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11006 t = build2 (fd->loop.cond_code, boolean_type_node,
11007 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11008 ? t : vback, e);
11009 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11012 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11013 gsi_remove (&gsi, true);
11015 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11016 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11019 /* Remove the GIMPLE_OMP_FOR statement. */
11020 gsi = gsi_for_stmt (fd->for_stmt);
11021 gsi_remove (&gsi, true);
11023 /* Remove the GIMPLE_OMP_RETURN statement. */
11024 gsi = gsi_last_bb (exit_bb);
11025 gsi_remove (&gsi, true);
11027 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11028 if (!broken_loop)
11029 remove_edge (BRANCH_EDGE (entry_bb));
11030 else
11032 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11033 region->outer->cont = NULL;
11036 /* Connect all the blocks. */
11037 if (!broken_loop)
11039 ep = find_edge (cont_bb, body_bb);
11040 if (gimple_omp_for_combined_p (fd->for_stmt))
11042 remove_edge (ep);
11043 ep = NULL;
11045 else if (fd->collapse > 1)
11047 remove_edge (ep);
11048 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11050 else
11051 ep->flags = EDGE_TRUE_VALUE;
11052 find_edge (cont_bb, fin_bb)->flags
11053 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11056 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11057 recompute_dominator (CDI_DOMINATORS, body_bb));
11058 if (!broken_loop)
11059 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11060 recompute_dominator (CDI_DOMINATORS, fin_bb));
11062 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11064 struct loop *loop = alloc_loop ();
11065 loop->header = body_bb;
11066 if (collapse_bb == NULL)
11067 loop->latch = cont_bb;
11068 add_loop (loop, body_bb->loop_father);
11072 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11073 partitioned loop. The lowering here is abstracted, in that the
11074 loop parameters are passed through internal functions, which are
11075 further lowered by oacc_device_lower, once we get to the target
11076 compiler. The loop is of the form:
11078 for (V = B; V LTGT E; V += S) {BODY}
11080 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11081 (constant 0 for no chunking) and we will have a GWV partitioning
11082 mask, specifying dimensions over which the loop is to be
11083 partitioned (see note below). We generate code that looks like:
11085 <entry_bb> [incoming FALL->body, BRANCH->exit]
11086 typedef signedintify (typeof (V)) T; // underlying signed integral type
11087 T range = E - B;
11088 T chunk_no = 0;
11089 T DIR = LTGT == '<' ? +1 : -1;
11090 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11091 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11093 <head_bb> [created by splitting end of entry_bb]
11094 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11095 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11096 if (!(offset LTGT bound)) goto bottom_bb;
11098 <body_bb> [incoming]
11099 V = B + offset;
11100 {BODY}
11102 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11103 offset += step;
11104 if (offset LTGT bound) goto body_bb; [*]
11106 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11107 chunk_no++;
11108 if (chunk < chunk_max) goto head_bb;
11110 <exit_bb> [incoming]
11111 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11113 [*] Needed if V live at end of loop
11115 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11116 transition, and will be specified by a more general mechanism shortly.
11119 static void
11120 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11122 tree v = fd->loop.v;
11123 enum tree_code cond_code = fd->loop.cond_code;
11124 enum tree_code plus_code = PLUS_EXPR;
11126 tree chunk_size = integer_minus_one_node;
11127 tree gwv = integer_zero_node;
11128 tree iter_type = TREE_TYPE (v);
11129 tree diff_type = iter_type;
11130 tree plus_type = iter_type;
11131 struct oacc_collapse *counts = NULL;
11133 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11134 == GF_OMP_FOR_KIND_OACC_LOOP);
11135 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11136 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11138 if (POINTER_TYPE_P (iter_type))
11140 plus_code = POINTER_PLUS_EXPR;
11141 plus_type = sizetype;
11143 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11144 diff_type = signed_type_for (diff_type);
11146 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11147 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11148 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11149 basic_block bottom_bb = NULL;
11151 /* entry_bb has two sucessors; the branch edge is to the exit
11152 block, fallthrough edge to body. */
11153 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11154 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11156 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11157 body_bb, or to a block whose only successor is the body_bb. Its
11158 fallthrough successor is the final block (same as the branch
11159 successor of the entry_bb). */
11160 if (cont_bb)
11162 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11163 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11165 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11166 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11168 else
11169 gcc_assert (!gimple_in_ssa_p (cfun));
11171 /* The exit block only has entry_bb and cont_bb as predecessors. */
11172 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11174 tree chunk_no;
11175 tree chunk_max = NULL_TREE;
11176 tree bound, offset;
11177 tree step = create_tmp_var (diff_type, ".step");
11178 bool up = cond_code == LT_EXPR;
11179 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11180 bool chunking = !gimple_in_ssa_p (cfun);;
11181 bool negating;
11183 /* SSA instances. */
11184 tree offset_incr = NULL_TREE;
11185 tree offset_init = NULL_TREE;
11187 gimple_stmt_iterator gsi;
11188 gassign *ass;
11189 gcall *call;
11190 gimple *stmt;
11191 tree expr;
11192 location_t loc;
11193 edge split, be, fte;
11195 /* Split the end of entry_bb to create head_bb. */
11196 split = split_block (entry_bb, last_stmt (entry_bb));
11197 basic_block head_bb = split->dest;
11198 entry_bb = split->src;
11200 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11201 gsi = gsi_last_bb (entry_bb);
11202 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11203 loc = gimple_location (for_stmt);
11205 if (gimple_in_ssa_p (cfun))
11207 offset_init = gimple_omp_for_index (for_stmt, 0);
11208 gcc_assert (integer_zerop (fd->loop.n1));
11209 /* The SSA parallelizer does gang parallelism. */
11210 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11213 if (fd->collapse > 1)
11215 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11216 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11217 TREE_TYPE (fd->loop.n2));
11219 if (SSA_VAR_P (fd->loop.n2))
11221 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11222 true, GSI_SAME_STMT);
11223 ass = gimple_build_assign (fd->loop.n2, total);
11224 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11229 tree b = fd->loop.n1;
11230 tree e = fd->loop.n2;
11231 tree s = fd->loop.step;
11233 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11234 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11236 /* Convert the step, avoiding possible unsigned->signed overflow. */
11237 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11238 if (negating)
11239 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11240 s = fold_convert (diff_type, s);
11241 if (negating)
11242 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11243 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11245 if (!chunking)
11246 chunk_size = integer_zero_node;
11247 expr = fold_convert (diff_type, chunk_size);
11248 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11249 NULL_TREE, true, GSI_SAME_STMT);
11250 /* Determine the range, avoiding possible unsigned->signed overflow. */
11251 negating = !up && TYPE_UNSIGNED (iter_type);
11252 expr = fold_build2 (MINUS_EXPR, plus_type,
11253 fold_convert (plus_type, negating ? b : e),
11254 fold_convert (plus_type, negating ? e : b));
11255 expr = fold_convert (diff_type, expr);
11256 if (negating)
11257 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11258 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11259 NULL_TREE, true, GSI_SAME_STMT);
11261 chunk_no = build_int_cst (diff_type, 0);
11262 if (chunking)
11264 gcc_assert (!gimple_in_ssa_p (cfun));
11266 expr = chunk_no;
11267 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11268 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11270 ass = gimple_build_assign (chunk_no, expr);
11271 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11273 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11274 build_int_cst (integer_type_node,
11275 IFN_GOACC_LOOP_CHUNKS),
11276 dir, range, s, chunk_size, gwv);
11277 gimple_call_set_lhs (call, chunk_max);
11278 gimple_set_location (call, loc);
11279 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11281 else
11282 chunk_size = chunk_no;
11284 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11285 build_int_cst (integer_type_node,
11286 IFN_GOACC_LOOP_STEP),
11287 dir, range, s, chunk_size, gwv);
11288 gimple_call_set_lhs (call, step);
11289 gimple_set_location (call, loc);
11290 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11292 /* Remove the GIMPLE_OMP_FOR. */
11293 gsi_remove (&gsi, true);
11295 /* Fixup edges from head_bb */
11296 be = BRANCH_EDGE (head_bb);
11297 fte = FALLTHRU_EDGE (head_bb);
11298 be->flags |= EDGE_FALSE_VALUE;
11299 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11301 basic_block body_bb = fte->dest;
11303 if (gimple_in_ssa_p (cfun))
11305 gsi = gsi_last_bb (cont_bb);
11306 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11308 offset = gimple_omp_continue_control_use (cont_stmt);
11309 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11311 else
11313 offset = create_tmp_var (diff_type, ".offset");
11314 offset_init = offset_incr = offset;
11316 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11318 /* Loop offset & bound go into head_bb. */
11319 gsi = gsi_start_bb (head_bb);
11321 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11322 build_int_cst (integer_type_node,
11323 IFN_GOACC_LOOP_OFFSET),
11324 dir, range, s,
11325 chunk_size, gwv, chunk_no);
11326 gimple_call_set_lhs (call, offset_init);
11327 gimple_set_location (call, loc);
11328 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11330 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11331 build_int_cst (integer_type_node,
11332 IFN_GOACC_LOOP_BOUND),
11333 dir, range, s,
11334 chunk_size, gwv, offset_init);
11335 gimple_call_set_lhs (call, bound);
11336 gimple_set_location (call, loc);
11337 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11339 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11340 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11341 GSI_CONTINUE_LINKING);
11343 /* V assignment goes into body_bb. */
11344 if (!gimple_in_ssa_p (cfun))
11346 gsi = gsi_start_bb (body_bb);
11348 expr = build2 (plus_code, iter_type, b,
11349 fold_convert (plus_type, offset));
11350 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11351 true, GSI_SAME_STMT);
11352 ass = gimple_build_assign (v, expr);
11353 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11354 if (fd->collapse > 1)
11355 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11358 /* Loop increment goes into cont_bb. If this is not a loop, we
11359 will have spawned threads as if it was, and each one will
11360 execute one iteration. The specification is not explicit about
11361 whether such constructs are ill-formed or not, and they can
11362 occur, especially when noreturn routines are involved. */
11363 if (cont_bb)
11365 gsi = gsi_last_bb (cont_bb);
11366 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11367 loc = gimple_location (cont_stmt);
11369 /* Increment offset. */
11370 if (gimple_in_ssa_p (cfun))
11371 expr= build2 (plus_code, iter_type, offset,
11372 fold_convert (plus_type, step));
11373 else
11374 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11375 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11376 true, GSI_SAME_STMT);
11377 ass = gimple_build_assign (offset_incr, expr);
11378 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11379 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11380 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11382 /* Remove the GIMPLE_OMP_CONTINUE. */
11383 gsi_remove (&gsi, true);
11385 /* Fixup edges from cont_bb */
11386 be = BRANCH_EDGE (cont_bb);
11387 fte = FALLTHRU_EDGE (cont_bb);
11388 be->flags |= EDGE_TRUE_VALUE;
11389 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11391 if (chunking)
11393 /* Split the beginning of exit_bb to make bottom_bb. We
11394 need to insert a nop at the start, because splitting is
11395 after a stmt, not before. */
11396 gsi = gsi_start_bb (exit_bb);
11397 stmt = gimple_build_nop ();
11398 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11399 split = split_block (exit_bb, stmt);
11400 bottom_bb = split->src;
11401 exit_bb = split->dest;
11402 gsi = gsi_last_bb (bottom_bb);
11404 /* Chunk increment and test goes into bottom_bb. */
11405 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11406 build_int_cst (diff_type, 1));
11407 ass = gimple_build_assign (chunk_no, expr);
11408 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11410 /* Chunk test at end of bottom_bb. */
11411 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11412 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11413 GSI_CONTINUE_LINKING);
11415 /* Fixup edges from bottom_bb. */
11416 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11417 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11421 gsi = gsi_last_bb (exit_bb);
11422 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11423 loc = gimple_location (gsi_stmt (gsi));
11425 if (!gimple_in_ssa_p (cfun))
11427 /* Insert the final value of V, in case it is live. This is the
11428 value for the only thread that survives past the join. */
11429 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11430 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11431 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11432 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11433 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11434 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11435 true, GSI_SAME_STMT);
11436 ass = gimple_build_assign (v, expr);
11437 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11440 /* Remove the OMP_RETURN. */
11441 gsi_remove (&gsi, true);
11443 if (cont_bb)
11445 /* We now have one or two nested loops. Update the loop
11446 structures. */
11447 struct loop *parent = entry_bb->loop_father;
11448 struct loop *body = body_bb->loop_father;
11450 if (chunking)
11452 struct loop *chunk_loop = alloc_loop ();
11453 chunk_loop->header = head_bb;
11454 chunk_loop->latch = bottom_bb;
11455 add_loop (chunk_loop, parent);
11456 parent = chunk_loop;
11458 else if (parent != body)
11460 gcc_assert (body->header == body_bb);
11461 gcc_assert (body->latch == cont_bb
11462 || single_pred (body->latch) == cont_bb);
11463 parent = NULL;
11466 if (parent)
11468 struct loop *body_loop = alloc_loop ();
11469 body_loop->header = body_bb;
11470 body_loop->latch = cont_bb;
11471 add_loop (body_loop, parent);
11476 /* Expand the OMP loop defined by REGION. */
11478 static void
11479 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11481 struct omp_for_data fd;
11482 struct omp_for_data_loop *loops;
11484 loops
11485 = (struct omp_for_data_loop *)
11486 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11487 * sizeof (struct omp_for_data_loop));
11488 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11489 &fd, loops);
11490 region->sched_kind = fd.sched_kind;
11491 region->sched_modifiers = fd.sched_modifiers;
11493 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11494 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11495 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11496 if (region->cont)
11498 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11499 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11500 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11502 else
11503 /* If there isn't a continue then this is a degerate case where
11504 the introduction of abnormal edges during lowering will prevent
11505 original loops from being detected. Fix that up. */
11506 loops_state_set (LOOPS_NEED_FIXUP);
11508 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11509 expand_omp_simd (region, &fd);
11510 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11511 expand_cilk_for (region, &fd);
11512 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11514 gcc_assert (!inner_stmt);
11515 expand_oacc_for (region, &fd);
11517 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11519 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11520 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11521 else
11522 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11524 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11525 && !fd.have_ordered)
11527 if (fd.chunk_size == NULL)
11528 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11529 else
11530 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11532 else
11534 int fn_index, start_ix, next_ix;
11536 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11537 == GF_OMP_FOR_KIND_FOR);
11538 if (fd.chunk_size == NULL
11539 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11540 fd.chunk_size = integer_zero_node;
11541 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11542 switch (fd.sched_kind)
11544 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11545 fn_index = 3;
11546 break;
11547 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11548 case OMP_CLAUSE_SCHEDULE_GUIDED:
11549 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11550 && !fd.ordered
11551 && !fd.have_ordered)
11553 fn_index = 3 + fd.sched_kind;
11554 break;
11556 /* FALLTHRU */
11557 default:
11558 fn_index = fd.sched_kind;
11559 break;
11561 if (!fd.ordered)
11562 fn_index += fd.have_ordered * 6;
11563 if (fd.ordered)
11564 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11565 else
11566 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11567 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11568 if (fd.iter_type == long_long_unsigned_type_node)
11570 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11571 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11572 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11573 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11575 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11576 (enum built_in_function) next_ix, inner_stmt);
11579 if (gimple_in_ssa_p (cfun))
11580 update_ssa (TODO_update_ssa_only_virtuals);
11584 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11586 v = GOMP_sections_start (n);
11588 switch (v)
11590 case 0:
11591 goto L2;
11592 case 1:
11593 section 1;
11594 goto L1;
11595 case 2:
11597 case n:
11599 default:
11600 abort ();
11603 v = GOMP_sections_next ();
11604 goto L0;
11606 reduction;
11608 If this is a combined parallel sections, replace the call to
11609 GOMP_sections_start with call to GOMP_sections_next. */
11611 static void
11612 expand_omp_sections (struct omp_region *region)
11614 tree t, u, vin = NULL, vmain, vnext, l2;
11615 unsigned len;
11616 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11617 gimple_stmt_iterator si, switch_si;
11618 gomp_sections *sections_stmt;
11619 gimple *stmt;
11620 gomp_continue *cont;
11621 edge_iterator ei;
11622 edge e;
11623 struct omp_region *inner;
11624 unsigned i, casei;
11625 bool exit_reachable = region->cont != NULL;
11627 gcc_assert (region->exit != NULL);
11628 entry_bb = region->entry;
11629 l0_bb = single_succ (entry_bb);
11630 l1_bb = region->cont;
11631 l2_bb = region->exit;
11632 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11633 l2 = gimple_block_label (l2_bb);
11634 else
11636 /* This can happen if there are reductions. */
11637 len = EDGE_COUNT (l0_bb->succs);
11638 gcc_assert (len > 0);
11639 e = EDGE_SUCC (l0_bb, len - 1);
11640 si = gsi_last_bb (e->dest);
11641 l2 = NULL_TREE;
11642 if (gsi_end_p (si)
11643 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11644 l2 = gimple_block_label (e->dest);
11645 else
11646 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11648 si = gsi_last_bb (e->dest);
11649 if (gsi_end_p (si)
11650 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11652 l2 = gimple_block_label (e->dest);
11653 break;
11657 if (exit_reachable)
11658 default_bb = create_empty_bb (l1_bb->prev_bb);
11659 else
11660 default_bb = create_empty_bb (l0_bb);
11662 /* We will build a switch() with enough cases for all the
11663 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11664 and a default case to abort if something goes wrong. */
11665 len = EDGE_COUNT (l0_bb->succs);
11667 /* Use vec::quick_push on label_vec throughout, since we know the size
11668 in advance. */
11669 auto_vec<tree> label_vec (len);
11671 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11672 GIMPLE_OMP_SECTIONS statement. */
11673 si = gsi_last_bb (entry_bb);
11674 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11675 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11676 vin = gimple_omp_sections_control (sections_stmt);
11677 if (!is_combined_parallel (region))
11679 /* If we are not inside a combined parallel+sections region,
11680 call GOMP_sections_start. */
11681 t = build_int_cst (unsigned_type_node, len - 1);
11682 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11683 stmt = gimple_build_call (u, 1, t);
11685 else
11687 /* Otherwise, call GOMP_sections_next. */
11688 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11689 stmt = gimple_build_call (u, 0);
11691 gimple_call_set_lhs (stmt, vin);
11692 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11693 gsi_remove (&si, true);
11695 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11696 L0_BB. */
11697 switch_si = gsi_last_bb (l0_bb);
11698 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11699 if (exit_reachable)
11701 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11702 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11703 vmain = gimple_omp_continue_control_use (cont);
11704 vnext = gimple_omp_continue_control_def (cont);
11706 else
11708 vmain = vin;
11709 vnext = NULL_TREE;
11712 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11713 label_vec.quick_push (t);
11714 i = 1;
11716 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11717 for (inner = region->inner, casei = 1;
11718 inner;
11719 inner = inner->next, i++, casei++)
11721 basic_block s_entry_bb, s_exit_bb;
11723 /* Skip optional reduction region. */
11724 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11726 --i;
11727 --casei;
11728 continue;
11731 s_entry_bb = inner->entry;
11732 s_exit_bb = inner->exit;
11734 t = gimple_block_label (s_entry_bb);
11735 u = build_int_cst (unsigned_type_node, casei);
11736 u = build_case_label (u, NULL, t);
11737 label_vec.quick_push (u);
11739 si = gsi_last_bb (s_entry_bb);
11740 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11741 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11742 gsi_remove (&si, true);
11743 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11745 if (s_exit_bb == NULL)
11746 continue;
11748 si = gsi_last_bb (s_exit_bb);
11749 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11750 gsi_remove (&si, true);
11752 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11755 /* Error handling code goes in DEFAULT_BB. */
11756 t = gimple_block_label (default_bb);
11757 u = build_case_label (NULL, NULL, t);
11758 make_edge (l0_bb, default_bb, 0);
11759 add_bb_to_loop (default_bb, current_loops->tree_root);
11761 stmt = gimple_build_switch (vmain, u, label_vec);
11762 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11763 gsi_remove (&switch_si, true);
11765 si = gsi_start_bb (default_bb);
11766 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11767 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11769 if (exit_reachable)
11771 tree bfn_decl;
11773 /* Code to get the next section goes in L1_BB. */
11774 si = gsi_last_bb (l1_bb);
11775 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11777 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11778 stmt = gimple_build_call (bfn_decl, 0);
11779 gimple_call_set_lhs (stmt, vnext);
11780 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11781 gsi_remove (&si, true);
11783 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11786 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11787 si = gsi_last_bb (l2_bb);
11788 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11789 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11790 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11791 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11792 else
11793 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11794 stmt = gimple_build_call (t, 0);
11795 if (gimple_omp_return_lhs (gsi_stmt (si)))
11796 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11797 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11798 gsi_remove (&si, true);
11800 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11804 /* Expand code for an OpenMP single directive. We've already expanded
11805 much of the code, here we simply place the GOMP_barrier call. */
11807 static void
11808 expand_omp_single (struct omp_region *region)
11810 basic_block entry_bb, exit_bb;
11811 gimple_stmt_iterator si;
11813 entry_bb = region->entry;
11814 exit_bb = region->exit;
11816 si = gsi_last_bb (entry_bb);
11817 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11818 gsi_remove (&si, true);
11819 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11821 si = gsi_last_bb (exit_bb);
11822 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11824 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11825 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11827 gsi_remove (&si, true);
11828 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11832 /* Generic expansion for OpenMP synchronization directives: master,
11833 ordered and critical. All we need to do here is remove the entry
11834 and exit markers for REGION. */
11836 static void
11837 expand_omp_synch (struct omp_region *region)
11839 basic_block entry_bb, exit_bb;
11840 gimple_stmt_iterator si;
11842 entry_bb = region->entry;
11843 exit_bb = region->exit;
11845 si = gsi_last_bb (entry_bb);
11846 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11847 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11848 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11849 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11850 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11851 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11852 gsi_remove (&si, true);
11853 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11855 if (exit_bb)
11857 si = gsi_last_bb (exit_bb);
11858 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11859 gsi_remove (&si, true);
11860 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11864 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11865 operation as a normal volatile load. */
11867 static bool
11868 expand_omp_atomic_load (basic_block load_bb, tree addr,
11869 tree loaded_val, int index)
11871 enum built_in_function tmpbase;
11872 gimple_stmt_iterator gsi;
11873 basic_block store_bb;
11874 location_t loc;
11875 gimple *stmt;
11876 tree decl, call, type, itype;
11878 gsi = gsi_last_bb (load_bb);
11879 stmt = gsi_stmt (gsi);
11880 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11881 loc = gimple_location (stmt);
11883 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11884 is smaller than word size, then expand_atomic_load assumes that the load
11885 is atomic. We could avoid the builtin entirely in this case. */
11887 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11888 decl = builtin_decl_explicit (tmpbase);
11889 if (decl == NULL_TREE)
11890 return false;
11892 type = TREE_TYPE (loaded_val);
11893 itype = TREE_TYPE (TREE_TYPE (decl));
11895 call = build_call_expr_loc (loc, decl, 2, addr,
11896 build_int_cst (NULL,
11897 gimple_omp_atomic_seq_cst_p (stmt)
11898 ? MEMMODEL_SEQ_CST
11899 : MEMMODEL_RELAXED));
11900 if (!useless_type_conversion_p (type, itype))
11901 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11902 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11904 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11905 gsi_remove (&gsi, true);
11907 store_bb = single_succ (load_bb);
11908 gsi = gsi_last_bb (store_bb);
11909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11910 gsi_remove (&gsi, true);
11912 if (gimple_in_ssa_p (cfun))
11913 update_ssa (TODO_update_ssa_no_phi);
11915 return true;
11918 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11919 operation as a normal volatile store. */
11921 static bool
11922 expand_omp_atomic_store (basic_block load_bb, tree addr,
11923 tree loaded_val, tree stored_val, int index)
11925 enum built_in_function tmpbase;
11926 gimple_stmt_iterator gsi;
11927 basic_block store_bb = single_succ (load_bb);
11928 location_t loc;
11929 gimple *stmt;
11930 tree decl, call, type, itype;
11931 machine_mode imode;
11932 bool exchange;
11934 gsi = gsi_last_bb (load_bb);
11935 stmt = gsi_stmt (gsi);
11936 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11938 /* If the load value is needed, then this isn't a store but an exchange. */
11939 exchange = gimple_omp_atomic_need_value_p (stmt);
11941 gsi = gsi_last_bb (store_bb);
11942 stmt = gsi_stmt (gsi);
11943 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11944 loc = gimple_location (stmt);
11946 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11947 is smaller than word size, then expand_atomic_store assumes that the store
11948 is atomic. We could avoid the builtin entirely in this case. */
11950 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11951 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11952 decl = builtin_decl_explicit (tmpbase);
11953 if (decl == NULL_TREE)
11954 return false;
11956 type = TREE_TYPE (stored_val);
11958 /* Dig out the type of the function's second argument. */
11959 itype = TREE_TYPE (decl);
11960 itype = TYPE_ARG_TYPES (itype);
11961 itype = TREE_CHAIN (itype);
11962 itype = TREE_VALUE (itype);
11963 imode = TYPE_MODE (itype);
11965 if (exchange && !can_atomic_exchange_p (imode, true))
11966 return false;
11968 if (!useless_type_conversion_p (itype, type))
11969 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11970 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11971 build_int_cst (NULL,
11972 gimple_omp_atomic_seq_cst_p (stmt)
11973 ? MEMMODEL_SEQ_CST
11974 : MEMMODEL_RELAXED));
11975 if (exchange)
11977 if (!useless_type_conversion_p (type, itype))
11978 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11979 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11982 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11983 gsi_remove (&gsi, true);
11985 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11986 gsi = gsi_last_bb (load_bb);
11987 gsi_remove (&gsi, true);
11989 if (gimple_in_ssa_p (cfun))
11990 update_ssa (TODO_update_ssa_no_phi);
11992 return true;
11995 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11996 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11997 size of the data type, and thus usable to find the index of the builtin
11998 decl. Returns false if the expression is not of the proper form. */
12000 static bool
12001 expand_omp_atomic_fetch_op (basic_block load_bb,
12002 tree addr, tree loaded_val,
12003 tree stored_val, int index)
12005 enum built_in_function oldbase, newbase, tmpbase;
12006 tree decl, itype, call;
12007 tree lhs, rhs;
12008 basic_block store_bb = single_succ (load_bb);
12009 gimple_stmt_iterator gsi;
12010 gimple *stmt;
12011 location_t loc;
12012 enum tree_code code;
12013 bool need_old, need_new;
12014 machine_mode imode;
12015 bool seq_cst;
12017 /* We expect to find the following sequences:
12019 load_bb:
12020 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12022 store_bb:
12023 val = tmp OP something; (or: something OP tmp)
12024 GIMPLE_OMP_STORE (val)
12026 ???FIXME: Allow a more flexible sequence.
12027 Perhaps use data flow to pick the statements.
12031 gsi = gsi_after_labels (store_bb);
12032 stmt = gsi_stmt (gsi);
12033 loc = gimple_location (stmt);
12034 if (!is_gimple_assign (stmt))
12035 return false;
12036 gsi_next (&gsi);
12037 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12038 return false;
12039 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12040 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12041 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12042 gcc_checking_assert (!need_old || !need_new);
12044 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12045 return false;
12047 /* Check for one of the supported fetch-op operations. */
12048 code = gimple_assign_rhs_code (stmt);
12049 switch (code)
12051 case PLUS_EXPR:
12052 case POINTER_PLUS_EXPR:
12053 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12054 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12055 break;
12056 case MINUS_EXPR:
12057 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12058 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12059 break;
12060 case BIT_AND_EXPR:
12061 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12062 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12063 break;
12064 case BIT_IOR_EXPR:
12065 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12066 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12067 break;
12068 case BIT_XOR_EXPR:
12069 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12070 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12071 break;
12072 default:
12073 return false;
12076 /* Make sure the expression is of the proper form. */
12077 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12078 rhs = gimple_assign_rhs2 (stmt);
12079 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12080 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12081 rhs = gimple_assign_rhs1 (stmt);
12082 else
12083 return false;
12085 tmpbase = ((enum built_in_function)
12086 ((need_new ? newbase : oldbase) + index + 1));
12087 decl = builtin_decl_explicit (tmpbase);
12088 if (decl == NULL_TREE)
12089 return false;
12090 itype = TREE_TYPE (TREE_TYPE (decl));
12091 imode = TYPE_MODE (itype);
12093 /* We could test all of the various optabs involved, but the fact of the
12094 matter is that (with the exception of i486 vs i586 and xadd) all targets
12095 that support any atomic operaton optab also implements compare-and-swap.
12096 Let optabs.c take care of expanding any compare-and-swap loop. */
12097 if (!can_compare_and_swap_p (imode, true))
12098 return false;
12100 gsi = gsi_last_bb (load_bb);
12101 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12103 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12104 It only requires that the operation happen atomically. Thus we can
12105 use the RELAXED memory model. */
12106 call = build_call_expr_loc (loc, decl, 3, addr,
12107 fold_convert_loc (loc, itype, rhs),
12108 build_int_cst (NULL,
12109 seq_cst ? MEMMODEL_SEQ_CST
12110 : MEMMODEL_RELAXED));
12112 if (need_old || need_new)
12114 lhs = need_old ? loaded_val : stored_val;
12115 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12116 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12118 else
12119 call = fold_convert_loc (loc, void_type_node, call);
12120 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12121 gsi_remove (&gsi, true);
12123 gsi = gsi_last_bb (store_bb);
12124 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12125 gsi_remove (&gsi, true);
12126 gsi = gsi_last_bb (store_bb);
12127 stmt = gsi_stmt (gsi);
12128 gsi_remove (&gsi, true);
12130 if (gimple_in_ssa_p (cfun))
12132 release_defs (stmt);
12133 update_ssa (TODO_update_ssa_no_phi);
12136 return true;
12139 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12141 oldval = *addr;
12142 repeat:
12143 newval = rhs; // with oldval replacing *addr in rhs
12144 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12145 if (oldval != newval)
12146 goto repeat;
12148 INDEX is log2 of the size of the data type, and thus usable to find the
12149 index of the builtin decl. */
12151 static bool
12152 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12153 tree addr, tree loaded_val, tree stored_val,
12154 int index)
12156 tree loadedi, storedi, initial, new_storedi, old_vali;
12157 tree type, itype, cmpxchg, iaddr;
12158 gimple_stmt_iterator si;
12159 basic_block loop_header = single_succ (load_bb);
12160 gimple *phi, *stmt;
12161 edge e;
12162 enum built_in_function fncode;
12164 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12165 order to use the RELAXED memory model effectively. */
12166 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12167 + index + 1);
12168 cmpxchg = builtin_decl_explicit (fncode);
12169 if (cmpxchg == NULL_TREE)
12170 return false;
12171 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12172 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12174 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12175 return false;
12177 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12178 si = gsi_last_bb (load_bb);
12179 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12181 /* For floating-point values, we'll need to view-convert them to integers
12182 so that we can perform the atomic compare and swap. Simplify the
12183 following code by always setting up the "i"ntegral variables. */
12184 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12186 tree iaddr_val;
12188 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12189 true));
12190 iaddr_val
12191 = force_gimple_operand_gsi (&si,
12192 fold_convert (TREE_TYPE (iaddr), addr),
12193 false, NULL_TREE, true, GSI_SAME_STMT);
12194 stmt = gimple_build_assign (iaddr, iaddr_val);
12195 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12196 loadedi = create_tmp_var (itype);
12197 if (gimple_in_ssa_p (cfun))
12198 loadedi = make_ssa_name (loadedi);
12200 else
12202 iaddr = addr;
12203 loadedi = loaded_val;
12206 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12207 tree loaddecl = builtin_decl_explicit (fncode);
12208 if (loaddecl)
12209 initial
12210 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12211 build_call_expr (loaddecl, 2, iaddr,
12212 build_int_cst (NULL_TREE,
12213 MEMMODEL_RELAXED)));
12214 else
12215 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12216 build_int_cst (TREE_TYPE (iaddr), 0));
12218 initial
12219 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12220 GSI_SAME_STMT);
12222 /* Move the value to the LOADEDI temporary. */
12223 if (gimple_in_ssa_p (cfun))
12225 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12226 phi = create_phi_node (loadedi, loop_header);
12227 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12228 initial);
12230 else
12231 gsi_insert_before (&si,
12232 gimple_build_assign (loadedi, initial),
12233 GSI_SAME_STMT);
12234 if (loadedi != loaded_val)
12236 gimple_stmt_iterator gsi2;
12237 tree x;
12239 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12240 gsi2 = gsi_start_bb (loop_header);
12241 if (gimple_in_ssa_p (cfun))
12243 gassign *stmt;
12244 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12245 true, GSI_SAME_STMT);
12246 stmt = gimple_build_assign (loaded_val, x);
12247 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12249 else
12251 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12252 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12253 true, GSI_SAME_STMT);
12256 gsi_remove (&si, true);
12258 si = gsi_last_bb (store_bb);
12259 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12261 if (iaddr == addr)
12262 storedi = stored_val;
12263 else
12264 storedi =
12265 force_gimple_operand_gsi (&si,
12266 build1 (VIEW_CONVERT_EXPR, itype,
12267 stored_val), true, NULL_TREE, true,
12268 GSI_SAME_STMT);
12270 /* Build the compare&swap statement. */
12271 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12272 new_storedi = force_gimple_operand_gsi (&si,
12273 fold_convert (TREE_TYPE (loadedi),
12274 new_storedi),
12275 true, NULL_TREE,
12276 true, GSI_SAME_STMT);
12278 if (gimple_in_ssa_p (cfun))
12279 old_vali = loadedi;
12280 else
12282 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12283 stmt = gimple_build_assign (old_vali, loadedi);
12284 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12286 stmt = gimple_build_assign (loadedi, new_storedi);
12287 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12290 /* Note that we always perform the comparison as an integer, even for
12291 floating point. This allows the atomic operation to properly
12292 succeed even with NaNs and -0.0. */
12293 stmt = gimple_build_cond_empty
12294 (build2 (NE_EXPR, boolean_type_node,
12295 new_storedi, old_vali));
12296 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12298 /* Update cfg. */
12299 e = single_succ_edge (store_bb);
12300 e->flags &= ~EDGE_FALLTHRU;
12301 e->flags |= EDGE_FALSE_VALUE;
12303 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12305 /* Copy the new value to loadedi (we already did that before the condition
12306 if we are not in SSA). */
12307 if (gimple_in_ssa_p (cfun))
12309 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12310 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12313 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12314 gsi_remove (&si, true);
12316 struct loop *loop = alloc_loop ();
12317 loop->header = loop_header;
12318 loop->latch = store_bb;
12319 add_loop (loop, loop_header->loop_father);
12321 if (gimple_in_ssa_p (cfun))
12322 update_ssa (TODO_update_ssa_no_phi);
12324 return true;
12327 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12329 GOMP_atomic_start ();
12330 *addr = rhs;
12331 GOMP_atomic_end ();
12333 The result is not globally atomic, but works so long as all parallel
12334 references are within #pragma omp atomic directives. According to
12335 responses received from omp@openmp.org, appears to be within spec.
12336 Which makes sense, since that's how several other compilers handle
12337 this situation as well.
12338 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12339 expanding. STORED_VAL is the operand of the matching
12340 GIMPLE_OMP_ATOMIC_STORE.
12342 We replace
12343 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12344 loaded_val = *addr;
12346 and replace
12347 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12348 *addr = stored_val;
12351 static bool
12352 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12353 tree addr, tree loaded_val, tree stored_val)
12355 gimple_stmt_iterator si;
12356 gassign *stmt;
12357 tree t;
12359 si = gsi_last_bb (load_bb);
12360 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12362 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12363 t = build_call_expr (t, 0);
12364 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12366 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12367 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12368 gsi_remove (&si, true);
12370 si = gsi_last_bb (store_bb);
12371 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12373 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12374 stored_val);
12375 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12377 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12378 t = build_call_expr (t, 0);
12379 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12380 gsi_remove (&si, true);
12382 if (gimple_in_ssa_p (cfun))
12383 update_ssa (TODO_update_ssa_no_phi);
12384 return true;
12387 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12388 using expand_omp_atomic_fetch_op. If it failed, we try to
12389 call expand_omp_atomic_pipeline, and if it fails too, the
12390 ultimate fallback is wrapping the operation in a mutex
12391 (expand_omp_atomic_mutex). REGION is the atomic region built
12392 by build_omp_regions_1(). */
12394 static void
12395 expand_omp_atomic (struct omp_region *region)
12397 basic_block load_bb = region->entry, store_bb = region->exit;
12398 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12399 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12400 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12401 tree addr = gimple_omp_atomic_load_rhs (load);
12402 tree stored_val = gimple_omp_atomic_store_val (store);
12403 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12404 HOST_WIDE_INT index;
12406 /* Make sure the type is one of the supported sizes. */
12407 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12408 index = exact_log2 (index);
12409 if (index >= 0 && index <= 4)
12411 unsigned int align = TYPE_ALIGN_UNIT (type);
12413 /* __sync builtins require strict data alignment. */
12414 if (exact_log2 (align) >= index)
12416 /* Atomic load. */
12417 if (loaded_val == stored_val
12418 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12419 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12420 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12421 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12422 return;
12424 /* Atomic store. */
12425 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12426 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12427 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12428 && store_bb == single_succ (load_bb)
12429 && first_stmt (store_bb) == store
12430 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12431 stored_val, index))
12432 return;
12434 /* When possible, use specialized atomic update functions. */
12435 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12436 && store_bb == single_succ (load_bb)
12437 && expand_omp_atomic_fetch_op (load_bb, addr,
12438 loaded_val, stored_val, index))
12439 return;
12441 /* If we don't have specialized __sync builtins, try and implement
12442 as a compare and swap loop. */
12443 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12444 loaded_val, stored_val, index))
12445 return;
12449 /* The ultimate fallback is wrapping the operation in a mutex. */
12450 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12454 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12455 macro on gomp-constants.h. We do not check for overflow. */
12457 static tree
12458 oacc_launch_pack (unsigned code, tree device, unsigned op)
12460 tree res;
12462 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12463 if (device)
12465 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12466 device, build_int_cst (unsigned_type_node,
12467 GOMP_LAUNCH_DEVICE_SHIFT));
12468 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12470 return res;
12473 /* Look for compute grid dimension clauses and convert to an attribute
12474 attached to FN. This permits the target-side code to (a) massage
12475 the dimensions, (b) emit that data and (c) optimize. Non-constant
12476 dimensions are pushed onto ARGS.
12478 The attribute value is a TREE_LIST. A set of dimensions is
12479 represented as a list of INTEGER_CST. Those that are runtime
12480 exprs are represented as an INTEGER_CST of zero.
12482 TOOO. Normally the attribute will just contain a single such list. If
12483 however it contains a list of lists, this will represent the use of
12484 device_type. Each member of the outer list is an assoc list of
12485 dimensions, keyed by the device type. The first entry will be the
12486 default. Well, that's the plan. */
12488 #define OACC_FN_ATTRIB "oacc function"
12490 /* Replace any existing oacc fn attribute with updated dimensions. */
12492 void
12493 replace_oacc_fn_attrib (tree fn, tree dims)
12495 tree ident = get_identifier (OACC_FN_ATTRIB);
12496 tree attribs = DECL_ATTRIBUTES (fn);
12498 /* If we happen to be present as the first attrib, drop it. */
12499 if (attribs && TREE_PURPOSE (attribs) == ident)
12500 attribs = TREE_CHAIN (attribs);
12501 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12504 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12505 function attribute. Push any that are non-constant onto the ARGS
12506 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12507 true, if these are for a kernels region offload function. */
12509 void
12510 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12512 /* Must match GOMP_DIM ordering. */
12513 static const omp_clause_code ids[]
12514 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12515 OMP_CLAUSE_VECTOR_LENGTH };
12516 unsigned ix;
12517 tree dims[GOMP_DIM_MAX];
12518 tree attr = NULL_TREE;
12519 unsigned non_const = 0;
12521 for (ix = GOMP_DIM_MAX; ix--;)
12523 tree clause = find_omp_clause (clauses, ids[ix]);
12524 tree dim = NULL_TREE;
12526 if (clause)
12527 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12528 dims[ix] = dim;
12529 if (dim && TREE_CODE (dim) != INTEGER_CST)
12531 dim = integer_zero_node;
12532 non_const |= GOMP_DIM_MASK (ix);
12534 attr = tree_cons (NULL_TREE, dim, attr);
12535 /* Note kernelness with TREE_PUBLIC. */
12536 if (is_kernel)
12537 TREE_PUBLIC (attr) = 1;
12540 replace_oacc_fn_attrib (fn, attr);
12542 if (non_const)
12544 /* Push a dynamic argument set. */
12545 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12546 NULL_TREE, non_const));
12547 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12548 if (non_const & GOMP_DIM_MASK (ix))
12549 args->safe_push (dims[ix]);
12553 /* Process the routine's dimension clauess to generate an attribute
12554 value. Issue diagnostics as appropriate. We default to SEQ
12555 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12556 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12557 can have a loop partitioned on it. non-zero indicates
12558 yes, zero indicates no. By construction once a non-zero has been
12559 reached, further inner dimensions must also be non-zero. We set
12560 TREE_VALUE to zero for the dimensions that may be partitioned and
12561 1 for the other ones -- if a loop is (erroneously) spawned at
12562 an outer level, we don't want to try and partition it. */
12564 tree
12565 build_oacc_routine_dims (tree clauses)
12567 /* Must match GOMP_DIM ordering. */
12568 static const omp_clause_code ids[] =
12569 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12570 int ix;
12571 int level = -1;
12573 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12574 for (ix = GOMP_DIM_MAX + 1; ix--;)
12575 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12577 if (level >= 0)
12578 error_at (OMP_CLAUSE_LOCATION (clauses),
12579 "multiple loop axes specified for routine");
12580 level = ix;
12581 break;
12584 /* Default to SEQ. */
12585 if (level < 0)
12586 level = GOMP_DIM_MAX;
12588 tree dims = NULL_TREE;
12590 for (ix = GOMP_DIM_MAX; ix--;)
12591 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12592 build_int_cst (integer_type_node, ix < level), dims);
12594 return dims;
12597 /* Retrieve the oacc function attrib and return it. Non-oacc
12598 functions will return NULL. */
12600 tree
12601 get_oacc_fn_attrib (tree fn)
12603 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12606 /* Return true if this oacc fn attrib is for a kernels offload
12607 region. We use the TREE_PUBLIC flag of each dimension -- only
12608 need to check the first one. */
12610 bool
12611 oacc_fn_attrib_kernels_p (tree attr)
12613 return TREE_PUBLIC (TREE_VALUE (attr));
12616 /* Return level at which oacc routine may spawn a partitioned loop, or
12617 -1 if it is not a routine (i.e. is an offload fn). */
12619 static int
12620 oacc_fn_attrib_level (tree attr)
12622 tree pos = TREE_VALUE (attr);
12624 if (!TREE_PURPOSE (pos))
12625 return -1;
12627 int ix = 0;
12628 for (ix = 0; ix != GOMP_DIM_MAX;
12629 ix++, pos = TREE_CHAIN (pos))
12630 if (!integer_zerop (TREE_PURPOSE (pos)))
12631 break;
12633 return ix;
12636 /* Extract an oacc execution dimension from FN. FN must be an
12637 offloaded function or routine that has already had its execution
12638 dimensions lowered to the target-specific values. */
12641 get_oacc_fn_dim_size (tree fn, int axis)
12643 tree attrs = get_oacc_fn_attrib (fn);
12645 gcc_assert (axis < GOMP_DIM_MAX);
12647 tree dims = TREE_VALUE (attrs);
12648 while (axis--)
12649 dims = TREE_CHAIN (dims);
12651 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12653 return size;
12656 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12657 IFN_GOACC_DIM_SIZE call. */
12660 get_oacc_ifn_dim_arg (const gimple *stmt)
12662 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12663 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12664 tree arg = gimple_call_arg (stmt, 0);
12665 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12667 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12668 return (int) axis;
12671 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12672 at REGION_EXIT. */
12674 static void
12675 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12676 basic_block region_exit)
12678 struct loop *outer = region_entry->loop_father;
12679 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12681 /* Don't parallelize the kernels region if it contains more than one outer
12682 loop. */
12683 unsigned int nr_outer_loops = 0;
12684 struct loop *single_outer = NULL;
12685 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12687 gcc_assert (loop_outer (loop) == outer);
12689 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12690 continue;
12692 if (region_exit != NULL
12693 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12694 continue;
12696 nr_outer_loops++;
12697 single_outer = loop;
12699 if (nr_outer_loops != 1)
12700 return;
12702 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12703 if (loop->next)
12704 return;
12706 /* Mark the loops in the region. */
12707 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12708 loop->in_oacc_kernels_region = true;
12711 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12713 struct GTY(()) grid_launch_attributes_trees
12715 tree kernel_dim_array_type;
12716 tree kernel_lattrs_dimnum_decl;
12717 tree kernel_lattrs_grid_decl;
12718 tree kernel_lattrs_group_decl;
12719 tree kernel_launch_attributes_type;
12722 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12724 /* Create types used to pass kernel launch attributes to target. */
12726 static void
12727 grid_create_kernel_launch_attr_types (void)
12729 if (grid_attr_trees)
12730 return;
12731 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12733 tree dim_arr_index_type
12734 = build_index_type (build_int_cst (integer_type_node, 2));
12735 grid_attr_trees->kernel_dim_array_type
12736 = build_array_type (uint32_type_node, dim_arr_index_type);
12738 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12739 grid_attr_trees->kernel_lattrs_dimnum_decl
12740 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12741 uint32_type_node);
12742 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12744 grid_attr_trees->kernel_lattrs_grid_decl
12745 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12746 grid_attr_trees->kernel_dim_array_type);
12747 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12748 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12749 grid_attr_trees->kernel_lattrs_group_decl
12750 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12751 grid_attr_trees->kernel_dim_array_type);
12752 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12753 = grid_attr_trees->kernel_lattrs_grid_decl;
12754 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12755 "__gomp_kernel_launch_attributes",
12756 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12759 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12760 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12761 of type uint32_type_node. */
12763 static void
12764 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12765 tree fld_decl, int index, tree value)
12767 tree ref = build4 (ARRAY_REF, uint32_type_node,
12768 build3 (COMPONENT_REF,
12769 grid_attr_trees->kernel_dim_array_type,
12770 range_var, fld_decl, NULL_TREE),
12771 build_int_cst (integer_type_node, index),
12772 NULL_TREE, NULL_TREE);
12773 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12776 /* Return a tree representation of a pointer to a structure with grid and
12777 work-group size information. Statements filling that information will be
12778 inserted before GSI, TGT_STMT is the target statement which has the
12779 necessary information in it. */
12781 static tree
12782 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12783 gomp_target *tgt_stmt)
12785 grid_create_kernel_launch_attr_types ();
12786 tree u32_one = build_one_cst (uint32_type_node);
12787 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12788 "__kernel_launch_attrs");
12790 unsigned max_dim = 0;
12791 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12792 clause;
12793 clause = OMP_CLAUSE_CHAIN (clause))
12795 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12796 continue;
12798 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12799 max_dim = MAX (dim, max_dim);
12801 grid_insert_store_range_dim (gsi, lattrs,
12802 grid_attr_trees->kernel_lattrs_grid_decl,
12803 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12804 grid_insert_store_range_dim (gsi, lattrs,
12805 grid_attr_trees->kernel_lattrs_group_decl,
12806 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12809 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12810 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12811 /* At this moment we cannot gridify a loop with a collapse clause. */
12812 /* TODO: Adjust when we support bigger collapse. */
12813 gcc_assert (max_dim == 0);
12814 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12815 TREE_ADDRESSABLE (lattrs) = 1;
12816 return build_fold_addr_expr (lattrs);
12819 /* Build target argument identifier from the DEVICE identifier, value
12820 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12822 static tree
12823 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12825 tree t = build_int_cst (integer_type_node, device);
12826 if (subseqent_param)
12827 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12828 build_int_cst (integer_type_node,
12829 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12830 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12831 build_int_cst (integer_type_node, id));
12832 return t;
12835 /* Like above but return it in type that can be directly stored as an element
12836 of the argument array. */
12838 static tree
12839 get_target_argument_identifier (int device, bool subseqent_param, int id)
12841 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12842 return fold_convert (ptr_type_node, t);
12845 /* Return a target argument consisting of DEVICE identifier, value identifier
12846 ID, and the actual VALUE. */
12848 static tree
12849 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12850 tree value)
12852 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12853 fold_convert (integer_type_node, value),
12854 build_int_cst (unsigned_type_node,
12855 GOMP_TARGET_ARG_VALUE_SHIFT));
12856 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12857 get_target_argument_identifier_1 (device, false, id));
12858 t = fold_convert (ptr_type_node, t);
12859 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12862 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12863 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12864 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12865 arguments. */
12867 static void
12868 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12869 int id, tree value, vec <tree> *args)
12871 if (tree_fits_shwi_p (value)
12872 && tree_to_shwi (value) > -(1 << 15)
12873 && tree_to_shwi (value) < (1 << 15))
12874 args->quick_push (get_target_argument_value (gsi, device, id, value));
12875 else
12877 args->quick_push (get_target_argument_identifier (device, true, id));
12878 value = fold_convert (ptr_type_node, value);
12879 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12880 GSI_SAME_STMT);
12881 args->quick_push (value);
12885 /* Create an array of arguments that is then passed to GOMP_target. */
12887 static tree
12888 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12890 auto_vec <tree, 6> args;
12891 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12892 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12893 if (c)
12894 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12895 else
12896 t = integer_minus_one_node;
12897 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12898 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12900 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12901 if (c)
12902 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12903 else
12904 t = integer_minus_one_node;
12905 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12906 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12907 &args);
12909 /* Add HSA-specific grid sizes, if available. */
12910 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12911 OMP_CLAUSE__GRIDDIM_))
12913 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12914 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12915 args.quick_push (t);
12916 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12919 /* Produce more, perhaps device specific, arguments here. */
12921 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12922 args.length () + 1),
12923 ".omp_target_args");
12924 for (unsigned i = 0; i < args.length (); i++)
12926 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12927 build_int_cst (integer_type_node, i),
12928 NULL_TREE, NULL_TREE);
12929 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12930 GSI_SAME_STMT);
12932 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12933 build_int_cst (integer_type_node, args.length ()),
12934 NULL_TREE, NULL_TREE);
12935 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12936 GSI_SAME_STMT);
12937 TREE_ADDRESSABLE (argarray) = 1;
12938 return build_fold_addr_expr (argarray);
12941 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12943 static void
12944 expand_omp_target (struct omp_region *region)
12946 basic_block entry_bb, exit_bb, new_bb;
12947 struct function *child_cfun;
12948 tree child_fn, block, t;
12949 gimple_stmt_iterator gsi;
12950 gomp_target *entry_stmt;
12951 gimple *stmt;
12952 edge e;
12953 bool offloaded, data_region;
12955 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12956 new_bb = region->entry;
12958 offloaded = is_gimple_omp_offloaded (entry_stmt);
12959 switch (gimple_omp_target_kind (entry_stmt))
12961 case GF_OMP_TARGET_KIND_REGION:
12962 case GF_OMP_TARGET_KIND_UPDATE:
12963 case GF_OMP_TARGET_KIND_ENTER_DATA:
12964 case GF_OMP_TARGET_KIND_EXIT_DATA:
12965 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12966 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12967 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12968 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12969 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12970 data_region = false;
12971 break;
12972 case GF_OMP_TARGET_KIND_DATA:
12973 case GF_OMP_TARGET_KIND_OACC_DATA:
12974 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12975 data_region = true;
12976 break;
12977 default:
12978 gcc_unreachable ();
12981 child_fn = NULL_TREE;
12982 child_cfun = NULL;
12983 if (offloaded)
12985 child_fn = gimple_omp_target_child_fn (entry_stmt);
12986 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12989 /* Supported by expand_omp_taskreg, but not here. */
12990 if (child_cfun != NULL)
12991 gcc_checking_assert (!child_cfun->cfg);
12992 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12994 entry_bb = region->entry;
12995 exit_bb = region->exit;
12997 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12998 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13000 if (offloaded)
13002 unsigned srcidx, dstidx, num;
13004 /* If the offloading region needs data sent from the parent
13005 function, then the very first statement (except possible
13006 tree profile counter updates) of the offloading body
13007 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13008 &.OMP_DATA_O is passed as an argument to the child function,
13009 we need to replace it with the argument as seen by the child
13010 function.
13012 In most cases, this will end up being the identity assignment
13013 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13014 a function call that has been inlined, the original PARM_DECL
13015 .OMP_DATA_I may have been converted into a different local
13016 variable. In which case, we need to keep the assignment. */
13017 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13018 if (data_arg)
13020 basic_block entry_succ_bb = single_succ (entry_bb);
13021 gimple_stmt_iterator gsi;
13022 tree arg;
13023 gimple *tgtcopy_stmt = NULL;
13024 tree sender = TREE_VEC_ELT (data_arg, 0);
13026 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13028 gcc_assert (!gsi_end_p (gsi));
13029 stmt = gsi_stmt (gsi);
13030 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13031 continue;
13033 if (gimple_num_ops (stmt) == 2)
13035 tree arg = gimple_assign_rhs1 (stmt);
13037 /* We're ignoring the subcode because we're
13038 effectively doing a STRIP_NOPS. */
13040 if (TREE_CODE (arg) == ADDR_EXPR
13041 && TREE_OPERAND (arg, 0) == sender)
13043 tgtcopy_stmt = stmt;
13044 break;
13049 gcc_assert (tgtcopy_stmt != NULL);
13050 arg = DECL_ARGUMENTS (child_fn);
13052 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13053 gsi_remove (&gsi, true);
13056 /* Declare local variables needed in CHILD_CFUN. */
13057 block = DECL_INITIAL (child_fn);
13058 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13059 /* The gimplifier could record temporaries in the offloading block
13060 rather than in containing function's local_decls chain,
13061 which would mean cgraph missed finalizing them. Do it now. */
13062 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13063 if (TREE_CODE (t) == VAR_DECL
13064 && TREE_STATIC (t)
13065 && !DECL_EXTERNAL (t))
13066 varpool_node::finalize_decl (t);
13067 DECL_SAVED_TREE (child_fn) = NULL;
13068 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13069 gimple_set_body (child_fn, NULL);
13070 TREE_USED (block) = 1;
13072 /* Reset DECL_CONTEXT on function arguments. */
13073 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13074 DECL_CONTEXT (t) = child_fn;
13076 /* Split ENTRY_BB at GIMPLE_*,
13077 so that it can be moved to the child function. */
13078 gsi = gsi_last_bb (entry_bb);
13079 stmt = gsi_stmt (gsi);
13080 gcc_assert (stmt
13081 && gimple_code (stmt) == gimple_code (entry_stmt));
13082 e = split_block (entry_bb, stmt);
13083 gsi_remove (&gsi, true);
13084 entry_bb = e->dest;
13085 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13087 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13088 if (exit_bb)
13090 gsi = gsi_last_bb (exit_bb);
13091 gcc_assert (!gsi_end_p (gsi)
13092 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13093 stmt = gimple_build_return (NULL);
13094 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13095 gsi_remove (&gsi, true);
13098 /* Move the offloading region into CHILD_CFUN. */
13100 block = gimple_block (entry_stmt);
13102 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13103 if (exit_bb)
13104 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13105 /* When the OMP expansion process cannot guarantee an up-to-date
13106 loop tree arrange for the child function to fixup loops. */
13107 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13108 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13110 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13111 num = vec_safe_length (child_cfun->local_decls);
13112 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13114 t = (*child_cfun->local_decls)[srcidx];
13115 if (DECL_CONTEXT (t) == cfun->decl)
13116 continue;
13117 if (srcidx != dstidx)
13118 (*child_cfun->local_decls)[dstidx] = t;
13119 dstidx++;
13121 if (dstidx != num)
13122 vec_safe_truncate (child_cfun->local_decls, dstidx);
13124 /* Inform the callgraph about the new function. */
13125 child_cfun->curr_properties = cfun->curr_properties;
13126 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13127 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13128 cgraph_node *node = cgraph_node::get_create (child_fn);
13129 node->parallelized_function = 1;
13130 cgraph_node::add_new_function (child_fn, true);
13132 /* Add the new function to the offload table. */
13133 if (ENABLE_OFFLOADING)
13134 vec_safe_push (offload_funcs, child_fn);
13136 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13137 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13139 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13140 fixed in a following pass. */
13141 push_cfun (child_cfun);
13142 if (need_asm)
13143 assign_assembler_name_if_neeeded (child_fn);
13144 cgraph_edge::rebuild_edges ();
13146 /* Some EH regions might become dead, see PR34608. If
13147 pass_cleanup_cfg isn't the first pass to happen with the
13148 new child, these dead EH edges might cause problems.
13149 Clean them up now. */
13150 if (flag_exceptions)
13152 basic_block bb;
13153 bool changed = false;
13155 FOR_EACH_BB_FN (bb, cfun)
13156 changed |= gimple_purge_dead_eh_edges (bb);
13157 if (changed)
13158 cleanup_tree_cfg ();
13160 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13161 verify_loop_structure ();
13162 pop_cfun ();
13164 if (dump_file && !gimple_in_ssa_p (cfun))
13166 omp_any_child_fn_dumped = true;
13167 dump_function_header (dump_file, child_fn, dump_flags);
13168 dump_function_to_file (child_fn, dump_file, dump_flags);
13172 /* Emit a library call to launch the offloading region, or do data
13173 transfers. */
13174 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13175 enum built_in_function start_ix;
13176 location_t clause_loc;
13177 unsigned int flags_i = 0;
13178 bool oacc_kernels_p = false;
13180 switch (gimple_omp_target_kind (entry_stmt))
13182 case GF_OMP_TARGET_KIND_REGION:
13183 start_ix = BUILT_IN_GOMP_TARGET;
13184 break;
13185 case GF_OMP_TARGET_KIND_DATA:
13186 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13187 break;
13188 case GF_OMP_TARGET_KIND_UPDATE:
13189 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13190 break;
13191 case GF_OMP_TARGET_KIND_ENTER_DATA:
13192 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13193 break;
13194 case GF_OMP_TARGET_KIND_EXIT_DATA:
13195 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13196 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13197 break;
13198 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13199 oacc_kernels_p = true;
13200 /* FALLTHROUGH */
13201 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13202 start_ix = BUILT_IN_GOACC_PARALLEL;
13203 break;
13204 case GF_OMP_TARGET_KIND_OACC_DATA:
13205 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13206 start_ix = BUILT_IN_GOACC_DATA_START;
13207 break;
13208 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13209 start_ix = BUILT_IN_GOACC_UPDATE;
13210 break;
13211 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13212 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13213 break;
13214 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13215 start_ix = BUILT_IN_GOACC_DECLARE;
13216 break;
13217 default:
13218 gcc_unreachable ();
13221 clauses = gimple_omp_target_clauses (entry_stmt);
13223 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13224 library choose) and there is no conditional. */
13225 cond = NULL_TREE;
13226 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13228 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13229 if (c)
13230 cond = OMP_CLAUSE_IF_EXPR (c);
13232 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13233 if (c)
13235 /* Even if we pass it to all library function calls, it is currently only
13236 defined/used for the OpenMP target ones. */
13237 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13238 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13239 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13240 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13242 device = OMP_CLAUSE_DEVICE_ID (c);
13243 clause_loc = OMP_CLAUSE_LOCATION (c);
13245 else
13246 clause_loc = gimple_location (entry_stmt);
13248 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13249 if (c)
13250 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13252 /* Ensure 'device' is of the correct type. */
13253 device = fold_convert_loc (clause_loc, integer_type_node, device);
13255 /* If we found the clause 'if (cond)', build
13256 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13257 if (cond)
13259 cond = gimple_boolify (cond);
13261 basic_block cond_bb, then_bb, else_bb;
13262 edge e;
13263 tree tmp_var;
13265 tmp_var = create_tmp_var (TREE_TYPE (device));
13266 if (offloaded)
13267 e = split_block_after_labels (new_bb);
13268 else
13270 gsi = gsi_last_bb (new_bb);
13271 gsi_prev (&gsi);
13272 e = split_block (new_bb, gsi_stmt (gsi));
13274 cond_bb = e->src;
13275 new_bb = e->dest;
13276 remove_edge (e);
13278 then_bb = create_empty_bb (cond_bb);
13279 else_bb = create_empty_bb (then_bb);
13280 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13281 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13283 stmt = gimple_build_cond_empty (cond);
13284 gsi = gsi_last_bb (cond_bb);
13285 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13287 gsi = gsi_start_bb (then_bb);
13288 stmt = gimple_build_assign (tmp_var, device);
13289 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13291 gsi = gsi_start_bb (else_bb);
13292 stmt = gimple_build_assign (tmp_var,
13293 build_int_cst (integer_type_node,
13294 GOMP_DEVICE_HOST_FALLBACK));
13295 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13297 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13298 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13299 add_bb_to_loop (then_bb, cond_bb->loop_father);
13300 add_bb_to_loop (else_bb, cond_bb->loop_father);
13301 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13302 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13304 device = tmp_var;
13307 gsi = gsi_last_bb (new_bb);
13308 t = gimple_omp_target_data_arg (entry_stmt);
13309 if (t == NULL)
13311 t1 = size_zero_node;
13312 t2 = build_zero_cst (ptr_type_node);
13313 t3 = t2;
13314 t4 = t2;
13316 else
13318 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13319 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13320 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13321 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13322 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13325 gimple *g;
13326 bool tagging = false;
13327 /* The maximum number used by any start_ix, without varargs. */
13328 auto_vec<tree, 11> args;
13329 args.quick_push (device);
13330 if (offloaded)
13331 args.quick_push (build_fold_addr_expr (child_fn));
13332 args.quick_push (t1);
13333 args.quick_push (t2);
13334 args.quick_push (t3);
13335 args.quick_push (t4);
13336 switch (start_ix)
13338 case BUILT_IN_GOACC_DATA_START:
13339 case BUILT_IN_GOACC_DECLARE:
13340 case BUILT_IN_GOMP_TARGET_DATA:
13341 break;
13342 case BUILT_IN_GOMP_TARGET:
13343 case BUILT_IN_GOMP_TARGET_UPDATE:
13344 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13345 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13346 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13347 if (c)
13348 depend = OMP_CLAUSE_DECL (c);
13349 else
13350 depend = build_int_cst (ptr_type_node, 0);
13351 args.quick_push (depend);
13352 if (start_ix == BUILT_IN_GOMP_TARGET)
13353 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13354 break;
13355 case BUILT_IN_GOACC_PARALLEL:
13357 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13358 tagging = true;
13360 /* FALLTHRU */
13361 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13362 case BUILT_IN_GOACC_UPDATE:
13364 tree t_async = NULL_TREE;
13366 /* If present, use the value specified by the respective
13367 clause, making sure that is of the correct type. */
13368 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13369 if (c)
13370 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13371 integer_type_node,
13372 OMP_CLAUSE_ASYNC_EXPR (c));
13373 else if (!tagging)
13374 /* Default values for t_async. */
13375 t_async = fold_convert_loc (gimple_location (entry_stmt),
13376 integer_type_node,
13377 build_int_cst (integer_type_node,
13378 GOMP_ASYNC_SYNC));
13379 if (tagging && t_async)
13381 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13383 if (TREE_CODE (t_async) == INTEGER_CST)
13385 /* See if we can pack the async arg in to the tag's
13386 operand. */
13387 i_async = TREE_INT_CST_LOW (t_async);
13388 if (i_async < GOMP_LAUNCH_OP_MAX)
13389 t_async = NULL_TREE;
13390 else
13391 i_async = GOMP_LAUNCH_OP_MAX;
13393 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13394 i_async));
13396 if (t_async)
13397 args.safe_push (t_async);
13399 /* Save the argument index, and ... */
13400 unsigned t_wait_idx = args.length ();
13401 unsigned num_waits = 0;
13402 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13403 if (!tagging || c)
13404 /* ... push a placeholder. */
13405 args.safe_push (integer_zero_node);
13407 for (; c; c = OMP_CLAUSE_CHAIN (c))
13408 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13410 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13411 integer_type_node,
13412 OMP_CLAUSE_WAIT_EXPR (c)));
13413 num_waits++;
13416 if (!tagging || num_waits)
13418 tree len;
13420 /* Now that we know the number, update the placeholder. */
13421 if (tagging)
13422 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13423 else
13424 len = build_int_cst (integer_type_node, num_waits);
13425 len = fold_convert_loc (gimple_location (entry_stmt),
13426 unsigned_type_node, len);
13427 args[t_wait_idx] = len;
13430 break;
13431 default:
13432 gcc_unreachable ();
13434 if (tagging)
13435 /* Push terminal marker - zero. */
13436 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13438 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13439 gimple_set_location (g, gimple_location (entry_stmt));
13440 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13441 if (!offloaded)
13443 g = gsi_stmt (gsi);
13444 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13445 gsi_remove (&gsi, true);
13447 if (data_region && region->exit)
13449 gsi = gsi_last_bb (region->exit);
13450 g = gsi_stmt (gsi);
13451 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13452 gsi_remove (&gsi, true);
13456 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13457 variable derived from the thread number. */
13459 static void
13460 grid_expand_omp_for_loop (struct omp_region *kfor)
13462 tree t, threadid;
13463 tree type, itype;
13464 gimple_stmt_iterator gsi;
13465 tree n1, step;
13466 struct omp_for_data fd;
13468 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13469 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13470 == GF_OMP_FOR_KIND_GRID_LOOP);
13471 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13473 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13474 gcc_assert (kfor->cont);
13475 extract_omp_for_data (for_stmt, &fd, NULL);
13477 itype = type = TREE_TYPE (fd.loop.v);
13478 if (POINTER_TYPE_P (type))
13479 itype = signed_type_for (type);
13481 gsi = gsi_start_bb (body_bb);
13483 n1 = fd.loop.n1;
13484 step = fd.loop.step;
13485 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13486 true, NULL_TREE, true, GSI_SAME_STMT);
13487 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13488 true, NULL_TREE, true, GSI_SAME_STMT);
13489 threadid = build_call_expr (builtin_decl_explicit
13490 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13491 threadid = fold_convert (itype, threadid);
13492 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13493 true, GSI_SAME_STMT);
13495 tree startvar = fd.loop.v;
13496 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13497 if (POINTER_TYPE_P (type))
13498 t = fold_build_pointer_plus (n1, t);
13499 else
13500 t = fold_build2 (PLUS_EXPR, type, t, n1);
13501 t = fold_convert (type, t);
13502 t = force_gimple_operand_gsi (&gsi, t,
13503 DECL_P (startvar)
13504 && TREE_ADDRESSABLE (startvar),
13505 NULL_TREE, true, GSI_SAME_STMT);
13506 gassign *assign_stmt = gimple_build_assign (startvar, t);
13507 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13509 /* Remove the omp for statement */
13510 gsi = gsi_last_bb (kfor->entry);
13511 gsi_remove (&gsi, true);
13513 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13514 gsi = gsi_last_bb (kfor->cont);
13515 gcc_assert (!gsi_end_p (gsi)
13516 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13517 gsi_remove (&gsi, true);
13519 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13520 gsi = gsi_last_bb (kfor->exit);
13521 gcc_assert (!gsi_end_p (gsi)
13522 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13523 gsi_remove (&gsi, true);
13525 /* Fixup the much simpler CFG. */
13526 remove_edge (find_edge (kfor->cont, body_bb));
13528 if (kfor->cont != body_bb)
13529 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13530 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13533 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13534 argument_decls. */
13536 struct grid_arg_decl_map
13538 tree old_arg;
13539 tree new_arg;
13542 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13543 pertaining to kernel function. */
13545 static tree
13546 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13548 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13549 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13550 tree t = *tp;
13552 if (t == adm->old_arg)
13553 *tp = adm->new_arg;
13554 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13555 return NULL_TREE;
13558 static void expand_omp (struct omp_region *region);
13560 /* If TARGET region contains a kernel body for loop, remove its region from the
13561 TARGET and expand it in GPGPU kernel fashion. */
13563 static void
13564 grid_expand_target_grid_body (struct omp_region *target)
13566 if (!hsa_gen_requested_p ())
13567 return;
13569 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13570 struct omp_region **pp;
13572 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13573 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13574 break;
13576 struct omp_region *gpukernel = *pp;
13578 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13579 if (!gpukernel)
13581 /* HSA cannot handle OACC stuff. */
13582 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13583 return;
13584 gcc_checking_assert (orig_child_fndecl);
13585 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13586 OMP_CLAUSE__GRIDDIM_));
13587 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13589 hsa_register_kernel (n);
13590 return;
13593 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13594 OMP_CLAUSE__GRIDDIM_));
13595 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13596 *pp = gpukernel->next;
13597 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13598 if ((*pp)->type == GIMPLE_OMP_FOR)
13599 break;
13601 struct omp_region *kfor = *pp;
13602 gcc_assert (kfor);
13603 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13604 == GF_OMP_FOR_KIND_GRID_LOOP);
13605 *pp = kfor->next;
13606 if (kfor->inner)
13607 expand_omp (kfor->inner);
13608 if (gpukernel->inner)
13609 expand_omp (gpukernel->inner);
13611 tree kern_fndecl = copy_node (orig_child_fndecl);
13612 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13613 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13614 tree tgtblock = gimple_block (tgt_stmt);
13615 tree fniniblock = make_node (BLOCK);
13616 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13617 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13618 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13619 DECL_INITIAL (kern_fndecl) = fniniblock;
13620 push_struct_function (kern_fndecl);
13621 cfun->function_end_locus = gimple_location (tgt_stmt);
13622 pop_cfun ();
13624 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13625 gcc_assert (!DECL_CHAIN (old_parm_decl));
13626 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13627 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13628 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13629 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13630 kern_cfun->curr_properties = cfun->curr_properties;
13632 remove_edge (BRANCH_EDGE (kfor->entry));
13633 grid_expand_omp_for_loop (kfor);
13635 /* Remove the omp for statement */
13636 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13637 gsi_remove (&gsi, true);
13638 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13639 return. */
13640 gsi = gsi_last_bb (gpukernel->exit);
13641 gcc_assert (!gsi_end_p (gsi)
13642 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13643 gimple *ret_stmt = gimple_build_return (NULL);
13644 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13645 gsi_remove (&gsi, true);
13647 /* Statements in the first BB in the target construct have been produced by
13648 target lowering and must be copied inside the GPUKERNEL, with the two
13649 exceptions of the first OMP statement and the OMP_DATA assignment
13650 statement. */
13651 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13652 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13653 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13654 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13655 !gsi_end_p (tsi); gsi_next (&tsi))
13657 gimple *stmt = gsi_stmt (tsi);
13658 if (is_gimple_omp (stmt))
13659 break;
13660 if (sender
13661 && is_gimple_assign (stmt)
13662 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13663 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13664 continue;
13665 gimple *copy = gimple_copy (stmt);
13666 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13667 gimple_set_block (copy, fniniblock);
13670 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13671 gpukernel->exit, inside_block);
13673 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13674 kcn->mark_force_output ();
13675 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13677 hsa_register_kernel (kcn, orig_child);
13679 cgraph_node::add_new_function (kern_fndecl, true);
13680 push_cfun (kern_cfun);
13681 cgraph_edge::rebuild_edges ();
13683 /* Re-map any mention of the PARM_DECL of the original function to the
13684 PARM_DECL of the new one.
13686 TODO: It would be great if lowering produced references into the GPU
13687 kernel decl straight away and we did not have to do this. */
13688 struct grid_arg_decl_map adm;
13689 adm.old_arg = old_parm_decl;
13690 adm.new_arg = new_parm_decl;
13691 basic_block bb;
13692 FOR_EACH_BB_FN (bb, kern_cfun)
13694 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13696 gimple *stmt = gsi_stmt (gsi);
13697 struct walk_stmt_info wi;
13698 memset (&wi, 0, sizeof (wi));
13699 wi.info = &adm;
13700 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13703 pop_cfun ();
13705 return;
13708 /* Expand the parallel region tree rooted at REGION. Expansion
13709 proceeds in depth-first order. Innermost regions are expanded
13710 first. This way, parallel regions that require a new function to
13711 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13712 internal dependencies in their body. */
13714 static void
13715 expand_omp (struct omp_region *region)
13717 omp_any_child_fn_dumped = false;
13718 while (region)
13720 location_t saved_location;
13721 gimple *inner_stmt = NULL;
13723 /* First, determine whether this is a combined parallel+workshare
13724 region. */
13725 if (region->type == GIMPLE_OMP_PARALLEL)
13726 determine_parallel_type (region);
13727 else if (region->type == GIMPLE_OMP_TARGET)
13728 grid_expand_target_grid_body (region);
13730 if (region->type == GIMPLE_OMP_FOR
13731 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13732 inner_stmt = last_stmt (region->inner->entry);
13734 if (region->inner)
13735 expand_omp (region->inner);
13737 saved_location = input_location;
13738 if (gimple_has_location (last_stmt (region->entry)))
13739 input_location = gimple_location (last_stmt (region->entry));
13741 switch (region->type)
13743 case GIMPLE_OMP_PARALLEL:
13744 case GIMPLE_OMP_TASK:
13745 expand_omp_taskreg (region);
13746 break;
13748 case GIMPLE_OMP_FOR:
13749 expand_omp_for (region, inner_stmt);
13750 break;
13752 case GIMPLE_OMP_SECTIONS:
13753 expand_omp_sections (region);
13754 break;
13756 case GIMPLE_OMP_SECTION:
13757 /* Individual omp sections are handled together with their
13758 parent GIMPLE_OMP_SECTIONS region. */
13759 break;
13761 case GIMPLE_OMP_SINGLE:
13762 expand_omp_single (region);
13763 break;
13765 case GIMPLE_OMP_ORDERED:
13767 gomp_ordered *ord_stmt
13768 = as_a <gomp_ordered *> (last_stmt (region->entry));
13769 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13770 OMP_CLAUSE_DEPEND))
13772 /* We'll expand these when expanding corresponding
13773 worksharing region with ordered(n) clause. */
13774 gcc_assert (region->outer
13775 && region->outer->type == GIMPLE_OMP_FOR);
13776 region->ord_stmt = ord_stmt;
13777 break;
13780 /* FALLTHRU */
13781 case GIMPLE_OMP_MASTER:
13782 case GIMPLE_OMP_TASKGROUP:
13783 case GIMPLE_OMP_CRITICAL:
13784 case GIMPLE_OMP_TEAMS:
13785 expand_omp_synch (region);
13786 break;
13788 case GIMPLE_OMP_ATOMIC_LOAD:
13789 expand_omp_atomic (region);
13790 break;
13792 case GIMPLE_OMP_TARGET:
13793 expand_omp_target (region);
13794 break;
13796 default:
13797 gcc_unreachable ();
13800 input_location = saved_location;
13801 region = region->next;
13803 if (omp_any_child_fn_dumped)
13805 if (dump_file)
13806 dump_function_header (dump_file, current_function_decl, dump_flags);
13807 omp_any_child_fn_dumped = false;
13812 /* Helper for build_omp_regions. Scan the dominator tree starting at
13813 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13814 true, the function ends once a single tree is built (otherwise, whole
13815 forest of OMP constructs may be built). */
13817 static void
13818 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13819 bool single_tree)
13821 gimple_stmt_iterator gsi;
13822 gimple *stmt;
13823 basic_block son;
13825 gsi = gsi_last_bb (bb);
13826 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13828 struct omp_region *region;
13829 enum gimple_code code;
13831 stmt = gsi_stmt (gsi);
13832 code = gimple_code (stmt);
13833 if (code == GIMPLE_OMP_RETURN)
13835 /* STMT is the return point out of region PARENT. Mark it
13836 as the exit point and make PARENT the immediately
13837 enclosing region. */
13838 gcc_assert (parent);
13839 region = parent;
13840 region->exit = bb;
13841 parent = parent->outer;
13843 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13845 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13846 GIMPLE_OMP_RETURN, but matches with
13847 GIMPLE_OMP_ATOMIC_LOAD. */
13848 gcc_assert (parent);
13849 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13850 region = parent;
13851 region->exit = bb;
13852 parent = parent->outer;
13854 else if (code == GIMPLE_OMP_CONTINUE)
13856 gcc_assert (parent);
13857 parent->cont = bb;
13859 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13861 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13862 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13864 else
13866 region = new_omp_region (bb, code, parent);
13867 /* Otherwise... */
13868 if (code == GIMPLE_OMP_TARGET)
13870 switch (gimple_omp_target_kind (stmt))
13872 case GF_OMP_TARGET_KIND_REGION:
13873 case GF_OMP_TARGET_KIND_DATA:
13874 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13875 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13876 case GF_OMP_TARGET_KIND_OACC_DATA:
13877 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13878 break;
13879 case GF_OMP_TARGET_KIND_UPDATE:
13880 case GF_OMP_TARGET_KIND_ENTER_DATA:
13881 case GF_OMP_TARGET_KIND_EXIT_DATA:
13882 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13883 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13884 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13885 /* ..., other than for those stand-alone directives... */
13886 region = NULL;
13887 break;
13888 default:
13889 gcc_unreachable ();
13892 else if (code == GIMPLE_OMP_ORDERED
13893 && find_omp_clause (gimple_omp_ordered_clauses
13894 (as_a <gomp_ordered *> (stmt)),
13895 OMP_CLAUSE_DEPEND))
13896 /* #pragma omp ordered depend is also just a stand-alone
13897 directive. */
13898 region = NULL;
13899 /* ..., this directive becomes the parent for a new region. */
13900 if (region)
13901 parent = region;
13905 if (single_tree && !parent)
13906 return;
13908 for (son = first_dom_son (CDI_DOMINATORS, bb);
13909 son;
13910 son = next_dom_son (CDI_DOMINATORS, son))
13911 build_omp_regions_1 (son, parent, single_tree);
13914 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13915 root_omp_region. */
13917 static void
13918 build_omp_regions_root (basic_block root)
13920 gcc_assert (root_omp_region == NULL);
13921 build_omp_regions_1 (root, NULL, true);
13922 gcc_assert (root_omp_region != NULL);
13925 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13927 void
13928 omp_expand_local (basic_block head)
13930 build_omp_regions_root (head);
13931 if (dump_file && (dump_flags & TDF_DETAILS))
13933 fprintf (dump_file, "\nOMP region tree\n\n");
13934 dump_omp_region (dump_file, root_omp_region, 0);
13935 fprintf (dump_file, "\n");
13938 remove_exit_barriers (root_omp_region);
13939 expand_omp (root_omp_region);
13941 free_omp_regions ();
13944 /* Scan the CFG and build a tree of OMP regions. Return the root of
13945 the OMP region tree. */
13947 static void
13948 build_omp_regions (void)
13950 gcc_assert (root_omp_region == NULL);
13951 calculate_dominance_info (CDI_DOMINATORS);
13952 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
13955 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13957 static unsigned int
13958 execute_expand_omp (void)
13960 build_omp_regions ();
13962 if (!root_omp_region)
13963 return 0;
13965 if (dump_file)
13967 fprintf (dump_file, "\nOMP region tree\n\n");
13968 dump_omp_region (dump_file, root_omp_region, 0);
13969 fprintf (dump_file, "\n");
13972 remove_exit_barriers (root_omp_region);
13974 expand_omp (root_omp_region);
13976 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13977 verify_loop_structure ();
13978 cleanup_tree_cfg ();
13980 free_omp_regions ();
13982 return 0;
13985 /* OMP expansion -- the default pass, run before creation of SSA form. */
13987 namespace {
13989 const pass_data pass_data_expand_omp =
13991 GIMPLE_PASS, /* type */
13992 "ompexp", /* name */
13993 OPTGROUP_NONE, /* optinfo_flags */
13994 TV_NONE, /* tv_id */
13995 PROP_gimple_any, /* properties_required */
13996 PROP_gimple_eomp, /* properties_provided */
13997 0, /* properties_destroyed */
13998 0, /* todo_flags_start */
13999 0, /* todo_flags_finish */
14002 class pass_expand_omp : public gimple_opt_pass
14004 public:
14005 pass_expand_omp (gcc::context *ctxt)
14006 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14009 /* opt_pass methods: */
14010 virtual unsigned int execute (function *)
14012 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14013 || flag_openmp_simd != 0)
14014 && !seen_error ());
14016 /* This pass always runs, to provide PROP_gimple_eomp.
14017 But often, there is nothing to do. */
14018 if (!gate)
14019 return 0;
14021 return execute_expand_omp ();
14024 }; // class pass_expand_omp
14026 } // anon namespace
14028 gimple_opt_pass *
14029 make_pass_expand_omp (gcc::context *ctxt)
14031 return new pass_expand_omp (ctxt);
14034 namespace {
14036 const pass_data pass_data_expand_omp_ssa =
14038 GIMPLE_PASS, /* type */
14039 "ompexpssa", /* name */
14040 OPTGROUP_NONE, /* optinfo_flags */
14041 TV_NONE, /* tv_id */
14042 PROP_cfg | PROP_ssa, /* properties_required */
14043 PROP_gimple_eomp, /* properties_provided */
14044 0, /* properties_destroyed */
14045 0, /* todo_flags_start */
14046 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14049 class pass_expand_omp_ssa : public gimple_opt_pass
14051 public:
14052 pass_expand_omp_ssa (gcc::context *ctxt)
14053 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14056 /* opt_pass methods: */
14057 virtual bool gate (function *fun)
14059 return !(fun->curr_properties & PROP_gimple_eomp);
14061 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14062 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14064 }; // class pass_expand_omp_ssa
14066 } // anon namespace
14068 gimple_opt_pass *
14069 make_pass_expand_omp_ssa (gcc::context *ctxt)
14071 return new pass_expand_omp_ssa (ctxt);
14074 /* Routines to lower OMP directives into OMP-GIMPLE. */
14076 /* If ctx is a worksharing context inside of a cancellable parallel
14077 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14078 and conditional branch to parallel's cancel_label to handle
14079 cancellation in the implicit barrier. */
14081 static void
14082 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14084 gimple *omp_return = gimple_seq_last_stmt (*body);
14085 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14086 if (gimple_omp_return_nowait_p (omp_return))
14087 return;
14088 if (ctx->outer
14089 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14090 && ctx->outer->cancellable)
14092 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14093 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14094 tree lhs = create_tmp_var (c_bool_type);
14095 gimple_omp_return_set_lhs (omp_return, lhs);
14096 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14097 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14098 fold_convert (c_bool_type,
14099 boolean_false_node),
14100 ctx->outer->cancel_label, fallthru_label);
14101 gimple_seq_add_stmt (body, g);
14102 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14106 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14107 CTX is the enclosing OMP context for the current statement. */
14109 static void
14110 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14112 tree block, control;
14113 gimple_stmt_iterator tgsi;
14114 gomp_sections *stmt;
14115 gimple *t;
14116 gbind *new_stmt, *bind;
14117 gimple_seq ilist, dlist, olist, new_body;
14119 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14121 push_gimplify_context ();
14123 dlist = NULL;
14124 ilist = NULL;
14125 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14126 &ilist, &dlist, ctx, NULL);
14128 new_body = gimple_omp_body (stmt);
14129 gimple_omp_set_body (stmt, NULL);
14130 tgsi = gsi_start (new_body);
14131 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14133 omp_context *sctx;
14134 gimple *sec_start;
14136 sec_start = gsi_stmt (tgsi);
14137 sctx = maybe_lookup_ctx (sec_start);
14138 gcc_assert (sctx);
14140 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14141 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14142 GSI_CONTINUE_LINKING);
14143 gimple_omp_set_body (sec_start, NULL);
14145 if (gsi_one_before_end_p (tgsi))
14147 gimple_seq l = NULL;
14148 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14149 &l, ctx);
14150 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14151 gimple_omp_section_set_last (sec_start);
14154 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14155 GSI_CONTINUE_LINKING);
14158 block = make_node (BLOCK);
14159 bind = gimple_build_bind (NULL, new_body, block);
14161 olist = NULL;
14162 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14164 block = make_node (BLOCK);
14165 new_stmt = gimple_build_bind (NULL, NULL, block);
14166 gsi_replace (gsi_p, new_stmt, true);
14168 pop_gimplify_context (new_stmt);
14169 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14170 BLOCK_VARS (block) = gimple_bind_vars (bind);
14171 if (BLOCK_VARS (block))
14172 TREE_USED (block) = 1;
14174 new_body = NULL;
14175 gimple_seq_add_seq (&new_body, ilist);
14176 gimple_seq_add_stmt (&new_body, stmt);
14177 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14178 gimple_seq_add_stmt (&new_body, bind);
14180 control = create_tmp_var (unsigned_type_node, ".section");
14181 t = gimple_build_omp_continue (control, control);
14182 gimple_omp_sections_set_control (stmt, control);
14183 gimple_seq_add_stmt (&new_body, t);
14185 gimple_seq_add_seq (&new_body, olist);
14186 if (ctx->cancellable)
14187 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14188 gimple_seq_add_seq (&new_body, dlist);
14190 new_body = maybe_catch_exception (new_body);
14192 t = gimple_build_omp_return
14193 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14194 OMP_CLAUSE_NOWAIT));
14195 gimple_seq_add_stmt (&new_body, t);
14196 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14198 gimple_bind_set_body (new_stmt, new_body);
14202 /* A subroutine of lower_omp_single. Expand the simple form of
14203 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14205 if (GOMP_single_start ())
14206 BODY;
14207 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14209 FIXME. It may be better to delay expanding the logic of this until
14210 pass_expand_omp. The expanded logic may make the job more difficult
14211 to a synchronization analysis pass. */
14213 static void
14214 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14216 location_t loc = gimple_location (single_stmt);
14217 tree tlabel = create_artificial_label (loc);
14218 tree flabel = create_artificial_label (loc);
14219 gimple *call, *cond;
14220 tree lhs, decl;
14222 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14223 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14224 call = gimple_build_call (decl, 0);
14225 gimple_call_set_lhs (call, lhs);
14226 gimple_seq_add_stmt (pre_p, call);
14228 cond = gimple_build_cond (EQ_EXPR, lhs,
14229 fold_convert_loc (loc, TREE_TYPE (lhs),
14230 boolean_true_node),
14231 tlabel, flabel);
14232 gimple_seq_add_stmt (pre_p, cond);
14233 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14234 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14235 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14239 /* A subroutine of lower_omp_single. Expand the simple form of
14240 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14242 #pragma omp single copyprivate (a, b, c)
14244 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14247 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14249 BODY;
14250 copyout.a = a;
14251 copyout.b = b;
14252 copyout.c = c;
14253 GOMP_single_copy_end (&copyout);
14255 else
14257 a = copyout_p->a;
14258 b = copyout_p->b;
14259 c = copyout_p->c;
14261 GOMP_barrier ();
14264 FIXME. It may be better to delay expanding the logic of this until
14265 pass_expand_omp. The expanded logic may make the job more difficult
14266 to a synchronization analysis pass. */
14268 static void
14269 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14270 omp_context *ctx)
14272 tree ptr_type, t, l0, l1, l2, bfn_decl;
14273 gimple_seq copyin_seq;
14274 location_t loc = gimple_location (single_stmt);
14276 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14278 ptr_type = build_pointer_type (ctx->record_type);
14279 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14281 l0 = create_artificial_label (loc);
14282 l1 = create_artificial_label (loc);
14283 l2 = create_artificial_label (loc);
14285 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14286 t = build_call_expr_loc (loc, bfn_decl, 0);
14287 t = fold_convert_loc (loc, ptr_type, t);
14288 gimplify_assign (ctx->receiver_decl, t, pre_p);
14290 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14291 build_int_cst (ptr_type, 0));
14292 t = build3 (COND_EXPR, void_type_node, t,
14293 build_and_jump (&l0), build_and_jump (&l1));
14294 gimplify_and_add (t, pre_p);
14296 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14298 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14300 copyin_seq = NULL;
14301 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14302 &copyin_seq, ctx);
14304 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14305 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14306 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14307 gimplify_and_add (t, pre_p);
14309 t = build_and_jump (&l2);
14310 gimplify_and_add (t, pre_p);
14312 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14314 gimple_seq_add_seq (pre_p, copyin_seq);
14316 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14320 /* Expand code for an OpenMP single directive. */
14322 static void
14323 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14325 tree block;
14326 gimple *t;
14327 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14328 gbind *bind;
14329 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14331 push_gimplify_context ();
14333 block = make_node (BLOCK);
14334 bind = gimple_build_bind (NULL, NULL, block);
14335 gsi_replace (gsi_p, bind, true);
14336 bind_body = NULL;
14337 dlist = NULL;
14338 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14339 &bind_body, &dlist, ctx, NULL);
14340 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14342 gimple_seq_add_stmt (&bind_body, single_stmt);
14344 if (ctx->record_type)
14345 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14346 else
14347 lower_omp_single_simple (single_stmt, &bind_body);
14349 gimple_omp_set_body (single_stmt, NULL);
14351 gimple_seq_add_seq (&bind_body, dlist);
14353 bind_body = maybe_catch_exception (bind_body);
14355 t = gimple_build_omp_return
14356 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14357 OMP_CLAUSE_NOWAIT));
14358 gimple_seq_add_stmt (&bind_body_tail, t);
14359 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14360 if (ctx->record_type)
14362 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14363 tree clobber = build_constructor (ctx->record_type, NULL);
14364 TREE_THIS_VOLATILE (clobber) = 1;
14365 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14366 clobber), GSI_SAME_STMT);
14368 gimple_seq_add_seq (&bind_body, bind_body_tail);
14369 gimple_bind_set_body (bind, bind_body);
14371 pop_gimplify_context (bind);
14373 gimple_bind_append_vars (bind, ctx->block_vars);
14374 BLOCK_VARS (block) = ctx->block_vars;
14375 if (BLOCK_VARS (block))
14376 TREE_USED (block) = 1;
14380 /* Expand code for an OpenMP master directive. */
14382 static void
14383 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14385 tree block, lab = NULL, x, bfn_decl;
14386 gimple *stmt = gsi_stmt (*gsi_p);
14387 gbind *bind;
14388 location_t loc = gimple_location (stmt);
14389 gimple_seq tseq;
14391 push_gimplify_context ();
14393 block = make_node (BLOCK);
14394 bind = gimple_build_bind (NULL, NULL, block);
14395 gsi_replace (gsi_p, bind, true);
14396 gimple_bind_add_stmt (bind, stmt);
14398 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14399 x = build_call_expr_loc (loc, bfn_decl, 0);
14400 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14401 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14402 tseq = NULL;
14403 gimplify_and_add (x, &tseq);
14404 gimple_bind_add_seq (bind, tseq);
14406 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14407 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14408 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14409 gimple_omp_set_body (stmt, NULL);
14411 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14413 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14415 pop_gimplify_context (bind);
14417 gimple_bind_append_vars (bind, ctx->block_vars);
14418 BLOCK_VARS (block) = ctx->block_vars;
14422 /* Expand code for an OpenMP taskgroup directive. */
14424 static void
14425 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14427 gimple *stmt = gsi_stmt (*gsi_p);
14428 gcall *x;
14429 gbind *bind;
14430 tree block = make_node (BLOCK);
14432 bind = gimple_build_bind (NULL, NULL, block);
14433 gsi_replace (gsi_p, bind, true);
14434 gimple_bind_add_stmt (bind, stmt);
14436 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14438 gimple_bind_add_stmt (bind, x);
14440 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14441 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14442 gimple_omp_set_body (stmt, NULL);
14444 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14446 gimple_bind_append_vars (bind, ctx->block_vars);
14447 BLOCK_VARS (block) = ctx->block_vars;
14451 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14453 static void
14454 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14455 omp_context *ctx)
14457 struct omp_for_data fd;
14458 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14459 return;
14461 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14462 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14463 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14464 if (!fd.ordered)
14465 return;
14467 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14468 tree c = gimple_omp_ordered_clauses (ord_stmt);
14469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14470 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14472 /* Merge depend clauses from multiple adjacent
14473 #pragma omp ordered depend(sink:...) constructs
14474 into one #pragma omp ordered depend(sink:...), so that
14475 we can optimize them together. */
14476 gimple_stmt_iterator gsi = *gsi_p;
14477 gsi_next (&gsi);
14478 while (!gsi_end_p (gsi))
14480 gimple *stmt = gsi_stmt (gsi);
14481 if (is_gimple_debug (stmt)
14482 || gimple_code (stmt) == GIMPLE_NOP)
14484 gsi_next (&gsi);
14485 continue;
14487 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14488 break;
14489 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14490 c = gimple_omp_ordered_clauses (ord_stmt2);
14491 if (c == NULL_TREE
14492 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14493 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14494 break;
14495 while (*list_p)
14496 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14497 *list_p = c;
14498 gsi_remove (&gsi, true);
14502 /* Canonicalize sink dependence clauses into one folded clause if
14503 possible.
14505 The basic algorithm is to create a sink vector whose first
14506 element is the GCD of all the first elements, and whose remaining
14507 elements are the minimum of the subsequent columns.
14509 We ignore dependence vectors whose first element is zero because
14510 such dependencies are known to be executed by the same thread.
14512 We take into account the direction of the loop, so a minimum
14513 becomes a maximum if the loop is iterating forwards. We also
14514 ignore sink clauses where the loop direction is unknown, or where
14515 the offsets are clearly invalid because they are not a multiple
14516 of the loop increment.
14518 For example:
14520 #pragma omp for ordered(2)
14521 for (i=0; i < N; ++i)
14522 for (j=0; j < M; ++j)
14524 #pragma omp ordered \
14525 depend(sink:i-8,j-2) \
14526 depend(sink:i,j-1) \ // Completely ignored because i+0.
14527 depend(sink:i-4,j-3) \
14528 depend(sink:i-6,j-4)
14529 #pragma omp ordered depend(source)
14532 Folded clause is:
14534 depend(sink:-gcd(8,4,6),-min(2,3,4))
14535 -or-
14536 depend(sink:-2,-2)
14539 /* FIXME: Computing GCD's where the first element is zero is
14540 non-trivial in the presence of collapsed loops. Do this later. */
14541 if (fd.collapse > 1)
14542 return;
14544 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14545 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14546 tree folded_dep = NULL_TREE;
14547 /* TRUE if the first dimension's offset is negative. */
14548 bool neg_offset_p = false;
14550 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14551 unsigned int i;
14552 while ((c = *list_p) != NULL)
14554 bool remove = false;
14556 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14557 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14558 goto next_ordered_clause;
14560 tree vec;
14561 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14562 vec && TREE_CODE (vec) == TREE_LIST;
14563 vec = TREE_CHAIN (vec), ++i)
14565 gcc_assert (i < len);
14567 /* extract_omp_for_data has canonicalized the condition. */
14568 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14569 || fd.loops[i].cond_code == GT_EXPR);
14570 bool forward = fd.loops[i].cond_code == LT_EXPR;
14571 bool maybe_lexically_later = true;
14573 /* While the committee makes up its mind, bail if we have any
14574 non-constant steps. */
14575 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14576 goto lower_omp_ordered_ret;
14578 tree itype = TREE_TYPE (TREE_VALUE (vec));
14579 if (POINTER_TYPE_P (itype))
14580 itype = sizetype;
14581 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14582 TYPE_PRECISION (itype),
14583 TYPE_SIGN (itype));
14585 /* Ignore invalid offsets that are not multiples of the step. */
14586 if (!wi::multiple_of_p
14587 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14588 UNSIGNED))
14590 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14591 "ignoring sink clause with offset that is not "
14592 "a multiple of the loop step");
14593 remove = true;
14594 goto next_ordered_clause;
14597 /* Calculate the first dimension. The first dimension of
14598 the folded dependency vector is the GCD of the first
14599 elements, while ignoring any first elements whose offset
14600 is 0. */
14601 if (i == 0)
14603 /* Ignore dependence vectors whose first dimension is 0. */
14604 if (offset == 0)
14606 remove = true;
14607 goto next_ordered_clause;
14609 else
14611 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14613 error_at (OMP_CLAUSE_LOCATION (c),
14614 "first offset must be in opposite direction "
14615 "of loop iterations");
14616 goto lower_omp_ordered_ret;
14618 if (forward)
14619 offset = -offset;
14620 neg_offset_p = forward;
14621 /* Initialize the first time around. */
14622 if (folded_dep == NULL_TREE)
14624 folded_dep = c;
14625 folded_deps[0] = offset;
14627 else
14628 folded_deps[0] = wi::gcd (folded_deps[0],
14629 offset, UNSIGNED);
14632 /* Calculate minimum for the remaining dimensions. */
14633 else
14635 folded_deps[len + i - 1] = offset;
14636 if (folded_dep == c)
14637 folded_deps[i] = offset;
14638 else if (maybe_lexically_later
14639 && !wi::eq_p (folded_deps[i], offset))
14641 if (forward ^ wi::gts_p (folded_deps[i], offset))
14643 unsigned int j;
14644 folded_dep = c;
14645 for (j = 1; j <= i; j++)
14646 folded_deps[j] = folded_deps[len + j - 1];
14648 else
14649 maybe_lexically_later = false;
14653 gcc_assert (i == len);
14655 remove = true;
14657 next_ordered_clause:
14658 if (remove)
14659 *list_p = OMP_CLAUSE_CHAIN (c);
14660 else
14661 list_p = &OMP_CLAUSE_CHAIN (c);
14664 if (folded_dep)
14666 if (neg_offset_p)
14667 folded_deps[0] = -folded_deps[0];
14669 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14670 if (POINTER_TYPE_P (itype))
14671 itype = sizetype;
14673 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14674 = wide_int_to_tree (itype, folded_deps[0]);
14675 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14676 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14679 lower_omp_ordered_ret:
14681 /* Ordered without clauses is #pragma omp threads, while we want
14682 a nop instead if we remove all clauses. */
14683 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14684 gsi_replace (gsi_p, gimple_build_nop (), true);
14688 /* Expand code for an OpenMP ordered directive. */
14690 static void
14691 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14693 tree block;
14694 gimple *stmt = gsi_stmt (*gsi_p);
14695 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14696 gcall *x;
14697 gbind *bind;
14698 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14699 OMP_CLAUSE_SIMD);
14700 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14701 OMP_CLAUSE_THREADS);
14703 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14704 OMP_CLAUSE_DEPEND))
14706 /* FIXME: This is needs to be moved to the expansion to verify various
14707 conditions only testable on cfg with dominators computed, and also
14708 all the depend clauses to be merged still might need to be available
14709 for the runtime checks. */
14710 if (0)
14711 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14712 return;
14715 push_gimplify_context ();
14717 block = make_node (BLOCK);
14718 bind = gimple_build_bind (NULL, NULL, block);
14719 gsi_replace (gsi_p, bind, true);
14720 gimple_bind_add_stmt (bind, stmt);
14722 if (simd)
14724 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14725 build_int_cst (NULL_TREE, threads));
14726 cfun->has_simduid_loops = true;
14728 else
14729 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14731 gimple_bind_add_stmt (bind, x);
14733 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14734 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14735 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14736 gimple_omp_set_body (stmt, NULL);
14738 if (simd)
14739 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14740 build_int_cst (NULL_TREE, threads));
14741 else
14742 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14744 gimple_bind_add_stmt (bind, x);
14746 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14748 pop_gimplify_context (bind);
14750 gimple_bind_append_vars (bind, ctx->block_vars);
14751 BLOCK_VARS (block) = gimple_bind_vars (bind);
14755 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14756 substitution of a couple of function calls. But in the NAMED case,
14757 requires that languages coordinate a symbol name. It is therefore
14758 best put here in common code. */
14760 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14762 static void
14763 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14765 tree block;
14766 tree name, lock, unlock;
14767 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14768 gbind *bind;
14769 location_t loc = gimple_location (stmt);
14770 gimple_seq tbody;
14772 name = gimple_omp_critical_name (stmt);
14773 if (name)
14775 tree decl;
14777 if (!critical_name_mutexes)
14778 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14780 tree *n = critical_name_mutexes->get (name);
14781 if (n == NULL)
14783 char *new_str;
14785 decl = create_tmp_var_raw (ptr_type_node);
14787 new_str = ACONCAT ((".gomp_critical_user_",
14788 IDENTIFIER_POINTER (name), NULL));
14789 DECL_NAME (decl) = get_identifier (new_str);
14790 TREE_PUBLIC (decl) = 1;
14791 TREE_STATIC (decl) = 1;
14792 DECL_COMMON (decl) = 1;
14793 DECL_ARTIFICIAL (decl) = 1;
14794 DECL_IGNORED_P (decl) = 1;
14796 varpool_node::finalize_decl (decl);
14798 critical_name_mutexes->put (name, decl);
14800 else
14801 decl = *n;
14803 /* If '#pragma omp critical' is inside offloaded region or
14804 inside function marked as offloadable, the symbol must be
14805 marked as offloadable too. */
14806 omp_context *octx;
14807 if (cgraph_node::get (current_function_decl)->offloadable)
14808 varpool_node::get_create (decl)->offloadable = 1;
14809 else
14810 for (octx = ctx->outer; octx; octx = octx->outer)
14811 if (is_gimple_omp_offloaded (octx->stmt))
14813 varpool_node::get_create (decl)->offloadable = 1;
14814 break;
14817 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14818 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14820 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14821 unlock = build_call_expr_loc (loc, unlock, 1,
14822 build_fold_addr_expr_loc (loc, decl));
14824 else
14826 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14827 lock = build_call_expr_loc (loc, lock, 0);
14829 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14830 unlock = build_call_expr_loc (loc, unlock, 0);
14833 push_gimplify_context ();
14835 block = make_node (BLOCK);
14836 bind = gimple_build_bind (NULL, NULL, block);
14837 gsi_replace (gsi_p, bind, true);
14838 gimple_bind_add_stmt (bind, stmt);
14840 tbody = gimple_bind_body (bind);
14841 gimplify_and_add (lock, &tbody);
14842 gimple_bind_set_body (bind, tbody);
14844 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14845 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14846 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14847 gimple_omp_set_body (stmt, NULL);
14849 tbody = gimple_bind_body (bind);
14850 gimplify_and_add (unlock, &tbody);
14851 gimple_bind_set_body (bind, tbody);
14853 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14855 pop_gimplify_context (bind);
14856 gimple_bind_append_vars (bind, ctx->block_vars);
14857 BLOCK_VARS (block) = gimple_bind_vars (bind);
14861 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14862 for a lastprivate clause. Given a loop control predicate of (V
14863 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14864 is appended to *DLIST, iterator initialization is appended to
14865 *BODY_P. */
14867 static void
14868 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14869 gimple_seq *dlist, struct omp_context *ctx)
14871 tree clauses, cond, vinit;
14872 enum tree_code cond_code;
14873 gimple_seq stmts;
14875 cond_code = fd->loop.cond_code;
14876 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14878 /* When possible, use a strict equality expression. This can let VRP
14879 type optimizations deduce the value and remove a copy. */
14880 if (tree_fits_shwi_p (fd->loop.step))
14882 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14883 if (step == 1 || step == -1)
14884 cond_code = EQ_EXPR;
14887 tree n2 = fd->loop.n2;
14888 if (fd->collapse > 1
14889 && TREE_CODE (n2) != INTEGER_CST
14890 && gimple_omp_for_combined_into_p (fd->for_stmt))
14892 struct omp_context *taskreg_ctx = NULL;
14893 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14895 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14896 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14897 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14899 if (gimple_omp_for_combined_into_p (gfor))
14901 gcc_assert (ctx->outer->outer
14902 && is_parallel_ctx (ctx->outer->outer));
14903 taskreg_ctx = ctx->outer->outer;
14905 else
14907 struct omp_for_data outer_fd;
14908 extract_omp_for_data (gfor, &outer_fd, NULL);
14909 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14912 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14913 taskreg_ctx = ctx->outer->outer;
14915 else if (is_taskreg_ctx (ctx->outer))
14916 taskreg_ctx = ctx->outer;
14917 if (taskreg_ctx)
14919 int i;
14920 tree innerc
14921 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14922 OMP_CLAUSE__LOOPTEMP_);
14923 gcc_assert (innerc);
14924 for (i = 0; i < fd->collapse; i++)
14926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14927 OMP_CLAUSE__LOOPTEMP_);
14928 gcc_assert (innerc);
14930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14931 OMP_CLAUSE__LOOPTEMP_);
14932 if (innerc)
14933 n2 = fold_convert (TREE_TYPE (n2),
14934 lookup_decl (OMP_CLAUSE_DECL (innerc),
14935 taskreg_ctx));
14938 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14940 clauses = gimple_omp_for_clauses (fd->for_stmt);
14941 stmts = NULL;
14942 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14943 if (!gimple_seq_empty_p (stmts))
14945 gimple_seq_add_seq (&stmts, *dlist);
14946 *dlist = stmts;
14948 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14949 vinit = fd->loop.n1;
14950 if (cond_code == EQ_EXPR
14951 && tree_fits_shwi_p (fd->loop.n2)
14952 && ! integer_zerop (fd->loop.n2))
14953 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14954 else
14955 vinit = unshare_expr (vinit);
14957 /* Initialize the iterator variable, so that threads that don't execute
14958 any iterations don't execute the lastprivate clauses by accident. */
14959 gimplify_assign (fd->loop.v, vinit, body_p);
14964 /* Lower code for an OMP loop directive. */
14966 static void
14967 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14969 tree *rhs_p, block;
14970 struct omp_for_data fd, *fdp = NULL;
14971 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14972 gbind *new_stmt;
14973 gimple_seq omp_for_body, body, dlist;
14974 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14975 size_t i;
14977 push_gimplify_context ();
14979 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14981 block = make_node (BLOCK);
14982 new_stmt = gimple_build_bind (NULL, NULL, block);
14983 /* Replace at gsi right away, so that 'stmt' is no member
14984 of a sequence anymore as we're going to add to a different
14985 one below. */
14986 gsi_replace (gsi_p, new_stmt, true);
14988 /* Move declaration of temporaries in the loop body before we make
14989 it go away. */
14990 omp_for_body = gimple_omp_body (stmt);
14991 if (!gimple_seq_empty_p (omp_for_body)
14992 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14994 gbind *inner_bind
14995 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14996 tree vars = gimple_bind_vars (inner_bind);
14997 gimple_bind_append_vars (new_stmt, vars);
14998 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14999 keep them on the inner_bind and it's block. */
15000 gimple_bind_set_vars (inner_bind, NULL_TREE);
15001 if (gimple_bind_block (inner_bind))
15002 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15005 if (gimple_omp_for_combined_into_p (stmt))
15007 extract_omp_for_data (stmt, &fd, NULL);
15008 fdp = &fd;
15010 /* We need two temporaries with fd.loop.v type (istart/iend)
15011 and then (fd.collapse - 1) temporaries with the same
15012 type for count2 ... countN-1 vars if not constant. */
15013 size_t count = 2;
15014 tree type = fd.iter_type;
15015 if (fd.collapse > 1
15016 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15017 count += fd.collapse - 1;
15018 bool taskreg_for
15019 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15020 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15021 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15022 tree clauses = *pc;
15023 if (taskreg_for)
15024 outerc
15025 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15026 OMP_CLAUSE__LOOPTEMP_);
15027 for (i = 0; i < count; i++)
15029 tree temp;
15030 if (taskreg_for)
15032 gcc_assert (outerc);
15033 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15034 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15035 OMP_CLAUSE__LOOPTEMP_);
15037 else
15039 temp = create_tmp_var (type);
15040 insert_decl_map (&ctx->outer->cb, temp, temp);
15042 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15043 OMP_CLAUSE_DECL (*pc) = temp;
15044 pc = &OMP_CLAUSE_CHAIN (*pc);
15046 *pc = clauses;
15049 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15050 dlist = NULL;
15051 body = NULL;
15052 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15053 fdp);
15054 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15056 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15058 /* Lower the header expressions. At this point, we can assume that
15059 the header is of the form:
15061 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15063 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15064 using the .omp_data_s mapping, if needed. */
15065 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15067 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15068 if (!is_gimple_min_invariant (*rhs_p))
15069 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15071 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15072 if (!is_gimple_min_invariant (*rhs_p))
15073 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15075 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15076 if (!is_gimple_min_invariant (*rhs_p))
15077 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15080 /* Once lowered, extract the bounds and clauses. */
15081 extract_omp_for_data (stmt, &fd, NULL);
15083 if (is_gimple_omp_oacc (ctx->stmt)
15084 && !ctx_in_oacc_kernels_region (ctx))
15085 lower_oacc_head_tail (gimple_location (stmt),
15086 gimple_omp_for_clauses (stmt),
15087 &oacc_head, &oacc_tail, ctx);
15089 /* Add OpenACC partitioning and reduction markers just before the loop */
15090 if (oacc_head)
15091 gimple_seq_add_seq (&body, oacc_head);
15093 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15095 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15096 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15097 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15098 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15100 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15101 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15102 OMP_CLAUSE_LINEAR_STEP (c)
15103 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15104 ctx);
15107 if (!gimple_omp_for_grid_phony (stmt))
15108 gimple_seq_add_stmt (&body, stmt);
15109 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15111 if (!gimple_omp_for_grid_phony (stmt))
15112 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15113 fd.loop.v));
15115 /* After the loop, add exit clauses. */
15116 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15118 if (ctx->cancellable)
15119 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15121 gimple_seq_add_seq (&body, dlist);
15123 body = maybe_catch_exception (body);
15125 if (!gimple_omp_for_grid_phony (stmt))
15127 /* Region exit marker goes at the end of the loop body. */
15128 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15129 maybe_add_implicit_barrier_cancel (ctx, &body);
15132 /* Add OpenACC joining and reduction markers just after the loop. */
15133 if (oacc_tail)
15134 gimple_seq_add_seq (&body, oacc_tail);
15136 pop_gimplify_context (new_stmt);
15138 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15139 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15140 if (BLOCK_VARS (block))
15141 TREE_USED (block) = 1;
15143 gimple_bind_set_body (new_stmt, body);
15144 gimple_omp_set_body (stmt, NULL);
15145 gimple_omp_for_set_pre_body (stmt, NULL);
15148 /* Callback for walk_stmts. Check if the current statement only contains
15149 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15151 static tree
15152 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15153 bool *handled_ops_p,
15154 struct walk_stmt_info *wi)
15156 int *info = (int *) wi->info;
15157 gimple *stmt = gsi_stmt (*gsi_p);
15159 *handled_ops_p = true;
15160 switch (gimple_code (stmt))
15162 WALK_SUBSTMTS;
15164 case GIMPLE_OMP_FOR:
15165 case GIMPLE_OMP_SECTIONS:
15166 *info = *info == 0 ? 1 : -1;
15167 break;
15168 default:
15169 *info = -1;
15170 break;
15172 return NULL;
15175 struct omp_taskcopy_context
15177 /* This field must be at the beginning, as we do "inheritance": Some
15178 callback functions for tree-inline.c (e.g., omp_copy_decl)
15179 receive a copy_body_data pointer that is up-casted to an
15180 omp_context pointer. */
15181 copy_body_data cb;
15182 omp_context *ctx;
15185 static tree
15186 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15188 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15190 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15191 return create_tmp_var (TREE_TYPE (var));
15193 return var;
15196 static tree
15197 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15199 tree name, new_fields = NULL, type, f;
15201 type = lang_hooks.types.make_type (RECORD_TYPE);
15202 name = DECL_NAME (TYPE_NAME (orig_type));
15203 name = build_decl (gimple_location (tcctx->ctx->stmt),
15204 TYPE_DECL, name, type);
15205 TYPE_NAME (type) = name;
15207 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15209 tree new_f = copy_node (f);
15210 DECL_CONTEXT (new_f) = type;
15211 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15212 TREE_CHAIN (new_f) = new_fields;
15213 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15214 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15215 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15216 &tcctx->cb, NULL);
15217 new_fields = new_f;
15218 tcctx->cb.decl_map->put (f, new_f);
15220 TYPE_FIELDS (type) = nreverse (new_fields);
15221 layout_type (type);
15222 return type;
15225 /* Create task copyfn. */
15227 static void
15228 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15230 struct function *child_cfun;
15231 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15232 tree record_type, srecord_type, bind, list;
15233 bool record_needs_remap = false, srecord_needs_remap = false;
15234 splay_tree_node n;
15235 struct omp_taskcopy_context tcctx;
15236 location_t loc = gimple_location (task_stmt);
15238 child_fn = gimple_omp_task_copy_fn (task_stmt);
15239 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15240 gcc_assert (child_cfun->cfg == NULL);
15241 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15243 /* Reset DECL_CONTEXT on function arguments. */
15244 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15245 DECL_CONTEXT (t) = child_fn;
15247 /* Populate the function. */
15248 push_gimplify_context ();
15249 push_cfun (child_cfun);
15251 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15252 TREE_SIDE_EFFECTS (bind) = 1;
15253 list = NULL;
15254 DECL_SAVED_TREE (child_fn) = bind;
15255 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15257 /* Remap src and dst argument types if needed. */
15258 record_type = ctx->record_type;
15259 srecord_type = ctx->srecord_type;
15260 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15261 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15263 record_needs_remap = true;
15264 break;
15266 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15267 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15269 srecord_needs_remap = true;
15270 break;
15273 if (record_needs_remap || srecord_needs_remap)
15275 memset (&tcctx, '\0', sizeof (tcctx));
15276 tcctx.cb.src_fn = ctx->cb.src_fn;
15277 tcctx.cb.dst_fn = child_fn;
15278 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15279 gcc_checking_assert (tcctx.cb.src_node);
15280 tcctx.cb.dst_node = tcctx.cb.src_node;
15281 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15282 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15283 tcctx.cb.eh_lp_nr = 0;
15284 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15285 tcctx.cb.decl_map = new hash_map<tree, tree>;
15286 tcctx.ctx = ctx;
15288 if (record_needs_remap)
15289 record_type = task_copyfn_remap_type (&tcctx, record_type);
15290 if (srecord_needs_remap)
15291 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15293 else
15294 tcctx.cb.decl_map = NULL;
15296 arg = DECL_ARGUMENTS (child_fn);
15297 TREE_TYPE (arg) = build_pointer_type (record_type);
15298 sarg = DECL_CHAIN (arg);
15299 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15301 /* First pass: initialize temporaries used in record_type and srecord_type
15302 sizes and field offsets. */
15303 if (tcctx.cb.decl_map)
15304 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15305 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15307 tree *p;
15309 decl = OMP_CLAUSE_DECL (c);
15310 p = tcctx.cb.decl_map->get (decl);
15311 if (p == NULL)
15312 continue;
15313 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15314 sf = (tree) n->value;
15315 sf = *tcctx.cb.decl_map->get (sf);
15316 src = build_simple_mem_ref_loc (loc, sarg);
15317 src = omp_build_component_ref (src, sf);
15318 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15319 append_to_statement_list (t, &list);
15322 /* Second pass: copy shared var pointers and copy construct non-VLA
15323 firstprivate vars. */
15324 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15325 switch (OMP_CLAUSE_CODE (c))
15327 splay_tree_key key;
15328 case OMP_CLAUSE_SHARED:
15329 decl = OMP_CLAUSE_DECL (c);
15330 key = (splay_tree_key) decl;
15331 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15332 key = (splay_tree_key) &DECL_UID (decl);
15333 n = splay_tree_lookup (ctx->field_map, key);
15334 if (n == NULL)
15335 break;
15336 f = (tree) n->value;
15337 if (tcctx.cb.decl_map)
15338 f = *tcctx.cb.decl_map->get (f);
15339 n = splay_tree_lookup (ctx->sfield_map, key);
15340 sf = (tree) n->value;
15341 if (tcctx.cb.decl_map)
15342 sf = *tcctx.cb.decl_map->get (sf);
15343 src = build_simple_mem_ref_loc (loc, sarg);
15344 src = omp_build_component_ref (src, sf);
15345 dst = build_simple_mem_ref_loc (loc, arg);
15346 dst = omp_build_component_ref (dst, f);
15347 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15348 append_to_statement_list (t, &list);
15349 break;
15350 case OMP_CLAUSE_FIRSTPRIVATE:
15351 decl = OMP_CLAUSE_DECL (c);
15352 if (is_variable_sized (decl))
15353 break;
15354 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15355 if (n == NULL)
15356 break;
15357 f = (tree) n->value;
15358 if (tcctx.cb.decl_map)
15359 f = *tcctx.cb.decl_map->get (f);
15360 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15361 if (n != NULL)
15363 sf = (tree) n->value;
15364 if (tcctx.cb.decl_map)
15365 sf = *tcctx.cb.decl_map->get (sf);
15366 src = build_simple_mem_ref_loc (loc, sarg);
15367 src = omp_build_component_ref (src, sf);
15368 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15369 src = build_simple_mem_ref_loc (loc, src);
15371 else
15372 src = decl;
15373 dst = build_simple_mem_ref_loc (loc, arg);
15374 dst = omp_build_component_ref (dst, f);
15375 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15376 append_to_statement_list (t, &list);
15377 break;
15378 case OMP_CLAUSE_PRIVATE:
15379 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15380 break;
15381 decl = OMP_CLAUSE_DECL (c);
15382 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15383 f = (tree) n->value;
15384 if (tcctx.cb.decl_map)
15385 f = *tcctx.cb.decl_map->get (f);
15386 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15387 if (n != NULL)
15389 sf = (tree) n->value;
15390 if (tcctx.cb.decl_map)
15391 sf = *tcctx.cb.decl_map->get (sf);
15392 src = build_simple_mem_ref_loc (loc, sarg);
15393 src = omp_build_component_ref (src, sf);
15394 if (use_pointer_for_field (decl, NULL))
15395 src = build_simple_mem_ref_loc (loc, src);
15397 else
15398 src = decl;
15399 dst = build_simple_mem_ref_loc (loc, arg);
15400 dst = omp_build_component_ref (dst, f);
15401 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15402 append_to_statement_list (t, &list);
15403 break;
15404 default:
15405 break;
15408 /* Last pass: handle VLA firstprivates. */
15409 if (tcctx.cb.decl_map)
15410 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15413 tree ind, ptr, df;
15415 decl = OMP_CLAUSE_DECL (c);
15416 if (!is_variable_sized (decl))
15417 continue;
15418 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15419 if (n == NULL)
15420 continue;
15421 f = (tree) n->value;
15422 f = *tcctx.cb.decl_map->get (f);
15423 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15424 ind = DECL_VALUE_EXPR (decl);
15425 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15426 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15427 n = splay_tree_lookup (ctx->sfield_map,
15428 (splay_tree_key) TREE_OPERAND (ind, 0));
15429 sf = (tree) n->value;
15430 sf = *tcctx.cb.decl_map->get (sf);
15431 src = build_simple_mem_ref_loc (loc, sarg);
15432 src = omp_build_component_ref (src, sf);
15433 src = build_simple_mem_ref_loc (loc, src);
15434 dst = build_simple_mem_ref_loc (loc, arg);
15435 dst = omp_build_component_ref (dst, f);
15436 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15437 append_to_statement_list (t, &list);
15438 n = splay_tree_lookup (ctx->field_map,
15439 (splay_tree_key) TREE_OPERAND (ind, 0));
15440 df = (tree) n->value;
15441 df = *tcctx.cb.decl_map->get (df);
15442 ptr = build_simple_mem_ref_loc (loc, arg);
15443 ptr = omp_build_component_ref (ptr, df);
15444 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15445 build_fold_addr_expr_loc (loc, dst));
15446 append_to_statement_list (t, &list);
15449 t = build1 (RETURN_EXPR, void_type_node, NULL);
15450 append_to_statement_list (t, &list);
15452 if (tcctx.cb.decl_map)
15453 delete tcctx.cb.decl_map;
15454 pop_gimplify_context (NULL);
15455 BIND_EXPR_BODY (bind) = list;
15456 pop_cfun ();
15459 static void
15460 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15462 tree c, clauses;
15463 gimple *g;
15464 size_t n_in = 0, n_out = 0, idx = 2, i;
15466 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15467 gcc_assert (clauses);
15468 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15470 switch (OMP_CLAUSE_DEPEND_KIND (c))
15472 case OMP_CLAUSE_DEPEND_IN:
15473 n_in++;
15474 break;
15475 case OMP_CLAUSE_DEPEND_OUT:
15476 case OMP_CLAUSE_DEPEND_INOUT:
15477 n_out++;
15478 break;
15479 case OMP_CLAUSE_DEPEND_SOURCE:
15480 case OMP_CLAUSE_DEPEND_SINK:
15481 /* FALLTHRU */
15482 default:
15483 gcc_unreachable ();
15485 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15486 tree array = create_tmp_var (type);
15487 TREE_ADDRESSABLE (array) = 1;
15488 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15489 NULL_TREE);
15490 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15491 gimple_seq_add_stmt (iseq, g);
15492 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15493 NULL_TREE);
15494 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15495 gimple_seq_add_stmt (iseq, g);
15496 for (i = 0; i < 2; i++)
15498 if ((i ? n_in : n_out) == 0)
15499 continue;
15500 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15501 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15502 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15504 tree t = OMP_CLAUSE_DECL (c);
15505 t = fold_convert (ptr_type_node, t);
15506 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15507 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15508 NULL_TREE, NULL_TREE);
15509 g = gimple_build_assign (r, t);
15510 gimple_seq_add_stmt (iseq, g);
15513 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15514 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15515 OMP_CLAUSE_CHAIN (c) = *pclauses;
15516 *pclauses = c;
15517 tree clobber = build_constructor (type, NULL);
15518 TREE_THIS_VOLATILE (clobber) = 1;
15519 g = gimple_build_assign (array, clobber);
15520 gimple_seq_add_stmt (oseq, g);
15523 /* Lower the OpenMP parallel or task directive in the current statement
15524 in GSI_P. CTX holds context information for the directive. */
15526 static void
15527 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15529 tree clauses;
15530 tree child_fn, t;
15531 gimple *stmt = gsi_stmt (*gsi_p);
15532 gbind *par_bind, *bind, *dep_bind = NULL;
15533 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15534 location_t loc = gimple_location (stmt);
15536 clauses = gimple_omp_taskreg_clauses (stmt);
15537 par_bind
15538 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15539 par_body = gimple_bind_body (par_bind);
15540 child_fn = ctx->cb.dst_fn;
15541 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15542 && !gimple_omp_parallel_combined_p (stmt))
15544 struct walk_stmt_info wi;
15545 int ws_num = 0;
15547 memset (&wi, 0, sizeof (wi));
15548 wi.info = &ws_num;
15549 wi.val_only = true;
15550 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15551 if (ws_num == 1)
15552 gimple_omp_parallel_set_combined_p (stmt, true);
15554 gimple_seq dep_ilist = NULL;
15555 gimple_seq dep_olist = NULL;
15556 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15557 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15559 push_gimplify_context ();
15560 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15561 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15562 &dep_ilist, &dep_olist);
15565 if (ctx->srecord_type)
15566 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15568 push_gimplify_context ();
15570 par_olist = NULL;
15571 par_ilist = NULL;
15572 par_rlist = NULL;
15573 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15574 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15575 if (phony_construct && ctx->record_type)
15577 gcc_checking_assert (!ctx->receiver_decl);
15578 ctx->receiver_decl = create_tmp_var
15579 (build_reference_type (ctx->record_type), ".omp_rec");
15581 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15582 lower_omp (&par_body, ctx);
15583 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15584 lower_reduction_clauses (clauses, &par_rlist, ctx);
15586 /* Declare all the variables created by mapping and the variables
15587 declared in the scope of the parallel body. */
15588 record_vars_into (ctx->block_vars, child_fn);
15589 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15591 if (ctx->record_type)
15593 ctx->sender_decl
15594 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15595 : ctx->record_type, ".omp_data_o");
15596 DECL_NAMELESS (ctx->sender_decl) = 1;
15597 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15598 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15601 olist = NULL;
15602 ilist = NULL;
15603 lower_send_clauses (clauses, &ilist, &olist, ctx);
15604 lower_send_shared_vars (&ilist, &olist, ctx);
15606 if (ctx->record_type)
15608 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15609 TREE_THIS_VOLATILE (clobber) = 1;
15610 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15611 clobber));
15614 /* Once all the expansions are done, sequence all the different
15615 fragments inside gimple_omp_body. */
15617 new_body = NULL;
15619 if (ctx->record_type)
15621 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15622 /* fixup_child_record_type might have changed receiver_decl's type. */
15623 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15624 gimple_seq_add_stmt (&new_body,
15625 gimple_build_assign (ctx->receiver_decl, t));
15628 gimple_seq_add_seq (&new_body, par_ilist);
15629 gimple_seq_add_seq (&new_body, par_body);
15630 gimple_seq_add_seq (&new_body, par_rlist);
15631 if (ctx->cancellable)
15632 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15633 gimple_seq_add_seq (&new_body, par_olist);
15634 new_body = maybe_catch_exception (new_body);
15635 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15636 gimple_seq_add_stmt (&new_body,
15637 gimple_build_omp_continue (integer_zero_node,
15638 integer_zero_node));
15639 if (!phony_construct)
15641 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15642 gimple_omp_set_body (stmt, new_body);
15645 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15646 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15647 gimple_bind_add_seq (bind, ilist);
15648 if (!phony_construct)
15649 gimple_bind_add_stmt (bind, stmt);
15650 else
15651 gimple_bind_add_seq (bind, new_body);
15652 gimple_bind_add_seq (bind, olist);
15654 pop_gimplify_context (NULL);
15656 if (dep_bind)
15658 gimple_bind_add_seq (dep_bind, dep_ilist);
15659 gimple_bind_add_stmt (dep_bind, bind);
15660 gimple_bind_add_seq (dep_bind, dep_olist);
15661 pop_gimplify_context (dep_bind);
15665 /* Lower the GIMPLE_OMP_TARGET in the current statement
15666 in GSI_P. CTX holds context information for the directive. */
15668 static void
15669 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15671 tree clauses;
15672 tree child_fn, t, c;
15673 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15674 gbind *tgt_bind, *bind, *dep_bind = NULL;
15675 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15676 location_t loc = gimple_location (stmt);
15677 bool offloaded, data_region;
15678 unsigned int map_cnt = 0;
15679 bool has_depend = false;
15681 offloaded = is_gimple_omp_offloaded (stmt);
15682 switch (gimple_omp_target_kind (stmt))
15684 case GF_OMP_TARGET_KIND_REGION:
15685 case GF_OMP_TARGET_KIND_UPDATE:
15686 case GF_OMP_TARGET_KIND_ENTER_DATA:
15687 case GF_OMP_TARGET_KIND_EXIT_DATA:
15688 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15689 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15690 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15691 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15692 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15693 data_region = false;
15694 break;
15695 case GF_OMP_TARGET_KIND_DATA:
15696 case GF_OMP_TARGET_KIND_OACC_DATA:
15697 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15698 data_region = true;
15699 break;
15700 default:
15701 gcc_unreachable ();
15704 clauses = gimple_omp_target_clauses (stmt);
15706 gimple_seq dep_ilist = NULL;
15707 gimple_seq dep_olist = NULL;
15708 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15710 push_gimplify_context ();
15711 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15712 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15713 &dep_ilist, &dep_olist);
15714 has_depend = true;
15717 tgt_bind = NULL;
15718 tgt_body = NULL;
15719 if (offloaded)
15721 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15722 tgt_body = gimple_bind_body (tgt_bind);
15724 else if (data_region)
15725 tgt_body = gimple_omp_body (stmt);
15726 child_fn = ctx->cb.dst_fn;
15728 push_gimplify_context ();
15729 fplist = NULL;
15731 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15732 switch (OMP_CLAUSE_CODE (c))
15734 tree var, x;
15736 default:
15737 break;
15738 case OMP_CLAUSE_MAP:
15739 #if CHECKING_P
15740 /* First check what we're prepared to handle in the following. */
15741 switch (OMP_CLAUSE_MAP_KIND (c))
15743 case GOMP_MAP_ALLOC:
15744 case GOMP_MAP_TO:
15745 case GOMP_MAP_FROM:
15746 case GOMP_MAP_TOFROM:
15747 case GOMP_MAP_POINTER:
15748 case GOMP_MAP_TO_PSET:
15749 case GOMP_MAP_FORCE_DEALLOC:
15750 case GOMP_MAP_RELEASE:
15751 case GOMP_MAP_ALWAYS_TO:
15752 case GOMP_MAP_ALWAYS_FROM:
15753 case GOMP_MAP_ALWAYS_TOFROM:
15754 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15755 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15756 case GOMP_MAP_STRUCT:
15757 case GOMP_MAP_ALWAYS_POINTER:
15758 break;
15759 case GOMP_MAP_FORCE_ALLOC:
15760 case GOMP_MAP_FORCE_TO:
15761 case GOMP_MAP_FORCE_FROM:
15762 case GOMP_MAP_FORCE_TOFROM:
15763 case GOMP_MAP_FORCE_PRESENT:
15764 case GOMP_MAP_FORCE_DEVICEPTR:
15765 case GOMP_MAP_DEVICE_RESIDENT:
15766 case GOMP_MAP_LINK:
15767 gcc_assert (is_gimple_omp_oacc (stmt));
15768 break;
15769 default:
15770 gcc_unreachable ();
15772 #endif
15773 /* FALLTHRU */
15774 case OMP_CLAUSE_TO:
15775 case OMP_CLAUSE_FROM:
15776 oacc_firstprivate:
15777 var = OMP_CLAUSE_DECL (c);
15778 if (!DECL_P (var))
15780 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15781 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15782 && (OMP_CLAUSE_MAP_KIND (c)
15783 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15784 map_cnt++;
15785 continue;
15788 if (DECL_SIZE (var)
15789 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15791 tree var2 = DECL_VALUE_EXPR (var);
15792 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15793 var2 = TREE_OPERAND (var2, 0);
15794 gcc_assert (DECL_P (var2));
15795 var = var2;
15798 if (offloaded
15799 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15800 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15801 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15803 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15805 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15806 && varpool_node::get_create (var)->offloadable)
15807 continue;
15809 tree type = build_pointer_type (TREE_TYPE (var));
15810 tree new_var = lookup_decl (var, ctx);
15811 x = create_tmp_var_raw (type, get_name (new_var));
15812 gimple_add_tmp_var (x);
15813 x = build_simple_mem_ref (x);
15814 SET_DECL_VALUE_EXPR (new_var, x);
15815 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15817 continue;
15820 if (!maybe_lookup_field (var, ctx))
15821 continue;
15823 if (offloaded)
15825 x = build_receiver_ref (var, true, ctx);
15826 tree new_var = lookup_decl (var, ctx);
15828 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15829 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15830 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15831 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15832 x = build_simple_mem_ref (x);
15833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15835 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15836 if (is_reference (new_var))
15838 /* Create a local object to hold the instance
15839 value. */
15840 tree type = TREE_TYPE (TREE_TYPE (new_var));
15841 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15842 tree inst = create_tmp_var (type, id);
15843 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15844 x = build_fold_addr_expr (inst);
15846 gimplify_assign (new_var, x, &fplist);
15848 else if (DECL_P (new_var))
15850 SET_DECL_VALUE_EXPR (new_var, x);
15851 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15853 else
15854 gcc_unreachable ();
15856 map_cnt++;
15857 break;
15859 case OMP_CLAUSE_FIRSTPRIVATE:
15860 if (is_oacc_parallel (ctx))
15861 goto oacc_firstprivate;
15862 map_cnt++;
15863 var = OMP_CLAUSE_DECL (c);
15864 if (!is_reference (var)
15865 && !is_gimple_reg_type (TREE_TYPE (var)))
15867 tree new_var = lookup_decl (var, ctx);
15868 if (is_variable_sized (var))
15870 tree pvar = DECL_VALUE_EXPR (var);
15871 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15872 pvar = TREE_OPERAND (pvar, 0);
15873 gcc_assert (DECL_P (pvar));
15874 tree new_pvar = lookup_decl (pvar, ctx);
15875 x = build_fold_indirect_ref (new_pvar);
15876 TREE_THIS_NOTRAP (x) = 1;
15878 else
15879 x = build_receiver_ref (var, true, ctx);
15880 SET_DECL_VALUE_EXPR (new_var, x);
15881 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15883 break;
15885 case OMP_CLAUSE_PRIVATE:
15886 if (is_gimple_omp_oacc (ctx->stmt))
15887 break;
15888 var = OMP_CLAUSE_DECL (c);
15889 if (is_variable_sized (var))
15891 tree new_var = lookup_decl (var, ctx);
15892 tree pvar = DECL_VALUE_EXPR (var);
15893 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15894 pvar = TREE_OPERAND (pvar, 0);
15895 gcc_assert (DECL_P (pvar));
15896 tree new_pvar = lookup_decl (pvar, ctx);
15897 x = build_fold_indirect_ref (new_pvar);
15898 TREE_THIS_NOTRAP (x) = 1;
15899 SET_DECL_VALUE_EXPR (new_var, x);
15900 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15902 break;
15904 case OMP_CLAUSE_USE_DEVICE_PTR:
15905 case OMP_CLAUSE_IS_DEVICE_PTR:
15906 var = OMP_CLAUSE_DECL (c);
15907 map_cnt++;
15908 if (is_variable_sized (var))
15910 tree new_var = lookup_decl (var, ctx);
15911 tree pvar = DECL_VALUE_EXPR (var);
15912 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15913 pvar = TREE_OPERAND (pvar, 0);
15914 gcc_assert (DECL_P (pvar));
15915 tree new_pvar = lookup_decl (pvar, ctx);
15916 x = build_fold_indirect_ref (new_pvar);
15917 TREE_THIS_NOTRAP (x) = 1;
15918 SET_DECL_VALUE_EXPR (new_var, x);
15919 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15921 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15923 tree new_var = lookup_decl (var, ctx);
15924 tree type = build_pointer_type (TREE_TYPE (var));
15925 x = create_tmp_var_raw (type, get_name (new_var));
15926 gimple_add_tmp_var (x);
15927 x = build_simple_mem_ref (x);
15928 SET_DECL_VALUE_EXPR (new_var, x);
15929 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15931 else
15933 tree new_var = lookup_decl (var, ctx);
15934 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15935 gimple_add_tmp_var (x);
15936 SET_DECL_VALUE_EXPR (new_var, x);
15937 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15939 break;
15942 if (offloaded)
15944 target_nesting_level++;
15945 lower_omp (&tgt_body, ctx);
15946 target_nesting_level--;
15948 else if (data_region)
15949 lower_omp (&tgt_body, ctx);
15951 if (offloaded)
15953 /* Declare all the variables created by mapping and the variables
15954 declared in the scope of the target body. */
15955 record_vars_into (ctx->block_vars, child_fn);
15956 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15959 olist = NULL;
15960 ilist = NULL;
15961 if (ctx->record_type)
15963 ctx->sender_decl
15964 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15965 DECL_NAMELESS (ctx->sender_decl) = 1;
15966 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15967 t = make_tree_vec (3);
15968 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15969 TREE_VEC_ELT (t, 1)
15970 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15971 ".omp_data_sizes");
15972 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15973 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15974 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15975 tree tkind_type = short_unsigned_type_node;
15976 int talign_shift = 8;
15977 TREE_VEC_ELT (t, 2)
15978 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15979 ".omp_data_kinds");
15980 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15981 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15982 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15983 gimple_omp_target_set_data_arg (stmt, t);
15985 vec<constructor_elt, va_gc> *vsize;
15986 vec<constructor_elt, va_gc> *vkind;
15987 vec_alloc (vsize, map_cnt);
15988 vec_alloc (vkind, map_cnt);
15989 unsigned int map_idx = 0;
15991 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15992 switch (OMP_CLAUSE_CODE (c))
15994 tree ovar, nc, s, purpose, var, x, type;
15995 unsigned int talign;
15997 default:
15998 break;
16000 case OMP_CLAUSE_MAP:
16001 case OMP_CLAUSE_TO:
16002 case OMP_CLAUSE_FROM:
16003 oacc_firstprivate_map:
16004 nc = c;
16005 ovar = OMP_CLAUSE_DECL (c);
16006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16007 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16008 || (OMP_CLAUSE_MAP_KIND (c)
16009 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16010 break;
16011 if (!DECL_P (ovar))
16013 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16014 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16016 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16017 == get_base_address (ovar));
16018 nc = OMP_CLAUSE_CHAIN (c);
16019 ovar = OMP_CLAUSE_DECL (nc);
16021 else
16023 tree x = build_sender_ref (ovar, ctx);
16024 tree v
16025 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16026 gimplify_assign (x, v, &ilist);
16027 nc = NULL_TREE;
16030 else
16032 if (DECL_SIZE (ovar)
16033 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16035 tree ovar2 = DECL_VALUE_EXPR (ovar);
16036 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16037 ovar2 = TREE_OPERAND (ovar2, 0);
16038 gcc_assert (DECL_P (ovar2));
16039 ovar = ovar2;
16041 if (!maybe_lookup_field (ovar, ctx))
16042 continue;
16045 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16046 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16047 talign = DECL_ALIGN_UNIT (ovar);
16048 if (nc)
16050 var = lookup_decl_in_outer_ctx (ovar, ctx);
16051 x = build_sender_ref (ovar, ctx);
16053 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16054 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16055 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16056 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16058 gcc_assert (offloaded);
16059 tree avar
16060 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16061 mark_addressable (avar);
16062 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16063 talign = DECL_ALIGN_UNIT (avar);
16064 avar = build_fold_addr_expr (avar);
16065 gimplify_assign (x, avar, &ilist);
16067 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16069 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16070 if (!is_reference (var))
16071 var = build_fold_addr_expr (var);
16072 else
16073 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16074 gimplify_assign (x, var, &ilist);
16076 else if (is_gimple_reg (var))
16078 gcc_assert (offloaded);
16079 tree avar = create_tmp_var (TREE_TYPE (var));
16080 mark_addressable (avar);
16081 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16082 if (GOMP_MAP_COPY_TO_P (map_kind)
16083 || map_kind == GOMP_MAP_POINTER
16084 || map_kind == GOMP_MAP_TO_PSET
16085 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16086 gimplify_assign (avar, var, &ilist);
16087 avar = build_fold_addr_expr (avar);
16088 gimplify_assign (x, avar, &ilist);
16089 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16090 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16091 && !TYPE_READONLY (TREE_TYPE (var)))
16093 x = unshare_expr (x);
16094 x = build_simple_mem_ref (x);
16095 gimplify_assign (var, x, &olist);
16098 else
16100 var = build_fold_addr_expr (var);
16101 gimplify_assign (x, var, &ilist);
16104 s = NULL_TREE;
16105 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16107 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16108 s = TREE_TYPE (ovar);
16109 if (TREE_CODE (s) == REFERENCE_TYPE)
16110 s = TREE_TYPE (s);
16111 s = TYPE_SIZE_UNIT (s);
16113 else
16114 s = OMP_CLAUSE_SIZE (c);
16115 if (s == NULL_TREE)
16116 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16117 s = fold_convert (size_type_node, s);
16118 purpose = size_int (map_idx++);
16119 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16120 if (TREE_CODE (s) != INTEGER_CST)
16121 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16123 unsigned HOST_WIDE_INT tkind, tkind_zero;
16124 switch (OMP_CLAUSE_CODE (c))
16126 case OMP_CLAUSE_MAP:
16127 tkind = OMP_CLAUSE_MAP_KIND (c);
16128 tkind_zero = tkind;
16129 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16130 switch (tkind)
16132 case GOMP_MAP_ALLOC:
16133 case GOMP_MAP_TO:
16134 case GOMP_MAP_FROM:
16135 case GOMP_MAP_TOFROM:
16136 case GOMP_MAP_ALWAYS_TO:
16137 case GOMP_MAP_ALWAYS_FROM:
16138 case GOMP_MAP_ALWAYS_TOFROM:
16139 case GOMP_MAP_RELEASE:
16140 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16141 break;
16142 case GOMP_MAP_DELETE:
16143 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16144 default:
16145 break;
16147 if (tkind_zero != tkind)
16149 if (integer_zerop (s))
16150 tkind = tkind_zero;
16151 else if (integer_nonzerop (s))
16152 tkind_zero = tkind;
16154 break;
16155 case OMP_CLAUSE_FIRSTPRIVATE:
16156 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16157 tkind = GOMP_MAP_TO;
16158 tkind_zero = tkind;
16159 break;
16160 case OMP_CLAUSE_TO:
16161 tkind = GOMP_MAP_TO;
16162 tkind_zero = tkind;
16163 break;
16164 case OMP_CLAUSE_FROM:
16165 tkind = GOMP_MAP_FROM;
16166 tkind_zero = tkind;
16167 break;
16168 default:
16169 gcc_unreachable ();
16171 gcc_checking_assert (tkind
16172 < (HOST_WIDE_INT_C (1U) << talign_shift));
16173 gcc_checking_assert (tkind_zero
16174 < (HOST_WIDE_INT_C (1U) << talign_shift));
16175 talign = ceil_log2 (talign);
16176 tkind |= talign << talign_shift;
16177 tkind_zero |= talign << talign_shift;
16178 gcc_checking_assert (tkind
16179 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16180 gcc_checking_assert (tkind_zero
16181 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16182 if (tkind == tkind_zero)
16183 x = build_int_cstu (tkind_type, tkind);
16184 else
16186 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16187 x = build3 (COND_EXPR, tkind_type,
16188 fold_build2 (EQ_EXPR, boolean_type_node,
16189 unshare_expr (s), size_zero_node),
16190 build_int_cstu (tkind_type, tkind_zero),
16191 build_int_cstu (tkind_type, tkind));
16193 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16194 if (nc && nc != c)
16195 c = nc;
16196 break;
16198 case OMP_CLAUSE_FIRSTPRIVATE:
16199 if (is_oacc_parallel (ctx))
16200 goto oacc_firstprivate_map;
16201 ovar = OMP_CLAUSE_DECL (c);
16202 if (is_reference (ovar))
16203 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16204 else
16205 talign = DECL_ALIGN_UNIT (ovar);
16206 var = lookup_decl_in_outer_ctx (ovar, ctx);
16207 x = build_sender_ref (ovar, ctx);
16208 tkind = GOMP_MAP_FIRSTPRIVATE;
16209 type = TREE_TYPE (ovar);
16210 if (is_reference (ovar))
16211 type = TREE_TYPE (type);
16212 bool use_firstprivate_int, force_addr;
16213 use_firstprivate_int = false;
16214 force_addr = false;
16215 if ((INTEGRAL_TYPE_P (type)
16216 && TYPE_PRECISION (type) <= POINTER_SIZE)
16217 || TREE_CODE (type) == POINTER_TYPE)
16218 use_firstprivate_int = true;
16219 if (has_depend)
16221 if (is_reference (var))
16222 use_firstprivate_int = false;
16223 else if (is_gimple_reg (var))
16225 if (DECL_HAS_VALUE_EXPR_P (var))
16227 tree v = get_base_address (var);
16228 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16230 use_firstprivate_int = false;
16231 force_addr = true;
16233 else
16234 switch (TREE_CODE (v))
16236 case INDIRECT_REF:
16237 case MEM_REF:
16238 use_firstprivate_int = false;
16239 force_addr = true;
16240 break;
16241 default:
16242 break;
16246 else
16247 use_firstprivate_int = false;
16249 if (use_firstprivate_int)
16251 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16252 tree t = var;
16253 if (is_reference (var))
16254 t = build_simple_mem_ref (var);
16255 if (TREE_CODE (type) != POINTER_TYPE)
16256 t = fold_convert (pointer_sized_int_node, t);
16257 t = fold_convert (TREE_TYPE (x), t);
16258 gimplify_assign (x, t, &ilist);
16260 else if (is_reference (var))
16261 gimplify_assign (x, var, &ilist);
16262 else if (!force_addr && is_gimple_reg (var))
16264 tree avar = create_tmp_var (TREE_TYPE (var));
16265 mark_addressable (avar);
16266 gimplify_assign (avar, var, &ilist);
16267 avar = build_fold_addr_expr (avar);
16268 gimplify_assign (x, avar, &ilist);
16270 else
16272 var = build_fold_addr_expr (var);
16273 gimplify_assign (x, var, &ilist);
16275 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16276 s = size_int (0);
16277 else if (is_reference (var))
16278 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16279 else
16280 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16281 s = fold_convert (size_type_node, s);
16282 purpose = size_int (map_idx++);
16283 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16284 if (TREE_CODE (s) != INTEGER_CST)
16285 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16287 gcc_checking_assert (tkind
16288 < (HOST_WIDE_INT_C (1U) << talign_shift));
16289 talign = ceil_log2 (talign);
16290 tkind |= talign << talign_shift;
16291 gcc_checking_assert (tkind
16292 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16293 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16294 build_int_cstu (tkind_type, tkind));
16295 break;
16297 case OMP_CLAUSE_USE_DEVICE_PTR:
16298 case OMP_CLAUSE_IS_DEVICE_PTR:
16299 ovar = OMP_CLAUSE_DECL (c);
16300 var = lookup_decl_in_outer_ctx (ovar, ctx);
16301 x = build_sender_ref (ovar, ctx);
16302 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16303 tkind = GOMP_MAP_USE_DEVICE_PTR;
16304 else
16305 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16306 type = TREE_TYPE (ovar);
16307 if (TREE_CODE (type) == ARRAY_TYPE)
16308 var = build_fold_addr_expr (var);
16309 else
16311 if (is_reference (ovar))
16313 type = TREE_TYPE (type);
16314 if (TREE_CODE (type) != ARRAY_TYPE)
16315 var = build_simple_mem_ref (var);
16316 var = fold_convert (TREE_TYPE (x), var);
16319 gimplify_assign (x, var, &ilist);
16320 s = size_int (0);
16321 purpose = size_int (map_idx++);
16322 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16323 gcc_checking_assert (tkind
16324 < (HOST_WIDE_INT_C (1U) << talign_shift));
16325 gcc_checking_assert (tkind
16326 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16327 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16328 build_int_cstu (tkind_type, tkind));
16329 break;
16332 gcc_assert (map_idx == map_cnt);
16334 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16335 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16336 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16337 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16338 for (int i = 1; i <= 2; i++)
16339 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16341 gimple_seq initlist = NULL;
16342 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16343 TREE_VEC_ELT (t, i)),
16344 &initlist, true, NULL_TREE);
16345 gimple_seq_add_seq (&ilist, initlist);
16347 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16348 NULL);
16349 TREE_THIS_VOLATILE (clobber) = 1;
16350 gimple_seq_add_stmt (&olist,
16351 gimple_build_assign (TREE_VEC_ELT (t, i),
16352 clobber));
16355 tree clobber = build_constructor (ctx->record_type, NULL);
16356 TREE_THIS_VOLATILE (clobber) = 1;
16357 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16358 clobber));
16361 /* Once all the expansions are done, sequence all the different
16362 fragments inside gimple_omp_body. */
16364 new_body = NULL;
16366 if (offloaded
16367 && ctx->record_type)
16369 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16370 /* fixup_child_record_type might have changed receiver_decl's type. */
16371 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16372 gimple_seq_add_stmt (&new_body,
16373 gimple_build_assign (ctx->receiver_decl, t));
16375 gimple_seq_add_seq (&new_body, fplist);
16377 if (offloaded || data_region)
16379 tree prev = NULL_TREE;
16380 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16381 switch (OMP_CLAUSE_CODE (c))
16383 tree var, x;
16384 default:
16385 break;
16386 case OMP_CLAUSE_FIRSTPRIVATE:
16387 if (is_gimple_omp_oacc (ctx->stmt))
16388 break;
16389 var = OMP_CLAUSE_DECL (c);
16390 if (is_reference (var)
16391 || is_gimple_reg_type (TREE_TYPE (var)))
16393 tree new_var = lookup_decl (var, ctx);
16394 tree type;
16395 type = TREE_TYPE (var);
16396 if (is_reference (var))
16397 type = TREE_TYPE (type);
16398 bool use_firstprivate_int;
16399 use_firstprivate_int = false;
16400 if ((INTEGRAL_TYPE_P (type)
16401 && TYPE_PRECISION (type) <= POINTER_SIZE)
16402 || TREE_CODE (type) == POINTER_TYPE)
16403 use_firstprivate_int = true;
16404 if (has_depend)
16406 tree v = lookup_decl_in_outer_ctx (var, ctx);
16407 if (is_reference (v))
16408 use_firstprivate_int = false;
16409 else if (is_gimple_reg (v))
16411 if (DECL_HAS_VALUE_EXPR_P (v))
16413 v = get_base_address (v);
16414 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16415 use_firstprivate_int = false;
16416 else
16417 switch (TREE_CODE (v))
16419 case INDIRECT_REF:
16420 case MEM_REF:
16421 use_firstprivate_int = false;
16422 break;
16423 default:
16424 break;
16428 else
16429 use_firstprivate_int = false;
16431 if (use_firstprivate_int)
16433 x = build_receiver_ref (var, false, ctx);
16434 if (TREE_CODE (type) != POINTER_TYPE)
16435 x = fold_convert (pointer_sized_int_node, x);
16436 x = fold_convert (type, x);
16437 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16438 fb_rvalue);
16439 if (is_reference (var))
16441 tree v = create_tmp_var_raw (type, get_name (var));
16442 gimple_add_tmp_var (v);
16443 TREE_ADDRESSABLE (v) = 1;
16444 gimple_seq_add_stmt (&new_body,
16445 gimple_build_assign (v, x));
16446 x = build_fold_addr_expr (v);
16448 gimple_seq_add_stmt (&new_body,
16449 gimple_build_assign (new_var, x));
16451 else
16453 x = build_receiver_ref (var, !is_reference (var), ctx);
16454 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16455 fb_rvalue);
16456 gimple_seq_add_stmt (&new_body,
16457 gimple_build_assign (new_var, x));
16460 else if (is_variable_sized (var))
16462 tree pvar = DECL_VALUE_EXPR (var);
16463 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16464 pvar = TREE_OPERAND (pvar, 0);
16465 gcc_assert (DECL_P (pvar));
16466 tree new_var = lookup_decl (pvar, ctx);
16467 x = build_receiver_ref (var, false, ctx);
16468 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16469 gimple_seq_add_stmt (&new_body,
16470 gimple_build_assign (new_var, x));
16472 break;
16473 case OMP_CLAUSE_PRIVATE:
16474 if (is_gimple_omp_oacc (ctx->stmt))
16475 break;
16476 var = OMP_CLAUSE_DECL (c);
16477 if (is_reference (var))
16479 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16480 tree new_var = lookup_decl (var, ctx);
16481 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16482 if (TREE_CONSTANT (x))
16484 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16485 get_name (var));
16486 gimple_add_tmp_var (x);
16487 TREE_ADDRESSABLE (x) = 1;
16488 x = build_fold_addr_expr_loc (clause_loc, x);
16490 else
16491 break;
16493 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16494 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16495 gimple_seq_add_stmt (&new_body,
16496 gimple_build_assign (new_var, x));
16498 break;
16499 case OMP_CLAUSE_USE_DEVICE_PTR:
16500 case OMP_CLAUSE_IS_DEVICE_PTR:
16501 var = OMP_CLAUSE_DECL (c);
16502 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16503 x = build_sender_ref (var, ctx);
16504 else
16505 x = build_receiver_ref (var, false, ctx);
16506 if (is_variable_sized (var))
16508 tree pvar = DECL_VALUE_EXPR (var);
16509 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16510 pvar = TREE_OPERAND (pvar, 0);
16511 gcc_assert (DECL_P (pvar));
16512 tree new_var = lookup_decl (pvar, ctx);
16513 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16514 gimple_seq_add_stmt (&new_body,
16515 gimple_build_assign (new_var, x));
16517 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16519 tree new_var = lookup_decl (var, ctx);
16520 new_var = DECL_VALUE_EXPR (new_var);
16521 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16522 new_var = TREE_OPERAND (new_var, 0);
16523 gcc_assert (DECL_P (new_var));
16524 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16525 gimple_seq_add_stmt (&new_body,
16526 gimple_build_assign (new_var, x));
16528 else
16530 tree type = TREE_TYPE (var);
16531 tree new_var = lookup_decl (var, ctx);
16532 if (is_reference (var))
16534 type = TREE_TYPE (type);
16535 if (TREE_CODE (type) != ARRAY_TYPE)
16537 tree v = create_tmp_var_raw (type, get_name (var));
16538 gimple_add_tmp_var (v);
16539 TREE_ADDRESSABLE (v) = 1;
16540 x = fold_convert (type, x);
16541 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16542 fb_rvalue);
16543 gimple_seq_add_stmt (&new_body,
16544 gimple_build_assign (v, x));
16545 x = build_fold_addr_expr (v);
16548 new_var = DECL_VALUE_EXPR (new_var);
16549 x = fold_convert (TREE_TYPE (new_var), x);
16550 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16551 gimple_seq_add_stmt (&new_body,
16552 gimple_build_assign (new_var, x));
16554 break;
16556 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16557 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16558 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16559 or references to VLAs. */
16560 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16561 switch (OMP_CLAUSE_CODE (c))
16563 tree var;
16564 default:
16565 break;
16566 case OMP_CLAUSE_MAP:
16567 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16568 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16570 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16571 HOST_WIDE_INT offset = 0;
16572 gcc_assert (prev);
16573 var = OMP_CLAUSE_DECL (c);
16574 if (DECL_P (var)
16575 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16576 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16577 ctx))
16578 && varpool_node::get_create (var)->offloadable)
16579 break;
16580 if (TREE_CODE (var) == INDIRECT_REF
16581 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16582 var = TREE_OPERAND (var, 0);
16583 if (TREE_CODE (var) == COMPONENT_REF)
16585 var = get_addr_base_and_unit_offset (var, &offset);
16586 gcc_assert (var != NULL_TREE && DECL_P (var));
16588 else if (DECL_SIZE (var)
16589 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16591 tree var2 = DECL_VALUE_EXPR (var);
16592 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16593 var2 = TREE_OPERAND (var2, 0);
16594 gcc_assert (DECL_P (var2));
16595 var = var2;
16597 tree new_var = lookup_decl (var, ctx), x;
16598 tree type = TREE_TYPE (new_var);
16599 bool is_ref;
16600 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16601 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16602 == COMPONENT_REF))
16604 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16605 is_ref = true;
16606 new_var = build2 (MEM_REF, type,
16607 build_fold_addr_expr (new_var),
16608 build_int_cst (build_pointer_type (type),
16609 offset));
16611 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16613 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16614 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16615 new_var = build2 (MEM_REF, type,
16616 build_fold_addr_expr (new_var),
16617 build_int_cst (build_pointer_type (type),
16618 offset));
16620 else
16621 is_ref = is_reference (var);
16622 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16623 is_ref = false;
16624 bool ref_to_array = false;
16625 if (is_ref)
16627 type = TREE_TYPE (type);
16628 if (TREE_CODE (type) == ARRAY_TYPE)
16630 type = build_pointer_type (type);
16631 ref_to_array = true;
16634 else if (TREE_CODE (type) == ARRAY_TYPE)
16636 tree decl2 = DECL_VALUE_EXPR (new_var);
16637 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16638 decl2 = TREE_OPERAND (decl2, 0);
16639 gcc_assert (DECL_P (decl2));
16640 new_var = decl2;
16641 type = TREE_TYPE (new_var);
16643 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16644 x = fold_convert_loc (clause_loc, type, x);
16645 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16647 tree bias = OMP_CLAUSE_SIZE (c);
16648 if (DECL_P (bias))
16649 bias = lookup_decl (bias, ctx);
16650 bias = fold_convert_loc (clause_loc, sizetype, bias);
16651 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16652 bias);
16653 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16654 TREE_TYPE (x), x, bias);
16656 if (ref_to_array)
16657 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16658 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16659 if (is_ref && !ref_to_array)
16661 tree t = create_tmp_var_raw (type, get_name (var));
16662 gimple_add_tmp_var (t);
16663 TREE_ADDRESSABLE (t) = 1;
16664 gimple_seq_add_stmt (&new_body,
16665 gimple_build_assign (t, x));
16666 x = build_fold_addr_expr_loc (clause_loc, t);
16668 gimple_seq_add_stmt (&new_body,
16669 gimple_build_assign (new_var, x));
16670 prev = NULL_TREE;
16672 else if (OMP_CLAUSE_CHAIN (c)
16673 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16674 == OMP_CLAUSE_MAP
16675 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16676 == GOMP_MAP_FIRSTPRIVATE_POINTER
16677 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16678 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16679 prev = c;
16680 break;
16681 case OMP_CLAUSE_PRIVATE:
16682 var = OMP_CLAUSE_DECL (c);
16683 if (is_variable_sized (var))
16685 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16686 tree new_var = lookup_decl (var, ctx);
16687 tree pvar = DECL_VALUE_EXPR (var);
16688 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16689 pvar = TREE_OPERAND (pvar, 0);
16690 gcc_assert (DECL_P (pvar));
16691 tree new_pvar = lookup_decl (pvar, ctx);
16692 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16693 tree al = size_int (DECL_ALIGN (var));
16694 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16695 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16696 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16697 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16698 gimple_seq_add_stmt (&new_body,
16699 gimple_build_assign (new_pvar, x));
16701 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16703 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16704 tree new_var = lookup_decl (var, ctx);
16705 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16706 if (TREE_CONSTANT (x))
16707 break;
16708 else
16710 tree atmp
16711 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16712 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16713 tree al = size_int (TYPE_ALIGN (rtype));
16714 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16717 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16718 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16719 gimple_seq_add_stmt (&new_body,
16720 gimple_build_assign (new_var, x));
16722 break;
16725 gimple_seq fork_seq = NULL;
16726 gimple_seq join_seq = NULL;
16728 if (is_oacc_parallel (ctx))
16730 /* If there are reductions on the offloaded region itself, treat
16731 them as a dummy GANG loop. */
16732 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16734 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16735 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16738 gimple_seq_add_seq (&new_body, fork_seq);
16739 gimple_seq_add_seq (&new_body, tgt_body);
16740 gimple_seq_add_seq (&new_body, join_seq);
16742 if (offloaded)
16743 new_body = maybe_catch_exception (new_body);
16745 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16746 gimple_omp_set_body (stmt, new_body);
16749 bind = gimple_build_bind (NULL, NULL,
16750 tgt_bind ? gimple_bind_block (tgt_bind)
16751 : NULL_TREE);
16752 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16753 gimple_bind_add_seq (bind, ilist);
16754 gimple_bind_add_stmt (bind, stmt);
16755 gimple_bind_add_seq (bind, olist);
16757 pop_gimplify_context (NULL);
16759 if (dep_bind)
16761 gimple_bind_add_seq (dep_bind, dep_ilist);
16762 gimple_bind_add_stmt (dep_bind, bind);
16763 gimple_bind_add_seq (dep_bind, dep_olist);
16764 pop_gimplify_context (dep_bind);
16768 /* Expand code for an OpenMP teams directive. */
16770 static void
16771 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16773 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16774 push_gimplify_context ();
16776 tree block = make_node (BLOCK);
16777 gbind *bind = gimple_build_bind (NULL, NULL, block);
16778 gsi_replace (gsi_p, bind, true);
16779 gimple_seq bind_body = NULL;
16780 gimple_seq dlist = NULL;
16781 gimple_seq olist = NULL;
16783 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16784 OMP_CLAUSE_NUM_TEAMS);
16785 if (num_teams == NULL_TREE)
16786 num_teams = build_int_cst (unsigned_type_node, 0);
16787 else
16789 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16790 num_teams = fold_convert (unsigned_type_node, num_teams);
16791 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16793 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16794 OMP_CLAUSE_THREAD_LIMIT);
16795 if (thread_limit == NULL_TREE)
16796 thread_limit = build_int_cst (unsigned_type_node, 0);
16797 else
16799 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16800 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16801 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16802 fb_rvalue);
16805 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16806 &bind_body, &dlist, ctx, NULL);
16807 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16808 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16809 if (!gimple_omp_teams_grid_phony (teams_stmt))
16811 gimple_seq_add_stmt (&bind_body, teams_stmt);
16812 location_t loc = gimple_location (teams_stmt);
16813 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16814 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16815 gimple_set_location (call, loc);
16816 gimple_seq_add_stmt (&bind_body, call);
16819 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16820 gimple_omp_set_body (teams_stmt, NULL);
16821 gimple_seq_add_seq (&bind_body, olist);
16822 gimple_seq_add_seq (&bind_body, dlist);
16823 if (!gimple_omp_teams_grid_phony (teams_stmt))
16824 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16825 gimple_bind_set_body (bind, bind_body);
16827 pop_gimplify_context (bind);
16829 gimple_bind_append_vars (bind, ctx->block_vars);
16830 BLOCK_VARS (block) = ctx->block_vars;
16831 if (BLOCK_VARS (block))
16832 TREE_USED (block) = 1;
16835 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16837 static void
16838 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16840 gimple *stmt = gsi_stmt (*gsi_p);
16841 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16842 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16843 gimple_build_omp_return (false));
16847 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16848 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16849 of OMP context, but with task_shared_vars set. */
16851 static tree
16852 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16853 void *data)
16855 tree t = *tp;
16857 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16858 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16859 return t;
16861 if (task_shared_vars
16862 && DECL_P (t)
16863 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16864 return t;
16866 /* If a global variable has been privatized, TREE_CONSTANT on
16867 ADDR_EXPR might be wrong. */
16868 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16869 recompute_tree_invariant_for_addr_expr (t);
16871 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16872 return NULL_TREE;
16875 /* Data to be communicated between lower_omp_regimplify_operands and
16876 lower_omp_regimplify_operands_p. */
16878 struct lower_omp_regimplify_operands_data
16880 omp_context *ctx;
16881 vec<tree> *decls;
16884 /* Helper function for lower_omp_regimplify_operands. Find
16885 omp_member_access_dummy_var vars and adjust temporarily their
16886 DECL_VALUE_EXPRs if needed. */
16888 static tree
16889 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16890 void *data)
16892 tree t = omp_member_access_dummy_var (*tp);
16893 if (t)
16895 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16896 lower_omp_regimplify_operands_data *ldata
16897 = (lower_omp_regimplify_operands_data *) wi->info;
16898 tree o = maybe_lookup_decl (t, ldata->ctx);
16899 if (o != t)
16901 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16902 ldata->decls->safe_push (*tp);
16903 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16904 SET_DECL_VALUE_EXPR (*tp, v);
16907 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16908 return NULL_TREE;
16911 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16912 of omp_member_access_dummy_var vars during regimplification. */
16914 static void
16915 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16916 gimple_stmt_iterator *gsi_p)
16918 auto_vec<tree, 10> decls;
16919 if (ctx)
16921 struct walk_stmt_info wi;
16922 memset (&wi, '\0', sizeof (wi));
16923 struct lower_omp_regimplify_operands_data data;
16924 data.ctx = ctx;
16925 data.decls = &decls;
16926 wi.info = &data;
16927 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16929 gimple_regimplify_operands (stmt, gsi_p);
16930 while (!decls.is_empty ())
16932 tree t = decls.pop ();
16933 tree v = decls.pop ();
16934 SET_DECL_VALUE_EXPR (t, v);
16938 static void
16939 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16941 gimple *stmt = gsi_stmt (*gsi_p);
16942 struct walk_stmt_info wi;
16943 gcall *call_stmt;
16945 if (gimple_has_location (stmt))
16946 input_location = gimple_location (stmt);
16948 if (task_shared_vars)
16949 memset (&wi, '\0', sizeof (wi));
16951 /* If we have issued syntax errors, avoid doing any heavy lifting.
16952 Just replace the OMP directives with a NOP to avoid
16953 confusing RTL expansion. */
16954 if (seen_error () && is_gimple_omp (stmt))
16956 gsi_replace (gsi_p, gimple_build_nop (), true);
16957 return;
16960 switch (gimple_code (stmt))
16962 case GIMPLE_COND:
16964 gcond *cond_stmt = as_a <gcond *> (stmt);
16965 if ((ctx || task_shared_vars)
16966 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16967 lower_omp_regimplify_p,
16968 ctx ? NULL : &wi, NULL)
16969 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16970 lower_omp_regimplify_p,
16971 ctx ? NULL : &wi, NULL)))
16972 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16974 break;
16975 case GIMPLE_CATCH:
16976 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16977 break;
16978 case GIMPLE_EH_FILTER:
16979 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16980 break;
16981 case GIMPLE_TRY:
16982 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16983 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16984 break;
16985 case GIMPLE_TRANSACTION:
16986 lower_omp (gimple_transaction_body_ptr (
16987 as_a <gtransaction *> (stmt)),
16988 ctx);
16989 break;
16990 case GIMPLE_BIND:
16991 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16992 break;
16993 case GIMPLE_OMP_PARALLEL:
16994 case GIMPLE_OMP_TASK:
16995 ctx = maybe_lookup_ctx (stmt);
16996 gcc_assert (ctx);
16997 if (ctx->cancellable)
16998 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16999 lower_omp_taskreg (gsi_p, ctx);
17000 break;
17001 case GIMPLE_OMP_FOR:
17002 ctx = maybe_lookup_ctx (stmt);
17003 gcc_assert (ctx);
17004 if (ctx->cancellable)
17005 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17006 lower_omp_for (gsi_p, ctx);
17007 break;
17008 case GIMPLE_OMP_SECTIONS:
17009 ctx = maybe_lookup_ctx (stmt);
17010 gcc_assert (ctx);
17011 if (ctx->cancellable)
17012 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17013 lower_omp_sections (gsi_p, ctx);
17014 break;
17015 case GIMPLE_OMP_SINGLE:
17016 ctx = maybe_lookup_ctx (stmt);
17017 gcc_assert (ctx);
17018 lower_omp_single (gsi_p, ctx);
17019 break;
17020 case GIMPLE_OMP_MASTER:
17021 ctx = maybe_lookup_ctx (stmt);
17022 gcc_assert (ctx);
17023 lower_omp_master (gsi_p, ctx);
17024 break;
17025 case GIMPLE_OMP_TASKGROUP:
17026 ctx = maybe_lookup_ctx (stmt);
17027 gcc_assert (ctx);
17028 lower_omp_taskgroup (gsi_p, ctx);
17029 break;
17030 case GIMPLE_OMP_ORDERED:
17031 ctx = maybe_lookup_ctx (stmt);
17032 gcc_assert (ctx);
17033 lower_omp_ordered (gsi_p, ctx);
17034 break;
17035 case GIMPLE_OMP_CRITICAL:
17036 ctx = maybe_lookup_ctx (stmt);
17037 gcc_assert (ctx);
17038 lower_omp_critical (gsi_p, ctx);
17039 break;
17040 case GIMPLE_OMP_ATOMIC_LOAD:
17041 if ((ctx || task_shared_vars)
17042 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17043 as_a <gomp_atomic_load *> (stmt)),
17044 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17045 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17046 break;
17047 case GIMPLE_OMP_TARGET:
17048 ctx = maybe_lookup_ctx (stmt);
17049 gcc_assert (ctx);
17050 lower_omp_target (gsi_p, ctx);
17051 break;
17052 case GIMPLE_OMP_TEAMS:
17053 ctx = maybe_lookup_ctx (stmt);
17054 gcc_assert (ctx);
17055 lower_omp_teams (gsi_p, ctx);
17056 break;
17057 case GIMPLE_OMP_GRID_BODY:
17058 ctx = maybe_lookup_ctx (stmt);
17059 gcc_assert (ctx);
17060 lower_omp_grid_body (gsi_p, ctx);
17061 break;
17062 case GIMPLE_CALL:
17063 tree fndecl;
17064 call_stmt = as_a <gcall *> (stmt);
17065 fndecl = gimple_call_fndecl (call_stmt);
17066 if (fndecl
17067 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17068 switch (DECL_FUNCTION_CODE (fndecl))
17070 case BUILT_IN_GOMP_BARRIER:
17071 if (ctx == NULL)
17072 break;
17073 /* FALLTHRU */
17074 case BUILT_IN_GOMP_CANCEL:
17075 case BUILT_IN_GOMP_CANCELLATION_POINT:
17076 omp_context *cctx;
17077 cctx = ctx;
17078 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17079 cctx = cctx->outer;
17080 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17081 if (!cctx->cancellable)
17083 if (DECL_FUNCTION_CODE (fndecl)
17084 == BUILT_IN_GOMP_CANCELLATION_POINT)
17086 stmt = gimple_build_nop ();
17087 gsi_replace (gsi_p, stmt, false);
17089 break;
17091 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17093 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17094 gimple_call_set_fndecl (call_stmt, fndecl);
17095 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17097 tree lhs;
17098 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17099 gimple_call_set_lhs (call_stmt, lhs);
17100 tree fallthru_label;
17101 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17102 gimple *g;
17103 g = gimple_build_label (fallthru_label);
17104 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17105 g = gimple_build_cond (NE_EXPR, lhs,
17106 fold_convert (TREE_TYPE (lhs),
17107 boolean_false_node),
17108 cctx->cancel_label, fallthru_label);
17109 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17110 break;
17111 default:
17112 break;
17114 /* FALLTHRU */
17115 default:
17116 if ((ctx || task_shared_vars)
17117 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17118 ctx ? NULL : &wi))
17120 /* Just remove clobbers, this should happen only if we have
17121 "privatized" local addressable variables in SIMD regions,
17122 the clobber isn't needed in that case and gimplifying address
17123 of the ARRAY_REF into a pointer and creating MEM_REF based
17124 clobber would create worse code than we get with the clobber
17125 dropped. */
17126 if (gimple_clobber_p (stmt))
17128 gsi_replace (gsi_p, gimple_build_nop (), true);
17129 break;
17131 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17133 break;
17137 static void
17138 lower_omp (gimple_seq *body, omp_context *ctx)
17140 location_t saved_location = input_location;
17141 gimple_stmt_iterator gsi;
17142 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17143 lower_omp_1 (&gsi, ctx);
17144 /* During gimplification, we haven't folded statments inside offloading
17145 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17146 if (target_nesting_level || taskreg_nesting_level)
17147 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17148 fold_stmt (&gsi);
17149 input_location = saved_location;
17152 /* Returen true if STMT is an assignment of a register-type into a local
17153 VAR_DECL. */
17155 static bool
17156 grid_reg_assignment_to_local_var_p (gimple *stmt)
17158 gassign *assign = dyn_cast <gassign *> (stmt);
17159 if (!assign)
17160 return false;
17161 tree lhs = gimple_assign_lhs (assign);
17162 if (TREE_CODE (lhs) != VAR_DECL
17163 || !is_gimple_reg_type (TREE_TYPE (lhs))
17164 || is_global_var (lhs))
17165 return false;
17166 return true;
17169 /* Return true if all statements in SEQ are assignments to local register-type
17170 variables. */
17172 static bool
17173 grid_seq_only_contains_local_assignments (gimple_seq seq)
17175 if (!seq)
17176 return true;
17178 gimple_stmt_iterator gsi;
17179 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17180 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17181 return false;
17182 return true;
17185 /* Scan statements in SEQ and call itself recursively on any bind. If during
17186 whole search only assignments to register-type local variables and one
17187 single OMP statement is encountered, return true, otherwise return false.
17188 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17189 are used for dumping a note about a failure. */
17191 static bool
17192 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17193 const char *name, gimple **ret)
17195 gimple_stmt_iterator gsi;
17196 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17198 gimple *stmt = gsi_stmt (gsi);
17200 if (grid_reg_assignment_to_local_var_p (stmt))
17201 continue;
17202 if (gbind *bind = dyn_cast <gbind *> (stmt))
17204 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17205 target_loc, name, ret))
17206 return false;
17208 else if (is_gimple_omp (stmt))
17210 if (*ret)
17212 if (dump_enabled_p ())
17213 dump_printf_loc (MSG_NOTE, target_loc,
17214 "Will not turn target construct into a simple "
17215 "GPGPU kernel because %s construct contains "
17216 "multiple OpenMP constructs\n", name);
17217 return false;
17219 *ret = stmt;
17221 else
17223 if (dump_enabled_p ())
17224 dump_printf_loc (MSG_NOTE, target_loc,
17225 "Will not turn target construct into a simple "
17226 "GPGPU kernel because %s construct contains "
17227 "a complex statement\n", name);
17228 return false;
17231 return true;
17234 /* Scan statements in SEQ and make sure that it and any binds in it contain
17235 only assignments to local register-type variables and one OMP construct. If
17236 so, return that construct, otherwise return NULL. If dumping is enabled and
17237 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17238 failure. */
17240 static gimple *
17241 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17242 const char *name)
17244 if (!seq)
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 has empty "
17250 "body\n",
17251 name);
17252 return NULL;
17255 gimple *ret = NULL;
17256 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17258 if (!ret && dump_enabled_p ())
17259 dump_printf_loc (MSG_NOTE, target_loc,
17260 "Will not turn target construct into a simple "
17261 "GPGPU kernel because %s construct does not contain"
17262 "any other OpenMP construct\n", name);
17263 return ret;
17265 else
17266 return NULL;
17269 /* Walker function looking for statements there is no point gridifying (and for
17270 noreturn function calls which we cannot do). Return non-NULL if such a
17271 function is found. */
17273 static tree
17274 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17275 bool *handled_ops_p,
17276 struct walk_stmt_info *wi)
17278 *handled_ops_p = false;
17279 gimple *stmt = gsi_stmt (*gsi);
17280 switch (gimple_code (stmt))
17282 case GIMPLE_CALL:
17283 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17285 *handled_ops_p = true;
17286 wi->info = stmt;
17287 return error_mark_node;
17289 break;
17291 /* We may reduce the following list if we find a way to implement the
17292 clauses, but now there is no point trying further. */
17293 case GIMPLE_OMP_CRITICAL:
17294 case GIMPLE_OMP_TASKGROUP:
17295 case GIMPLE_OMP_TASK:
17296 case GIMPLE_OMP_SECTION:
17297 case GIMPLE_OMP_SECTIONS:
17298 case GIMPLE_OMP_SECTIONS_SWITCH:
17299 case GIMPLE_OMP_TARGET:
17300 case GIMPLE_OMP_ORDERED:
17301 *handled_ops_p = true;
17302 wi->info = stmt;
17303 return error_mark_node;
17305 case GIMPLE_OMP_FOR:
17306 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17307 && gimple_omp_for_combined_into_p (stmt))
17309 *handled_ops_p = true;
17310 wi->info = stmt;
17311 return error_mark_node;
17313 break;
17315 default:
17316 break;
17318 return NULL;
17322 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17323 kernel, return true, otherwise return false. In the case of success, also
17324 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17325 none. */
17327 static bool
17328 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17330 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17331 return false;
17333 location_t tloc = gimple_location (target);
17334 gimple *stmt
17335 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17336 tloc, "target");
17337 if (!stmt)
17338 return false;
17339 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17340 tree group_size = NULL;
17341 if (!teams)
17343 dump_printf_loc (MSG_NOTE, tloc,
17344 "Will not turn target construct into a simple "
17345 "GPGPU kernel because it does not have a sole teams "
17346 "construct in it.\n");
17347 return false;
17350 tree clauses = gimple_omp_teams_clauses (teams);
17351 while (clauses)
17353 switch (OMP_CLAUSE_CODE (clauses))
17355 case OMP_CLAUSE_NUM_TEAMS:
17356 if (dump_enabled_p ())
17357 dump_printf_loc (MSG_NOTE, tloc,
17358 "Will not turn target construct into a "
17359 "gridified GPGPU kernel because we cannot "
17360 "handle num_teams clause of teams "
17361 "construct\n ");
17362 return false;
17364 case OMP_CLAUSE_REDUCTION:
17365 if (dump_enabled_p ())
17366 dump_printf_loc (MSG_NOTE, tloc,
17367 "Will not turn target construct into a "
17368 "gridified GPGPU kernel because a reduction "
17369 "clause is present\n ");
17370 return false;
17372 case OMP_CLAUSE_LASTPRIVATE:
17373 if (dump_enabled_p ())
17374 dump_printf_loc (MSG_NOTE, tloc,
17375 "Will not turn target construct into a "
17376 "gridified GPGPU kernel because a lastprivate "
17377 "clause is present\n ");
17378 return false;
17380 case OMP_CLAUSE_THREAD_LIMIT:
17381 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17382 break;
17384 default:
17385 break;
17387 clauses = OMP_CLAUSE_CHAIN (clauses);
17390 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17391 "teams");
17392 if (!stmt)
17393 return false;
17394 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17395 if (!dist)
17397 dump_printf_loc (MSG_NOTE, tloc,
17398 "Will not turn target construct into a simple "
17399 "GPGPU kernel because the teams construct does not have "
17400 "a sole distribute construct in it.\n");
17401 return false;
17404 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17405 if (!gimple_omp_for_combined_p (dist))
17407 if (dump_enabled_p ())
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a gridified GPGPU "
17410 "kernel because we cannot handle a standalone "
17411 "distribute construct\n ");
17412 return false;
17414 if (dist->collapse > 1)
17416 if (dump_enabled_p ())
17417 dump_printf_loc (MSG_NOTE, tloc,
17418 "Will not turn target construct into a gridified GPGPU "
17419 "kernel because the distribute construct contains "
17420 "collapse clause\n");
17421 return false;
17423 struct omp_for_data fd;
17424 extract_omp_for_data (dist, &fd, NULL);
17425 if (fd.chunk_size)
17427 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17429 if (dump_enabled_p ())
17430 dump_printf_loc (MSG_NOTE, tloc,
17431 "Will not turn target construct into a "
17432 "gridified GPGPU kernel because the teams "
17433 "thread limit is different from distribute "
17434 "schedule chunk\n");
17435 return false;
17437 group_size = fd.chunk_size;
17439 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17440 "distribute");
17441 gomp_parallel *par;
17442 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17443 return false;
17445 clauses = gimple_omp_parallel_clauses (par);
17446 while (clauses)
17448 switch (OMP_CLAUSE_CODE (clauses))
17450 case OMP_CLAUSE_NUM_THREADS:
17451 if (dump_enabled_p ())
17452 dump_printf_loc (MSG_NOTE, tloc,
17453 "Will not turn target construct into a gridified"
17454 "GPGPU kernel because there is a num_threads "
17455 "clause of the parallel construct\n");
17456 return false;
17458 case OMP_CLAUSE_REDUCTION:
17459 if (dump_enabled_p ())
17460 dump_printf_loc (MSG_NOTE, tloc,
17461 "Will not turn target construct into a "
17462 "gridified GPGPU kernel because a reduction "
17463 "clause is present\n ");
17464 return false;
17466 case OMP_CLAUSE_LASTPRIVATE:
17467 if (dump_enabled_p ())
17468 dump_printf_loc (MSG_NOTE, tloc,
17469 "Will not turn target construct into a "
17470 "gridified GPGPU kernel because a lastprivate "
17471 "clause is present\n ");
17472 return false;
17474 default:
17475 break;
17477 clauses = OMP_CLAUSE_CHAIN (clauses);
17480 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17481 "parallel");
17482 gomp_for *gfor;
17483 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17484 return false;
17486 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17488 if (dump_enabled_p ())
17489 dump_printf_loc (MSG_NOTE, tloc,
17490 "Will not turn target construct into a gridified GPGPU "
17491 "kernel because the inner loop is not a simple for "
17492 "loop\n");
17493 return false;
17495 if (gfor->collapse > 1)
17497 if (dump_enabled_p ())
17498 dump_printf_loc (MSG_NOTE, tloc,
17499 "Will not turn target construct into a gridified GPGPU "
17500 "kernel because the inner loop contains collapse "
17501 "clause\n");
17502 return false;
17505 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17507 if (dump_enabled_p ())
17508 dump_printf_loc (MSG_NOTE, tloc,
17509 "Will not turn target construct into a gridified GPGPU "
17510 "kernel because the inner loop pre_body contains"
17511 "a complex instruction\n");
17512 return false;
17515 clauses = gimple_omp_for_clauses (gfor);
17516 while (clauses)
17518 switch (OMP_CLAUSE_CODE (clauses))
17520 case OMP_CLAUSE_SCHEDULE:
17521 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17523 if (dump_enabled_p ())
17524 dump_printf_loc (MSG_NOTE, tloc,
17525 "Will not turn target construct into a "
17526 "gridified GPGPU kernel because the inner "
17527 "loop has a non-automatic scheduling clause\n");
17528 return false;
17530 break;
17532 case OMP_CLAUSE_REDUCTION:
17533 if (dump_enabled_p ())
17534 dump_printf_loc (MSG_NOTE, tloc,
17535 "Will not turn target construct into a "
17536 "gridified GPGPU kernel because a reduction "
17537 "clause is present\n ");
17538 return false;
17540 case OMP_CLAUSE_LASTPRIVATE:
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a "
17544 "gridified GPGPU kernel because a lastprivate "
17545 "clause is present\n ");
17546 return false;
17548 default:
17549 break;
17551 clauses = OMP_CLAUSE_CHAIN (clauses);
17554 struct walk_stmt_info wi;
17555 memset (&wi, 0, sizeof (wi));
17556 if (walk_gimple_seq (gimple_omp_body (gfor),
17557 grid_find_ungridifiable_statement,
17558 NULL, &wi))
17560 gimple *bad = (gimple *) wi.info;
17561 if (dump_enabled_p ())
17563 if (is_gimple_call (bad))
17564 dump_printf_loc (MSG_NOTE, tloc,
17565 "Will not turn target construct into a gridified "
17566 " GPGPU kernel because the inner loop contains "
17567 "call to a noreturn function\n");
17568 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17569 dump_printf_loc (MSG_NOTE, tloc,
17570 "Will not turn target construct into a gridified "
17571 " GPGPU kernel because the inner loop contains "
17572 "a simd construct\n");
17573 else
17574 dump_printf_loc (MSG_NOTE, tloc,
17575 "Will not turn target construct into a gridified "
17576 "GPGPU kernel because the inner loop contains "
17577 "statement %s which cannot be transformed\n",
17578 gimple_code_name[(int) gimple_code (bad)]);
17580 return false;
17583 *group_size_p = group_size;
17584 return true;
17587 /* Operand walker, used to remap pre-body declarations according to a hash map
17588 provided in DATA. */
17590 static tree
17591 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17593 tree t = *tp;
17595 if (DECL_P (t) || TYPE_P (t))
17596 *walk_subtrees = 0;
17597 else
17598 *walk_subtrees = 1;
17600 if (TREE_CODE (t) == VAR_DECL)
17602 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17603 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17604 tree *repl = declmap->get (t);
17605 if (repl)
17606 *tp = *repl;
17608 return NULL_TREE;
17611 /* Copy leading register-type assignments to local variables in SRC to just
17612 before DST, Creating temporaries, adjusting mapping of operands in WI and
17613 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17614 Return the first statement that does not conform to
17615 grid_reg_assignment_to_local_var_p or NULL. */
17617 static gimple *
17618 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17619 gbind *tgt_bind, struct walk_stmt_info *wi)
17621 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17622 gimple_stmt_iterator gsi;
17623 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17625 gimple *stmt = gsi_stmt (gsi);
17626 if (gbind *bind = dyn_cast <gbind *> (stmt))
17628 gimple *r = grid_copy_leading_local_assignments
17629 (gimple_bind_body (bind), dst, tgt_bind, wi);
17630 if (r)
17631 return r;
17632 else
17633 continue;
17635 if (!grid_reg_assignment_to_local_var_p (stmt))
17636 return stmt;
17637 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17638 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17639 TREE_TYPE (lhs));
17640 DECL_CONTEXT (repl) = current_function_decl;
17641 gimple_bind_append_vars (tgt_bind, repl);
17643 declmap->put (lhs, repl);
17644 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17645 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17646 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17648 return NULL;
17651 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17652 components, mark them as part of kernel and return the inner loop, and copy
17653 assignment leading to them just before DST, remapping them using WI and
17654 adding new temporaries to TGT_BIND. */
17656 static gomp_for *
17657 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17658 gbind *tgt_bind, struct walk_stmt_info *wi)
17660 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17661 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17662 gcc_assert (teams);
17663 gimple_omp_teams_set_grid_phony (teams, true);
17664 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17665 tgt_bind, wi);
17666 gcc_checking_assert (stmt);
17667 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17668 gcc_assert (dist);
17669 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17670 if (prebody)
17671 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17672 gimple_omp_for_set_grid_phony (dist, true);
17673 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17674 tgt_bind, wi);
17675 gcc_checking_assert (stmt);
17677 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17678 gimple_omp_parallel_set_grid_phony (parallel, true);
17679 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17680 tgt_bind, wi);
17681 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17682 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17683 prebody = gimple_omp_for_pre_body (inner_loop);
17684 if (prebody)
17685 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17687 return inner_loop;
17690 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17691 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17692 is the bind into which temporaries inserted before TARGET should be
17693 added. */
17695 static void
17696 grid_attempt_target_gridification (gomp_target *target,
17697 gimple_stmt_iterator *gsi,
17698 gbind *tgt_bind)
17700 tree group_size;
17701 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17702 return;
17704 location_t loc = gimple_location (target);
17705 if (dump_enabled_p ())
17706 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17707 "Target construct will be turned into a gridified GPGPU "
17708 "kernel\n");
17710 /* Copy target body to a GPUKERNEL construct: */
17711 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17712 (gimple_omp_body (target));
17714 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17715 struct walk_stmt_info wi;
17716 memset (&wi, 0, sizeof (struct walk_stmt_info));
17717 wi.info = declmap;
17719 /* Copy assignments in between OMP statements before target, mark OMP
17720 statements within copy appropriatly. */
17721 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17722 tgt_bind, &wi);
17724 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17725 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17726 tree new_block = gimple_bind_block (new_bind);
17727 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17728 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17729 BLOCK_SUBBLOCKS (enc_block) = new_block;
17730 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17731 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17732 gimple_seq_add_stmt
17733 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17734 gpukernel);
17736 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17737 push_gimplify_context ();
17738 size_t collapse = gimple_omp_for_collapse (inner_loop);
17739 for (size_t i = 0; i < collapse; i++)
17741 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17742 if (POINTER_TYPE_P (type))
17743 itype = signed_type_for (type);
17744 else
17745 itype = type;
17747 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17748 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17749 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17750 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17751 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17752 adjust_for_condition (loc, &cond_code, &n2);
17753 tree step;
17754 step = get_omp_for_step_from_incr (loc,
17755 gimple_omp_for_incr (inner_loop, i));
17756 gimple_seq tmpseq = NULL;
17757 n1 = fold_convert (itype, n1);
17758 n2 = fold_convert (itype, n2);
17759 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17760 t = fold_build2 (PLUS_EXPR, itype, step, t);
17761 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17762 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17763 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17764 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17765 fold_build1 (NEGATE_EXPR, itype, t),
17766 fold_build1 (NEGATE_EXPR, itype, step));
17767 else
17768 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17769 tree gs = fold_convert (uint32_type_node, t);
17770 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17771 if (!gimple_seq_empty_p (tmpseq))
17772 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17774 tree ws;
17775 if (i == 0 && group_size)
17777 ws = fold_convert (uint32_type_node, group_size);
17778 tmpseq = NULL;
17779 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17780 if (!gimple_seq_empty_p (tmpseq))
17781 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17783 else
17784 ws = build_zero_cst (uint32_type_node);
17786 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17787 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17788 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17789 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17790 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17791 gimple_omp_target_set_clauses (target, c);
17793 pop_gimplify_context (tgt_bind);
17794 delete declmap;
17795 return;
17798 /* Walker function doing all the work for create_target_kernels. */
17800 static tree
17801 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17802 bool *handled_ops_p,
17803 struct walk_stmt_info *incoming)
17805 *handled_ops_p = false;
17807 gimple *stmt = gsi_stmt (*gsi);
17808 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17809 if (target)
17811 gbind *tgt_bind = (gbind *) incoming->info;
17812 gcc_checking_assert (tgt_bind);
17813 grid_attempt_target_gridification (target, gsi, tgt_bind);
17814 return NULL_TREE;
17816 gbind *bind = dyn_cast <gbind *> (stmt);
17817 if (bind)
17819 *handled_ops_p = true;
17820 struct walk_stmt_info wi;
17821 memset (&wi, 0, sizeof (wi));
17822 wi.info = bind;
17823 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17824 grid_gridify_all_targets_stmt, NULL, &wi);
17826 return NULL_TREE;
17829 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17830 have their bodies duplicated, with the new copy being put into a
17831 gimple_omp_grid_body statement. All kernel-related construct within the
17832 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17833 re-structuring is often needed, such as copying pre-bodies before the target
17834 construct so that kernel grid sizes can be computed. */
17836 static void
17837 grid_gridify_all_targets (gimple_seq *body_p)
17839 struct walk_stmt_info wi;
17840 memset (&wi, 0, sizeof (wi));
17841 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17845 /* Main entry point. */
17847 static unsigned int
17848 execute_lower_omp (void)
17850 gimple_seq body;
17851 int i;
17852 omp_context *ctx;
17854 /* This pass always runs, to provide PROP_gimple_lomp.
17855 But often, there is nothing to do. */
17856 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17857 && flag_openmp_simd == 0)
17858 return 0;
17860 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17861 delete_omp_context);
17863 body = gimple_body (current_function_decl);
17865 if (hsa_gen_requested_p ())
17866 grid_gridify_all_targets (&body);
17868 scan_omp (&body, NULL);
17869 gcc_assert (taskreg_nesting_level == 0);
17870 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17871 finish_taskreg_scan (ctx);
17872 taskreg_contexts.release ();
17874 if (all_contexts->root)
17876 if (task_shared_vars)
17877 push_gimplify_context ();
17878 lower_omp (&body, NULL);
17879 if (task_shared_vars)
17880 pop_gimplify_context (NULL);
17883 if (all_contexts)
17885 splay_tree_delete (all_contexts);
17886 all_contexts = NULL;
17888 BITMAP_FREE (task_shared_vars);
17889 return 0;
17892 namespace {
17894 const pass_data pass_data_lower_omp =
17896 GIMPLE_PASS, /* type */
17897 "omplower", /* name */
17898 OPTGROUP_NONE, /* optinfo_flags */
17899 TV_NONE, /* tv_id */
17900 PROP_gimple_any, /* properties_required */
17901 PROP_gimple_lomp, /* properties_provided */
17902 0, /* properties_destroyed */
17903 0, /* todo_flags_start */
17904 0, /* todo_flags_finish */
17907 class pass_lower_omp : public gimple_opt_pass
17909 public:
17910 pass_lower_omp (gcc::context *ctxt)
17911 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17914 /* opt_pass methods: */
17915 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17917 }; // class pass_lower_omp
17919 } // anon namespace
17921 gimple_opt_pass *
17922 make_pass_lower_omp (gcc::context *ctxt)
17924 return new pass_lower_omp (ctxt);
17927 /* The following is a utility to diagnose structured block violations.
17928 It is not part of the "omplower" pass, as that's invoked too late. It
17929 should be invoked by the respective front ends after gimplification. */
17931 static splay_tree all_labels;
17933 /* Check for mismatched contexts and generate an error if needed. Return
17934 true if an error is detected. */
17936 static bool
17937 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17938 gimple *branch_ctx, gimple *label_ctx)
17940 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17941 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17943 if (label_ctx == branch_ctx)
17944 return false;
17946 const char* kind = NULL;
17948 if (flag_cilkplus)
17950 if ((branch_ctx
17951 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17952 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17953 || (label_ctx
17954 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17955 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17956 kind = "Cilk Plus";
17958 if (flag_openacc)
17960 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17961 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17963 gcc_checking_assert (kind == NULL);
17964 kind = "OpenACC";
17967 if (kind == NULL)
17969 gcc_checking_assert (flag_openmp);
17970 kind = "OpenMP";
17974 Previously we kept track of the label's entire context in diagnose_sb_[12]
17975 so we could traverse it and issue a correct "exit" or "enter" error
17976 message upon a structured block violation.
17978 We built the context by building a list with tree_cons'ing, but there is
17979 no easy counterpart in gimple tuples. It seems like far too much work
17980 for issuing exit/enter error messages. If someone really misses the
17981 distinct error message... patches welcome.
17984 #if 0
17985 /* Try to avoid confusing the user by producing and error message
17986 with correct "exit" or "enter" verbiage. We prefer "exit"
17987 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17988 if (branch_ctx == NULL)
17989 exit_p = false;
17990 else
17992 while (label_ctx)
17994 if (TREE_VALUE (label_ctx) == branch_ctx)
17996 exit_p = false;
17997 break;
17999 label_ctx = TREE_CHAIN (label_ctx);
18003 if (exit_p)
18004 error ("invalid exit from %s structured block", kind);
18005 else
18006 error ("invalid entry to %s structured block", kind);
18007 #endif
18009 /* If it's obvious we have an invalid entry, be specific about the error. */
18010 if (branch_ctx == NULL)
18011 error ("invalid entry to %s structured block", kind);
18012 else
18014 /* Otherwise, be vague and lazy, but efficient. */
18015 error ("invalid branch to/from %s structured block", kind);
18018 gsi_replace (gsi_p, gimple_build_nop (), false);
18019 return true;
18022 /* Pass 1: Create a minimal tree of structured blocks, and record
18023 where each label is found. */
18025 static tree
18026 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18027 struct walk_stmt_info *wi)
18029 gimple *context = (gimple *) wi->info;
18030 gimple *inner_context;
18031 gimple *stmt = gsi_stmt (*gsi_p);
18033 *handled_ops_p = true;
18035 switch (gimple_code (stmt))
18037 WALK_SUBSTMTS;
18039 case GIMPLE_OMP_PARALLEL:
18040 case GIMPLE_OMP_TASK:
18041 case GIMPLE_OMP_SECTIONS:
18042 case GIMPLE_OMP_SINGLE:
18043 case GIMPLE_OMP_SECTION:
18044 case GIMPLE_OMP_MASTER:
18045 case GIMPLE_OMP_ORDERED:
18046 case GIMPLE_OMP_CRITICAL:
18047 case GIMPLE_OMP_TARGET:
18048 case GIMPLE_OMP_TEAMS:
18049 case GIMPLE_OMP_TASKGROUP:
18050 /* The minimal context here is just the current OMP construct. */
18051 inner_context = stmt;
18052 wi->info = inner_context;
18053 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18054 wi->info = context;
18055 break;
18057 case GIMPLE_OMP_FOR:
18058 inner_context = stmt;
18059 wi->info = inner_context;
18060 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18061 walk them. */
18062 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18063 diagnose_sb_1, NULL, wi);
18064 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18065 wi->info = context;
18066 break;
18068 case GIMPLE_LABEL:
18069 splay_tree_insert (all_labels,
18070 (splay_tree_key) gimple_label_label (
18071 as_a <glabel *> (stmt)),
18072 (splay_tree_value) context);
18073 break;
18075 default:
18076 break;
18079 return NULL_TREE;
18082 /* Pass 2: Check each branch and see if its context differs from that of
18083 the destination label's context. */
18085 static tree
18086 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18087 struct walk_stmt_info *wi)
18089 gimple *context = (gimple *) wi->info;
18090 splay_tree_node n;
18091 gimple *stmt = gsi_stmt (*gsi_p);
18093 *handled_ops_p = true;
18095 switch (gimple_code (stmt))
18097 WALK_SUBSTMTS;
18099 case GIMPLE_OMP_PARALLEL:
18100 case GIMPLE_OMP_TASK:
18101 case GIMPLE_OMP_SECTIONS:
18102 case GIMPLE_OMP_SINGLE:
18103 case GIMPLE_OMP_SECTION:
18104 case GIMPLE_OMP_MASTER:
18105 case GIMPLE_OMP_ORDERED:
18106 case GIMPLE_OMP_CRITICAL:
18107 case GIMPLE_OMP_TARGET:
18108 case GIMPLE_OMP_TEAMS:
18109 case GIMPLE_OMP_TASKGROUP:
18110 wi->info = stmt;
18111 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18112 wi->info = context;
18113 break;
18115 case GIMPLE_OMP_FOR:
18116 wi->info = stmt;
18117 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18118 walk them. */
18119 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18120 diagnose_sb_2, NULL, wi);
18121 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18122 wi->info = context;
18123 break;
18125 case GIMPLE_COND:
18127 gcond *cond_stmt = as_a <gcond *> (stmt);
18128 tree lab = gimple_cond_true_label (cond_stmt);
18129 if (lab)
18131 n = splay_tree_lookup (all_labels,
18132 (splay_tree_key) lab);
18133 diagnose_sb_0 (gsi_p, context,
18134 n ? (gimple *) n->value : NULL);
18136 lab = gimple_cond_false_label (cond_stmt);
18137 if (lab)
18139 n = splay_tree_lookup (all_labels,
18140 (splay_tree_key) lab);
18141 diagnose_sb_0 (gsi_p, context,
18142 n ? (gimple *) n->value : NULL);
18145 break;
18147 case GIMPLE_GOTO:
18149 tree lab = gimple_goto_dest (stmt);
18150 if (TREE_CODE (lab) != LABEL_DECL)
18151 break;
18153 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18154 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18156 break;
18158 case GIMPLE_SWITCH:
18160 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18161 unsigned int i;
18162 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18164 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18165 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18166 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18167 break;
18170 break;
18172 case GIMPLE_RETURN:
18173 diagnose_sb_0 (gsi_p, context, NULL);
18174 break;
18176 default:
18177 break;
18180 return NULL_TREE;
18183 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18184 GIMPLE_* codes. */
18185 bool
18186 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18187 int *region_idx)
18189 gimple *last = last_stmt (bb);
18190 enum gimple_code code = gimple_code (last);
18191 struct omp_region *cur_region = *region;
18192 bool fallthru = false;
18194 switch (code)
18196 case GIMPLE_OMP_PARALLEL:
18197 case GIMPLE_OMP_TASK:
18198 case GIMPLE_OMP_FOR:
18199 case GIMPLE_OMP_SINGLE:
18200 case GIMPLE_OMP_TEAMS:
18201 case GIMPLE_OMP_MASTER:
18202 case GIMPLE_OMP_TASKGROUP:
18203 case GIMPLE_OMP_CRITICAL:
18204 case GIMPLE_OMP_SECTION:
18205 case GIMPLE_OMP_GRID_BODY:
18206 cur_region = new_omp_region (bb, code, cur_region);
18207 fallthru = true;
18208 break;
18210 case GIMPLE_OMP_ORDERED:
18211 cur_region = new_omp_region (bb, code, cur_region);
18212 fallthru = true;
18213 if (find_omp_clause (gimple_omp_ordered_clauses
18214 (as_a <gomp_ordered *> (last)),
18215 OMP_CLAUSE_DEPEND))
18216 cur_region = cur_region->outer;
18217 break;
18219 case GIMPLE_OMP_TARGET:
18220 cur_region = new_omp_region (bb, code, cur_region);
18221 fallthru = true;
18222 switch (gimple_omp_target_kind (last))
18224 case GF_OMP_TARGET_KIND_REGION:
18225 case GF_OMP_TARGET_KIND_DATA:
18226 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18227 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18228 case GF_OMP_TARGET_KIND_OACC_DATA:
18229 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18230 break;
18231 case GF_OMP_TARGET_KIND_UPDATE:
18232 case GF_OMP_TARGET_KIND_ENTER_DATA:
18233 case GF_OMP_TARGET_KIND_EXIT_DATA:
18234 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18235 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18236 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18237 cur_region = cur_region->outer;
18238 break;
18239 default:
18240 gcc_unreachable ();
18242 break;
18244 case GIMPLE_OMP_SECTIONS:
18245 cur_region = new_omp_region (bb, code, cur_region);
18246 fallthru = true;
18247 break;
18249 case GIMPLE_OMP_SECTIONS_SWITCH:
18250 fallthru = false;
18251 break;
18253 case GIMPLE_OMP_ATOMIC_LOAD:
18254 case GIMPLE_OMP_ATOMIC_STORE:
18255 fallthru = true;
18256 break;
18258 case GIMPLE_OMP_RETURN:
18259 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18260 somewhere other than the next block. This will be
18261 created later. */
18262 cur_region->exit = bb;
18263 if (cur_region->type == GIMPLE_OMP_TASK)
18264 /* Add an edge corresponding to not scheduling the task
18265 immediately. */
18266 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18267 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18268 cur_region = cur_region->outer;
18269 break;
18271 case GIMPLE_OMP_CONTINUE:
18272 cur_region->cont = bb;
18273 switch (cur_region->type)
18275 case GIMPLE_OMP_FOR:
18276 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18277 succs edges as abnormal to prevent splitting
18278 them. */
18279 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18280 /* Make the loopback edge. */
18281 make_edge (bb, single_succ (cur_region->entry),
18282 EDGE_ABNORMAL);
18284 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18285 corresponds to the case that the body of the loop
18286 is not executed at all. */
18287 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18288 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18289 fallthru = false;
18290 break;
18292 case GIMPLE_OMP_SECTIONS:
18293 /* Wire up the edges into and out of the nested sections. */
18295 basic_block switch_bb = single_succ (cur_region->entry);
18297 struct omp_region *i;
18298 for (i = cur_region->inner; i ; i = i->next)
18300 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18301 make_edge (switch_bb, i->entry, 0);
18302 make_edge (i->exit, bb, EDGE_FALLTHRU);
18305 /* Make the loopback edge to the block with
18306 GIMPLE_OMP_SECTIONS_SWITCH. */
18307 make_edge (bb, switch_bb, 0);
18309 /* Make the edge from the switch to exit. */
18310 make_edge (switch_bb, bb->next_bb, 0);
18311 fallthru = false;
18313 break;
18315 case GIMPLE_OMP_TASK:
18316 fallthru = true;
18317 break;
18319 default:
18320 gcc_unreachable ();
18322 break;
18324 default:
18325 gcc_unreachable ();
18328 if (*region != cur_region)
18330 *region = cur_region;
18331 if (cur_region)
18332 *region_idx = cur_region->entry->index;
18333 else
18334 *region_idx = 0;
18337 return fallthru;
18340 static unsigned int
18341 diagnose_omp_structured_block_errors (void)
18343 struct walk_stmt_info wi;
18344 gimple_seq body = gimple_body (current_function_decl);
18346 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18348 memset (&wi, 0, sizeof (wi));
18349 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18351 memset (&wi, 0, sizeof (wi));
18352 wi.want_locations = true;
18353 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18355 gimple_set_body (current_function_decl, body);
18357 splay_tree_delete (all_labels);
18358 all_labels = NULL;
18360 return 0;
18363 namespace {
18365 const pass_data pass_data_diagnose_omp_blocks =
18367 GIMPLE_PASS, /* type */
18368 "*diagnose_omp_blocks", /* name */
18369 OPTGROUP_NONE, /* optinfo_flags */
18370 TV_NONE, /* tv_id */
18371 PROP_gimple_any, /* properties_required */
18372 0, /* properties_provided */
18373 0, /* properties_destroyed */
18374 0, /* todo_flags_start */
18375 0, /* todo_flags_finish */
18378 class pass_diagnose_omp_blocks : public gimple_opt_pass
18380 public:
18381 pass_diagnose_omp_blocks (gcc::context *ctxt)
18382 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18385 /* opt_pass methods: */
18386 virtual bool gate (function *)
18388 return flag_cilkplus || flag_openacc || flag_openmp;
18390 virtual unsigned int execute (function *)
18392 return diagnose_omp_structured_block_errors ();
18395 }; // class pass_diagnose_omp_blocks
18397 } // anon namespace
18399 gimple_opt_pass *
18400 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18402 return new pass_diagnose_omp_blocks (ctxt);
18405 /* SIMD clone supporting code. */
18407 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
18408 of arguments to reserve space for. */
18410 static struct cgraph_simd_clone *
18411 simd_clone_struct_alloc (int nargs)
18413 struct cgraph_simd_clone *clone_info;
18414 size_t len = (sizeof (struct cgraph_simd_clone)
18415 + nargs * sizeof (struct cgraph_simd_clone_arg));
18416 clone_info = (struct cgraph_simd_clone *)
18417 ggc_internal_cleared_alloc (len);
18418 return clone_info;
18421 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
18423 static inline void
18424 simd_clone_struct_copy (struct cgraph_simd_clone *to,
18425 struct cgraph_simd_clone *from)
18427 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
18428 + ((from->nargs - from->inbranch)
18429 * sizeof (struct cgraph_simd_clone_arg))));
18432 /* Return vector of parameter types of function FNDECL. This uses
18433 TYPE_ARG_TYPES if available, otherwise falls back to types of
18434 DECL_ARGUMENTS types. */
18436 vec<tree>
18437 simd_clone_vector_of_formal_parm_types (tree fndecl)
18439 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
18440 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
18441 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
18442 unsigned int i;
18443 tree arg;
18444 FOR_EACH_VEC_ELT (args, i, arg)
18445 args[i] = TREE_TYPE (args[i]);
18446 return args;
18449 /* Given a simd function in NODE, extract the simd specific
18450 information from the OMP clauses passed in CLAUSES, and return
18451 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
18452 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
18453 otherwise set to FALSE. */
18455 static struct cgraph_simd_clone *
18456 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
18457 bool *inbranch_specified)
18459 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
18460 tree t;
18461 int n;
18462 *inbranch_specified = false;
18464 n = args.length ();
18465 if (n > 0 && args.last () == void_type_node)
18466 n--;
18468 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
18469 be cloned have a distinctive artificial label in addition to "omp
18470 declare simd". */
18471 bool cilk_clone
18472 = (flag_cilkplus
18473 && lookup_attribute ("cilk simd function",
18474 DECL_ATTRIBUTES (node->decl)));
18476 /* Allocate one more than needed just in case this is an in-branch
18477 clone which will require a mask argument. */
18478 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
18479 clone_info->nargs = n;
18480 clone_info->cilk_elemental = cilk_clone;
18482 if (!clauses)
18484 args.release ();
18485 return clone_info;
18487 clauses = TREE_VALUE (clauses);
18488 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
18489 return clone_info;
18491 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
18493 switch (OMP_CLAUSE_CODE (t))
18495 case OMP_CLAUSE_INBRANCH:
18496 clone_info->inbranch = 1;
18497 *inbranch_specified = true;
18498 break;
18499 case OMP_CLAUSE_NOTINBRANCH:
18500 clone_info->inbranch = 0;
18501 *inbranch_specified = true;
18502 break;
18503 case OMP_CLAUSE_SIMDLEN:
18504 clone_info->simdlen
18505 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
18506 break;
18507 case OMP_CLAUSE_LINEAR:
18509 tree decl = OMP_CLAUSE_DECL (t);
18510 tree step = OMP_CLAUSE_LINEAR_STEP (t);
18511 int argno = TREE_INT_CST_LOW (decl);
18512 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
18514 enum cgraph_simd_clone_arg_type arg_type;
18515 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18516 switch (OMP_CLAUSE_LINEAR_KIND (t))
18518 case OMP_CLAUSE_LINEAR_REF:
18519 arg_type
18520 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
18521 break;
18522 case OMP_CLAUSE_LINEAR_UVAL:
18523 arg_type
18524 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
18525 break;
18526 case OMP_CLAUSE_LINEAR_VAL:
18527 case OMP_CLAUSE_LINEAR_DEFAULT:
18528 arg_type
18529 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
18530 break;
18531 default:
18532 gcc_unreachable ();
18534 else
18535 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
18536 clone_info->args[argno].arg_type = arg_type;
18537 clone_info->args[argno].linear_step = tree_to_shwi (step);
18538 gcc_assert (clone_info->args[argno].linear_step >= 0
18539 && clone_info->args[argno].linear_step < n);
18541 else
18543 if (POINTER_TYPE_P (args[argno]))
18544 step = fold_convert (ssizetype, step);
18545 if (!tree_fits_shwi_p (step))
18547 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18548 "ignoring large linear step");
18549 args.release ();
18550 return NULL;
18552 else if (integer_zerop (step))
18554 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18555 "ignoring zero linear step");
18556 args.release ();
18557 return NULL;
18559 else
18561 enum cgraph_simd_clone_arg_type arg_type;
18562 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18563 switch (OMP_CLAUSE_LINEAR_KIND (t))
18565 case OMP_CLAUSE_LINEAR_REF:
18566 arg_type
18567 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
18568 break;
18569 case OMP_CLAUSE_LINEAR_UVAL:
18570 arg_type
18571 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
18572 break;
18573 case OMP_CLAUSE_LINEAR_VAL:
18574 case OMP_CLAUSE_LINEAR_DEFAULT:
18575 arg_type
18576 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
18577 break;
18578 default:
18579 gcc_unreachable ();
18581 else
18582 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
18583 clone_info->args[argno].arg_type = arg_type;
18584 clone_info->args[argno].linear_step = tree_to_shwi (step);
18587 break;
18589 case OMP_CLAUSE_UNIFORM:
18591 tree decl = OMP_CLAUSE_DECL (t);
18592 int argno = tree_to_uhwi (decl);
18593 clone_info->args[argno].arg_type
18594 = SIMD_CLONE_ARG_TYPE_UNIFORM;
18595 break;
18597 case OMP_CLAUSE_ALIGNED:
18599 tree decl = OMP_CLAUSE_DECL (t);
18600 int argno = tree_to_uhwi (decl);
18601 clone_info->args[argno].alignment
18602 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
18603 break;
18605 default:
18606 break;
18609 args.release ();
18610 return clone_info;
18613 /* Given a SIMD clone in NODE, calculate the characteristic data
18614 type and return the coresponding type. The characteristic data
18615 type is computed as described in the Intel Vector ABI. */
18617 static tree
18618 simd_clone_compute_base_data_type (struct cgraph_node *node,
18619 struct cgraph_simd_clone *clone_info)
18621 tree type = integer_type_node;
18622 tree fndecl = node->decl;
18624 /* a) For non-void function, the characteristic data type is the
18625 return type. */
18626 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
18627 type = TREE_TYPE (TREE_TYPE (fndecl));
18629 /* b) If the function has any non-uniform, non-linear parameters,
18630 then the characteristic data type is the type of the first
18631 such parameter. */
18632 else
18634 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
18635 for (unsigned int i = 0; i < clone_info->nargs; ++i)
18636 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
18638 type = map[i];
18639 break;
18641 map.release ();
18644 /* c) If the characteristic data type determined by a) or b) above
18645 is struct, union, or class type which is pass-by-value (except
18646 for the type that maps to the built-in complex data type), the
18647 characteristic data type is int. */
18648 if (RECORD_OR_UNION_TYPE_P (type)
18649 && !aggregate_value_p (type, NULL)
18650 && TREE_CODE (type) != COMPLEX_TYPE)
18651 return integer_type_node;
18653 /* d) If none of the above three classes is applicable, the
18654 characteristic data type is int. */
18656 return type;
18658 /* e) For Intel Xeon Phi native and offload compilation, if the
18659 resulting characteristic data type is 8-bit or 16-bit integer
18660 data type, the characteristic data type is int. */
18661 /* Well, we don't handle Xeon Phi yet. */
18664 static tree
18665 simd_clone_mangle (struct cgraph_node *node,
18666 struct cgraph_simd_clone *clone_info)
18668 char vecsize_mangle = clone_info->vecsize_mangle;
18669 char mask = clone_info->inbranch ? 'M' : 'N';
18670 unsigned int simdlen = clone_info->simdlen;
18671 unsigned int n;
18672 pretty_printer pp;
18674 gcc_assert (vecsize_mangle && simdlen);
18676 pp_string (&pp, "_ZGV");
18677 pp_character (&pp, vecsize_mangle);
18678 pp_character (&pp, mask);
18679 pp_decimal_int (&pp, simdlen);
18681 for (n = 0; n < clone_info->nargs; ++n)
18683 struct cgraph_simd_clone_arg arg = clone_info->args[n];
18685 switch (arg.arg_type)
18687 case SIMD_CLONE_ARG_TYPE_UNIFORM:
18688 pp_character (&pp, 'u');
18689 break;
18690 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
18691 pp_character (&pp, 'l');
18692 goto mangle_linear;
18693 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
18694 pp_character (&pp, 'R');
18695 goto mangle_linear;
18696 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
18697 pp_character (&pp, 'L');
18698 goto mangle_linear;
18699 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
18700 pp_character (&pp, 'U');
18701 goto mangle_linear;
18702 mangle_linear:
18703 gcc_assert (arg.linear_step != 0);
18704 if (arg.linear_step > 1)
18705 pp_unsigned_wide_integer (&pp, arg.linear_step);
18706 else if (arg.linear_step < 0)
18708 pp_character (&pp, 'n');
18709 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
18710 arg.linear_step));
18712 break;
18713 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
18714 pp_string (&pp, "ls");
18715 pp_unsigned_wide_integer (&pp, arg.linear_step);
18716 break;
18717 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
18718 pp_string (&pp, "Rs");
18719 pp_unsigned_wide_integer (&pp, arg.linear_step);
18720 break;
18721 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
18722 pp_string (&pp, "Ls");
18723 pp_unsigned_wide_integer (&pp, arg.linear_step);
18724 break;
18725 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
18726 pp_string (&pp, "Us");
18727 pp_unsigned_wide_integer (&pp, arg.linear_step);
18728 break;
18729 default:
18730 pp_character (&pp, 'v');
18732 if (arg.alignment)
18734 pp_character (&pp, 'a');
18735 pp_decimal_int (&pp, arg.alignment);
18739 pp_underscore (&pp);
18740 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
18741 if (*str == '*')
18742 ++str;
18743 pp_string (&pp, str);
18744 str = pp_formatted_text (&pp);
18746 /* If there already is a SIMD clone with the same mangled name, don't
18747 add another one. This can happen e.g. for
18748 #pragma omp declare simd
18749 #pragma omp declare simd simdlen(8)
18750 int foo (int, int);
18751 if the simdlen is assumed to be 8 for the first one, etc. */
18752 for (struct cgraph_node *clone = node->simd_clones; clone;
18753 clone = clone->simdclone->next_clone)
18754 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
18755 str) == 0)
18756 return NULL_TREE;
18758 return get_identifier (str);
18761 /* Create a simd clone of OLD_NODE and return it. */
18763 static struct cgraph_node *
18764 simd_clone_create (struct cgraph_node *old_node)
18766 struct cgraph_node *new_node;
18767 if (old_node->definition)
18769 if (!old_node->has_gimple_body_p ())
18770 return NULL;
18771 old_node->get_body ();
18772 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
18773 false, NULL, NULL,
18774 "simdclone");
18776 else
18778 tree old_decl = old_node->decl;
18779 tree new_decl = copy_node (old_node->decl);
18780 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
18781 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
18782 SET_DECL_RTL (new_decl, NULL);
18783 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
18784 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
18785 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
18786 if (old_node->in_other_partition)
18787 new_node->in_other_partition = 1;
18789 if (new_node == NULL)
18790 return new_node;
18792 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
18794 /* The function cgraph_function_versioning () will force the new
18795 symbol local. Undo this, and inherit external visability from
18796 the old node. */
18797 new_node->local.local = old_node->local.local;
18798 new_node->externally_visible = old_node->externally_visible;
18800 return new_node;
18803 /* Adjust the return type of the given function to its appropriate
18804 vector counterpart. Returns a simd array to be used throughout the
18805 function as a return value. */
18807 static tree
18808 simd_clone_adjust_return_type (struct cgraph_node *node)
18810 tree fndecl = node->decl;
18811 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
18812 unsigned int veclen;
18813 tree t;
18815 /* Adjust the function return type. */
18816 if (orig_rettype == void_type_node)
18817 return NULL_TREE;
18818 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
18819 t = TREE_TYPE (TREE_TYPE (fndecl));
18820 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
18821 veclen = node->simdclone->vecsize_int;
18822 else
18823 veclen = node->simdclone->vecsize_float;
18824 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
18825 if (veclen > node->simdclone->simdlen)
18826 veclen = node->simdclone->simdlen;
18827 if (POINTER_TYPE_P (t))
18828 t = pointer_sized_int_node;
18829 if (veclen == node->simdclone->simdlen)
18830 t = build_vector_type (t, node->simdclone->simdlen);
18831 else
18833 t = build_vector_type (t, veclen);
18834 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
18836 TREE_TYPE (TREE_TYPE (fndecl)) = t;
18837 if (!node->definition)
18838 return NULL_TREE;
18840 t = DECL_RESULT (fndecl);
18841 /* Adjust the DECL_RESULT. */
18842 gcc_assert (TREE_TYPE (t) != void_type_node);
18843 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
18844 relayout_decl (t);
18846 tree atype = build_array_type_nelts (orig_rettype,
18847 node->simdclone->simdlen);
18848 if (veclen != node->simdclone->simdlen)
18849 return build1 (VIEW_CONVERT_EXPR, atype, t);
18851 /* Set up a SIMD array to use as the return value. */
18852 tree retval = create_tmp_var_raw (atype, "retval");
18853 gimple_add_tmp_var (retval);
18854 return retval;
18857 /* Each vector argument has a corresponding array to be used locally
18858 as part of the eventual loop. Create such temporary array and
18859 return it.
18861 PREFIX is the prefix to be used for the temporary.
18863 TYPE is the inner element type.
18865 SIMDLEN is the number of elements. */
18867 static tree
18868 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
18870 tree atype = build_array_type_nelts (type, simdlen);
18871 tree avar = create_tmp_var_raw (atype, prefix);
18872 gimple_add_tmp_var (avar);
18873 return avar;
18876 /* Modify the function argument types to their corresponding vector
18877 counterparts if appropriate. Also, create one array for each simd
18878 argument to be used locally when using the function arguments as
18879 part of the loop.
18881 NODE is the function whose arguments are to be adjusted.
18883 Returns an adjustment vector that will be filled describing how the
18884 argument types will be adjusted. */
18886 static ipa_parm_adjustment_vec
18887 simd_clone_adjust_argument_types (struct cgraph_node *node)
18889 vec<tree> args;
18890 ipa_parm_adjustment_vec adjustments;
18892 if (node->definition)
18893 args = ipa_get_vector_of_formal_parms (node->decl);
18894 else
18895 args = simd_clone_vector_of_formal_parm_types (node->decl);
18896 adjustments.create (args.length ());
18897 unsigned i, j, veclen;
18898 struct ipa_parm_adjustment adj;
18899 for (i = 0; i < node->simdclone->nargs; ++i)
18901 memset (&adj, 0, sizeof (adj));
18902 tree parm = args[i];
18903 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
18904 adj.base_index = i;
18905 adj.base = parm;
18907 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
18908 node->simdclone->args[i].orig_type = parm_type;
18910 switch (node->simdclone->args[i].arg_type)
18912 default:
18913 /* No adjustment necessary for scalar arguments. */
18914 adj.op = IPA_PARM_OP_COPY;
18915 break;
18916 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
18917 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
18918 if (node->definition)
18919 node->simdclone->args[i].simd_array
18920 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18921 TREE_TYPE (parm_type),
18922 node->simdclone->simdlen);
18923 adj.op = IPA_PARM_OP_COPY;
18924 break;
18925 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
18926 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
18927 case SIMD_CLONE_ARG_TYPE_VECTOR:
18928 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
18929 veclen = node->simdclone->vecsize_int;
18930 else
18931 veclen = node->simdclone->vecsize_float;
18932 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
18933 if (veclen > node->simdclone->simdlen)
18934 veclen = node->simdclone->simdlen;
18935 adj.arg_prefix = "simd";
18936 if (POINTER_TYPE_P (parm_type))
18937 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18938 else
18939 adj.type = build_vector_type (parm_type, veclen);
18940 node->simdclone->args[i].vector_type = adj.type;
18941 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18943 adjustments.safe_push (adj);
18944 if (j == veclen)
18946 memset (&adj, 0, sizeof (adj));
18947 adj.op = IPA_PARM_OP_NEW;
18948 adj.arg_prefix = "simd";
18949 adj.base_index = i;
18950 adj.type = node->simdclone->args[i].vector_type;
18954 if (node->definition)
18955 node->simdclone->args[i].simd_array
18956 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18957 parm_type, node->simdclone->simdlen);
18959 adjustments.safe_push (adj);
18962 if (node->simdclone->inbranch)
18964 tree base_type
18965 = simd_clone_compute_base_data_type (node->simdclone->origin,
18966 node->simdclone);
18968 memset (&adj, 0, sizeof (adj));
18969 adj.op = IPA_PARM_OP_NEW;
18970 adj.arg_prefix = "mask";
18972 adj.base_index = i;
18973 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
18974 veclen = node->simdclone->vecsize_int;
18975 else
18976 veclen = node->simdclone->vecsize_float;
18977 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
18978 if (veclen > node->simdclone->simdlen)
18979 veclen = node->simdclone->simdlen;
18980 if (POINTER_TYPE_P (base_type))
18981 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18982 else
18983 adj.type = build_vector_type (base_type, veclen);
18984 adjustments.safe_push (adj);
18986 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18987 adjustments.safe_push (adj);
18989 /* We have previously allocated one extra entry for the mask. Use
18990 it and fill it. */
18991 struct cgraph_simd_clone *sc = node->simdclone;
18992 sc->nargs++;
18993 if (node->definition)
18995 sc->args[i].orig_arg
18996 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
18997 sc->args[i].simd_array
18998 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
19000 sc->args[i].orig_type = base_type;
19001 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
19004 if (node->definition)
19005 ipa_modify_formal_parameters (node->decl, adjustments);
19006 else
19008 tree new_arg_types = NULL_TREE, new_reversed;
19009 bool last_parm_void = false;
19010 if (args.length () > 0 && args.last () == void_type_node)
19011 last_parm_void = true;
19013 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
19014 j = adjustments.length ();
19015 for (i = 0; i < j; i++)
19017 struct ipa_parm_adjustment *adj = &adjustments[i];
19018 tree ptype;
19019 if (adj->op == IPA_PARM_OP_COPY)
19020 ptype = args[adj->base_index];
19021 else
19022 ptype = adj->type;
19023 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
19025 new_reversed = nreverse (new_arg_types);
19026 if (last_parm_void)
19028 if (new_reversed)
19029 TREE_CHAIN (new_arg_types) = void_list_node;
19030 else
19031 new_reversed = void_list_node;
19034 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
19035 TYPE_ARG_TYPES (new_type) = new_reversed;
19036 TREE_TYPE (node->decl) = new_type;
19038 adjustments.release ();
19040 args.release ();
19041 return adjustments;
19044 /* Initialize and copy the function arguments in NODE to their
19045 corresponding local simd arrays. Returns a fresh gimple_seq with
19046 the instruction sequence generated. */
19048 static gimple_seq
19049 simd_clone_init_simd_arrays (struct cgraph_node *node,
19050 ipa_parm_adjustment_vec adjustments)
19052 gimple_seq seq = NULL;
19053 unsigned i = 0, j = 0, k;
19055 for (tree arg = DECL_ARGUMENTS (node->decl);
19056 arg;
19057 arg = DECL_CHAIN (arg), i++, j++)
19059 if (adjustments[j].op == IPA_PARM_OP_COPY
19060 || POINTER_TYPE_P (TREE_TYPE (arg)))
19061 continue;
19063 node->simdclone->args[i].vector_arg = arg;
19065 tree array = node->simdclone->args[i].simd_array;
19066 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
19068 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19069 tree ptr = build_fold_addr_expr (array);
19070 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19071 build_int_cst (ptype, 0));
19072 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19073 gimplify_and_add (t, &seq);
19075 else
19077 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
19078 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19079 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
19081 tree ptr = build_fold_addr_expr (array);
19082 int elemsize;
19083 if (k)
19085 arg = DECL_CHAIN (arg);
19086 j++;
19088 elemsize
19089 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
19090 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19091 build_int_cst (ptype, k * elemsize));
19092 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19093 gimplify_and_add (t, &seq);
19097 return seq;
19100 /* Callback info for ipa_simd_modify_stmt_ops below. */
19102 struct modify_stmt_info {
19103 ipa_parm_adjustment_vec adjustments;
19104 gimple *stmt;
19105 /* True if the parent statement was modified by
19106 ipa_simd_modify_stmt_ops. */
19107 bool modified;
19110 /* Callback for walk_gimple_op.
19112 Adjust operands from a given statement as specified in the
19113 adjustments vector in the callback data. */
19115 static tree
19116 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
19118 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
19119 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
19120 tree *orig_tp = tp;
19121 if (TREE_CODE (*tp) == ADDR_EXPR)
19122 tp = &TREE_OPERAND (*tp, 0);
19123 struct ipa_parm_adjustment *cand = NULL;
19124 if (TREE_CODE (*tp) == PARM_DECL)
19125 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
19126 else
19128 if (TYPE_P (*tp))
19129 *walk_subtrees = 0;
19132 tree repl = NULL_TREE;
19133 if (cand)
19134 repl = unshare_expr (cand->new_decl);
19135 else
19137 if (tp != orig_tp)
19139 *walk_subtrees = 0;
19140 bool modified = info->modified;
19141 info->modified = false;
19142 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
19143 if (!info->modified)
19145 info->modified = modified;
19146 return NULL_TREE;
19148 info->modified = modified;
19149 repl = *tp;
19151 else
19152 return NULL_TREE;
19155 if (tp != orig_tp)
19157 repl = build_fold_addr_expr (repl);
19158 gimple *stmt;
19159 if (is_gimple_debug (info->stmt))
19161 tree vexpr = make_node (DEBUG_EXPR_DECL);
19162 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
19163 DECL_ARTIFICIAL (vexpr) = 1;
19164 TREE_TYPE (vexpr) = TREE_TYPE (repl);
19165 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
19166 repl = vexpr;
19168 else
19170 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
19171 repl = gimple_assign_lhs (stmt);
19173 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
19174 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
19175 *orig_tp = repl;
19177 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
19179 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
19180 *tp = vce;
19182 else
19183 *tp = repl;
19185 info->modified = true;
19186 return NULL_TREE;
19189 /* Traverse the function body and perform all modifications as
19190 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
19191 modified such that the replacement/reduction value will now be an
19192 offset into the corresponding simd_array.
19194 This function will replace all function argument uses with their
19195 corresponding simd array elements, and ajust the return values
19196 accordingly. */
19198 static void
19199 ipa_simd_modify_function_body (struct cgraph_node *node,
19200 ipa_parm_adjustment_vec adjustments,
19201 tree retval_array, tree iter)
19203 basic_block bb;
19204 unsigned int i, j, l;
19206 /* Re-use the adjustments array, but this time use it to replace
19207 every function argument use to an offset into the corresponding
19208 simd_array. */
19209 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
19211 if (!node->simdclone->args[i].vector_arg)
19212 continue;
19214 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19215 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
19216 adjustments[j].new_decl
19217 = build4 (ARRAY_REF,
19218 basetype,
19219 node->simdclone->args[i].simd_array,
19220 iter,
19221 NULL_TREE, NULL_TREE);
19222 if (adjustments[j].op == IPA_PARM_OP_NONE
19223 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
19224 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
19227 l = adjustments.length ();
19228 for (i = 1; i < num_ssa_names; i++)
19230 tree name = ssa_name (i);
19231 if (name
19232 && SSA_NAME_VAR (name)
19233 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
19235 for (j = 0; j < l; j++)
19236 if (SSA_NAME_VAR (name) == adjustments[j].base
19237 && adjustments[j].new_decl)
19239 tree base_var;
19240 if (adjustments[j].new_ssa_base == NULL_TREE)
19242 base_var
19243 = copy_var_decl (adjustments[j].base,
19244 DECL_NAME (adjustments[j].base),
19245 TREE_TYPE (adjustments[j].base));
19246 adjustments[j].new_ssa_base = base_var;
19248 else
19249 base_var = adjustments[j].new_ssa_base;
19250 if (SSA_NAME_IS_DEFAULT_DEF (name))
19252 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19253 gimple_stmt_iterator gsi = gsi_after_labels (bb);
19254 tree new_decl = unshare_expr (adjustments[j].new_decl);
19255 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
19256 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19257 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
19258 gimple *stmt = gimple_build_assign (name, new_decl);
19259 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
19261 else
19262 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19267 struct modify_stmt_info info;
19268 info.adjustments = adjustments;
19270 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
19272 gimple_stmt_iterator gsi;
19274 gsi = gsi_start_bb (bb);
19275 while (!gsi_end_p (gsi))
19277 gimple *stmt = gsi_stmt (gsi);
19278 info.stmt = stmt;
19279 struct walk_stmt_info wi;
19281 memset (&wi, 0, sizeof (wi));
19282 info.modified = false;
19283 wi.info = &info;
19284 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
19286 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
19288 tree retval = gimple_return_retval (return_stmt);
19289 if (!retval)
19291 gsi_remove (&gsi, true);
19292 continue;
19295 /* Replace `return foo' with `retval_array[iter] = foo'. */
19296 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
19297 retval_array, iter, NULL, NULL);
19298 stmt = gimple_build_assign (ref, retval);
19299 gsi_replace (&gsi, stmt, true);
19300 info.modified = true;
19303 if (info.modified)
19305 update_stmt (stmt);
19306 if (maybe_clean_eh_stmt (stmt))
19307 gimple_purge_dead_eh_edges (gimple_bb (stmt));
19309 gsi_next (&gsi);
19314 /* Helper function of simd_clone_adjust, return linear step addend
19315 of Ith argument. */
19317 static tree
19318 simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
19319 tree addtype, basic_block entry_bb)
19321 tree ptype = NULL_TREE;
19322 switch (node->simdclone->args[i].arg_type)
19324 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
19325 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
19326 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
19327 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
19328 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
19329 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
19330 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
19331 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19332 break;
19333 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
19334 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
19335 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
19336 break;
19337 default:
19338 gcc_unreachable ();
19341 unsigned int idx = node->simdclone->args[i].linear_step;
19342 tree arg = node->simdclone->args[idx].orig_arg;
19343 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
19344 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19345 gimple *g;
19346 tree ret;
19347 if (is_gimple_reg (arg))
19348 ret = get_or_create_ssa_default_def (cfun, arg);
19349 else
19351 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
19352 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19353 ret = gimple_assign_lhs (g);
19355 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
19357 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
19358 build_simple_mem_ref (ret));
19359 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19360 ret = gimple_assign_lhs (g);
19362 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
19364 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
19365 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19366 ret = gimple_assign_lhs (g);
19368 if (POINTER_TYPE_P (ptype))
19370 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
19371 if (size && TREE_CODE (size) == INTEGER_CST)
19373 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
19374 ret, fold_convert (addtype, size));
19375 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19376 ret = gimple_assign_lhs (g);
19379 return ret;
19382 /* Adjust the argument types in NODE to their appropriate vector
19383 counterparts. */
19385 static void
19386 simd_clone_adjust (struct cgraph_node *node)
19388 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
19390 targetm.simd_clone.adjust (node);
19392 tree retval = simd_clone_adjust_return_type (node);
19393 ipa_parm_adjustment_vec adjustments
19394 = simd_clone_adjust_argument_types (node);
19396 push_gimplify_context ();
19398 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
19400 /* Adjust all uses of vector arguments accordingly. Adjust all
19401 return values accordingly. */
19402 tree iter = create_tmp_var (unsigned_type_node, "iter");
19403 tree iter1 = make_ssa_name (iter);
19404 tree iter2 = make_ssa_name (iter);
19405 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
19407 /* Initialize the iteration variable. */
19408 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19409 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
19410 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19411 /* Insert the SIMD array and iv initialization at function
19412 entry. */
19413 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
19415 pop_gimplify_context (NULL);
19417 /* Create a new BB right before the original exit BB, to hold the
19418 iteration increment and the condition/branch. */
19419 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
19420 basic_block incr_bb = create_empty_bb (orig_exit);
19421 add_bb_to_loop (incr_bb, body_bb->loop_father);
19422 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
19423 flag. Set it now to be a FALLTHRU_EDGE. */
19424 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
19425 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
19426 for (unsigned i = 0;
19427 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
19429 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
19430 redirect_edge_succ (e, incr_bb);
19432 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
19433 e->probability = REG_BR_PROB_BASE;
19434 gsi = gsi_last_bb (incr_bb);
19435 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
19436 build_int_cst (unsigned_type_node, 1));
19437 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19439 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
19440 struct loop *loop = alloc_loop ();
19441 cfun->has_force_vectorize_loops = true;
19442 loop->safelen = node->simdclone->simdlen;
19443 loop->force_vectorize = true;
19444 loop->header = body_bb;
19446 /* Branch around the body if the mask applies. */
19447 if (node->simdclone->inbranch)
19449 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
19450 tree mask_array
19451 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
19452 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
19453 tree aref = build4 (ARRAY_REF,
19454 TREE_TYPE (TREE_TYPE (mask_array)),
19455 mask_array, iter1,
19456 NULL, NULL);
19457 g = gimple_build_assign (mask, aref);
19458 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19459 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
19460 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
19462 aref = build1 (VIEW_CONVERT_EXPR,
19463 build_nonstandard_integer_type (bitsize, 0), mask);
19464 mask = make_ssa_name (TREE_TYPE (aref));
19465 g = gimple_build_assign (mask, aref);
19466 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19469 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
19470 NULL, NULL);
19471 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19472 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
19473 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
19476 /* Generate the condition. */
19477 g = gimple_build_cond (LT_EXPR,
19478 iter2,
19479 build_int_cst (unsigned_type_node,
19480 node->simdclone->simdlen),
19481 NULL, NULL);
19482 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19483 e = split_block (incr_bb, gsi_stmt (gsi));
19484 basic_block latch_bb = e->dest;
19485 basic_block new_exit_bb;
19486 new_exit_bb = split_block_after_labels (latch_bb)->dest;
19487 loop->latch = latch_bb;
19489 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
19491 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
19492 /* The successor of incr_bb is already pointing to latch_bb; just
19493 change the flags.
19494 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
19495 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
19497 gphi *phi = create_phi_node (iter1, body_bb);
19498 edge preheader_edge = find_edge (entry_bb, body_bb);
19499 edge latch_edge = single_succ_edge (latch_bb);
19500 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
19501 UNKNOWN_LOCATION);
19502 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19504 /* Generate the new return. */
19505 gsi = gsi_last_bb (new_exit_bb);
19506 if (retval
19507 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
19508 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
19509 retval = TREE_OPERAND (retval, 0);
19510 else if (retval)
19512 retval = build1 (VIEW_CONVERT_EXPR,
19513 TREE_TYPE (TREE_TYPE (node->decl)),
19514 retval);
19515 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
19516 false, GSI_CONTINUE_LINKING);
19518 g = gimple_build_return (retval);
19519 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19521 /* Handle aligned clauses by replacing default defs of the aligned
19522 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
19523 lhs. Handle linear by adding PHIs. */
19524 for (unsigned i = 0; i < node->simdclone->nargs; i++)
19525 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19526 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
19527 || !is_gimple_reg_type
19528 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19530 tree orig_arg = node->simdclone->args[i].orig_arg;
19531 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
19532 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19533 else
19535 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
19536 gimple_add_tmp_var (iter1);
19538 gsi = gsi_after_labels (entry_bb);
19539 g = gimple_build_assign (iter1, orig_arg);
19540 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19541 gsi = gsi_after_labels (body_bb);
19542 g = gimple_build_assign (orig_arg, iter1);
19543 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19545 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19546 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
19547 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19548 == REFERENCE_TYPE
19549 && TREE_ADDRESSABLE
19550 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19552 tree orig_arg = node->simdclone->args[i].orig_arg;
19553 tree def = ssa_default_def (cfun, orig_arg);
19554 if (def && !has_zero_uses (def))
19556 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
19557 gimple_add_tmp_var (iter1);
19558 gsi = gsi_after_labels (entry_bb);
19559 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
19560 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19561 gsi = gsi_after_labels (body_bb);
19562 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
19563 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19566 else if (node->simdclone->args[i].alignment
19567 && node->simdclone->args[i].arg_type
19568 == SIMD_CLONE_ARG_TYPE_UNIFORM
19569 && (node->simdclone->args[i].alignment
19570 & (node->simdclone->args[i].alignment - 1)) == 0
19571 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19572 == POINTER_TYPE)
19574 unsigned int alignment = node->simdclone->args[i].alignment;
19575 tree orig_arg = node->simdclone->args[i].orig_arg;
19576 tree def = ssa_default_def (cfun, orig_arg);
19577 if (def && !has_zero_uses (def))
19579 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
19580 gimple_seq seq = NULL;
19581 bool need_cvt = false;
19582 gcall *call
19583 = gimple_build_call (fn, 2, def, size_int (alignment));
19584 g = call;
19585 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
19586 ptr_type_node))
19587 need_cvt = true;
19588 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
19589 gimple_call_set_lhs (g, t);
19590 gimple_seq_add_stmt_without_update (&seq, g);
19591 if (need_cvt)
19593 t = make_ssa_name (orig_arg);
19594 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
19595 gimple_seq_add_stmt_without_update (&seq, g);
19597 gsi_insert_seq_on_edge_immediate
19598 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
19600 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19601 int freq = compute_call_stmt_bb_frequency (current_function_decl,
19602 entry_bb);
19603 node->create_edge (cgraph_node::get_create (fn),
19604 call, entry_bb->count, freq);
19606 imm_use_iterator iter;
19607 use_operand_p use_p;
19608 gimple *use_stmt;
19609 tree repl = gimple_get_lhs (g);
19610 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19611 if (is_gimple_debug (use_stmt) || use_stmt == call)
19612 continue;
19613 else
19614 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19615 SET_USE (use_p, repl);
19618 else if ((node->simdclone->args[i].arg_type
19619 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
19620 || (node->simdclone->args[i].arg_type
19621 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
19622 || (node->simdclone->args[i].arg_type
19623 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
19624 || (node->simdclone->args[i].arg_type
19625 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
19627 tree orig_arg = node->simdclone->args[i].orig_arg;
19628 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19629 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
19630 tree def = NULL_TREE;
19631 if (TREE_ADDRESSABLE (orig_arg))
19633 def = make_ssa_name (TREE_TYPE (orig_arg));
19634 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19635 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
19636 gsi = gsi_after_labels (entry_bb);
19637 g = gimple_build_assign (def, orig_arg);
19638 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19640 else
19642 def = ssa_default_def (cfun, orig_arg);
19643 if (!def || has_zero_uses (def))
19644 def = NULL_TREE;
19645 else
19647 iter1 = make_ssa_name (orig_arg);
19648 iter2 = make_ssa_name (orig_arg);
19651 if (def)
19653 phi = create_phi_node (iter1, body_bb);
19654 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
19655 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19656 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19657 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19658 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19659 ? TREE_TYPE (orig_arg) : sizetype;
19660 tree addcst = simd_clone_linear_addend (node, i, addtype,
19661 entry_bb);
19662 gsi = gsi_last_bb (incr_bb);
19663 g = gimple_build_assign (iter2, code, iter1, addcst);
19664 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19666 imm_use_iterator iter;
19667 use_operand_p use_p;
19668 gimple *use_stmt;
19669 if (TREE_ADDRESSABLE (orig_arg))
19671 gsi = gsi_after_labels (body_bb);
19672 g = gimple_build_assign (orig_arg, iter1);
19673 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19675 else
19676 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19677 if (use_stmt == phi)
19678 continue;
19679 else
19680 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19681 SET_USE (use_p, iter1);
19684 else if (node->simdclone->args[i].arg_type
19685 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
19686 || (node->simdclone->args[i].arg_type
19687 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
19689 tree orig_arg = node->simdclone->args[i].orig_arg;
19690 tree def = ssa_default_def (cfun, orig_arg);
19691 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
19692 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
19693 if (def && !has_zero_uses (def))
19695 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
19696 iter1 = make_ssa_name (orig_arg);
19697 iter2 = make_ssa_name (orig_arg);
19698 tree iter3 = make_ssa_name (rtype);
19699 tree iter4 = make_ssa_name (rtype);
19700 tree iter5 = make_ssa_name (rtype);
19701 gsi = gsi_after_labels (entry_bb);
19702 gimple *load
19703 = gimple_build_assign (iter3, build_simple_mem_ref (def));
19704 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
19706 tree array = node->simdclone->args[i].simd_array;
19707 TREE_ADDRESSABLE (array) = 1;
19708 tree ptr = build_fold_addr_expr (array);
19709 phi = create_phi_node (iter1, body_bb);
19710 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
19711 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19712 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
19713 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
19714 gsi = gsi_last_bb (incr_bb);
19715 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19717 phi = create_phi_node (iter4, body_bb);
19718 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
19719 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
19720 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19721 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19722 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19723 ? TREE_TYPE (iter3) : sizetype;
19724 tree addcst = simd_clone_linear_addend (node, i, addtype,
19725 entry_bb);
19726 g = gimple_build_assign (iter5, code, iter4, addcst);
19727 gsi = gsi_last_bb (incr_bb);
19728 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19730 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
19731 gsi = gsi_after_labels (body_bb);
19732 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19734 imm_use_iterator iter;
19735 use_operand_p use_p;
19736 gimple *use_stmt;
19737 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19738 if (use_stmt == load)
19739 continue;
19740 else
19741 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19742 SET_USE (use_p, iter1);
19744 if (!TYPE_READONLY (rtype))
19746 tree v = make_ssa_name (rtype);
19747 tree aref = build4 (ARRAY_REF, rtype, array,
19748 size_zero_node, NULL_TREE,
19749 NULL_TREE);
19750 gsi = gsi_after_labels (new_exit_bb);
19751 g = gimple_build_assign (v, aref);
19752 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19753 g = gimple_build_assign (build_simple_mem_ref (def), v);
19754 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19759 calculate_dominance_info (CDI_DOMINATORS);
19760 add_loop (loop, loop->header->loop_father);
19761 update_ssa (TODO_update_ssa);
19763 pop_cfun ();
19766 /* If the function in NODE is tagged as an elemental SIMD function,
19767 create the appropriate SIMD clones. */
19769 static void
19770 expand_simd_clones (struct cgraph_node *node)
19772 tree attr = lookup_attribute ("omp declare simd",
19773 DECL_ATTRIBUTES (node->decl));
19774 if (attr == NULL_TREE
19775 || node->global.inlined_to
19776 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
19777 return;
19779 /* Ignore
19780 #pragma omp declare simd
19781 extern int foo ();
19782 in C, there we don't know the argument types at all. */
19783 if (!node->definition
19784 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
19785 return;
19787 /* Call this before creating clone_info, as it might ggc_collect. */
19788 if (node->definition && node->has_gimple_body_p ())
19789 node->get_body ();
19793 /* Start with parsing the "omp declare simd" attribute(s). */
19794 bool inbranch_clause_specified;
19795 struct cgraph_simd_clone *clone_info
19796 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
19797 &inbranch_clause_specified);
19798 if (clone_info == NULL)
19799 continue;
19801 int orig_simdlen = clone_info->simdlen;
19802 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
19803 /* The target can return 0 (no simd clones should be created),
19804 1 (just one ISA of simd clones should be created) or higher
19805 count of ISA variants. In that case, clone_info is initialized
19806 for the first ISA variant. */
19807 int count
19808 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
19809 base_type, 0);
19810 if (count == 0)
19811 continue;
19813 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
19814 also create one inbranch and one !inbranch clone of it. */
19815 for (int i = 0; i < count * 2; i++)
19817 struct cgraph_simd_clone *clone = clone_info;
19818 if (inbranch_clause_specified && (i & 1) != 0)
19819 continue;
19821 if (i != 0)
19823 clone = simd_clone_struct_alloc (clone_info->nargs
19824 + ((i & 1) != 0));
19825 simd_clone_struct_copy (clone, clone_info);
19826 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
19827 and simd_clone_adjust_argument_types did to the first
19828 clone's info. */
19829 clone->nargs -= clone_info->inbranch;
19830 clone->simdlen = orig_simdlen;
19831 /* And call the target hook again to get the right ISA. */
19832 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
19833 base_type,
19834 i / 2);
19835 if ((i & 1) != 0)
19836 clone->inbranch = 1;
19839 /* simd_clone_mangle might fail if such a clone has been created
19840 already. */
19841 tree id = simd_clone_mangle (node, clone);
19842 if (id == NULL_TREE)
19843 continue;
19845 /* Only when we are sure we want to create the clone actually
19846 clone the function (or definitions) or create another
19847 extern FUNCTION_DECL (for prototypes without definitions). */
19848 struct cgraph_node *n = simd_clone_create (node);
19849 if (n == NULL)
19850 continue;
19852 n->simdclone = clone;
19853 clone->origin = node;
19854 clone->next_clone = NULL;
19855 if (node->simd_clones == NULL)
19857 clone->prev_clone = n;
19858 node->simd_clones = n;
19860 else
19862 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
19863 clone->prev_clone->simdclone->next_clone = n;
19864 node->simd_clones->simdclone->prev_clone = n;
19866 symtab->change_decl_assembler_name (n->decl, id);
19867 /* And finally adjust the return type, parameters and for
19868 definitions also function body. */
19869 if (node->definition)
19870 simd_clone_adjust (n);
19871 else
19873 simd_clone_adjust_return_type (n);
19874 simd_clone_adjust_argument_types (n);
19878 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
19881 /* Entry point for IPA simd clone creation pass. */
19883 static unsigned int
19884 ipa_omp_simd_clone (void)
19886 struct cgraph_node *node;
19887 FOR_EACH_FUNCTION (node)
19888 expand_simd_clones (node);
19889 return 0;
19892 namespace {
19894 const pass_data pass_data_omp_simd_clone =
19896 SIMPLE_IPA_PASS, /* type */
19897 "simdclone", /* name */
19898 OPTGROUP_NONE, /* optinfo_flags */
19899 TV_NONE, /* tv_id */
19900 ( PROP_ssa | PROP_cfg ), /* properties_required */
19901 0, /* properties_provided */
19902 0, /* properties_destroyed */
19903 0, /* todo_flags_start */
19904 0, /* todo_flags_finish */
19907 class pass_omp_simd_clone : public simple_ipa_opt_pass
19909 public:
19910 pass_omp_simd_clone(gcc::context *ctxt)
19911 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
19914 /* opt_pass methods: */
19915 virtual bool gate (function *);
19916 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
19919 bool
19920 pass_omp_simd_clone::gate (function *)
19922 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
19925 } // anon namespace
19927 simple_ipa_opt_pass *
19928 make_pass_omp_simd_clone (gcc::context *ctxt)
19930 return new pass_omp_simd_clone (ctxt);
19933 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
19934 adds their addresses and sizes to constructor-vector V_CTOR. */
19935 static void
19936 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
19937 vec<constructor_elt, va_gc> *v_ctor)
19939 unsigned len = vec_safe_length (v_decls);
19940 for (unsigned i = 0; i < len; i++)
19942 tree it = (*v_decls)[i];
19943 bool is_var = TREE_CODE (it) == VAR_DECL;
19944 bool is_link_var
19945 = is_var
19946 #ifdef ACCEL_COMPILER
19947 && DECL_HAS_VALUE_EXPR_P (it)
19948 #endif
19949 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
19951 tree size = NULL_TREE;
19952 if (is_var)
19953 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
19955 tree addr;
19956 if (!is_link_var)
19957 addr = build_fold_addr_expr (it);
19958 else
19960 #ifdef ACCEL_COMPILER
19961 /* For "omp declare target link" vars add address of the pointer to
19962 the target table, instead of address of the var. */
19963 tree value_expr = DECL_VALUE_EXPR (it);
19964 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
19965 varpool_node::finalize_decl (link_ptr_decl);
19966 addr = build_fold_addr_expr (link_ptr_decl);
19967 #else
19968 addr = build_fold_addr_expr (it);
19969 #endif
19971 /* Most significant bit of the size marks "omp declare target link"
19972 vars in host and target tables. */
19973 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
19974 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
19975 * BITS_PER_UNIT - 1);
19976 size = wide_int_to_tree (const_ptr_type_node, isize);
19979 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
19980 if (is_var)
19981 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
19985 /* Create new symbols containing (address, size) pairs for global variables,
19986 marked with "omp declare target" attribute, as well as addresses for the
19987 functions, which are outlined offloading regions. */
19988 void
19989 omp_finish_file (void)
19991 unsigned num_funcs = vec_safe_length (offload_funcs);
19992 unsigned num_vars = vec_safe_length (offload_vars);
19994 if (num_funcs == 0 && num_vars == 0)
19995 return;
19997 if (targetm_common.have_named_sections)
19999 vec<constructor_elt, va_gc> *v_f, *v_v;
20000 vec_alloc (v_f, num_funcs);
20001 vec_alloc (v_v, num_vars * 2);
20003 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
20004 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
20006 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
20007 num_vars * 2);
20008 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
20009 num_funcs);
20010 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20011 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20012 tree ctor_v = build_constructor (vars_decl_type, v_v);
20013 tree ctor_f = build_constructor (funcs_decl_type, v_f);
20014 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
20015 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
20016 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20017 get_identifier (".offload_func_table"),
20018 funcs_decl_type);
20019 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20020 get_identifier (".offload_var_table"),
20021 vars_decl_type);
20022 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
20023 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
20024 otherwise a joint table in a binary will contain padding between
20025 tables from multiple object files. */
20026 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
20027 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
20028 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
20029 DECL_INITIAL (funcs_decl) = ctor_f;
20030 DECL_INITIAL (vars_decl) = ctor_v;
20031 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
20032 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
20034 varpool_node::finalize_decl (vars_decl);
20035 varpool_node::finalize_decl (funcs_decl);
20037 else
20039 for (unsigned i = 0; i < num_funcs; i++)
20041 tree it = (*offload_funcs)[i];
20042 targetm.record_offload_symbol (it);
20044 for (unsigned i = 0; i < num_vars; i++)
20046 tree it = (*offload_vars)[i];
20047 targetm.record_offload_symbol (it);
20052 /* Find the number of threads (POS = false), or thread number (POS =
20053 true) for an OpenACC region partitioned as MASK. Setup code
20054 required for the calculation is added to SEQ. */
20056 static tree
20057 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
20059 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
20060 unsigned ix;
20062 /* Start at gang level, and examine relevant dimension indices. */
20063 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20064 if (GOMP_DIM_MASK (ix) & mask)
20066 tree arg = build_int_cst (unsigned_type_node, ix);
20068 if (res)
20070 /* We had an outer index, so scale that by the size of
20071 this dimension. */
20072 tree n = create_tmp_var (integer_type_node);
20073 gimple *call
20074 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
20076 gimple_call_set_lhs (call, n);
20077 gimple_seq_add_stmt (seq, call);
20078 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
20080 if (pos)
20082 /* Determine index in this dimension. */
20083 tree id = create_tmp_var (integer_type_node);
20084 gimple *call = gimple_build_call_internal
20085 (IFN_GOACC_DIM_POS, 1, arg);
20087 gimple_call_set_lhs (call, id);
20088 gimple_seq_add_stmt (seq, call);
20089 if (res)
20090 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
20091 else
20092 res = id;
20096 if (res == NULL_TREE)
20097 res = integer_zero_node;
20099 return res;
20102 /* Transform IFN_GOACC_LOOP calls to actual code. See
20103 expand_oacc_for for where these are generated. At the vector
20104 level, we stride loops, such that each member of a warp will
20105 operate on adjacent iterations. At the worker and gang level,
20106 each gang/warp executes a set of contiguous iterations. Chunking
20107 can override this such that each iteration engine executes a
20108 contiguous chunk, and then moves on to stride to the next chunk. */
20110 static void
20111 oacc_xform_loop (gcall *call)
20113 gimple_stmt_iterator gsi = gsi_for_stmt (call);
20114 enum ifn_goacc_loop_kind code
20115 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
20116 tree dir = gimple_call_arg (call, 1);
20117 tree range = gimple_call_arg (call, 2);
20118 tree step = gimple_call_arg (call, 3);
20119 tree chunk_size = NULL_TREE;
20120 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
20121 tree lhs = gimple_call_lhs (call);
20122 tree type = TREE_TYPE (lhs);
20123 tree diff_type = TREE_TYPE (range);
20124 tree r = NULL_TREE;
20125 gimple_seq seq = NULL;
20126 bool chunking = false, striding = true;
20127 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
20128 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
20130 #ifdef ACCEL_COMPILER
20131 chunk_size = gimple_call_arg (call, 4);
20132 if (integer_minus_onep (chunk_size) /* Force static allocation. */
20133 || integer_zerop (chunk_size)) /* Default (also static). */
20135 /* If we're at the gang level, we want each to execute a
20136 contiguous run of iterations. Otherwise we want each element
20137 to stride. */
20138 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
20139 chunking = false;
20141 else
20143 /* Chunk of size 1 is striding. */
20144 striding = integer_onep (chunk_size);
20145 chunking = !striding;
20147 #endif
20149 /* striding=true, chunking=true
20150 -> invalid.
20151 striding=true, chunking=false
20152 -> chunks=1
20153 striding=false,chunking=true
20154 -> chunks=ceil (range/(chunksize*threads*step))
20155 striding=false,chunking=false
20156 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
20157 push_gimplify_context (true);
20159 switch (code)
20161 default: gcc_unreachable ();
20163 case IFN_GOACC_LOOP_CHUNKS:
20164 if (!chunking)
20165 r = build_int_cst (type, 1);
20166 else
20168 /* chunk_max
20169 = (range - dir) / (chunks * step * num_threads) + dir */
20170 tree per = oacc_thread_numbers (false, mask, &seq);
20171 per = fold_convert (type, per);
20172 chunk_size = fold_convert (type, chunk_size);
20173 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
20174 per = fold_build2 (MULT_EXPR, type, per, step);
20175 r = build2 (MINUS_EXPR, type, range, dir);
20176 r = build2 (PLUS_EXPR, type, r, per);
20177 r = build2 (TRUNC_DIV_EXPR, type, r, per);
20179 break;
20181 case IFN_GOACC_LOOP_STEP:
20183 /* If striding, step by the entire compute volume, otherwise
20184 step by the inner volume. */
20185 unsigned volume = striding ? mask : inner_mask;
20187 r = oacc_thread_numbers (false, volume, &seq);
20188 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
20190 break;
20192 case IFN_GOACC_LOOP_OFFSET:
20193 if (striding)
20195 r = oacc_thread_numbers (true, mask, &seq);
20196 r = fold_convert (diff_type, r);
20198 else
20200 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20201 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20202 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20203 inner_size, outer_size);
20205 volume = fold_convert (diff_type, volume);
20206 if (chunking)
20207 chunk_size = fold_convert (diff_type, chunk_size);
20208 else
20210 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20212 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20213 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20214 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20217 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20218 fold_convert (diff_type, inner_size));
20219 r = oacc_thread_numbers (true, outer_mask, &seq);
20220 r = fold_convert (diff_type, r);
20221 r = build2 (MULT_EXPR, diff_type, r, span);
20223 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
20224 inner = fold_convert (diff_type, inner);
20225 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
20227 if (chunking)
20229 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
20230 tree per
20231 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
20232 per = build2 (MULT_EXPR, diff_type, per, chunk);
20234 r = build2 (PLUS_EXPR, diff_type, r, per);
20237 r = fold_build2 (MULT_EXPR, diff_type, r, step);
20238 if (type != diff_type)
20239 r = fold_convert (type, r);
20240 break;
20242 case IFN_GOACC_LOOP_BOUND:
20243 if (striding)
20244 r = range;
20245 else
20247 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20248 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20249 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20250 inner_size, outer_size);
20252 volume = fold_convert (diff_type, volume);
20253 if (chunking)
20254 chunk_size = fold_convert (diff_type, chunk_size);
20255 else
20257 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20259 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20260 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20261 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20264 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20265 fold_convert (diff_type, inner_size));
20267 r = fold_build2 (MULT_EXPR, diff_type, span, step);
20269 tree offset = gimple_call_arg (call, 6);
20270 r = build2 (PLUS_EXPR, diff_type, r,
20271 fold_convert (diff_type, offset));
20272 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
20273 diff_type, r, range);
20275 if (diff_type != type)
20276 r = fold_convert (type, r);
20277 break;
20280 gimplify_assign (lhs, r, &seq);
20282 pop_gimplify_context (NULL);
20284 gsi_replace_with_seq (&gsi, seq, true);
20287 /* Default partitioned and minimum partitioned dimensions. */
20289 static int oacc_default_dims[GOMP_DIM_MAX];
20290 static int oacc_min_dims[GOMP_DIM_MAX];
20292 /* Parse the default dimension parameter. This is a set of
20293 :-separated optional compute dimensions. Each specified dimension
20294 is a positive integer. When device type support is added, it is
20295 planned to be a comma separated list of such compute dimensions,
20296 with all but the first prefixed by the colon-terminated device
20297 type. */
20299 static void
20300 oacc_parse_default_dims (const char *dims)
20302 int ix;
20304 for (ix = GOMP_DIM_MAX; ix--;)
20306 oacc_default_dims[ix] = -1;
20307 oacc_min_dims[ix] = 1;
20310 #ifndef ACCEL_COMPILER
20311 /* Cannot be overridden on the host. */
20312 dims = NULL;
20313 #endif
20314 if (dims)
20316 const char *pos = dims;
20318 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
20320 if (ix)
20322 if (*pos != ':')
20323 goto malformed;
20324 pos++;
20327 if (*pos != ':')
20329 long val;
20330 const char *eptr;
20332 errno = 0;
20333 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
20334 if (errno || val <= 0 || (int) val != val)
20335 goto malformed;
20336 pos = eptr;
20337 oacc_default_dims[ix] = (int) val;
20340 if (*pos)
20342 malformed:
20343 error_at (UNKNOWN_LOCATION,
20344 "-fopenacc-dim operand is malformed at '%s'", pos);
20348 /* Allow the backend to validate the dimensions. */
20349 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
20350 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
20353 /* Validate and update the dimensions for offloaded FN. ATTRS is the
20354 raw attribute. DIMS is an array of dimensions, which is filled in.
20355 LEVEL is the partitioning level of a routine, or -1 for an offload
20356 region itself. USED is the mask of partitioned execution in the
20357 function. */
20359 static void
20360 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
20362 tree purpose[GOMP_DIM_MAX];
20363 unsigned ix;
20364 tree pos = TREE_VALUE (attrs);
20365 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
20367 /* Make sure the attribute creator attached the dimension
20368 information. */
20369 gcc_assert (pos);
20371 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20373 purpose[ix] = TREE_PURPOSE (pos);
20374 tree val = TREE_VALUE (pos);
20375 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
20376 pos = TREE_CHAIN (pos);
20379 bool changed = targetm.goacc.validate_dims (fn, dims, level);
20381 /* Default anything left to 1 or a partitioned default. */
20382 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20383 if (dims[ix] < 0)
20385 /* The OpenACC spec says 'If the [num_gangs] clause is not
20386 specified, an implementation-defined default will be used;
20387 the default may depend on the code within the construct.'
20388 (2.5.6). Thus an implementation is free to choose
20389 non-unity default for a parallel region that doesn't have
20390 any gang-partitioned loops. However, it appears that there
20391 is a sufficient body of user code that expects non-gang
20392 partitioned regions to not execute in gang-redundant mode.
20393 So we (a) don't warn about the non-portability and (b) pick
20394 the minimum permissible dimension size when there is no
20395 partitioned execution. Otherwise we pick the global
20396 default for the dimension, which the user can control. The
20397 same wording and logic applies to num_workers and
20398 vector_length, however the worker- or vector- single
20399 execution doesn't have the same impact as gang-redundant
20400 execution. (If the minimum gang-level partioning is not 1,
20401 the target is probably too confusing.) */
20402 dims[ix] = (used & GOMP_DIM_MASK (ix)
20403 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
20404 changed = true;
20407 if (changed)
20409 /* Replace the attribute with new values. */
20410 pos = NULL_TREE;
20411 for (ix = GOMP_DIM_MAX; ix--;)
20413 pos = tree_cons (purpose[ix],
20414 build_int_cst (integer_type_node, dims[ix]),
20415 pos);
20416 if (is_kernel)
20417 TREE_PUBLIC (pos) = 1;
20419 replace_oacc_fn_attrib (fn, pos);
20423 /* Create an empty OpenACC loop structure at LOC. */
20425 static oacc_loop *
20426 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
20428 oacc_loop *loop = XCNEW (oacc_loop);
20430 loop->parent = parent;
20431 loop->child = loop->sibling = NULL;
20433 if (parent)
20435 loop->sibling = parent->child;
20436 parent->child = loop;
20439 loop->loc = loc;
20440 loop->marker = NULL;
20441 memset (loop->heads, 0, sizeof (loop->heads));
20442 memset (loop->tails, 0, sizeof (loop->tails));
20443 loop->routine = NULL_TREE;
20445 loop->mask = loop->flags = 0;
20446 loop->ifns = 0;
20447 loop->chunk_size = 0;
20448 loop->head_end = NULL;
20450 return loop;
20453 /* Create an outermost, dummy OpenACC loop for offloaded function
20454 DECL. */
20456 static oacc_loop *
20457 new_oacc_loop_outer (tree decl)
20459 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
20462 /* Start a new OpenACC loop structure beginning at head marker HEAD.
20463 Link into PARENT loop. Return the new loop. */
20465 static oacc_loop *
20466 new_oacc_loop (oacc_loop *parent, gcall *marker)
20468 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
20470 loop->marker = marker;
20472 /* TODO: This is where device_type flattening would occur for the loop
20473 flags. */
20475 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
20477 tree chunk_size = integer_zero_node;
20478 if (loop->flags & OLF_GANG_STATIC)
20479 chunk_size = gimple_call_arg (marker, 4);
20480 loop->chunk_size = chunk_size;
20482 return loop;
20485 /* Create a dummy loop encompassing a call to a openACC routine.
20486 Extract the routine's partitioning requirements. */
20488 static void
20489 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
20491 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
20492 int level = oacc_fn_attrib_level (attrs);
20494 gcc_assert (level >= 0);
20496 loop->marker = call;
20497 loop->routine = decl;
20498 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
20499 ^ (GOMP_DIM_MASK (level) - 1));
20502 /* Finish off the current OpenACC loop ending at tail marker TAIL.
20503 Return the parent loop. */
20505 static oacc_loop *
20506 finish_oacc_loop (oacc_loop *loop)
20508 /* If the loop has been collapsed, don't partition it. */
20509 if (!loop->ifns)
20510 loop->mask = loop->flags = 0;
20511 return loop->parent;
20514 /* Free all OpenACC loop structures within LOOP (inclusive). */
20516 static void
20517 free_oacc_loop (oacc_loop *loop)
20519 if (loop->sibling)
20520 free_oacc_loop (loop->sibling);
20521 if (loop->child)
20522 free_oacc_loop (loop->child);
20524 free (loop);
20527 /* Dump out the OpenACC loop head or tail beginning at FROM. */
20529 static void
20530 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
20531 const char *title, int level)
20533 enum ifn_unique_kind kind
20534 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20536 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
20537 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20539 gimple *stmt = gsi_stmt (gsi);
20541 if (is_gimple_call (stmt)
20542 && gimple_call_internal_p (stmt)
20543 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20545 enum ifn_unique_kind k
20546 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
20547 (gimple_call_arg (stmt, 0)));
20549 if (k == kind && stmt != from)
20550 break;
20552 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
20554 gsi_next (&gsi);
20555 while (gsi_end_p (gsi))
20556 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20560 /* Dump OpenACC loops LOOP, its siblings and its children. */
20562 static void
20563 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
20565 int ix;
20567 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
20568 loop->flags, loop->mask,
20569 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
20571 if (loop->marker)
20572 print_gimple_stmt (file, loop->marker, depth * 2, 0);
20574 if (loop->routine)
20575 fprintf (file, "%*sRoutine %s:%u:%s\n",
20576 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
20577 DECL_SOURCE_LINE (loop->routine),
20578 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
20580 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20581 if (loop->heads[ix])
20582 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
20583 for (ix = GOMP_DIM_MAX; ix--;)
20584 if (loop->tails[ix])
20585 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
20587 if (loop->child)
20588 dump_oacc_loop (file, loop->child, depth + 1);
20589 if (loop->sibling)
20590 dump_oacc_loop (file, loop->sibling, depth);
20593 void debug_oacc_loop (oacc_loop *);
20595 /* Dump loops to stderr. */
20597 DEBUG_FUNCTION void
20598 debug_oacc_loop (oacc_loop *loop)
20600 dump_oacc_loop (stderr, loop, 0);
20603 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
20604 structures as we go. By construction these loops are properly
20605 nested. */
20607 static void
20608 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
20610 int marker = 0;
20611 int remaining = 0;
20613 if (bb->flags & BB_VISITED)
20614 return;
20616 follow:
20617 bb->flags |= BB_VISITED;
20619 /* Scan for loop markers. */
20620 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
20621 gsi_next (&gsi))
20623 gimple *stmt = gsi_stmt (gsi);
20625 if (!is_gimple_call (stmt))
20626 continue;
20628 gcall *call = as_a <gcall *> (stmt);
20630 /* If this is a routine, make a dummy loop for it. */
20631 if (tree decl = gimple_call_fndecl (call))
20632 if (tree attrs = get_oacc_fn_attrib (decl))
20634 gcc_assert (!marker);
20635 new_oacc_loop_routine (loop, call, decl, attrs);
20638 if (!gimple_call_internal_p (call))
20639 continue;
20641 switch (gimple_call_internal_fn (call))
20643 default:
20644 break;
20646 case IFN_GOACC_LOOP:
20647 /* Count the goacc loop abstraction fns, to determine if the
20648 loop was collapsed already. */
20649 loop->ifns++;
20650 break;
20652 case IFN_UNIQUE:
20653 enum ifn_unique_kind kind
20654 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
20655 (gimple_call_arg (call, 0)));
20656 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
20657 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
20659 if (gimple_call_num_args (call) == 2)
20661 gcc_assert (marker && !remaining);
20662 marker = 0;
20663 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
20664 loop = finish_oacc_loop (loop);
20665 else
20666 loop->head_end = call;
20668 else
20670 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
20672 if (!marker)
20674 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20675 loop = new_oacc_loop (loop, call);
20676 remaining = count;
20678 gcc_assert (count == remaining);
20679 if (remaining)
20681 remaining--;
20682 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20683 loop->heads[marker] = call;
20684 else
20685 loop->tails[remaining] = call;
20687 marker++;
20692 if (remaining || marker)
20694 bb = single_succ (bb);
20695 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
20696 goto follow;
20699 /* Walk successor blocks. */
20700 edge e;
20701 edge_iterator ei;
20703 FOR_EACH_EDGE (e, ei, bb->succs)
20704 oacc_loop_discover_walk (loop, e->dest);
20707 /* LOOP is the first sibling. Reverse the order in place and return
20708 the new first sibling. Recurse to child loops. */
20710 static oacc_loop *
20711 oacc_loop_sibling_nreverse (oacc_loop *loop)
20713 oacc_loop *last = NULL;
20716 if (loop->child)
20717 loop->child = oacc_loop_sibling_nreverse (loop->child);
20719 oacc_loop *next = loop->sibling;
20720 loop->sibling = last;
20721 last = loop;
20722 loop = next;
20724 while (loop);
20726 return last;
20729 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
20730 the current function. */
20732 static oacc_loop *
20733 oacc_loop_discovery ()
20735 basic_block bb;
20737 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
20738 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
20740 /* The siblings were constructed in reverse order, reverse them so
20741 that diagnostics come out in an unsurprising order. */
20742 top = oacc_loop_sibling_nreverse (top);
20744 /* Reset the visited flags. */
20745 FOR_ALL_BB_FN (bb, cfun)
20746 bb->flags &= ~BB_VISITED;
20748 return top;
20751 /* Transform the abstract internal function markers starting at FROM
20752 to be for partitioning level LEVEL. Stop when we meet another HEAD
20753 or TAIL marker. */
20755 static void
20756 oacc_loop_xform_head_tail (gcall *from, int level)
20758 enum ifn_unique_kind kind
20759 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20760 tree replacement = build_int_cst (unsigned_type_node, level);
20762 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20764 gimple *stmt = gsi_stmt (gsi);
20766 if (is_gimple_call (stmt)
20767 && gimple_call_internal_p (stmt)
20768 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20770 enum ifn_unique_kind k
20771 = ((enum ifn_unique_kind)
20772 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
20774 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
20775 *gimple_call_arg_ptr (stmt, 2) = replacement;
20776 else if (k == kind && stmt != from)
20777 break;
20779 else if (is_gimple_call (stmt)
20780 && gimple_call_internal_p (stmt)
20781 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
20782 *gimple_call_arg_ptr (stmt, 3) = replacement;
20784 gsi_next (&gsi);
20785 while (gsi_end_p (gsi))
20786 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20790 /* Transform the IFN_GOACC_LOOP internal functions by providing the
20791 determined partitioning mask and chunking argument. END_MARKER
20792 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
20793 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
20794 the replacement partitioning mask and CHUNK_ARG is the replacement
20795 chunking arg. */
20797 static void
20798 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
20799 tree mask_arg, tree chunk_arg)
20801 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
20803 gcc_checking_assert (ifns);
20804 for (;;)
20806 for (; !gsi_end_p (gsi); gsi_next (&gsi))
20808 gimple *stmt = gsi_stmt (gsi);
20810 if (!is_gimple_call (stmt))
20811 continue;
20813 gcall *call = as_a <gcall *> (stmt);
20815 if (!gimple_call_internal_p (call))
20816 continue;
20818 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
20819 continue;
20821 *gimple_call_arg_ptr (call, 5) = mask_arg;
20822 *gimple_call_arg_ptr (call, 4) = chunk_arg;
20823 ifns--;
20824 if (!ifns)
20825 return;
20828 /* The LOOP_BOUND ifn could be in the single successor
20829 block. */
20830 basic_block bb = single_succ (gsi_bb (gsi));
20831 gsi = gsi_start_bb (bb);
20835 /* Process the discovered OpenACC loops, setting the correct
20836 partitioning level etc. */
20838 static void
20839 oacc_loop_process (oacc_loop *loop)
20841 if (loop->child)
20842 oacc_loop_process (loop->child);
20844 if (loop->mask && !loop->routine)
20846 int ix;
20847 unsigned mask = loop->mask;
20848 unsigned dim = GOMP_DIM_GANG;
20849 tree mask_arg = build_int_cst (unsigned_type_node, mask);
20850 tree chunk_arg = loop->chunk_size;
20852 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
20854 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
20856 gcc_assert (mask);
20858 while (!(GOMP_DIM_MASK (dim) & mask))
20859 dim++;
20861 oacc_loop_xform_head_tail (loop->heads[ix], dim);
20862 oacc_loop_xform_head_tail (loop->tails[ix], dim);
20864 mask ^= GOMP_DIM_MASK (dim);
20868 if (loop->sibling)
20869 oacc_loop_process (loop->sibling);
20872 /* Walk the OpenACC loop heirarchy checking and assigning the
20873 programmer-specified partitionings. OUTER_MASK is the partitioning
20874 this loop is contained within. Return mask of partitioning
20875 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
20876 bit. */
20878 static unsigned
20879 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
20881 unsigned this_mask = loop->mask;
20882 unsigned mask_all = 0;
20883 bool noisy = true;
20885 #ifdef ACCEL_COMPILER
20886 /* When device_type is supported, we want the device compiler to be
20887 noisy, if the loop parameters are device_type-specific. */
20888 noisy = false;
20889 #endif
20891 if (!loop->routine)
20893 bool auto_par = (loop->flags & OLF_AUTO) != 0;
20894 bool seq_par = (loop->flags & OLF_SEQ) != 0;
20896 this_mask = ((loop->flags >> OLF_DIM_BASE)
20897 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
20899 if ((this_mask != 0) + auto_par + seq_par > 1)
20901 if (noisy)
20902 error_at (loop->loc,
20903 seq_par
20904 ? "%<seq%> overrides other OpenACC loop specifiers"
20905 : "%<auto%> conflicts with other OpenACC loop specifiers");
20906 auto_par = false;
20907 loop->flags &= ~OLF_AUTO;
20908 if (seq_par)
20910 loop->flags &=
20911 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
20912 this_mask = 0;
20915 if (auto_par && (loop->flags & OLF_INDEPENDENT))
20916 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
20919 if (this_mask & outer_mask)
20921 const oacc_loop *outer;
20922 for (outer = loop->parent; outer; outer = outer->parent)
20923 if (outer->mask & this_mask)
20924 break;
20926 if (noisy)
20928 if (outer)
20930 error_at (loop->loc,
20931 "%s uses same OpenACC parallelism as containing loop",
20932 loop->routine ? "routine call" : "inner loop");
20933 inform (outer->loc, "containing loop here");
20935 else
20936 error_at (loop->loc,
20937 "%s uses OpenACC parallelism disallowed by containing routine",
20938 loop->routine ? "routine call" : "loop");
20940 if (loop->routine)
20941 inform (DECL_SOURCE_LOCATION (loop->routine),
20942 "routine %qD declared here", loop->routine);
20944 this_mask &= ~outer_mask;
20946 else
20948 unsigned outermost = this_mask & -this_mask;
20950 if (outermost && outermost <= outer_mask)
20952 if (noisy)
20954 error_at (loop->loc,
20955 "incorrectly nested OpenACC loop parallelism");
20957 const oacc_loop *outer;
20958 for (outer = loop->parent;
20959 outer->flags && outer->flags < outermost;
20960 outer = outer->parent)
20961 continue;
20962 inform (outer->loc, "containing loop here");
20965 this_mask &= ~outermost;
20969 loop->mask = this_mask;
20970 mask_all |= this_mask;
20972 if (loop->child)
20973 mask_all |= oacc_loop_fixed_partitions (loop->child,
20974 outer_mask | this_mask);
20976 if (loop->sibling)
20977 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
20979 return mask_all;
20982 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
20983 OUTER_MASK is the partitioning this loop is contained within.
20984 Return the cumulative partitioning used by this loop, siblings and
20985 children. */
20987 static unsigned
20988 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
20990 unsigned inner_mask = 0;
20991 bool noisy = true;
20993 #ifdef ACCEL_COMPILER
20994 /* When device_type is supported, we want the device compiler to be
20995 noisy, if the loop parameters are device_type-specific. */
20996 noisy = false;
20997 #endif
20999 if (loop->child)
21000 inner_mask |= oacc_loop_auto_partitions (loop->child,
21001 outer_mask | loop->mask);
21003 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
21005 unsigned this_mask = 0;
21007 /* Determine the outermost partitioning used within this loop. */
21008 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
21009 this_mask = (this_mask & -this_mask);
21011 /* Pick the partitioning just inside that one. */
21012 this_mask >>= 1;
21014 /* And avoid picking one use by an outer loop. */
21015 this_mask &= ~outer_mask;
21017 if (!this_mask && noisy)
21018 warning_at (loop->loc, 0,
21019 "insufficient partitioning available to parallelize loop");
21021 if (dump_file)
21022 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
21023 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
21024 this_mask);
21026 loop->mask = this_mask;
21028 inner_mask |= loop->mask;
21030 if (loop->sibling)
21031 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
21033 return inner_mask;
21036 /* Walk the OpenACC loop heirarchy to check and assign partitioning
21037 axes. Return mask of partitioning. */
21039 static unsigned
21040 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
21042 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
21044 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
21046 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
21047 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
21049 return mask_all;
21052 /* Default fork/join early expander. Delete the function calls if
21053 there is no RTL expander. */
21055 bool
21056 default_goacc_fork_join (gcall *ARG_UNUSED (call),
21057 const int *ARG_UNUSED (dims), bool is_fork)
21059 if (is_fork)
21060 return targetm.have_oacc_fork ();
21061 else
21062 return targetm.have_oacc_join ();
21065 /* Default goacc.reduction early expander.
21067 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
21068 If RES_PTR is not integer-zerop:
21069 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
21070 TEARDOWN - emit '*RES_PTR = VAR'
21071 If LHS is not NULL
21072 emit 'LHS = VAR' */
21074 void
21075 default_goacc_reduction (gcall *call)
21077 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
21078 gimple_stmt_iterator gsi = gsi_for_stmt (call);
21079 tree lhs = gimple_call_lhs (call);
21080 tree var = gimple_call_arg (call, 2);
21081 gimple_seq seq = NULL;
21083 if (code == IFN_GOACC_REDUCTION_SETUP
21084 || code == IFN_GOACC_REDUCTION_TEARDOWN)
21086 /* Setup and Teardown need to copy from/to the receiver object,
21087 if there is one. */
21088 tree ref_to_res = gimple_call_arg (call, 1);
21090 if (!integer_zerop (ref_to_res))
21092 tree dst = build_simple_mem_ref (ref_to_res);
21093 tree src = var;
21095 if (code == IFN_GOACC_REDUCTION_SETUP)
21097 src = dst;
21098 dst = lhs;
21099 lhs = NULL;
21101 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
21105 /* Copy VAR to LHS, if there is an LHS. */
21106 if (lhs)
21107 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
21109 gsi_replace_with_seq (&gsi, seq, true);
21112 /* Main entry point for oacc transformations which run on the device
21113 compiler after LTO, so we know what the target device is at this
21114 point (including the host fallback). */
21116 static unsigned int
21117 execute_oacc_device_lower ()
21119 tree attrs = get_oacc_fn_attrib (current_function_decl);
21121 if (!attrs)
21122 /* Not an offloaded function. */
21123 return 0;
21125 /* Parse the default dim argument exactly once. */
21126 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
21128 oacc_parse_default_dims (flag_openacc_dims);
21129 flag_openacc_dims = (char *)&flag_openacc_dims;
21132 /* Discover, partition and process the loops. */
21133 oacc_loop *loops = oacc_loop_discovery ();
21134 int fn_level = oacc_fn_attrib_level (attrs);
21136 if (dump_file)
21137 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
21138 ? "Function is kernels offload\n"
21139 : fn_level < 0 ? "Function is parallel offload\n"
21140 : "Function is routine level %d\n", fn_level);
21142 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
21143 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
21144 int dims[GOMP_DIM_MAX];
21146 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
21148 if (dump_file)
21150 const char *comma = "Compute dimensions [";
21151 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
21152 fprintf (dump_file, "%s%d", comma, dims[ix]);
21153 fprintf (dump_file, "]\n");
21156 oacc_loop_process (loops);
21157 if (dump_file)
21159 fprintf (dump_file, "OpenACC loops\n");
21160 dump_oacc_loop (dump_file, loops, 0);
21161 fprintf (dump_file, "\n");
21164 /* Offloaded targets may introduce new basic blocks, which require
21165 dominance information to update SSA. */
21166 calculate_dominance_info (CDI_DOMINATORS);
21168 /* Now lower internal loop functions to target-specific code
21169 sequences. */
21170 basic_block bb;
21171 FOR_ALL_BB_FN (bb, cfun)
21172 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
21174 gimple *stmt = gsi_stmt (gsi);
21175 if (!is_gimple_call (stmt))
21177 gsi_next (&gsi);
21178 continue;
21181 gcall *call = as_a <gcall *> (stmt);
21182 if (!gimple_call_internal_p (call))
21184 gsi_next (&gsi);
21185 continue;
21188 /* Rewind to allow rescan. */
21189 gsi_prev (&gsi);
21190 bool rescan = false, remove = false;
21191 enum internal_fn ifn_code = gimple_call_internal_fn (call);
21193 switch (ifn_code)
21195 default: break;
21197 case IFN_GOACC_LOOP:
21198 oacc_xform_loop (call);
21199 rescan = true;
21200 break;
21202 case IFN_GOACC_REDUCTION:
21203 /* Mark the function for SSA renaming. */
21204 mark_virtual_operands_for_renaming (cfun);
21206 /* If the level is -1, this ended up being an unused
21207 axis. Handle as a default. */
21208 if (integer_minus_onep (gimple_call_arg (call, 3)))
21209 default_goacc_reduction (call);
21210 else
21211 targetm.goacc.reduction (call);
21212 rescan = true;
21213 break;
21215 case IFN_UNIQUE:
21217 enum ifn_unique_kind kind
21218 = ((enum ifn_unique_kind)
21219 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
21221 switch (kind)
21223 default:
21224 gcc_unreachable ();
21226 case IFN_UNIQUE_OACC_FORK:
21227 case IFN_UNIQUE_OACC_JOIN:
21228 if (integer_minus_onep (gimple_call_arg (call, 2)))
21229 remove = true;
21230 else if (!targetm.goacc.fork_join
21231 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
21232 remove = true;
21233 break;
21235 case IFN_UNIQUE_OACC_HEAD_MARK:
21236 case IFN_UNIQUE_OACC_TAIL_MARK:
21237 remove = true;
21238 break;
21240 break;
21244 if (gsi_end_p (gsi))
21245 /* We rewound past the beginning of the BB. */
21246 gsi = gsi_start_bb (bb);
21247 else
21248 /* Undo the rewind. */
21249 gsi_next (&gsi);
21251 if (remove)
21253 if (gimple_vdef (call))
21254 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
21255 if (gimple_call_lhs (call))
21257 /* Propagate the data dependency var. */
21258 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
21259 gimple_call_arg (call, 1));
21260 gsi_replace (&gsi, ass, false);
21262 else
21263 gsi_remove (&gsi, true);
21265 else if (!rescan)
21266 /* If not rescanning, advance over the call. */
21267 gsi_next (&gsi);
21270 free_oacc_loop (loops);
21272 return 0;
21275 /* Default launch dimension validator. Force everything to 1. A
21276 backend that wants to provide larger dimensions must override this
21277 hook. */
21279 bool
21280 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
21281 int ARG_UNUSED (fn_level))
21283 bool changed = false;
21285 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
21287 if (dims[ix] != 1)
21289 dims[ix] = 1;
21290 changed = true;
21294 return changed;
21297 /* Default dimension bound is unknown on accelerator and 1 on host. */
21300 default_goacc_dim_limit (int ARG_UNUSED (axis))
21302 #ifdef ACCEL_COMPILER
21303 return 0;
21304 #else
21305 return 1;
21306 #endif
21309 namespace {
21311 const pass_data pass_data_oacc_device_lower =
21313 GIMPLE_PASS, /* type */
21314 "oaccdevlow", /* name */
21315 OPTGROUP_NONE, /* optinfo_flags */
21316 TV_NONE, /* tv_id */
21317 PROP_cfg, /* properties_required */
21318 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
21319 0, /* properties_destroyed */
21320 0, /* todo_flags_start */
21321 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
21324 class pass_oacc_device_lower : public gimple_opt_pass
21326 public:
21327 pass_oacc_device_lower (gcc::context *ctxt)
21328 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
21331 /* opt_pass methods: */
21332 virtual unsigned int execute (function *)
21334 bool gate = flag_openacc != 0;
21336 if (!gate)
21337 return 0;
21339 return execute_oacc_device_lower ();
21342 }; // class pass_oacc_device_lower
21344 } // anon namespace
21346 gimple_opt_pass *
21347 make_pass_oacc_device_lower (gcc::context *ctxt)
21349 return new pass_oacc_device_lower (ctxt);
21352 /* "omp declare target link" handling pass. */
21354 namespace {
21356 const pass_data pass_data_omp_target_link =
21358 GIMPLE_PASS, /* type */
21359 "omptargetlink", /* name */
21360 OPTGROUP_NONE, /* optinfo_flags */
21361 TV_NONE, /* tv_id */
21362 PROP_ssa, /* properties_required */
21363 0, /* properties_provided */
21364 0, /* properties_destroyed */
21365 0, /* todo_flags_start */
21366 TODO_update_ssa, /* todo_flags_finish */
21369 class pass_omp_target_link : public gimple_opt_pass
21371 public:
21372 pass_omp_target_link (gcc::context *ctxt)
21373 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
21376 /* opt_pass methods: */
21377 virtual bool gate (function *fun)
21379 #ifdef ACCEL_COMPILER
21380 tree attrs = DECL_ATTRIBUTES (fun->decl);
21381 return lookup_attribute ("omp declare target", attrs)
21382 || lookup_attribute ("omp target entrypoint", attrs);
21383 #else
21384 (void) fun;
21385 return false;
21386 #endif
21389 virtual unsigned execute (function *);
21392 /* Callback for walk_gimple_stmt used to scan for link var operands. */
21394 static tree
21395 find_link_var_op (tree *tp, int *walk_subtrees, void *)
21397 tree t = *tp;
21399 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
21400 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
21402 *walk_subtrees = 0;
21403 return t;
21406 return NULL_TREE;
21409 unsigned
21410 pass_omp_target_link::execute (function *fun)
21412 basic_block bb;
21413 FOR_EACH_BB_FN (bb, fun)
21415 gimple_stmt_iterator gsi;
21416 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
21417 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
21418 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
21421 return 0;
21424 } // anon namespace
21426 gimple_opt_pass *
21427 make_pass_omp_target_link (gcc::context *ctxt)
21429 return new pass_omp_target_link (ctxt);
21432 #include "gt-omp-low.h"