Some fixes for profile test cases for autofdo
[official-gcc.git] / gcc / omp-low.c
blobecba096c5c169bb4933937339efdb7851240b2c0
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83 #include "symbol-summary.h"
84 #include "hsa.h"
85 #include "params.h"
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
92 expressions.
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
102 struct omp_region
104 /* The enclosing region. */
105 struct omp_region *outer;
107 /* First child region. */
108 struct omp_region *inner;
110 /* Next peer region. */
111 struct omp_region *next;
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 basic_block exit;
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 basic_block cont;
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind;
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple *stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
201 struct omp_for_data_loop
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
207 /* A structure describing the main elements of a parallel loop. */
209 struct omp_for_data
211 struct omp_for_data_loop loop;
212 tree chunk_size;
213 gomp_for *for_stmt;
214 tree pre, iter_type;
215 int collapse;
216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
218 unsigned char sched_modifiers;
219 enum omp_clause_schedule_kind sched_kind;
220 struct omp_for_data_loop *loops;
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
226 struct oacc_loop
228 oacc_loop *parent; /* Containing loop. */
230 oacc_loop *child; /* First inner loop. */
232 oacc_loop *sibling; /* Next loop within same parent. */
234 location_t loc; /* Location of the loop start. */
236 gcall *marker; /* Initial head marker. */
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
241 tree routine; /* Pseudo-loop enclosing a routine. */
243 unsigned mask; /* Partitioning mask. */
244 unsigned inner; /* Partitioning of inner loops. */
245 unsigned flags; /* Partitioning flags. */
246 unsigned ifns; /* Contained loop abstraction functions. */
247 tree chunk_size; /* Chunk size. */
248 gcall *head_end; /* Final marker of head sequence. */
251 /* Flags for an OpenACC loop. */
253 enum oacc_loop_flags {
254 OLF_SEQ = 1u << 0, /* Explicitly sequential */
255 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
256 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
257 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
259 /* Explicitly specified loop axes. */
260 OLF_DIM_BASE = 4,
261 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
262 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
263 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
265 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
269 static splay_tree all_contexts;
270 static int taskreg_nesting_level;
271 static int target_nesting_level;
272 static struct omp_region *root_omp_region;
273 static bitmap task_shared_vars;
274 static vec<omp_context *> taskreg_contexts;
275 static bool omp_any_child_fn_dumped;
277 static void scan_omp (gimple_seq *, omp_context *);
278 static tree scan_omp_1_op (tree *, int *, void *);
279 static gphi *find_phi_with_arg_on_edge (tree, edge);
281 #define WALK_SUBSTMTS \
282 case GIMPLE_BIND: \
283 case GIMPLE_TRY: \
284 case GIMPLE_CATCH: \
285 case GIMPLE_EH_FILTER: \
286 case GIMPLE_TRANSACTION: \
287 /* The sub-statements for these should be walked. */ \
288 *handled_ops_p = false; \
289 break;
291 /* Return true if CTX corresponds to an oacc parallel region. */
293 static bool
294 is_oacc_parallel (omp_context *ctx)
296 enum gimple_code outer_type = gimple_code (ctx->stmt);
297 return ((outer_type == GIMPLE_OMP_TARGET)
298 && (gimple_omp_target_kind (ctx->stmt)
299 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
302 /* Return true if CTX corresponds to an oacc kernels region. */
304 static bool
305 is_oacc_kernels (omp_context *ctx)
307 enum gimple_code outer_type = gimple_code (ctx->stmt);
308 return ((outer_type == GIMPLE_OMP_TARGET)
309 && (gimple_omp_target_kind (ctx->stmt)
310 == GF_OMP_TARGET_KIND_OACC_KERNELS));
313 /* If DECL is the artificial dummy VAR_DECL created for non-static
314 data member privatization, return the underlying "this" parameter,
315 otherwise return NULL. */
317 tree
318 omp_member_access_dummy_var (tree decl)
320 if (!VAR_P (decl)
321 || !DECL_ARTIFICIAL (decl)
322 || !DECL_IGNORED_P (decl)
323 || !DECL_HAS_VALUE_EXPR_P (decl)
324 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
325 return NULL_TREE;
327 tree v = DECL_VALUE_EXPR (decl);
328 if (TREE_CODE (v) != COMPONENT_REF)
329 return NULL_TREE;
331 while (1)
332 switch (TREE_CODE (v))
334 case COMPONENT_REF:
335 case MEM_REF:
336 case INDIRECT_REF:
337 CASE_CONVERT:
338 case POINTER_PLUS_EXPR:
339 v = TREE_OPERAND (v, 0);
340 continue;
341 case PARM_DECL:
342 if (DECL_CONTEXT (v) == current_function_decl
343 && DECL_ARTIFICIAL (v)
344 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
345 return v;
346 return NULL_TREE;
347 default:
348 return NULL_TREE;
352 /* Helper for unshare_and_remap, called through walk_tree. */
354 static tree
355 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
357 tree *pair = (tree *) data;
358 if (*tp == pair[0])
360 *tp = unshare_expr (pair[1]);
361 *walk_subtrees = 0;
363 else if (IS_TYPE_OR_DECL_P (*tp))
364 *walk_subtrees = 0;
365 return NULL_TREE;
368 /* Return unshare_expr (X) with all occurrences of FROM
369 replaced with TO. */
371 static tree
372 unshare_and_remap (tree x, tree from, tree to)
374 tree pair[2] = { from, to };
375 x = unshare_expr (x);
376 walk_tree (&x, unshare_and_remap_1, pair, NULL);
377 return x;
380 /* Holds offload tables with decls. */
381 vec<tree, va_gc> *offload_funcs, *offload_vars;
383 /* Convenience function for calling scan_omp_1_op on tree operands. */
385 static inline tree
386 scan_omp_op (tree *tp, omp_context *ctx)
388 struct walk_stmt_info wi;
390 memset (&wi, 0, sizeof (wi));
391 wi.info = ctx;
392 wi.want_locations = true;
394 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
397 static void lower_omp (gimple_seq *, omp_context *);
398 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
399 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
401 /* Find an OMP clause of type KIND within CLAUSES. */
403 tree
404 find_omp_clause (tree clauses, enum omp_clause_code kind)
406 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
407 if (OMP_CLAUSE_CODE (clauses) == kind)
408 return clauses;
410 return NULL_TREE;
413 /* Return true if CTX is for an omp parallel. */
415 static inline bool
416 is_parallel_ctx (omp_context *ctx)
418 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
422 /* Return true if CTX is for an omp task. */
424 static inline bool
425 is_task_ctx (omp_context *ctx)
427 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
431 /* Return true if CTX is for an omp taskloop. */
433 static inline bool
434 is_taskloop_ctx (omp_context *ctx)
436 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
437 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
441 /* Return true if CTX is for an omp parallel or omp task. */
443 static inline bool
444 is_taskreg_ctx (omp_context *ctx)
446 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
450 /* Return true if REGION is a combined parallel+workshare region. */
452 static inline bool
453 is_combined_parallel (struct omp_region *region)
455 return region->is_combined_parallel;
458 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
459 GT_EXPR. */
461 static void
462 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
464 switch (*cond_code)
466 case LT_EXPR:
467 case GT_EXPR:
468 case NE_EXPR:
469 break;
470 case LE_EXPR:
471 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
472 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
473 else
474 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
475 build_int_cst (TREE_TYPE (*n2), 1));
476 *cond_code = LT_EXPR;
477 break;
478 case GE_EXPR:
479 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
480 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
481 else
482 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
483 build_int_cst (TREE_TYPE (*n2), 1));
484 *cond_code = GT_EXPR;
485 break;
486 default:
487 gcc_unreachable ();
491 /* Return the looping step from INCR, extracted from the step of a gimple omp
492 for statement. */
494 static tree
495 get_omp_for_step_from_incr (location_t loc, tree incr)
497 tree step;
498 switch (TREE_CODE (incr))
500 case PLUS_EXPR:
501 step = TREE_OPERAND (incr, 1);
502 break;
503 case POINTER_PLUS_EXPR:
504 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
505 break;
506 case MINUS_EXPR:
507 step = TREE_OPERAND (incr, 1);
508 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
509 break;
510 default:
511 gcc_unreachable ();
513 return step;
516 /* Extract the header elements of parallel loop FOR_STMT and store
517 them into *FD. */
519 static void
520 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
521 struct omp_for_data_loop *loops)
523 tree t, var, *collapse_iter, *collapse_count;
524 tree count = NULL_TREE, iter_type = long_integer_type_node;
525 struct omp_for_data_loop *loop;
526 int i;
527 struct omp_for_data_loop dummy_loop;
528 location_t loc = gimple_location (for_stmt);
529 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
530 bool distribute = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_DISTRIBUTE;
532 bool taskloop = gimple_omp_for_kind (for_stmt)
533 == GF_OMP_FOR_KIND_TASKLOOP;
534 tree iterv, countv;
536 fd->for_stmt = for_stmt;
537 fd->pre = NULL;
538 if (gimple_omp_for_collapse (for_stmt) > 1)
539 fd->loops = loops;
540 else
541 fd->loops = &fd->loop;
543 fd->have_nowait = distribute || simd;
544 fd->have_ordered = false;
545 fd->collapse = 1;
546 fd->ordered = 0;
547 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
548 fd->sched_modifiers = 0;
549 fd->chunk_size = NULL_TREE;
550 fd->simd_schedule = false;
551 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
552 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
553 collapse_iter = NULL;
554 collapse_count = NULL;
556 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
557 switch (OMP_CLAUSE_CODE (t))
559 case OMP_CLAUSE_NOWAIT:
560 fd->have_nowait = true;
561 break;
562 case OMP_CLAUSE_ORDERED:
563 fd->have_ordered = true;
564 if (OMP_CLAUSE_ORDERED_EXPR (t))
565 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
566 break;
567 case OMP_CLAUSE_SCHEDULE:
568 gcc_assert (!distribute && !taskloop);
569 fd->sched_kind
570 = (enum omp_clause_schedule_kind)
571 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
572 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
573 & ~OMP_CLAUSE_SCHEDULE_MASK);
574 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
575 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
576 break;
577 case OMP_CLAUSE_DIST_SCHEDULE:
578 gcc_assert (distribute);
579 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
580 break;
581 case OMP_CLAUSE_COLLAPSE:
582 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
583 if (fd->collapse > 1)
585 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
586 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
588 break;
589 default:
590 break;
592 if (fd->ordered && fd->collapse == 1 && loops != NULL)
594 fd->loops = loops;
595 iterv = NULL_TREE;
596 countv = NULL_TREE;
597 collapse_iter = &iterv;
598 collapse_count = &countv;
601 /* FIXME: for now map schedule(auto) to schedule(static).
602 There should be analysis to determine whether all iterations
603 are approximately the same amount of work (then schedule(static)
604 is best) or if it varies (then schedule(dynamic,N) is better). */
605 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
607 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
608 gcc_assert (fd->chunk_size == NULL);
610 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
611 if (taskloop)
612 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
613 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
614 gcc_assert (fd->chunk_size == NULL);
615 else if (fd->chunk_size == NULL)
617 /* We only need to compute a default chunk size for ordered
618 static loops and dynamic loops. */
619 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
620 || fd->have_ordered)
621 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
622 ? integer_zero_node : integer_one_node;
625 int cnt = fd->ordered ? fd->ordered : fd->collapse;
626 for (i = 0; i < cnt; i++)
628 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
629 loop = &fd->loop;
630 else if (loops != NULL)
631 loop = loops + i;
632 else
633 loop = &dummy_loop;
635 loop->v = gimple_omp_for_index (for_stmt, i);
636 gcc_assert (SSA_VAR_P (loop->v));
637 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
638 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
639 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
640 loop->n1 = gimple_omp_for_initial (for_stmt, i);
642 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
643 loop->n2 = gimple_omp_for_final (for_stmt, i);
644 gcc_assert (loop->cond_code != NE_EXPR
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
647 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
649 t = gimple_omp_for_incr (for_stmt, i);
650 gcc_assert (TREE_OPERAND (t, 0) == var);
651 loop->step = get_omp_for_step_from_incr (loc, t);
653 if (simd
654 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
655 && !fd->have_ordered))
657 if (fd->collapse == 1)
658 iter_type = TREE_TYPE (loop->v);
659 else if (i == 0
660 || TYPE_PRECISION (iter_type)
661 < TYPE_PRECISION (TREE_TYPE (loop->v)))
662 iter_type
663 = build_nonstandard_integer_type
664 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
666 else if (iter_type != long_long_unsigned_type_node)
668 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
669 iter_type = long_long_unsigned_type_node;
670 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
671 && TYPE_PRECISION (TREE_TYPE (loop->v))
672 >= TYPE_PRECISION (iter_type))
674 tree n;
676 if (loop->cond_code == LT_EXPR)
677 n = fold_build2_loc (loc,
678 PLUS_EXPR, TREE_TYPE (loop->v),
679 loop->n2, loop->step);
680 else
681 n = loop->n1;
682 if (TREE_CODE (n) != INTEGER_CST
683 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
684 iter_type = long_long_unsigned_type_node;
686 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
687 > TYPE_PRECISION (iter_type))
689 tree n1, n2;
691 if (loop->cond_code == LT_EXPR)
693 n1 = loop->n1;
694 n2 = fold_build2_loc (loc,
695 PLUS_EXPR, TREE_TYPE (loop->v),
696 loop->n2, loop->step);
698 else
700 n1 = fold_build2_loc (loc,
701 MINUS_EXPR, TREE_TYPE (loop->v),
702 loop->n2, loop->step);
703 n2 = loop->n1;
705 if (TREE_CODE (n1) != INTEGER_CST
706 || TREE_CODE (n2) != INTEGER_CST
707 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
708 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
709 iter_type = long_long_unsigned_type_node;
713 if (i >= fd->collapse)
714 continue;
716 if (collapse_count && *collapse_count == NULL)
718 t = fold_binary (loop->cond_code, boolean_type_node,
719 fold_convert (TREE_TYPE (loop->v), loop->n1),
720 fold_convert (TREE_TYPE (loop->v), loop->n2));
721 if (t && integer_zerop (t))
722 count = build_zero_cst (long_long_unsigned_type_node);
723 else if ((i == 0 || count != NULL_TREE)
724 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
725 && TREE_CONSTANT (loop->n1)
726 && TREE_CONSTANT (loop->n2)
727 && TREE_CODE (loop->step) == INTEGER_CST)
729 tree itype = TREE_TYPE (loop->v);
731 if (POINTER_TYPE_P (itype))
732 itype = signed_type_for (itype);
733 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
734 t = fold_build2_loc (loc,
735 PLUS_EXPR, itype,
736 fold_convert_loc (loc, itype, loop->step), t);
737 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
738 fold_convert_loc (loc, itype, loop->n2));
739 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
740 fold_convert_loc (loc, itype, loop->n1));
741 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
742 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
743 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
744 fold_build1_loc (loc, NEGATE_EXPR, itype,
745 fold_convert_loc (loc, itype,
746 loop->step)));
747 else
748 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
749 fold_convert_loc (loc, itype, loop->step));
750 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
751 if (count != NULL_TREE)
752 count = fold_build2_loc (loc,
753 MULT_EXPR, long_long_unsigned_type_node,
754 count, t);
755 else
756 count = t;
757 if (TREE_CODE (count) != INTEGER_CST)
758 count = NULL_TREE;
760 else if (count && !integer_zerop (count))
761 count = NULL_TREE;
765 if (count
766 && !simd
767 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
768 || fd->have_ordered))
770 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
771 iter_type = long_long_unsigned_type_node;
772 else
773 iter_type = long_integer_type_node;
775 else if (collapse_iter && *collapse_iter != NULL)
776 iter_type = TREE_TYPE (*collapse_iter);
777 fd->iter_type = iter_type;
778 if (collapse_iter && *collapse_iter == NULL)
779 *collapse_iter = create_tmp_var (iter_type, ".iter");
780 if (collapse_count && *collapse_count == NULL)
782 if (count)
783 *collapse_count = fold_convert_loc (loc, iter_type, count);
784 else
785 *collapse_count = create_tmp_var (iter_type, ".count");
788 if (fd->collapse > 1 || (fd->ordered && loops))
790 fd->loop.v = *collapse_iter;
791 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
792 fd->loop.n2 = *collapse_count;
793 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
794 fd->loop.cond_code = LT_EXPR;
796 else if (loops)
797 loops[0] = fd->loop;
801 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
802 is the immediate dominator of PAR_ENTRY_BB, return true if there
803 are no data dependencies that would prevent expanding the parallel
804 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
806 When expanding a combined parallel+workshare region, the call to
807 the child function may need additional arguments in the case of
808 GIMPLE_OMP_FOR regions. In some cases, these arguments are
809 computed out of variables passed in from the parent to the child
810 via 'struct .omp_data_s'. For instance:
812 #pragma omp parallel for schedule (guided, i * 4)
813 for (j ...)
815 Is lowered into:
817 # BLOCK 2 (PAR_ENTRY_BB)
818 .omp_data_o.i = i;
819 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
821 # BLOCK 3 (WS_ENTRY_BB)
822 .omp_data_i = &.omp_data_o;
823 D.1667 = .omp_data_i->i;
824 D.1598 = D.1667 * 4;
825 #pragma omp for schedule (guided, D.1598)
827 When we outline the parallel region, the call to the child function
828 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
829 that value is computed *after* the call site. So, in principle we
830 cannot do the transformation.
832 To see whether the code in WS_ENTRY_BB blocks the combined
833 parallel+workshare call, we collect all the variables used in the
834 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
835 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
836 call.
838 FIXME. If we had the SSA form built at this point, we could merely
839 hoist the code in block 3 into block 2 and be done with it. But at
840 this point we don't have dataflow information and though we could
841 hack something up here, it is really not worth the aggravation. */
843 static bool
844 workshare_safe_to_combine_p (basic_block ws_entry_bb)
846 struct omp_for_data fd;
847 gimple *ws_stmt = last_stmt (ws_entry_bb);
849 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
850 return true;
852 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
854 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
856 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
857 return false;
858 if (fd.iter_type != long_integer_type_node)
859 return false;
861 /* FIXME. We give up too easily here. If any of these arguments
862 are not constants, they will likely involve variables that have
863 been mapped into fields of .omp_data_s for sharing with the child
864 function. With appropriate data flow, it would be possible to
865 see through this. */
866 if (!is_gimple_min_invariant (fd.loop.n1)
867 || !is_gimple_min_invariant (fd.loop.n2)
868 || !is_gimple_min_invariant (fd.loop.step)
869 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
870 return false;
872 return true;
876 static int omp_max_vf (void);
878 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
879 presence (SIMD_SCHEDULE). */
881 static tree
882 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
884 if (!simd_schedule)
885 return chunk_size;
887 int vf = omp_max_vf ();
888 if (vf == 1)
889 return chunk_size;
891 tree type = TREE_TYPE (chunk_size);
892 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
893 build_int_cst (type, vf - 1));
894 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
895 build_int_cst (type, -vf));
899 /* Collect additional arguments needed to emit a combined
900 parallel+workshare call. WS_STMT is the workshare directive being
901 expanded. */
903 static vec<tree, va_gc> *
904 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
906 tree t;
907 location_t loc = gimple_location (ws_stmt);
908 vec<tree, va_gc> *ws_args;
910 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
912 struct omp_for_data fd;
913 tree n1, n2;
915 extract_omp_for_data (for_stmt, &fd, NULL);
916 n1 = fd.loop.n1;
917 n2 = fd.loop.n2;
919 if (gimple_omp_for_combined_into_p (for_stmt))
921 tree innerc
922 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
923 OMP_CLAUSE__LOOPTEMP_);
924 gcc_assert (innerc);
925 n1 = OMP_CLAUSE_DECL (innerc);
926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
927 OMP_CLAUSE__LOOPTEMP_);
928 gcc_assert (innerc);
929 n2 = OMP_CLAUSE_DECL (innerc);
932 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
934 t = fold_convert_loc (loc, long_integer_type_node, n1);
935 ws_args->quick_push (t);
937 t = fold_convert_loc (loc, long_integer_type_node, n2);
938 ws_args->quick_push (t);
940 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
941 ws_args->quick_push (t);
943 if (fd.chunk_size)
945 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
946 t = omp_adjust_chunk_size (t, fd.simd_schedule);
947 ws_args->quick_push (t);
950 return ws_args;
952 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
954 /* Number of sections is equal to the number of edges from the
955 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
956 the exit of the sections region. */
957 basic_block bb = single_succ (gimple_bb (ws_stmt));
958 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
959 vec_alloc (ws_args, 1);
960 ws_args->quick_push (t);
961 return ws_args;
964 gcc_unreachable ();
968 /* Discover whether REGION is a combined parallel+workshare region. */
970 static void
971 determine_parallel_type (struct omp_region *region)
973 basic_block par_entry_bb, par_exit_bb;
974 basic_block ws_entry_bb, ws_exit_bb;
976 if (region == NULL || region->inner == NULL
977 || region->exit == NULL || region->inner->exit == NULL
978 || region->inner->cont == NULL)
979 return;
981 /* We only support parallel+for and parallel+sections. */
982 if (region->type != GIMPLE_OMP_PARALLEL
983 || (region->inner->type != GIMPLE_OMP_FOR
984 && region->inner->type != GIMPLE_OMP_SECTIONS))
985 return;
987 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
988 WS_EXIT_BB -> PAR_EXIT_BB. */
989 par_entry_bb = region->entry;
990 par_exit_bb = region->exit;
991 ws_entry_bb = region->inner->entry;
992 ws_exit_bb = region->inner->exit;
994 if (single_succ (par_entry_bb) == ws_entry_bb
995 && single_succ (ws_exit_bb) == par_exit_bb
996 && workshare_safe_to_combine_p (ws_entry_bb)
997 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
998 || (last_and_only_stmt (ws_entry_bb)
999 && last_and_only_stmt (par_exit_bb))))
1001 gimple *par_stmt = last_stmt (par_entry_bb);
1002 gimple *ws_stmt = last_stmt (ws_entry_bb);
1004 if (region->inner->type == GIMPLE_OMP_FOR)
1006 /* If this is a combined parallel loop, we need to determine
1007 whether or not to use the combined library calls. There
1008 are two cases where we do not apply the transformation:
1009 static loops and any kind of ordered loop. In the first
1010 case, we already open code the loop so there is no need
1011 to do anything else. In the latter case, the combined
1012 parallel loop call would still need extra synchronization
1013 to implement ordered semantics, so there would not be any
1014 gain in using the combined call. */
1015 tree clauses = gimple_omp_for_clauses (ws_stmt);
1016 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1017 if (c == NULL
1018 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1019 == OMP_CLAUSE_SCHEDULE_STATIC)
1020 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1022 region->is_combined_parallel = false;
1023 region->inner->is_combined_parallel = false;
1024 return;
1028 region->is_combined_parallel = true;
1029 region->inner->is_combined_parallel = true;
1030 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1035 /* Return true if EXPR is variable sized. */
1037 static inline bool
1038 is_variable_sized (const_tree expr)
1040 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1043 /* Return true if DECL is a reference type. */
1045 static inline bool
1046 is_reference (tree decl)
1048 return lang_hooks.decls.omp_privatize_by_reference (decl);
1051 /* Return the type of a decl. If the decl is reference type,
1052 return its base type. */
1053 static inline tree
1054 get_base_type (tree decl)
1056 tree type = TREE_TYPE (decl);
1057 if (is_reference (decl))
1058 type = TREE_TYPE (type);
1059 return type;
1062 /* Lookup variables. The "maybe" form
1063 allows for the variable form to not have been entered, otherwise we
1064 assert that the variable must have been entered. */
1066 static inline tree
1067 lookup_decl (tree var, omp_context *ctx)
1069 tree *n = ctx->cb.decl_map->get (var);
1070 return *n;
1073 static inline tree
1074 maybe_lookup_decl (const_tree var, omp_context *ctx)
1076 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1077 return n ? *n : NULL_TREE;
1080 static inline tree
1081 lookup_field (tree var, omp_context *ctx)
1083 splay_tree_node n;
1084 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1085 return (tree) n->value;
1088 static inline tree
1089 lookup_sfield (splay_tree_key key, omp_context *ctx)
1091 splay_tree_node n;
1092 n = splay_tree_lookup (ctx->sfield_map
1093 ? ctx->sfield_map : ctx->field_map, key);
1094 return (tree) n->value;
1097 static inline tree
1098 lookup_sfield (tree var, omp_context *ctx)
1100 return lookup_sfield ((splay_tree_key) var, ctx);
1103 static inline tree
1104 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1106 splay_tree_node n;
1107 n = splay_tree_lookup (ctx->field_map, key);
1108 return n ? (tree) n->value : NULL_TREE;
1111 static inline tree
1112 maybe_lookup_field (tree var, omp_context *ctx)
1114 return maybe_lookup_field ((splay_tree_key) var, ctx);
1117 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1118 the parallel context if DECL is to be shared. */
1120 static bool
1121 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1123 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1124 return true;
1126 /* We can only use copy-in/copy-out semantics for shared variables
1127 when we know the value is not accessible from an outer scope. */
1128 if (shared_ctx)
1130 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1132 /* ??? Trivially accessible from anywhere. But why would we even
1133 be passing an address in this case? Should we simply assert
1134 this to be false, or should we have a cleanup pass that removes
1135 these from the list of mappings? */
1136 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1137 return true;
1139 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1140 without analyzing the expression whether or not its location
1141 is accessible to anyone else. In the case of nested parallel
1142 regions it certainly may be. */
1143 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1144 return true;
1146 /* Do not use copy-in/copy-out for variables that have their
1147 address taken. */
1148 if (TREE_ADDRESSABLE (decl))
1149 return true;
1151 /* lower_send_shared_vars only uses copy-in, but not copy-out
1152 for these. */
1153 if (TREE_READONLY (decl)
1154 || ((TREE_CODE (decl) == RESULT_DECL
1155 || TREE_CODE (decl) == PARM_DECL)
1156 && DECL_BY_REFERENCE (decl)))
1157 return false;
1159 /* Disallow copy-in/out in nested parallel if
1160 decl is shared in outer parallel, otherwise
1161 each thread could store the shared variable
1162 in its own copy-in location, making the
1163 variable no longer really shared. */
1164 if (shared_ctx->is_nested)
1166 omp_context *up;
1168 for (up = shared_ctx->outer; up; up = up->outer)
1169 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1170 break;
1172 if (up)
1174 tree c;
1176 for (c = gimple_omp_taskreg_clauses (up->stmt);
1177 c; c = OMP_CLAUSE_CHAIN (c))
1178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1179 && OMP_CLAUSE_DECL (c) == decl)
1180 break;
1182 if (c)
1183 goto maybe_mark_addressable_and_ret;
1187 /* For tasks avoid using copy-in/out. As tasks can be
1188 deferred or executed in different thread, when GOMP_task
1189 returns, the task hasn't necessarily terminated. */
1190 if (is_task_ctx (shared_ctx))
1192 tree outer;
1193 maybe_mark_addressable_and_ret:
1194 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1195 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1197 /* Taking address of OUTER in lower_send_shared_vars
1198 might need regimplification of everything that uses the
1199 variable. */
1200 if (!task_shared_vars)
1201 task_shared_vars = BITMAP_ALLOC (NULL);
1202 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1203 TREE_ADDRESSABLE (outer) = 1;
1205 return true;
1209 return false;
1212 /* Construct a new automatic decl similar to VAR. */
1214 static tree
1215 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1217 tree copy = copy_var_decl (var, name, type);
1219 DECL_CONTEXT (copy) = current_function_decl;
1220 DECL_CHAIN (copy) = ctx->block_vars;
1221 /* If VAR is listed in task_shared_vars, it means it wasn't
1222 originally addressable and is just because task needs to take
1223 it's address. But we don't need to take address of privatizations
1224 from that var. */
1225 if (TREE_ADDRESSABLE (var)
1226 && task_shared_vars
1227 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1228 TREE_ADDRESSABLE (copy) = 0;
1229 ctx->block_vars = copy;
1231 return copy;
1234 static tree
1235 omp_copy_decl_1 (tree var, omp_context *ctx)
1237 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1240 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1241 as appropriate. */
1242 static tree
1243 omp_build_component_ref (tree obj, tree field)
1245 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1246 if (TREE_THIS_VOLATILE (field))
1247 TREE_THIS_VOLATILE (ret) |= 1;
1248 if (TREE_READONLY (field))
1249 TREE_READONLY (ret) |= 1;
1250 return ret;
1253 /* Build tree nodes to access the field for VAR on the receiver side. */
1255 static tree
1256 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1258 tree x, field = lookup_field (var, ctx);
1260 /* If the receiver record type was remapped in the child function,
1261 remap the field into the new record type. */
1262 x = maybe_lookup_field (field, ctx);
1263 if (x != NULL)
1264 field = x;
1266 x = build_simple_mem_ref (ctx->receiver_decl);
1267 TREE_THIS_NOTRAP (x) = 1;
1268 x = omp_build_component_ref (x, field);
1269 if (by_ref)
1271 x = build_simple_mem_ref (x);
1272 TREE_THIS_NOTRAP (x) = 1;
1275 return x;
1278 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1279 of a parallel, this is a component reference; for workshare constructs
1280 this is some variable. */
1282 static tree
1283 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1285 tree x;
1287 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1288 x = var;
1289 else if (is_variable_sized (var))
1291 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1292 x = build_outer_var_ref (x, ctx, lastprivate);
1293 x = build_simple_mem_ref (x);
1295 else if (is_taskreg_ctx (ctx))
1297 bool by_ref = use_pointer_for_field (var, NULL);
1298 x = build_receiver_ref (var, by_ref, ctx);
1300 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1301 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1303 /* #pragma omp simd isn't a worksharing construct, and can reference even
1304 private vars in its linear etc. clauses. */
1305 x = NULL_TREE;
1306 if (ctx->outer && is_taskreg_ctx (ctx))
1307 x = lookup_decl (var, ctx->outer);
1308 else if (ctx->outer)
1309 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1310 if (x == NULL_TREE)
1311 x = var;
1313 else if (lastprivate && is_taskloop_ctx (ctx))
1315 gcc_assert (ctx->outer);
1316 splay_tree_node n
1317 = splay_tree_lookup (ctx->outer->field_map,
1318 (splay_tree_key) &DECL_UID (var));
1319 if (n == NULL)
1321 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1322 x = var;
1323 else
1324 x = lookup_decl (var, ctx->outer);
1326 else
1328 tree field = (tree) n->value;
1329 /* If the receiver record type was remapped in the child function,
1330 remap the field into the new record type. */
1331 x = maybe_lookup_field (field, ctx->outer);
1332 if (x != NULL)
1333 field = x;
1335 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1336 x = omp_build_component_ref (x, field);
1337 if (use_pointer_for_field (var, ctx->outer))
1338 x = build_simple_mem_ref (x);
1341 else if (ctx->outer)
1343 omp_context *outer = ctx->outer;
1344 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1346 outer = outer->outer;
1347 gcc_assert (outer
1348 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1350 x = lookup_decl (var, outer);
1352 else if (is_reference (var))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1355 x = var;
1356 else if (omp_member_access_dummy_var (var))
1357 x = var;
1358 else
1359 gcc_unreachable ();
1361 if (x == var)
1363 tree t = omp_member_access_dummy_var (var);
1364 if (t)
1366 x = DECL_VALUE_EXPR (var);
1367 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1368 if (o != t)
1369 x = unshare_and_remap (x, t, o);
1370 else
1371 x = unshare_expr (x);
1375 if (is_reference (var))
1376 x = build_simple_mem_ref (x);
1378 return x;
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1383 static tree
1384 build_sender_ref (splay_tree_key key, omp_context *ctx)
1386 tree field = lookup_sfield (key, ctx);
1387 return omp_build_component_ref (ctx->sender_decl, field);
1390 static tree
1391 build_sender_ref (tree var, omp_context *ctx)
1393 return build_sender_ref ((splay_tree_key) var, ctx);
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1397 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1399 static void
1400 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1401 bool base_pointers_restrict = false)
1403 tree field, type, sfield = NULL_TREE;
1404 splay_tree_key key = (splay_tree_key) var;
1406 if ((mask & 8) != 0)
1408 key = (splay_tree_key) &DECL_UID (var);
1409 gcc_checking_assert (key != (splay_tree_key) var);
1411 gcc_assert ((mask & 1) == 0
1412 || !splay_tree_lookup (ctx->field_map, key));
1413 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1414 || !splay_tree_lookup (ctx->sfield_map, key));
1415 gcc_assert ((mask & 3) == 3
1416 || !is_gimple_omp_oacc (ctx->stmt));
1418 type = TREE_TYPE (var);
1419 /* Prevent redeclaring the var in the split-off function with a restrict
1420 pointer type. Note that we only clear type itself, restrict qualifiers in
1421 the pointed-to type will be ignored by points-to analysis. */
1422 if (POINTER_TYPE_P (type)
1423 && TYPE_RESTRICT (type))
1424 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1426 if (mask & 4)
1428 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1429 type = build_pointer_type (build_pointer_type (type));
1431 else if (by_ref)
1433 type = build_pointer_type (type);
1434 if (base_pointers_restrict)
1435 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1437 else if ((mask & 3) == 1 && is_reference (var))
1438 type = TREE_TYPE (type);
1440 field = build_decl (DECL_SOURCE_LOCATION (var),
1441 FIELD_DECL, DECL_NAME (var), type);
1443 /* Remember what variable this field was created for. This does have a
1444 side effect of making dwarf2out ignore this member, so for helpful
1445 debugging we clear it later in delete_omp_context. */
1446 DECL_ABSTRACT_ORIGIN (field) = var;
1447 if (type == TREE_TYPE (var))
1449 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1450 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1451 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1453 else
1454 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1456 if ((mask & 3) == 3)
1458 insert_field_into_struct (ctx->record_type, field);
1459 if (ctx->srecord_type)
1461 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1462 FIELD_DECL, DECL_NAME (var), type);
1463 DECL_ABSTRACT_ORIGIN (sfield) = var;
1464 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1465 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1466 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1467 insert_field_into_struct (ctx->srecord_type, sfield);
1470 else
1472 if (ctx->srecord_type == NULL_TREE)
1474 tree t;
1476 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1477 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1478 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1480 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1481 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1482 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1483 insert_field_into_struct (ctx->srecord_type, sfield);
1484 splay_tree_insert (ctx->sfield_map,
1485 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1486 (splay_tree_value) sfield);
1489 sfield = field;
1490 insert_field_into_struct ((mask & 1) ? ctx->record_type
1491 : ctx->srecord_type, field);
1494 if (mask & 1)
1495 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1496 if ((mask & 2) && ctx->sfield_map)
1497 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1500 static tree
1501 install_var_local (tree var, omp_context *ctx)
1503 tree new_var = omp_copy_decl_1 (var, ctx);
1504 insert_decl_map (&ctx->cb, var, new_var);
1505 return new_var;
1508 /* Adjust the replacement for DECL in CTX for the new context. This means
1509 copying the DECL_VALUE_EXPR, and fixing up the type. */
1511 static void
1512 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1514 tree new_decl, size;
1516 new_decl = lookup_decl (decl, ctx);
1518 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1520 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1521 && DECL_HAS_VALUE_EXPR_P (decl))
1523 tree ve = DECL_VALUE_EXPR (decl);
1524 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1525 SET_DECL_VALUE_EXPR (new_decl, ve);
1526 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1529 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1531 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1532 if (size == error_mark_node)
1533 size = TYPE_SIZE (TREE_TYPE (new_decl));
1534 DECL_SIZE (new_decl) = size;
1536 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1537 if (size == error_mark_node)
1538 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1539 DECL_SIZE_UNIT (new_decl) = size;
1543 /* The callback for remap_decl. Search all containing contexts for a
1544 mapping of the variable; this avoids having to duplicate the splay
1545 tree ahead of time. We know a mapping doesn't already exist in the
1546 given context. Create new mappings to implement default semantics. */
1548 static tree
1549 omp_copy_decl (tree var, copy_body_data *cb)
1551 omp_context *ctx = (omp_context *) cb;
1552 tree new_var;
1554 if (TREE_CODE (var) == LABEL_DECL)
1556 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1557 DECL_CONTEXT (new_var) = current_function_decl;
1558 insert_decl_map (&ctx->cb, var, new_var);
1559 return new_var;
1562 while (!is_taskreg_ctx (ctx))
1564 ctx = ctx->outer;
1565 if (ctx == NULL)
1566 return var;
1567 new_var = maybe_lookup_decl (var, ctx);
1568 if (new_var)
1569 return new_var;
1572 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1573 return var;
1575 return error_mark_node;
1579 /* Debugging dumps for parallel regions. */
1580 void dump_omp_region (FILE *, struct omp_region *, int);
1581 void debug_omp_region (struct omp_region *);
1582 void debug_all_omp_regions (void);
1584 /* Dump the parallel region tree rooted at REGION. */
1586 void
1587 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1589 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1590 gimple_code_name[region->type]);
1592 if (region->inner)
1593 dump_omp_region (file, region->inner, indent + 4);
1595 if (region->cont)
1597 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1598 region->cont->index);
1601 if (region->exit)
1602 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1603 region->exit->index);
1604 else
1605 fprintf (file, "%*s[no exit marker]\n", indent, "");
1607 if (region->next)
1608 dump_omp_region (file, region->next, indent);
1611 DEBUG_FUNCTION void
1612 debug_omp_region (struct omp_region *region)
1614 dump_omp_region (stderr, region, 0);
1617 DEBUG_FUNCTION void
1618 debug_all_omp_regions (void)
1620 dump_omp_region (stderr, root_omp_region, 0);
1624 /* Create a new parallel region starting at STMT inside region PARENT. */
1626 static struct omp_region *
1627 new_omp_region (basic_block bb, enum gimple_code type,
1628 struct omp_region *parent)
1630 struct omp_region *region = XCNEW (struct omp_region);
1632 region->outer = parent;
1633 region->entry = bb;
1634 region->type = type;
1636 if (parent)
1638 /* This is a nested region. Add it to the list of inner
1639 regions in PARENT. */
1640 region->next = parent->inner;
1641 parent->inner = region;
1643 else
1645 /* This is a toplevel region. Add it to the list of toplevel
1646 regions in ROOT_OMP_REGION. */
1647 region->next = root_omp_region;
1648 root_omp_region = region;
1651 return region;
1654 /* Release the memory associated with the region tree rooted at REGION. */
1656 static void
1657 free_omp_region_1 (struct omp_region *region)
1659 struct omp_region *i, *n;
1661 for (i = region->inner; i ; i = n)
1663 n = i->next;
1664 free_omp_region_1 (i);
1667 free (region);
1670 /* Release the memory for the entire omp region tree. */
1672 void
1673 free_omp_regions (void)
1675 struct omp_region *r, *n;
1676 for (r = root_omp_region; r ; r = n)
1678 n = r->next;
1679 free_omp_region_1 (r);
1681 root_omp_region = NULL;
1685 /* Create a new context, with OUTER_CTX being the surrounding context. */
1687 static omp_context *
1688 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1690 omp_context *ctx = XCNEW (omp_context);
1692 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1693 (splay_tree_value) ctx);
1694 ctx->stmt = stmt;
1696 if (outer_ctx)
1698 ctx->outer = outer_ctx;
1699 ctx->cb = outer_ctx->cb;
1700 ctx->cb.block = NULL;
1701 ctx->depth = outer_ctx->depth + 1;
1703 else
1705 ctx->cb.src_fn = current_function_decl;
1706 ctx->cb.dst_fn = current_function_decl;
1707 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1708 gcc_checking_assert (ctx->cb.src_node);
1709 ctx->cb.dst_node = ctx->cb.src_node;
1710 ctx->cb.src_cfun = cfun;
1711 ctx->cb.copy_decl = omp_copy_decl;
1712 ctx->cb.eh_lp_nr = 0;
1713 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1714 ctx->depth = 1;
1717 ctx->cb.decl_map = new hash_map<tree, tree>;
1719 return ctx;
1722 static gimple_seq maybe_catch_exception (gimple_seq);
1724 /* Finalize task copyfn. */
1726 static void
1727 finalize_task_copyfn (gomp_task *task_stmt)
1729 struct function *child_cfun;
1730 tree child_fn;
1731 gimple_seq seq = NULL, new_seq;
1732 gbind *bind;
1734 child_fn = gimple_omp_task_copy_fn (task_stmt);
1735 if (child_fn == NULL_TREE)
1736 return;
1738 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1739 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1741 push_cfun (child_cfun);
1742 bind = gimplify_body (child_fn, false);
1743 gimple_seq_add_stmt (&seq, bind);
1744 new_seq = maybe_catch_exception (seq);
1745 if (new_seq != seq)
1747 bind = gimple_build_bind (NULL, new_seq, NULL);
1748 seq = NULL;
1749 gimple_seq_add_stmt (&seq, bind);
1751 gimple_set_body (child_fn, seq);
1752 pop_cfun ();
1754 /* Inform the callgraph about the new function. */
1755 cgraph_node *node = cgraph_node::get_create (child_fn);
1756 node->parallelized_function = 1;
1757 cgraph_node::add_new_function (child_fn, false);
1760 /* Destroy a omp_context data structures. Called through the splay tree
1761 value delete callback. */
1763 static void
1764 delete_omp_context (splay_tree_value value)
1766 omp_context *ctx = (omp_context *) value;
1768 delete ctx->cb.decl_map;
1770 if (ctx->field_map)
1771 splay_tree_delete (ctx->field_map);
1772 if (ctx->sfield_map)
1773 splay_tree_delete (ctx->sfield_map);
1775 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1776 it produces corrupt debug information. */
1777 if (ctx->record_type)
1779 tree t;
1780 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1781 DECL_ABSTRACT_ORIGIN (t) = NULL;
1783 if (ctx->srecord_type)
1785 tree t;
1786 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1787 DECL_ABSTRACT_ORIGIN (t) = NULL;
1790 if (is_task_ctx (ctx))
1791 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1793 XDELETE (ctx);
1796 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1797 context. */
1799 static void
1800 fixup_child_record_type (omp_context *ctx)
1802 tree f, type = ctx->record_type;
1804 if (!ctx->receiver_decl)
1805 return;
1806 /* ??? It isn't sufficient to just call remap_type here, because
1807 variably_modified_type_p doesn't work the way we expect for
1808 record types. Testing each field for whether it needs remapping
1809 and creating a new record by hand works, however. */
1810 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1811 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1812 break;
1813 if (f)
1815 tree name, new_fields = NULL;
1817 type = lang_hooks.types.make_type (RECORD_TYPE);
1818 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1819 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1820 TYPE_DECL, name, type);
1821 TYPE_NAME (type) = name;
1823 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1825 tree new_f = copy_node (f);
1826 DECL_CONTEXT (new_f) = type;
1827 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1828 DECL_CHAIN (new_f) = new_fields;
1829 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1830 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1831 &ctx->cb, NULL);
1832 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1834 new_fields = new_f;
1836 /* Arrange to be able to look up the receiver field
1837 given the sender field. */
1838 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1839 (splay_tree_value) new_f);
1841 TYPE_FIELDS (type) = nreverse (new_fields);
1842 layout_type (type);
1845 /* In a target region we never modify any of the pointers in *.omp_data_i,
1846 so attempt to help the optimizers. */
1847 if (is_gimple_omp_offloaded (ctx->stmt))
1848 type = build_qualified_type (type, TYPE_QUAL_CONST);
1850 TREE_TYPE (ctx->receiver_decl)
1851 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1854 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1855 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1856 restrict. */
1858 static void
1859 scan_sharing_clauses (tree clauses, omp_context *ctx,
1860 bool base_pointers_restrict = false)
1862 tree c, decl;
1863 bool scan_array_reductions = false;
1865 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1867 bool by_ref;
1869 switch (OMP_CLAUSE_CODE (c))
1871 case OMP_CLAUSE_PRIVATE:
1872 decl = OMP_CLAUSE_DECL (c);
1873 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1874 goto do_private;
1875 else if (!is_variable_sized (decl))
1876 install_var_local (decl, ctx);
1877 break;
1879 case OMP_CLAUSE_SHARED:
1880 decl = OMP_CLAUSE_DECL (c);
1881 /* Ignore shared directives in teams construct. */
1882 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1884 /* Global variables don't need to be copied,
1885 the receiver side will use them directly. */
1886 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1887 if (is_global_var (odecl))
1888 break;
1889 insert_decl_map (&ctx->cb, decl, odecl);
1890 break;
1892 gcc_assert (is_taskreg_ctx (ctx));
1893 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1894 || !is_variable_sized (decl));
1895 /* Global variables don't need to be copied,
1896 the receiver side will use them directly. */
1897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1898 break;
1899 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1901 use_pointer_for_field (decl, ctx);
1902 break;
1904 by_ref = use_pointer_for_field (decl, NULL);
1905 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1906 || TREE_ADDRESSABLE (decl)
1907 || by_ref
1908 || is_reference (decl))
1910 by_ref = use_pointer_for_field (decl, ctx);
1911 install_var_field (decl, by_ref, 3, ctx);
1912 install_var_local (decl, ctx);
1913 break;
1915 /* We don't need to copy const scalar vars back. */
1916 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1917 goto do_private;
1919 case OMP_CLAUSE_REDUCTION:
1920 decl = OMP_CLAUSE_DECL (c);
1921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1922 && TREE_CODE (decl) == MEM_REF)
1924 tree t = TREE_OPERAND (decl, 0);
1925 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1926 t = TREE_OPERAND (t, 0);
1927 if (TREE_CODE (t) == INDIRECT_REF
1928 || TREE_CODE (t) == ADDR_EXPR)
1929 t = TREE_OPERAND (t, 0);
1930 install_var_local (t, ctx);
1931 if (is_taskreg_ctx (ctx)
1932 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1933 && !is_variable_sized (t))
1935 by_ref = use_pointer_for_field (t, ctx);
1936 install_var_field (t, by_ref, 3, ctx);
1938 break;
1940 goto do_private;
1942 case OMP_CLAUSE_LASTPRIVATE:
1943 /* Let the corresponding firstprivate clause create
1944 the variable. */
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1949 case OMP_CLAUSE_FIRSTPRIVATE:
1950 case OMP_CLAUSE_LINEAR:
1951 decl = OMP_CLAUSE_DECL (c);
1952 do_private:
1953 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1955 && is_gimple_omp_offloaded (ctx->stmt))
1957 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1958 install_var_field (decl, !is_reference (decl), 3, ctx);
1959 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1960 install_var_field (decl, true, 3, ctx);
1961 else
1962 install_var_field (decl, false, 3, ctx);
1964 if (is_variable_sized (decl))
1966 if (is_task_ctx (ctx))
1967 install_var_field (decl, false, 1, ctx);
1968 break;
1970 else if (is_taskreg_ctx (ctx))
1972 bool global
1973 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1974 by_ref = use_pointer_for_field (decl, NULL);
1976 if (is_task_ctx (ctx)
1977 && (global || by_ref || is_reference (decl)))
1979 install_var_field (decl, false, 1, ctx);
1980 if (!global)
1981 install_var_field (decl, by_ref, 2, ctx);
1983 else if (!global)
1984 install_var_field (decl, by_ref, 3, ctx);
1986 install_var_local (decl, ctx);
1987 break;
1989 case OMP_CLAUSE_USE_DEVICE_PTR:
1990 decl = OMP_CLAUSE_DECL (c);
1991 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1995 if (DECL_SIZE (decl)
1996 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1998 tree decl2 = DECL_VALUE_EXPR (decl);
1999 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2000 decl2 = TREE_OPERAND (decl2, 0);
2001 gcc_assert (DECL_P (decl2));
2002 install_var_local (decl2, ctx);
2004 install_var_local (decl, ctx);
2005 break;
2007 case OMP_CLAUSE_IS_DEVICE_PTR:
2008 decl = OMP_CLAUSE_DECL (c);
2009 goto do_private;
2011 case OMP_CLAUSE__LOOPTEMP_:
2012 gcc_assert (is_taskreg_ctx (ctx));
2013 decl = OMP_CLAUSE_DECL (c);
2014 install_var_field (decl, false, 3, ctx);
2015 install_var_local (decl, ctx);
2016 break;
2018 case OMP_CLAUSE_COPYPRIVATE:
2019 case OMP_CLAUSE_COPYIN:
2020 decl = OMP_CLAUSE_DECL (c);
2021 by_ref = use_pointer_for_field (decl, NULL);
2022 install_var_field (decl, by_ref, 3, ctx);
2023 break;
2025 case OMP_CLAUSE_DEFAULT:
2026 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2027 break;
2029 case OMP_CLAUSE_FINAL:
2030 case OMP_CLAUSE_IF:
2031 case OMP_CLAUSE_NUM_THREADS:
2032 case OMP_CLAUSE_NUM_TEAMS:
2033 case OMP_CLAUSE_THREAD_LIMIT:
2034 case OMP_CLAUSE_DEVICE:
2035 case OMP_CLAUSE_SCHEDULE:
2036 case OMP_CLAUSE_DIST_SCHEDULE:
2037 case OMP_CLAUSE_DEPEND:
2038 case OMP_CLAUSE_PRIORITY:
2039 case OMP_CLAUSE_GRAINSIZE:
2040 case OMP_CLAUSE_NUM_TASKS:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
2042 case OMP_CLAUSE_NUM_GANGS:
2043 case OMP_CLAUSE_NUM_WORKERS:
2044 case OMP_CLAUSE_VECTOR_LENGTH:
2045 if (ctx->outer)
2046 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2047 break;
2049 case OMP_CLAUSE_TO:
2050 case OMP_CLAUSE_FROM:
2051 case OMP_CLAUSE_MAP:
2052 if (ctx->outer)
2053 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2054 decl = OMP_CLAUSE_DECL (c);
2055 /* Global variables with "omp declare target" attribute
2056 don't need to be copied, the receiver side will use them
2057 directly. However, global variables with "omp declare target link"
2058 attribute need to be copied. */
2059 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2060 && DECL_P (decl)
2061 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2062 && (OMP_CLAUSE_MAP_KIND (c)
2063 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2064 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2065 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2066 && varpool_node::get_create (decl)->offloadable
2067 && !lookup_attribute ("omp declare target link",
2068 DECL_ATTRIBUTES (decl)))
2069 break;
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2071 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2073 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2074 not offloaded; there is nothing to map for those. */
2075 if (!is_gimple_omp_offloaded (ctx->stmt)
2076 && !POINTER_TYPE_P (TREE_TYPE (decl))
2077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2078 break;
2080 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2081 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2082 || (OMP_CLAUSE_MAP_KIND (c)
2083 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2085 if (TREE_CODE (decl) == COMPONENT_REF
2086 || (TREE_CODE (decl) == INDIRECT_REF
2087 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2088 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2089 == REFERENCE_TYPE)))
2090 break;
2091 if (DECL_SIZE (decl)
2092 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2094 tree decl2 = DECL_VALUE_EXPR (decl);
2095 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2096 decl2 = TREE_OPERAND (decl2, 0);
2097 gcc_assert (DECL_P (decl2));
2098 install_var_local (decl2, ctx);
2100 install_var_local (decl, ctx);
2101 break;
2103 if (DECL_P (decl))
2105 if (DECL_SIZE (decl)
2106 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2108 tree decl2 = DECL_VALUE_EXPR (decl);
2109 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2110 decl2 = TREE_OPERAND (decl2, 0);
2111 gcc_assert (DECL_P (decl2));
2112 install_var_field (decl2, true, 3, ctx);
2113 install_var_local (decl2, ctx);
2114 install_var_local (decl, ctx);
2116 else
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2120 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2121 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2122 install_var_field (decl, true, 7, ctx);
2123 else
2124 install_var_field (decl, true, 3, ctx,
2125 base_pointers_restrict);
2126 if (is_gimple_omp_offloaded (ctx->stmt)
2127 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2128 install_var_local (decl, ctx);
2131 else
2133 tree base = get_base_address (decl);
2134 tree nc = OMP_CLAUSE_CHAIN (c);
2135 if (DECL_P (base)
2136 && nc != NULL_TREE
2137 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2138 && OMP_CLAUSE_DECL (nc) == base
2139 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2140 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2142 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2145 else
2147 if (ctx->outer)
2149 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2150 decl = OMP_CLAUSE_DECL (c);
2152 gcc_assert (!splay_tree_lookup (ctx->field_map,
2153 (splay_tree_key) decl));
2154 tree field
2155 = build_decl (OMP_CLAUSE_LOCATION (c),
2156 FIELD_DECL, NULL_TREE, ptr_type_node);
2157 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2158 insert_field_into_struct (ctx->record_type, field);
2159 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2160 (splay_tree_value) field);
2163 break;
2165 case OMP_CLAUSE__GRIDDIM_:
2166 if (ctx->outer)
2168 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2171 break;
2173 case OMP_CLAUSE_NOWAIT:
2174 case OMP_CLAUSE_ORDERED:
2175 case OMP_CLAUSE_COLLAPSE:
2176 case OMP_CLAUSE_UNTIED:
2177 case OMP_CLAUSE_MERGEABLE:
2178 case OMP_CLAUSE_PROC_BIND:
2179 case OMP_CLAUSE_SAFELEN:
2180 case OMP_CLAUSE_SIMDLEN:
2181 case OMP_CLAUSE_THREADS:
2182 case OMP_CLAUSE_SIMD:
2183 case OMP_CLAUSE_NOGROUP:
2184 case OMP_CLAUSE_DEFAULTMAP:
2185 case OMP_CLAUSE_ASYNC:
2186 case OMP_CLAUSE_WAIT:
2187 case OMP_CLAUSE_GANG:
2188 case OMP_CLAUSE_WORKER:
2189 case OMP_CLAUSE_VECTOR:
2190 case OMP_CLAUSE_INDEPENDENT:
2191 case OMP_CLAUSE_AUTO:
2192 case OMP_CLAUSE_SEQ:
2193 break;
2195 case OMP_CLAUSE_ALIGNED:
2196 decl = OMP_CLAUSE_DECL (c);
2197 if (is_global_var (decl)
2198 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2199 install_var_local (decl, ctx);
2200 break;
2202 case OMP_CLAUSE_TILE:
2203 case OMP_CLAUSE__CACHE_:
2204 default:
2205 gcc_unreachable ();
2209 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2211 switch (OMP_CLAUSE_CODE (c))
2213 case OMP_CLAUSE_LASTPRIVATE:
2214 /* Let the corresponding firstprivate clause create
2215 the variable. */
2216 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2217 scan_array_reductions = true;
2218 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2219 break;
2220 /* FALLTHRU */
2222 case OMP_CLAUSE_FIRSTPRIVATE:
2223 case OMP_CLAUSE_PRIVATE:
2224 case OMP_CLAUSE_LINEAR:
2225 case OMP_CLAUSE_IS_DEVICE_PTR:
2226 decl = OMP_CLAUSE_DECL (c);
2227 if (is_variable_sized (decl))
2229 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2230 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2231 && is_gimple_omp_offloaded (ctx->stmt))
2233 tree decl2 = DECL_VALUE_EXPR (decl);
2234 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2235 decl2 = TREE_OPERAND (decl2, 0);
2236 gcc_assert (DECL_P (decl2));
2237 install_var_local (decl2, ctx);
2238 fixup_remapped_decl (decl2, ctx, false);
2240 install_var_local (decl, ctx);
2242 fixup_remapped_decl (decl, ctx,
2243 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2244 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2245 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2246 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2247 scan_array_reductions = true;
2248 break;
2250 case OMP_CLAUSE_REDUCTION:
2251 decl = OMP_CLAUSE_DECL (c);
2252 if (TREE_CODE (decl) != MEM_REF)
2254 if (is_variable_sized (decl))
2255 install_var_local (decl, ctx);
2256 fixup_remapped_decl (decl, ctx, false);
2258 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2259 scan_array_reductions = true;
2260 break;
2262 case OMP_CLAUSE_SHARED:
2263 /* Ignore shared directives in teams construct. */
2264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2265 break;
2266 decl = OMP_CLAUSE_DECL (c);
2267 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2268 break;
2269 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2272 ctx->outer)))
2273 break;
2274 bool by_ref = use_pointer_for_field (decl, ctx);
2275 install_var_field (decl, by_ref, 11, ctx);
2276 break;
2278 fixup_remapped_decl (decl, ctx, false);
2279 break;
2281 case OMP_CLAUSE_MAP:
2282 if (!is_gimple_omp_offloaded (ctx->stmt))
2283 break;
2284 decl = OMP_CLAUSE_DECL (c);
2285 if (DECL_P (decl)
2286 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2287 && (OMP_CLAUSE_MAP_KIND (c)
2288 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2289 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2290 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2291 && varpool_node::get_create (decl)->offloadable)
2292 break;
2293 if (DECL_P (decl))
2295 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2296 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2297 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2298 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2300 tree new_decl = lookup_decl (decl, ctx);
2301 TREE_TYPE (new_decl)
2302 = remap_type (TREE_TYPE (decl), &ctx->cb);
2304 else if (DECL_SIZE (decl)
2305 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2307 tree decl2 = DECL_VALUE_EXPR (decl);
2308 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2309 decl2 = TREE_OPERAND (decl2, 0);
2310 gcc_assert (DECL_P (decl2));
2311 fixup_remapped_decl (decl2, ctx, false);
2312 fixup_remapped_decl (decl, ctx, true);
2314 else
2315 fixup_remapped_decl (decl, ctx, false);
2317 break;
2319 case OMP_CLAUSE_COPYPRIVATE:
2320 case OMP_CLAUSE_COPYIN:
2321 case OMP_CLAUSE_DEFAULT:
2322 case OMP_CLAUSE_IF:
2323 case OMP_CLAUSE_NUM_THREADS:
2324 case OMP_CLAUSE_NUM_TEAMS:
2325 case OMP_CLAUSE_THREAD_LIMIT:
2326 case OMP_CLAUSE_DEVICE:
2327 case OMP_CLAUSE_SCHEDULE:
2328 case OMP_CLAUSE_DIST_SCHEDULE:
2329 case OMP_CLAUSE_NOWAIT:
2330 case OMP_CLAUSE_ORDERED:
2331 case OMP_CLAUSE_COLLAPSE:
2332 case OMP_CLAUSE_UNTIED:
2333 case OMP_CLAUSE_FINAL:
2334 case OMP_CLAUSE_MERGEABLE:
2335 case OMP_CLAUSE_PROC_BIND:
2336 case OMP_CLAUSE_SAFELEN:
2337 case OMP_CLAUSE_SIMDLEN:
2338 case OMP_CLAUSE_ALIGNED:
2339 case OMP_CLAUSE_DEPEND:
2340 case OMP_CLAUSE__LOOPTEMP_:
2341 case OMP_CLAUSE_TO:
2342 case OMP_CLAUSE_FROM:
2343 case OMP_CLAUSE_PRIORITY:
2344 case OMP_CLAUSE_GRAINSIZE:
2345 case OMP_CLAUSE_NUM_TASKS:
2346 case OMP_CLAUSE_THREADS:
2347 case OMP_CLAUSE_SIMD:
2348 case OMP_CLAUSE_NOGROUP:
2349 case OMP_CLAUSE_DEFAULTMAP:
2350 case OMP_CLAUSE_USE_DEVICE_PTR:
2351 case OMP_CLAUSE__CILK_FOR_COUNT_:
2352 case OMP_CLAUSE_ASYNC:
2353 case OMP_CLAUSE_WAIT:
2354 case OMP_CLAUSE_NUM_GANGS:
2355 case OMP_CLAUSE_NUM_WORKERS:
2356 case OMP_CLAUSE_VECTOR_LENGTH:
2357 case OMP_CLAUSE_GANG:
2358 case OMP_CLAUSE_WORKER:
2359 case OMP_CLAUSE_VECTOR:
2360 case OMP_CLAUSE_INDEPENDENT:
2361 case OMP_CLAUSE_AUTO:
2362 case OMP_CLAUSE_SEQ:
2363 case OMP_CLAUSE__GRIDDIM_:
2364 break;
2366 case OMP_CLAUSE_TILE:
2367 case OMP_CLAUSE__CACHE_:
2368 default:
2369 gcc_unreachable ();
2373 gcc_checking_assert (!scan_array_reductions
2374 || !is_gimple_omp_oacc (ctx->stmt));
2375 if (scan_array_reductions)
2377 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2379 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2381 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2384 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2386 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2387 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2388 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2389 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2393 /* Create a new name for omp child function. Returns an identifier. If
2394 IS_CILK_FOR is true then the suffix for the child function is
2395 "_cilk_for_fn." */
2397 static tree
2398 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2400 if (is_cilk_for)
2401 return clone_function_name (current_function_decl, "_cilk_for_fn");
2402 return clone_function_name (current_function_decl,
2403 task_copy ? "_omp_cpyfn" : "_omp_fn");
2406 /* Returns the type of the induction variable for the child function for
2407 _Cilk_for and the types for _high and _low variables based on TYPE. */
2409 static tree
2410 cilk_for_check_loop_diff_type (tree type)
2412 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2414 if (TYPE_UNSIGNED (type))
2415 return uint32_type_node;
2416 else
2417 return integer_type_node;
2419 else
2421 if (TYPE_UNSIGNED (type))
2422 return uint64_type_node;
2423 else
2424 return long_long_integer_type_node;
2428 /* Build a decl for the omp child function. It'll not contain a body
2429 yet, just the bare decl. */
2431 static void
2432 create_omp_child_function (omp_context *ctx, bool task_copy)
2434 tree decl, type, name, t;
2436 tree cilk_for_count
2437 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2438 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2439 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2440 tree cilk_var_type = NULL_TREE;
2442 name = create_omp_child_function_name (task_copy,
2443 cilk_for_count != NULL_TREE);
2444 if (task_copy)
2445 type = build_function_type_list (void_type_node, ptr_type_node,
2446 ptr_type_node, NULL_TREE);
2447 else if (cilk_for_count)
2449 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2450 cilk_var_type = cilk_for_check_loop_diff_type (type);
2451 type = build_function_type_list (void_type_node, ptr_type_node,
2452 cilk_var_type, cilk_var_type, NULL_TREE);
2454 else
2455 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2457 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2459 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2460 || !task_copy);
2461 if (!task_copy)
2462 ctx->cb.dst_fn = decl;
2463 else
2464 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2466 TREE_STATIC (decl) = 1;
2467 TREE_USED (decl) = 1;
2468 DECL_ARTIFICIAL (decl) = 1;
2469 DECL_IGNORED_P (decl) = 0;
2470 TREE_PUBLIC (decl) = 0;
2471 DECL_UNINLINABLE (decl) = 1;
2472 DECL_EXTERNAL (decl) = 0;
2473 DECL_CONTEXT (decl) = NULL_TREE;
2474 DECL_INITIAL (decl) = make_node (BLOCK);
2475 if (cgraph_node::get (current_function_decl)->offloadable)
2476 cgraph_node::get_create (decl)->offloadable = 1;
2477 else
2479 omp_context *octx;
2480 for (octx = ctx; octx; octx = octx->outer)
2481 if (is_gimple_omp_offloaded (octx->stmt))
2483 cgraph_node::get_create (decl)->offloadable = 1;
2484 if (ENABLE_OFFLOADING)
2485 g->have_offload = true;
2487 break;
2491 if (cgraph_node::get_create (decl)->offloadable
2492 && !lookup_attribute ("omp declare target",
2493 DECL_ATTRIBUTES (current_function_decl)))
2494 DECL_ATTRIBUTES (decl)
2495 = tree_cons (get_identifier ("omp target entrypoint"),
2496 NULL_TREE, DECL_ATTRIBUTES (decl));
2498 t = build_decl (DECL_SOURCE_LOCATION (decl),
2499 RESULT_DECL, NULL_TREE, void_type_node);
2500 DECL_ARTIFICIAL (t) = 1;
2501 DECL_IGNORED_P (t) = 1;
2502 DECL_CONTEXT (t) = decl;
2503 DECL_RESULT (decl) = t;
2505 /* _Cilk_for's child function requires two extra parameters called
2506 __low and __high that are set the by Cilk runtime when it calls this
2507 function. */
2508 if (cilk_for_count)
2510 t = build_decl (DECL_SOURCE_LOCATION (decl),
2511 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2512 DECL_ARTIFICIAL (t) = 1;
2513 DECL_NAMELESS (t) = 1;
2514 DECL_ARG_TYPE (t) = ptr_type_node;
2515 DECL_CONTEXT (t) = current_function_decl;
2516 TREE_USED (t) = 1;
2517 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2518 DECL_ARGUMENTS (decl) = t;
2520 t = build_decl (DECL_SOURCE_LOCATION (decl),
2521 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2522 DECL_ARTIFICIAL (t) = 1;
2523 DECL_NAMELESS (t) = 1;
2524 DECL_ARG_TYPE (t) = ptr_type_node;
2525 DECL_CONTEXT (t) = current_function_decl;
2526 TREE_USED (t) = 1;
2527 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2528 DECL_ARGUMENTS (decl) = t;
2531 tree data_name = get_identifier (".omp_data_i");
2532 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2533 ptr_type_node);
2534 DECL_ARTIFICIAL (t) = 1;
2535 DECL_NAMELESS (t) = 1;
2536 DECL_ARG_TYPE (t) = ptr_type_node;
2537 DECL_CONTEXT (t) = current_function_decl;
2538 TREE_USED (t) = 1;
2539 TREE_READONLY (t) = 1;
2540 if (cilk_for_count)
2541 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2542 DECL_ARGUMENTS (decl) = t;
2543 if (!task_copy)
2544 ctx->receiver_decl = t;
2545 else
2547 t = build_decl (DECL_SOURCE_LOCATION (decl),
2548 PARM_DECL, get_identifier (".omp_data_o"),
2549 ptr_type_node);
2550 DECL_ARTIFICIAL (t) = 1;
2551 DECL_NAMELESS (t) = 1;
2552 DECL_ARG_TYPE (t) = ptr_type_node;
2553 DECL_CONTEXT (t) = current_function_decl;
2554 TREE_USED (t) = 1;
2555 TREE_ADDRESSABLE (t) = 1;
2556 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2557 DECL_ARGUMENTS (decl) = t;
2560 /* Allocate memory for the function structure. The call to
2561 allocate_struct_function clobbers CFUN, so we need to restore
2562 it afterward. */
2563 push_struct_function (decl);
2564 cfun->function_end_locus = gimple_location (ctx->stmt);
2565 init_tree_ssa (cfun);
2566 pop_cfun ();
2569 /* Callback for walk_gimple_seq. Check if combined parallel
2570 contains gimple_omp_for_combined_into_p OMP_FOR. */
2572 static tree
2573 find_combined_for (gimple_stmt_iterator *gsi_p,
2574 bool *handled_ops_p,
2575 struct walk_stmt_info *wi)
2577 gimple *stmt = gsi_stmt (*gsi_p);
2579 *handled_ops_p = true;
2580 switch (gimple_code (stmt))
2582 WALK_SUBSTMTS;
2584 case GIMPLE_OMP_FOR:
2585 if (gimple_omp_for_combined_into_p (stmt)
2586 && gimple_omp_for_kind (stmt)
2587 == *(const enum gf_mask *) (wi->info))
2589 wi->info = stmt;
2590 return integer_zero_node;
2592 break;
2593 default:
2594 break;
2596 return NULL;
2599 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2601 static void
2602 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2603 omp_context *outer_ctx)
2605 struct walk_stmt_info wi;
2607 memset (&wi, 0, sizeof (wi));
2608 wi.val_only = true;
2609 wi.info = (void *) &msk;
2610 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2611 if (wi.info != (void *) &msk)
2613 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2614 struct omp_for_data fd;
2615 extract_omp_for_data (for_stmt, &fd, NULL);
2616 /* We need two temporaries with fd.loop.v type (istart/iend)
2617 and then (fd.collapse - 1) temporaries with the same
2618 type for count2 ... countN-1 vars if not constant. */
2619 size_t count = 2, i;
2620 tree type = fd.iter_type;
2621 if (fd.collapse > 1
2622 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2624 count += fd.collapse - 1;
2625 /* If there are lastprivate clauses on the inner
2626 GIMPLE_OMP_FOR, add one more temporaries for the total number
2627 of iterations (product of count1 ... countN-1). */
2628 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2629 OMP_CLAUSE_LASTPRIVATE))
2630 count++;
2631 else if (msk == GF_OMP_FOR_KIND_FOR
2632 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2633 OMP_CLAUSE_LASTPRIVATE))
2634 count++;
2636 for (i = 0; i < count; i++)
2638 tree temp = create_tmp_var (type);
2639 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2640 insert_decl_map (&outer_ctx->cb, temp, temp);
2641 OMP_CLAUSE_DECL (c) = temp;
2642 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2643 gimple_omp_taskreg_set_clauses (stmt, c);
2648 /* Scan an OpenMP parallel directive. */
2650 static void
2651 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2653 omp_context *ctx;
2654 tree name;
2655 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2657 /* Ignore parallel directives with empty bodies, unless there
2658 are copyin clauses. */
2659 if (optimize > 0
2660 && empty_body_p (gimple_omp_body (stmt))
2661 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2662 OMP_CLAUSE_COPYIN) == NULL)
2664 gsi_replace (gsi, gimple_build_nop (), false);
2665 return;
2668 if (gimple_omp_parallel_combined_p (stmt))
2669 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2671 ctx = new_omp_context (stmt, outer_ctx);
2672 taskreg_contexts.safe_push (ctx);
2673 if (taskreg_nesting_level > 1)
2674 ctx->is_nested = true;
2675 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2676 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2677 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2678 name = create_tmp_var_name (".omp_data_s");
2679 name = build_decl (gimple_location (stmt),
2680 TYPE_DECL, name, ctx->record_type);
2681 DECL_ARTIFICIAL (name) = 1;
2682 DECL_NAMELESS (name) = 1;
2683 TYPE_NAME (ctx->record_type) = name;
2684 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2685 if (!gimple_omp_parallel_grid_phony (stmt))
2687 create_omp_child_function (ctx, false);
2688 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2691 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2692 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2694 if (TYPE_FIELDS (ctx->record_type) == NULL)
2695 ctx->record_type = ctx->receiver_decl = NULL;
2698 /* Scan an OpenMP task directive. */
2700 static void
2701 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2703 omp_context *ctx;
2704 tree name, t;
2705 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2707 /* Ignore task directives with empty bodies. */
2708 if (optimize > 0
2709 && empty_body_p (gimple_omp_body (stmt)))
2711 gsi_replace (gsi, gimple_build_nop (), false);
2712 return;
2715 if (gimple_omp_task_taskloop_p (stmt))
2716 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2718 ctx = new_omp_context (stmt, outer_ctx);
2719 taskreg_contexts.safe_push (ctx);
2720 if (taskreg_nesting_level > 1)
2721 ctx->is_nested = true;
2722 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2723 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2724 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2725 name = create_tmp_var_name (".omp_data_s");
2726 name = build_decl (gimple_location (stmt),
2727 TYPE_DECL, name, ctx->record_type);
2728 DECL_ARTIFICIAL (name) = 1;
2729 DECL_NAMELESS (name) = 1;
2730 TYPE_NAME (ctx->record_type) = name;
2731 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2732 create_omp_child_function (ctx, false);
2733 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2735 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2737 if (ctx->srecord_type)
2739 name = create_tmp_var_name (".omp_data_a");
2740 name = build_decl (gimple_location (stmt),
2741 TYPE_DECL, name, ctx->srecord_type);
2742 DECL_ARTIFICIAL (name) = 1;
2743 DECL_NAMELESS (name) = 1;
2744 TYPE_NAME (ctx->srecord_type) = name;
2745 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2746 create_omp_child_function (ctx, true);
2749 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2751 if (TYPE_FIELDS (ctx->record_type) == NULL)
2753 ctx->record_type = ctx->receiver_decl = NULL;
2754 t = build_int_cst (long_integer_type_node, 0);
2755 gimple_omp_task_set_arg_size (stmt, t);
2756 t = build_int_cst (long_integer_type_node, 1);
2757 gimple_omp_task_set_arg_align (stmt, t);
2762 /* If any decls have been made addressable during scan_omp,
2763 adjust their fields if needed, and layout record types
2764 of parallel/task constructs. */
2766 static void
2767 finish_taskreg_scan (omp_context *ctx)
2769 if (ctx->record_type == NULL_TREE)
2770 return;
2772 /* If any task_shared_vars were needed, verify all
2773 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2774 statements if use_pointer_for_field hasn't changed
2775 because of that. If it did, update field types now. */
2776 if (task_shared_vars)
2778 tree c;
2780 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2781 c; c = OMP_CLAUSE_CHAIN (c))
2782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2783 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2785 tree decl = OMP_CLAUSE_DECL (c);
2787 /* Global variables don't need to be copied,
2788 the receiver side will use them directly. */
2789 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2790 continue;
2791 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2792 || !use_pointer_for_field (decl, ctx))
2793 continue;
2794 tree field = lookup_field (decl, ctx);
2795 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2796 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2797 continue;
2798 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2799 TREE_THIS_VOLATILE (field) = 0;
2800 DECL_USER_ALIGN (field) = 0;
2801 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2802 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2803 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2804 if (ctx->srecord_type)
2806 tree sfield = lookup_sfield (decl, ctx);
2807 TREE_TYPE (sfield) = TREE_TYPE (field);
2808 TREE_THIS_VOLATILE (sfield) = 0;
2809 DECL_USER_ALIGN (sfield) = 0;
2810 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2811 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2812 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2817 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2819 layout_type (ctx->record_type);
2820 fixup_child_record_type (ctx);
2822 else
2824 location_t loc = gimple_location (ctx->stmt);
2825 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2826 /* Move VLA fields to the end. */
2827 p = &TYPE_FIELDS (ctx->record_type);
2828 while (*p)
2829 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2830 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2832 *q = *p;
2833 *p = TREE_CHAIN (*p);
2834 TREE_CHAIN (*q) = NULL_TREE;
2835 q = &TREE_CHAIN (*q);
2837 else
2838 p = &DECL_CHAIN (*p);
2839 *p = vla_fields;
2840 if (gimple_omp_task_taskloop_p (ctx->stmt))
2842 /* Move fields corresponding to first and second _looptemp_
2843 clause first. There are filled by GOMP_taskloop
2844 and thus need to be in specific positions. */
2845 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2846 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2847 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2848 OMP_CLAUSE__LOOPTEMP_);
2849 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2850 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2851 p = &TYPE_FIELDS (ctx->record_type);
2852 while (*p)
2853 if (*p == f1 || *p == f2)
2854 *p = DECL_CHAIN (*p);
2855 else
2856 p = &DECL_CHAIN (*p);
2857 DECL_CHAIN (f1) = f2;
2858 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2859 TYPE_FIELDS (ctx->record_type) = f1;
2860 if (ctx->srecord_type)
2862 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2863 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2864 p = &TYPE_FIELDS (ctx->srecord_type);
2865 while (*p)
2866 if (*p == f1 || *p == f2)
2867 *p = DECL_CHAIN (*p);
2868 else
2869 p = &DECL_CHAIN (*p);
2870 DECL_CHAIN (f1) = f2;
2871 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2872 TYPE_FIELDS (ctx->srecord_type) = f1;
2875 layout_type (ctx->record_type);
2876 fixup_child_record_type (ctx);
2877 if (ctx->srecord_type)
2878 layout_type (ctx->srecord_type);
2879 tree t = fold_convert_loc (loc, long_integer_type_node,
2880 TYPE_SIZE_UNIT (ctx->record_type));
2881 gimple_omp_task_set_arg_size (ctx->stmt, t);
2882 t = build_int_cst (long_integer_type_node,
2883 TYPE_ALIGN_UNIT (ctx->record_type));
2884 gimple_omp_task_set_arg_align (ctx->stmt, t);
2888 /* Find the enclosing offload context. */
2890 static omp_context *
2891 enclosing_target_ctx (omp_context *ctx)
2893 for (; ctx; ctx = ctx->outer)
2894 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2895 break;
2897 return ctx;
2900 /* Return true if ctx is part of an oacc kernels region. */
2902 static bool
2903 ctx_in_oacc_kernels_region (omp_context *ctx)
2905 for (;ctx != NULL; ctx = ctx->outer)
2907 gimple *stmt = ctx->stmt;
2908 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2909 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2910 return true;
2913 return false;
2916 /* Check the parallelism clauses inside a kernels regions.
2917 Until kernels handling moves to use the same loop indirection
2918 scheme as parallel, we need to do this checking early. */
2920 static unsigned
2921 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2923 bool checking = true;
2924 unsigned outer_mask = 0;
2925 unsigned this_mask = 0;
2926 bool has_seq = false, has_auto = false;
2928 if (ctx->outer)
2929 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2930 if (!stmt)
2932 checking = false;
2933 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2934 return outer_mask;
2935 stmt = as_a <gomp_for *> (ctx->stmt);
2938 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2940 switch (OMP_CLAUSE_CODE (c))
2942 case OMP_CLAUSE_GANG:
2943 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2944 break;
2945 case OMP_CLAUSE_WORKER:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2947 break;
2948 case OMP_CLAUSE_VECTOR:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2950 break;
2951 case OMP_CLAUSE_SEQ:
2952 has_seq = true;
2953 break;
2954 case OMP_CLAUSE_AUTO:
2955 has_auto = true;
2956 break;
2957 default:
2958 break;
2962 if (checking)
2964 if (has_seq && (this_mask || has_auto))
2965 error_at (gimple_location (stmt), "%<seq%> overrides other"
2966 " OpenACC loop specifiers");
2967 else if (has_auto && this_mask)
2968 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2969 " OpenACC loop specifiers");
2971 if (this_mask & outer_mask)
2972 error_at (gimple_location (stmt), "inner loop uses same"
2973 " OpenACC parallelism as containing loop");
2976 return outer_mask | this_mask;
2979 /* Scan a GIMPLE_OMP_FOR. */
2981 static void
2982 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2984 omp_context *ctx;
2985 size_t i;
2986 tree clauses = gimple_omp_for_clauses (stmt);
2988 ctx = new_omp_context (stmt, outer_ctx);
2990 if (is_gimple_omp_oacc (stmt))
2992 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2994 if (!tgt || is_oacc_parallel (tgt))
2995 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2997 char const *check = NULL;
2999 switch (OMP_CLAUSE_CODE (c))
3001 case OMP_CLAUSE_GANG:
3002 check = "gang";
3003 break;
3005 case OMP_CLAUSE_WORKER:
3006 check = "worker";
3007 break;
3009 case OMP_CLAUSE_VECTOR:
3010 check = "vector";
3011 break;
3013 default:
3014 break;
3017 if (check && OMP_CLAUSE_OPERAND (c, 0))
3018 error_at (gimple_location (stmt),
3019 "argument not permitted on %qs clause in"
3020 " OpenACC %<parallel%>", check);
3023 if (tgt && is_oacc_kernels (tgt))
3025 /* Strip out reductions, as they are not handled yet. */
3026 tree *prev_ptr = &clauses;
3028 while (tree probe = *prev_ptr)
3030 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3032 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3033 *prev_ptr = *next_ptr;
3034 else
3035 prev_ptr = next_ptr;
3038 gimple_omp_for_set_clauses (stmt, clauses);
3039 check_oacc_kernel_gwv (stmt, ctx);
3043 scan_sharing_clauses (clauses, ctx);
3045 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3046 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3048 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3049 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3050 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3053 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3056 /* Scan an OpenMP sections directive. */
3058 static void
3059 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3061 omp_context *ctx;
3063 ctx = new_omp_context (stmt, outer_ctx);
3064 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3065 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3068 /* Scan an OpenMP single directive. */
3070 static void
3071 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3073 omp_context *ctx;
3074 tree name;
3076 ctx = new_omp_context (stmt, outer_ctx);
3077 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3078 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3079 name = create_tmp_var_name (".omp_copy_s");
3080 name = build_decl (gimple_location (stmt),
3081 TYPE_DECL, name, ctx->record_type);
3082 TYPE_NAME (ctx->record_type) = name;
3084 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3085 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3087 if (TYPE_FIELDS (ctx->record_type) == NULL)
3088 ctx->record_type = NULL;
3089 else
3090 layout_type (ctx->record_type);
3093 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3094 used in the corresponding offloaded function are restrict. */
3096 static bool
3097 omp_target_base_pointers_restrict_p (tree clauses)
3099 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3100 used by OpenACC. */
3101 if (flag_openacc == 0)
3102 return false;
3104 /* I. Basic example:
3106 void foo (void)
3108 unsigned int a[2], b[2];
3110 #pragma acc kernels \
3111 copyout (a) \
3112 copyout (b)
3114 a[0] = 0;
3115 b[0] = 1;
3119 After gimplification, we have:
3121 #pragma omp target oacc_kernels \
3122 map(force_from:a [len: 8]) \
3123 map(force_from:b [len: 8])
3125 a[0] = 0;
3126 b[0] = 1;
3129 Because both mappings have the force prefix, we know that they will be
3130 allocated when calling the corresponding offloaded function, which means we
3131 can mark the base pointers for a and b in the offloaded function as
3132 restrict. */
3134 tree c;
3135 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3137 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3138 return false;
3140 switch (OMP_CLAUSE_MAP_KIND (c))
3142 case GOMP_MAP_FORCE_ALLOC:
3143 case GOMP_MAP_FORCE_TO:
3144 case GOMP_MAP_FORCE_FROM:
3145 case GOMP_MAP_FORCE_TOFROM:
3146 break;
3147 default:
3148 return false;
3152 return true;
3155 /* Scan a GIMPLE_OMP_TARGET. */
3157 static void
3158 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3160 omp_context *ctx;
3161 tree name;
3162 bool offloaded = is_gimple_omp_offloaded (stmt);
3163 tree clauses = gimple_omp_target_clauses (stmt);
3165 ctx = new_omp_context (stmt, outer_ctx);
3166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3169 name = create_tmp_var_name (".omp_data_t");
3170 name = build_decl (gimple_location (stmt),
3171 TYPE_DECL, name, ctx->record_type);
3172 DECL_ARTIFICIAL (name) = 1;
3173 DECL_NAMELESS (name) = 1;
3174 TYPE_NAME (ctx->record_type) = name;
3175 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3177 bool base_pointers_restrict = false;
3178 if (offloaded)
3180 create_omp_child_function (ctx, false);
3181 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3183 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3184 if (base_pointers_restrict
3185 && dump_file && (dump_flags & TDF_DETAILS))
3186 fprintf (dump_file,
3187 "Base pointers in offloaded function are restrict\n");
3190 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3191 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3193 if (TYPE_FIELDS (ctx->record_type) == NULL)
3194 ctx->record_type = ctx->receiver_decl = NULL;
3195 else
3197 TYPE_FIELDS (ctx->record_type)
3198 = nreverse (TYPE_FIELDS (ctx->record_type));
3199 if (flag_checking)
3201 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3202 for (tree field = TYPE_FIELDS (ctx->record_type);
3203 field;
3204 field = DECL_CHAIN (field))
3205 gcc_assert (DECL_ALIGN (field) == align);
3207 layout_type (ctx->record_type);
3208 if (offloaded)
3209 fixup_child_record_type (ctx);
3213 /* Scan an OpenMP teams directive. */
3215 static void
3216 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3218 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3219 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3220 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3223 /* Check nesting restrictions. */
3224 static bool
3225 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3227 tree c;
3229 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3230 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3231 the original copy of its contents. */
3232 return true;
3234 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3235 inside an OpenACC CTX. */
3236 if (!(is_gimple_omp (stmt)
3237 && is_gimple_omp_oacc (stmt))
3238 /* Except for atomic codes that we share with OpenMP. */
3239 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3240 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3242 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3244 error_at (gimple_location (stmt),
3245 "non-OpenACC construct inside of OpenACC routine");
3246 return false;
3248 else
3249 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3250 if (is_gimple_omp (octx->stmt)
3251 && is_gimple_omp_oacc (octx->stmt))
3253 error_at (gimple_location (stmt),
3254 "non-OpenACC construct inside of OpenACC region");
3255 return false;
3259 if (ctx != NULL)
3261 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3262 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3264 c = NULL_TREE;
3265 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3267 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3268 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3270 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3271 && (ctx->outer == NULL
3272 || !gimple_omp_for_combined_into_p (ctx->stmt)
3273 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3274 || (gimple_omp_for_kind (ctx->outer->stmt)
3275 != GF_OMP_FOR_KIND_FOR)
3276 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3278 error_at (gimple_location (stmt),
3279 "%<ordered simd threads%> must be closely "
3280 "nested inside of %<for simd%> region");
3281 return false;
3283 return true;
3286 error_at (gimple_location (stmt),
3287 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3288 " may not be nested inside %<simd%> region");
3289 return false;
3291 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3293 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3294 || (gimple_omp_for_kind (stmt)
3295 != GF_OMP_FOR_KIND_DISTRIBUTE))
3296 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3298 error_at (gimple_location (stmt),
3299 "only %<distribute%> or %<parallel%> regions are "
3300 "allowed to be strictly nested inside %<teams%> "
3301 "region");
3302 return false;
3306 switch (gimple_code (stmt))
3308 case GIMPLE_OMP_FOR:
3309 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3310 return true;
3311 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3313 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3315 error_at (gimple_location (stmt),
3316 "%<distribute%> region must be strictly nested "
3317 "inside %<teams%> construct");
3318 return false;
3320 return true;
3322 /* We split taskloop into task and nested taskloop in it. */
3323 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3324 return true;
3325 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3327 bool ok = false;
3329 if (ctx)
3330 switch (gimple_code (ctx->stmt))
3332 case GIMPLE_OMP_FOR:
3333 ok = (gimple_omp_for_kind (ctx->stmt)
3334 == GF_OMP_FOR_KIND_OACC_LOOP);
3335 break;
3337 case GIMPLE_OMP_TARGET:
3338 switch (gimple_omp_target_kind (ctx->stmt))
3340 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3341 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3342 ok = true;
3343 break;
3345 default:
3346 break;
3349 default:
3350 break;
3352 else if (get_oacc_fn_attrib (current_function_decl))
3353 ok = true;
3354 if (!ok)
3356 error_at (gimple_location (stmt),
3357 "OpenACC loop directive must be associated with"
3358 " an OpenACC compute region");
3359 return false;
3362 /* FALLTHRU */
3363 case GIMPLE_CALL:
3364 if (is_gimple_call (stmt)
3365 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3366 == BUILT_IN_GOMP_CANCEL
3367 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3368 == BUILT_IN_GOMP_CANCELLATION_POINT))
3370 const char *bad = NULL;
3371 const char *kind = NULL;
3372 const char *construct
3373 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL)
3375 ? "#pragma omp cancel"
3376 : "#pragma omp cancellation point";
3377 if (ctx == NULL)
3379 error_at (gimple_location (stmt), "orphaned %qs construct",
3380 construct);
3381 return false;
3383 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3384 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3385 : 0)
3387 case 1:
3388 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3389 bad = "#pragma omp parallel";
3390 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3391 == BUILT_IN_GOMP_CANCEL
3392 && !integer_zerop (gimple_call_arg (stmt, 1)))
3393 ctx->cancellable = true;
3394 kind = "parallel";
3395 break;
3396 case 2:
3397 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3398 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3399 bad = "#pragma omp for";
3400 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3401 == BUILT_IN_GOMP_CANCEL
3402 && !integer_zerop (gimple_call_arg (stmt, 1)))
3404 ctx->cancellable = true;
3405 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3406 OMP_CLAUSE_NOWAIT))
3407 warning_at (gimple_location (stmt), 0,
3408 "%<#pragma omp cancel for%> inside "
3409 "%<nowait%> for construct");
3410 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3411 OMP_CLAUSE_ORDERED))
3412 warning_at (gimple_location (stmt), 0,
3413 "%<#pragma omp cancel for%> inside "
3414 "%<ordered%> for construct");
3416 kind = "for";
3417 break;
3418 case 4:
3419 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3420 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3421 bad = "#pragma omp sections";
3422 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3423 == BUILT_IN_GOMP_CANCEL
3424 && !integer_zerop (gimple_call_arg (stmt, 1)))
3426 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3428 ctx->cancellable = true;
3429 if (find_omp_clause (gimple_omp_sections_clauses
3430 (ctx->stmt),
3431 OMP_CLAUSE_NOWAIT))
3432 warning_at (gimple_location (stmt), 0,
3433 "%<#pragma omp cancel sections%> inside "
3434 "%<nowait%> sections construct");
3436 else
3438 gcc_assert (ctx->outer
3439 && gimple_code (ctx->outer->stmt)
3440 == GIMPLE_OMP_SECTIONS);
3441 ctx->outer->cancellable = true;
3442 if (find_omp_clause (gimple_omp_sections_clauses
3443 (ctx->outer->stmt),
3444 OMP_CLAUSE_NOWAIT))
3445 warning_at (gimple_location (stmt), 0,
3446 "%<#pragma omp cancel sections%> inside "
3447 "%<nowait%> sections construct");
3450 kind = "sections";
3451 break;
3452 case 8:
3453 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3454 bad = "#pragma omp task";
3455 else
3457 for (omp_context *octx = ctx->outer;
3458 octx; octx = octx->outer)
3460 switch (gimple_code (octx->stmt))
3462 case GIMPLE_OMP_TASKGROUP:
3463 break;
3464 case GIMPLE_OMP_TARGET:
3465 if (gimple_omp_target_kind (octx->stmt)
3466 != GF_OMP_TARGET_KIND_REGION)
3467 continue;
3468 /* FALLTHRU */
3469 case GIMPLE_OMP_PARALLEL:
3470 case GIMPLE_OMP_TEAMS:
3471 error_at (gimple_location (stmt),
3472 "%<%s taskgroup%> construct not closely "
3473 "nested inside of %<taskgroup%> region",
3474 construct);
3475 return false;
3476 default:
3477 continue;
3479 break;
3481 ctx->cancellable = true;
3483 kind = "taskgroup";
3484 break;
3485 default:
3486 error_at (gimple_location (stmt), "invalid arguments");
3487 return false;
3489 if (bad)
3491 error_at (gimple_location (stmt),
3492 "%<%s %s%> construct not closely nested inside of %qs",
3493 construct, kind, bad);
3494 return false;
3497 /* FALLTHRU */
3498 case GIMPLE_OMP_SECTIONS:
3499 case GIMPLE_OMP_SINGLE:
3500 for (; ctx != NULL; ctx = ctx->outer)
3501 switch (gimple_code (ctx->stmt))
3503 case GIMPLE_OMP_FOR:
3504 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3505 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3506 break;
3507 /* FALLTHRU */
3508 case GIMPLE_OMP_SECTIONS:
3509 case GIMPLE_OMP_SINGLE:
3510 case GIMPLE_OMP_ORDERED:
3511 case GIMPLE_OMP_MASTER:
3512 case GIMPLE_OMP_TASK:
3513 case GIMPLE_OMP_CRITICAL:
3514 if (is_gimple_call (stmt))
3516 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3517 != BUILT_IN_GOMP_BARRIER)
3518 return true;
3519 error_at (gimple_location (stmt),
3520 "barrier region may not be closely nested inside "
3521 "of work-sharing, %<critical%>, %<ordered%>, "
3522 "%<master%>, explicit %<task%> or %<taskloop%> "
3523 "region");
3524 return false;
3526 error_at (gimple_location (stmt),
3527 "work-sharing region may not be closely nested inside "
3528 "of work-sharing, %<critical%>, %<ordered%>, "
3529 "%<master%>, explicit %<task%> or %<taskloop%> region");
3530 return false;
3531 case GIMPLE_OMP_PARALLEL:
3532 case GIMPLE_OMP_TEAMS:
3533 return true;
3534 case GIMPLE_OMP_TARGET:
3535 if (gimple_omp_target_kind (ctx->stmt)
3536 == GF_OMP_TARGET_KIND_REGION)
3537 return true;
3538 break;
3539 default:
3540 break;
3542 break;
3543 case GIMPLE_OMP_MASTER:
3544 for (; ctx != NULL; ctx = ctx->outer)
3545 switch (gimple_code (ctx->stmt))
3547 case GIMPLE_OMP_FOR:
3548 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3549 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3550 break;
3551 /* FALLTHRU */
3552 case GIMPLE_OMP_SECTIONS:
3553 case GIMPLE_OMP_SINGLE:
3554 case GIMPLE_OMP_TASK:
3555 error_at (gimple_location (stmt),
3556 "%<master%> region may not be closely nested inside "
3557 "of work-sharing, explicit %<task%> or %<taskloop%> "
3558 "region");
3559 return false;
3560 case GIMPLE_OMP_PARALLEL:
3561 case GIMPLE_OMP_TEAMS:
3562 return true;
3563 case GIMPLE_OMP_TARGET:
3564 if (gimple_omp_target_kind (ctx->stmt)
3565 == GF_OMP_TARGET_KIND_REGION)
3566 return true;
3567 break;
3568 default:
3569 break;
3571 break;
3572 case GIMPLE_OMP_TASK:
3573 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3574 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3575 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3576 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3578 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3579 error_at (OMP_CLAUSE_LOCATION (c),
3580 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3581 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3582 return false;
3584 break;
3585 case GIMPLE_OMP_ORDERED:
3586 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3587 c; c = OMP_CLAUSE_CHAIN (c))
3589 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3591 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3592 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3593 continue;
3595 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3596 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3597 || kind == OMP_CLAUSE_DEPEND_SINK)
3599 tree oclause;
3600 /* Look for containing ordered(N) loop. */
3601 if (ctx == NULL
3602 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3603 || (oclause
3604 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3605 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3607 error_at (OMP_CLAUSE_LOCATION (c),
3608 "%<ordered%> construct with %<depend%> clause "
3609 "must be closely nested inside an %<ordered%> "
3610 "loop");
3611 return false;
3613 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3615 error_at (OMP_CLAUSE_LOCATION (c),
3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside a loop with "
3618 "%<ordered%> clause with a parameter");
3619 return false;
3622 else
3624 error_at (OMP_CLAUSE_LOCATION (c),
3625 "invalid depend kind in omp %<ordered%> %<depend%>");
3626 return false;
3629 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3630 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3632 /* ordered simd must be closely nested inside of simd region,
3633 and simd region must not encounter constructs other than
3634 ordered simd, therefore ordered simd may be either orphaned,
3635 or ctx->stmt must be simd. The latter case is handled already
3636 earlier. */
3637 if (ctx != NULL)
3639 error_at (gimple_location (stmt),
3640 "%<ordered%> %<simd%> must be closely nested inside "
3641 "%<simd%> region");
3642 return false;
3645 for (; ctx != NULL; ctx = ctx->outer)
3646 switch (gimple_code (ctx->stmt))
3648 case GIMPLE_OMP_CRITICAL:
3649 case GIMPLE_OMP_TASK:
3650 case GIMPLE_OMP_ORDERED:
3651 ordered_in_taskloop:
3652 error_at (gimple_location (stmt),
3653 "%<ordered%> region may not be closely nested inside "
3654 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3655 "%<taskloop%> region");
3656 return false;
3657 case GIMPLE_OMP_FOR:
3658 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3659 goto ordered_in_taskloop;
3660 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3661 OMP_CLAUSE_ORDERED) == NULL)
3663 error_at (gimple_location (stmt),
3664 "%<ordered%> region must be closely nested inside "
3665 "a loop region with an %<ordered%> clause");
3666 return false;
3668 return true;
3669 case GIMPLE_OMP_TARGET:
3670 if (gimple_omp_target_kind (ctx->stmt)
3671 != GF_OMP_TARGET_KIND_REGION)
3672 break;
3673 /* FALLTHRU */
3674 case GIMPLE_OMP_PARALLEL:
3675 case GIMPLE_OMP_TEAMS:
3676 error_at (gimple_location (stmt),
3677 "%<ordered%> region must be closely nested inside "
3678 "a loop region with an %<ordered%> clause");
3679 return false;
3680 default:
3681 break;
3683 break;
3684 case GIMPLE_OMP_CRITICAL:
3686 tree this_stmt_name
3687 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3688 for (; ctx != NULL; ctx = ctx->outer)
3689 if (gomp_critical *other_crit
3690 = dyn_cast <gomp_critical *> (ctx->stmt))
3691 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3693 error_at (gimple_location (stmt),
3694 "%<critical%> region may not be nested inside "
3695 "a %<critical%> region with the same name");
3696 return false;
3699 break;
3700 case GIMPLE_OMP_TEAMS:
3701 if (ctx == NULL
3702 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3703 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3705 error_at (gimple_location (stmt),
3706 "%<teams%> construct not closely nested inside of "
3707 "%<target%> construct");
3708 return false;
3710 break;
3711 case GIMPLE_OMP_TARGET:
3712 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3713 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3714 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3715 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3717 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3718 error_at (OMP_CLAUSE_LOCATION (c),
3719 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3720 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3721 return false;
3723 if (is_gimple_omp_offloaded (stmt)
3724 && get_oacc_fn_attrib (cfun->decl) != NULL)
3726 error_at (gimple_location (stmt),
3727 "OpenACC region inside of OpenACC routine, nested "
3728 "parallelism not supported yet");
3729 return false;
3731 for (; ctx != NULL; ctx = ctx->outer)
3733 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3735 if (is_gimple_omp (stmt)
3736 && is_gimple_omp_oacc (stmt)
3737 && is_gimple_omp (ctx->stmt))
3739 error_at (gimple_location (stmt),
3740 "OpenACC construct inside of non-OpenACC region");
3741 return false;
3743 continue;
3746 const char *stmt_name, *ctx_stmt_name;
3747 switch (gimple_omp_target_kind (stmt))
3749 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3750 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3751 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3752 case GF_OMP_TARGET_KIND_ENTER_DATA:
3753 stmt_name = "target enter data"; break;
3754 case GF_OMP_TARGET_KIND_EXIT_DATA:
3755 stmt_name = "target exit data"; break;
3756 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3757 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3758 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3760 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3761 stmt_name = "enter/exit data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3763 break;
3764 default: gcc_unreachable ();
3766 switch (gimple_omp_target_kind (ctx->stmt))
3768 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3769 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3770 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3771 ctx_stmt_name = "parallel"; break;
3772 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3773 ctx_stmt_name = "kernels"; break;
3774 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3775 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3776 ctx_stmt_name = "host_data"; break;
3777 default: gcc_unreachable ();
3780 /* OpenACC/OpenMP mismatch? */
3781 if (is_gimple_omp_oacc (stmt)
3782 != is_gimple_omp_oacc (ctx->stmt))
3784 error_at (gimple_location (stmt),
3785 "%s %qs construct inside of %s %qs region",
3786 (is_gimple_omp_oacc (stmt)
3787 ? "OpenACC" : "OpenMP"), stmt_name,
3788 (is_gimple_omp_oacc (ctx->stmt)
3789 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3790 return false;
3792 if (is_gimple_omp_offloaded (ctx->stmt))
3794 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3795 if (is_gimple_omp_oacc (ctx->stmt))
3797 error_at (gimple_location (stmt),
3798 "%qs construct inside of %qs region",
3799 stmt_name, ctx_stmt_name);
3800 return false;
3802 else
3804 warning_at (gimple_location (stmt), 0,
3805 "%qs construct inside of %qs region",
3806 stmt_name, ctx_stmt_name);
3810 break;
3811 default:
3812 break;
3814 return true;
3818 /* Helper function scan_omp.
3820 Callback for walk_tree or operators in walk_gimple_stmt used to
3821 scan for OMP directives in TP. */
3823 static tree
3824 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3826 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3827 omp_context *ctx = (omp_context *) wi->info;
3828 tree t = *tp;
3830 switch (TREE_CODE (t))
3832 case VAR_DECL:
3833 case PARM_DECL:
3834 case LABEL_DECL:
3835 case RESULT_DECL:
3836 if (ctx)
3838 tree repl = remap_decl (t, &ctx->cb);
3839 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3840 *tp = repl;
3842 break;
3844 default:
3845 if (ctx && TYPE_P (t))
3846 *tp = remap_type (t, &ctx->cb);
3847 else if (!DECL_P (t))
3849 *walk_subtrees = 1;
3850 if (ctx)
3852 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3853 if (tem != TREE_TYPE (t))
3855 if (TREE_CODE (t) == INTEGER_CST)
3856 *tp = wide_int_to_tree (tem, t);
3857 else
3858 TREE_TYPE (t) = tem;
3862 break;
3865 return NULL_TREE;
3868 /* Return true if FNDECL is a setjmp or a longjmp. */
3870 static bool
3871 setjmp_or_longjmp_p (const_tree fndecl)
3873 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3874 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3875 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3876 return true;
3878 tree declname = DECL_NAME (fndecl);
3879 if (!declname)
3880 return false;
3881 const char *name = IDENTIFIER_POINTER (declname);
3882 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3886 /* Helper function for scan_omp.
3888 Callback for walk_gimple_stmt used to scan for OMP directives in
3889 the current statement in GSI. */
3891 static tree
3892 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3893 struct walk_stmt_info *wi)
3895 gimple *stmt = gsi_stmt (*gsi);
3896 omp_context *ctx = (omp_context *) wi->info;
3898 if (gimple_has_location (stmt))
3899 input_location = gimple_location (stmt);
3901 /* Check the nesting restrictions. */
3902 bool remove = false;
3903 if (is_gimple_omp (stmt))
3904 remove = !check_omp_nesting_restrictions (stmt, ctx);
3905 else if (is_gimple_call (stmt))
3907 tree fndecl = gimple_call_fndecl (stmt);
3908 if (fndecl)
3910 if (setjmp_or_longjmp_p (fndecl)
3911 && ctx
3912 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3913 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3915 remove = true;
3916 error_at (gimple_location (stmt),
3917 "setjmp/longjmp inside simd construct");
3919 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3920 switch (DECL_FUNCTION_CODE (fndecl))
3922 case BUILT_IN_GOMP_BARRIER:
3923 case BUILT_IN_GOMP_CANCEL:
3924 case BUILT_IN_GOMP_CANCELLATION_POINT:
3925 case BUILT_IN_GOMP_TASKYIELD:
3926 case BUILT_IN_GOMP_TASKWAIT:
3927 case BUILT_IN_GOMP_TASKGROUP_START:
3928 case BUILT_IN_GOMP_TASKGROUP_END:
3929 remove = !check_omp_nesting_restrictions (stmt, ctx);
3930 break;
3931 default:
3932 break;
3936 if (remove)
3938 stmt = gimple_build_nop ();
3939 gsi_replace (gsi, stmt, false);
3942 *handled_ops_p = true;
3944 switch (gimple_code (stmt))
3946 case GIMPLE_OMP_PARALLEL:
3947 taskreg_nesting_level++;
3948 scan_omp_parallel (gsi, ctx);
3949 taskreg_nesting_level--;
3950 break;
3952 case GIMPLE_OMP_TASK:
3953 taskreg_nesting_level++;
3954 scan_omp_task (gsi, ctx);
3955 taskreg_nesting_level--;
3956 break;
3958 case GIMPLE_OMP_FOR:
3959 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3960 break;
3962 case GIMPLE_OMP_SECTIONS:
3963 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3964 break;
3966 case GIMPLE_OMP_SINGLE:
3967 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3968 break;
3970 case GIMPLE_OMP_SECTION:
3971 case GIMPLE_OMP_MASTER:
3972 case GIMPLE_OMP_TASKGROUP:
3973 case GIMPLE_OMP_ORDERED:
3974 case GIMPLE_OMP_CRITICAL:
3975 case GIMPLE_OMP_GRID_BODY:
3976 ctx = new_omp_context (stmt, ctx);
3977 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3978 break;
3980 case GIMPLE_OMP_TARGET:
3981 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3982 break;
3984 case GIMPLE_OMP_TEAMS:
3985 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3986 break;
3988 case GIMPLE_BIND:
3990 tree var;
3992 *handled_ops_p = false;
3993 if (ctx)
3994 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3995 var ;
3996 var = DECL_CHAIN (var))
3997 insert_decl_map (&ctx->cb, var, var);
3999 break;
4000 default:
4001 *handled_ops_p = false;
4002 break;
4005 return NULL_TREE;
4009 /* Scan all the statements starting at the current statement. CTX
4010 contains context information about the OMP directives and
4011 clauses found during the scan. */
4013 static void
4014 scan_omp (gimple_seq *body_p, omp_context *ctx)
4016 location_t saved_location;
4017 struct walk_stmt_info wi;
4019 memset (&wi, 0, sizeof (wi));
4020 wi.info = ctx;
4021 wi.want_locations = true;
4023 saved_location = input_location;
4024 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4025 input_location = saved_location;
4028 /* Re-gimplification and code generation routines. */
4030 /* Build a call to GOMP_barrier. */
4032 static gimple *
4033 build_omp_barrier (tree lhs)
4035 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4036 : BUILT_IN_GOMP_BARRIER);
4037 gcall *g = gimple_build_call (fndecl, 0);
4038 if (lhs)
4039 gimple_call_set_lhs (g, lhs);
4040 return g;
4043 /* If a context was created for STMT when it was scanned, return it. */
4045 static omp_context *
4046 maybe_lookup_ctx (gimple *stmt)
4048 splay_tree_node n;
4049 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4050 return n ? (omp_context *) n->value : NULL;
4054 /* Find the mapping for DECL in CTX or the immediately enclosing
4055 context that has a mapping for DECL.
4057 If CTX is a nested parallel directive, we may have to use the decl
4058 mappings created in CTX's parent context. Suppose that we have the
4059 following parallel nesting (variable UIDs showed for clarity):
4061 iD.1562 = 0;
4062 #omp parallel shared(iD.1562) -> outer parallel
4063 iD.1562 = iD.1562 + 1;
4065 #omp parallel shared (iD.1562) -> inner parallel
4066 iD.1562 = iD.1562 - 1;
4068 Each parallel structure will create a distinct .omp_data_s structure
4069 for copying iD.1562 in/out of the directive:
4071 outer parallel .omp_data_s.1.i -> iD.1562
4072 inner parallel .omp_data_s.2.i -> iD.1562
4074 A shared variable mapping will produce a copy-out operation before
4075 the parallel directive and a copy-in operation after it. So, in
4076 this case we would have:
4078 iD.1562 = 0;
4079 .omp_data_o.1.i = iD.1562;
4080 #omp parallel shared(iD.1562) -> outer parallel
4081 .omp_data_i.1 = &.omp_data_o.1
4082 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4084 .omp_data_o.2.i = iD.1562; -> **
4085 #omp parallel shared(iD.1562) -> inner parallel
4086 .omp_data_i.2 = &.omp_data_o.2
4087 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4090 ** This is a problem. The symbol iD.1562 cannot be referenced
4091 inside the body of the outer parallel region. But since we are
4092 emitting this copy operation while expanding the inner parallel
4093 directive, we need to access the CTX structure of the outer
4094 parallel directive to get the correct mapping:
4096 .omp_data_o.2.i = .omp_data_i.1->i
4098 Since there may be other workshare or parallel directives enclosing
4099 the parallel directive, it may be necessary to walk up the context
4100 parent chain. This is not a problem in general because nested
4101 parallelism happens only rarely. */
4103 static tree
4104 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4106 tree t;
4107 omp_context *up;
4109 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4110 t = maybe_lookup_decl (decl, up);
4112 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4114 return t ? t : decl;
4118 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4119 in outer contexts. */
4121 static tree
4122 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4124 tree t = NULL;
4125 omp_context *up;
4127 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4128 t = maybe_lookup_decl (decl, up);
4130 return t ? t : decl;
4134 /* Construct the initialization value for reduction operation OP. */
4136 tree
4137 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4139 switch (op)
4141 case PLUS_EXPR:
4142 case MINUS_EXPR:
4143 case BIT_IOR_EXPR:
4144 case BIT_XOR_EXPR:
4145 case TRUTH_OR_EXPR:
4146 case TRUTH_ORIF_EXPR:
4147 case TRUTH_XOR_EXPR:
4148 case NE_EXPR:
4149 return build_zero_cst (type);
4151 case MULT_EXPR:
4152 case TRUTH_AND_EXPR:
4153 case TRUTH_ANDIF_EXPR:
4154 case EQ_EXPR:
4155 return fold_convert_loc (loc, type, integer_one_node);
4157 case BIT_AND_EXPR:
4158 return fold_convert_loc (loc, type, integer_minus_one_node);
4160 case MAX_EXPR:
4161 if (SCALAR_FLOAT_TYPE_P (type))
4163 REAL_VALUE_TYPE max, min;
4164 if (HONOR_INFINITIES (type))
4166 real_inf (&max);
4167 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4169 else
4170 real_maxval (&min, 1, TYPE_MODE (type));
4171 return build_real (type, min);
4173 else if (POINTER_TYPE_P (type))
4175 wide_int min
4176 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4177 return wide_int_to_tree (type, min);
4179 else
4181 gcc_assert (INTEGRAL_TYPE_P (type));
4182 return TYPE_MIN_VALUE (type);
4185 case MIN_EXPR:
4186 if (SCALAR_FLOAT_TYPE_P (type))
4188 REAL_VALUE_TYPE max;
4189 if (HONOR_INFINITIES (type))
4190 real_inf (&max);
4191 else
4192 real_maxval (&max, 0, TYPE_MODE (type));
4193 return build_real (type, max);
4195 else if (POINTER_TYPE_P (type))
4197 wide_int max
4198 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4199 return wide_int_to_tree (type, max);
4201 else
4203 gcc_assert (INTEGRAL_TYPE_P (type));
4204 return TYPE_MAX_VALUE (type);
4207 default:
4208 gcc_unreachable ();
4212 /* Construct the initialization value for reduction CLAUSE. */
4214 tree
4215 omp_reduction_init (tree clause, tree type)
4217 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4218 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4221 /* Return alignment to be assumed for var in CLAUSE, which should be
4222 OMP_CLAUSE_ALIGNED. */
4224 static tree
4225 omp_clause_aligned_alignment (tree clause)
4227 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4228 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4230 /* Otherwise return implementation defined alignment. */
4231 unsigned int al = 1;
4232 machine_mode mode, vmode;
4233 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4234 if (vs)
4235 vs = 1 << floor_log2 (vs);
4236 static enum mode_class classes[]
4237 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4238 for (int i = 0; i < 4; i += 2)
4239 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4240 mode != VOIDmode;
4241 mode = GET_MODE_WIDER_MODE (mode))
4243 vmode = targetm.vectorize.preferred_simd_mode (mode);
4244 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4245 continue;
4246 while (vs
4247 && GET_MODE_SIZE (vmode) < vs
4248 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4249 vmode = GET_MODE_2XWIDER_MODE (vmode);
4251 tree type = lang_hooks.types.type_for_mode (mode, 1);
4252 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4253 continue;
4254 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4255 / GET_MODE_SIZE (mode));
4256 if (TYPE_MODE (type) != vmode)
4257 continue;
4258 if (TYPE_ALIGN_UNIT (type) > al)
4259 al = TYPE_ALIGN_UNIT (type);
4261 return build_int_cst (integer_type_node, al);
4264 /* Return maximum possible vectorization factor for the target. */
4266 static int
4267 omp_max_vf (void)
4269 if (!optimize
4270 || optimize_debug
4271 || !flag_tree_loop_optimize
4272 || (!flag_tree_loop_vectorize
4273 && (global_options_set.x_flag_tree_loop_vectorize
4274 || global_options_set.x_flag_tree_vectorize)))
4275 return 1;
4277 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4278 if (vs)
4280 vs = 1 << floor_log2 (vs);
4281 return vs;
4283 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4284 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4285 return GET_MODE_NUNITS (vqimode);
4286 return 1;
4289 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4290 privatization. */
4292 static bool
4293 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4294 tree &idx, tree &lane, tree &ivar, tree &lvar)
4296 if (max_vf == 0)
4298 max_vf = omp_max_vf ();
4299 if (max_vf > 1)
4301 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4302 OMP_CLAUSE_SAFELEN);
4303 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4304 max_vf = 1;
4305 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4306 max_vf) == -1)
4307 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4309 if (max_vf > 1)
4311 idx = create_tmp_var (unsigned_type_node);
4312 lane = create_tmp_var (unsigned_type_node);
4315 if (max_vf == 1)
4316 return false;
4318 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4319 tree avar = create_tmp_var_raw (atype);
4320 if (TREE_ADDRESSABLE (new_var))
4321 TREE_ADDRESSABLE (avar) = 1;
4322 DECL_ATTRIBUTES (avar)
4323 = tree_cons (get_identifier ("omp simd array"), NULL,
4324 DECL_ATTRIBUTES (avar));
4325 gimple_add_tmp_var (avar);
4326 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4327 NULL_TREE, NULL_TREE);
4328 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4329 NULL_TREE, NULL_TREE);
4330 if (DECL_P (new_var))
4332 SET_DECL_VALUE_EXPR (new_var, lvar);
4333 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4335 return true;
4338 /* Helper function of lower_rec_input_clauses. For a reference
4339 in simd reduction, add an underlying variable it will reference. */
4341 static void
4342 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4344 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4345 if (TREE_CONSTANT (z))
4347 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4348 get_name (new_vard));
4349 gimple_add_tmp_var (z);
4350 TREE_ADDRESSABLE (z) = 1;
4351 z = build_fold_addr_expr_loc (loc, z);
4352 gimplify_assign (new_vard, z, ilist);
4356 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4357 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4358 private variables. Initialization statements go in ILIST, while calls
4359 to destructors go in DLIST. */
4361 static void
4362 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4363 omp_context *ctx, struct omp_for_data *fd)
4365 tree c, dtor, copyin_seq, x, ptr;
4366 bool copyin_by_ref = false;
4367 bool lastprivate_firstprivate = false;
4368 bool reduction_omp_orig_ref = false;
4369 int pass;
4370 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4371 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4372 int max_vf = 0;
4373 tree lane = NULL_TREE, idx = NULL_TREE;
4374 tree ivar = NULL_TREE, lvar = NULL_TREE;
4375 gimple_seq llist[2] = { NULL, NULL };
4377 copyin_seq = NULL;
4379 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4380 with data sharing clauses referencing variable sized vars. That
4381 is unnecessarily hard to support and very unlikely to result in
4382 vectorized code anyway. */
4383 if (is_simd)
4384 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4385 switch (OMP_CLAUSE_CODE (c))
4387 case OMP_CLAUSE_LINEAR:
4388 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4389 max_vf = 1;
4390 /* FALLTHRU */
4391 case OMP_CLAUSE_PRIVATE:
4392 case OMP_CLAUSE_FIRSTPRIVATE:
4393 case OMP_CLAUSE_LASTPRIVATE:
4394 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4395 max_vf = 1;
4396 break;
4397 case OMP_CLAUSE_REDUCTION:
4398 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4399 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4400 max_vf = 1;
4401 break;
4402 default:
4403 continue;
4406 /* Do all the fixed sized types in the first pass, and the variable sized
4407 types in the second pass. This makes sure that the scalar arguments to
4408 the variable sized types are processed before we use them in the
4409 variable sized operations. */
4410 for (pass = 0; pass < 2; ++pass)
4412 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4414 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4415 tree var, new_var;
4416 bool by_ref;
4417 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4419 switch (c_kind)
4421 case OMP_CLAUSE_PRIVATE:
4422 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4423 continue;
4424 break;
4425 case OMP_CLAUSE_SHARED:
4426 /* Ignore shared directives in teams construct. */
4427 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4428 continue;
4429 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4431 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4432 || is_global_var (OMP_CLAUSE_DECL (c)));
4433 continue;
4435 case OMP_CLAUSE_FIRSTPRIVATE:
4436 case OMP_CLAUSE_COPYIN:
4437 break;
4438 case OMP_CLAUSE_LINEAR:
4439 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4440 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4441 lastprivate_firstprivate = true;
4442 break;
4443 case OMP_CLAUSE_REDUCTION:
4444 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4445 reduction_omp_orig_ref = true;
4446 break;
4447 case OMP_CLAUSE__LOOPTEMP_:
4448 /* Handle _looptemp_ clauses only on parallel/task. */
4449 if (fd)
4450 continue;
4451 break;
4452 case OMP_CLAUSE_LASTPRIVATE:
4453 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4455 lastprivate_firstprivate = true;
4456 if (pass != 0 || is_taskloop_ctx (ctx))
4457 continue;
4459 /* Even without corresponding firstprivate, if
4460 decl is Fortran allocatable, it needs outer var
4461 reference. */
4462 else if (pass == 0
4463 && lang_hooks.decls.omp_private_outer_ref
4464 (OMP_CLAUSE_DECL (c)))
4465 lastprivate_firstprivate = true;
4466 break;
4467 case OMP_CLAUSE_ALIGNED:
4468 if (pass == 0)
4469 continue;
4470 var = OMP_CLAUSE_DECL (c);
4471 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4472 && !is_global_var (var))
4474 new_var = maybe_lookup_decl (var, ctx);
4475 if (new_var == NULL_TREE)
4476 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4477 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4478 tree alarg = omp_clause_aligned_alignment (c);
4479 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4480 x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
4481 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4482 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4483 gimplify_and_add (x, ilist);
4485 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4486 && is_global_var (var))
4488 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4489 new_var = lookup_decl (var, ctx);
4490 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4491 t = build_fold_addr_expr_loc (clause_loc, t);
4492 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4493 tree alarg = omp_clause_aligned_alignment (c);
4494 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4495 t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
4496 t = fold_convert_loc (clause_loc, ptype, t);
4497 x = create_tmp_var (ptype);
4498 t = build2 (MODIFY_EXPR, ptype, x, t);
4499 gimplify_and_add (t, ilist);
4500 t = build_simple_mem_ref_loc (clause_loc, x);
4501 SET_DECL_VALUE_EXPR (new_var, t);
4502 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4504 continue;
4505 default:
4506 continue;
4509 new_var = var = OMP_CLAUSE_DECL (c);
4510 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4512 var = TREE_OPERAND (var, 0);
4513 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4514 var = TREE_OPERAND (var, 0);
4515 if (TREE_CODE (var) == INDIRECT_REF
4516 || TREE_CODE (var) == ADDR_EXPR)
4517 var = TREE_OPERAND (var, 0);
4518 if (is_variable_sized (var))
4520 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4521 var = DECL_VALUE_EXPR (var);
4522 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4523 var = TREE_OPERAND (var, 0);
4524 gcc_assert (DECL_P (var));
4526 new_var = var;
4528 if (c_kind != OMP_CLAUSE_COPYIN)
4529 new_var = lookup_decl (var, ctx);
4531 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4533 if (pass != 0)
4534 continue;
4536 /* C/C++ array section reductions. */
4537 else if (c_kind == OMP_CLAUSE_REDUCTION
4538 && var != OMP_CLAUSE_DECL (c))
4540 if (pass == 0)
4541 continue;
4543 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4544 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4545 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4547 tree b = TREE_OPERAND (orig_var, 1);
4548 b = maybe_lookup_decl (b, ctx);
4549 if (b == NULL)
4551 b = TREE_OPERAND (orig_var, 1);
4552 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4554 if (integer_zerop (bias))
4555 bias = b;
4556 else
4558 bias = fold_convert_loc (clause_loc,
4559 TREE_TYPE (b), bias);
4560 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4561 TREE_TYPE (b), b, bias);
4563 orig_var = TREE_OPERAND (orig_var, 0);
4565 if (TREE_CODE (orig_var) == INDIRECT_REF
4566 || TREE_CODE (orig_var) == ADDR_EXPR)
4567 orig_var = TREE_OPERAND (orig_var, 0);
4568 tree d = OMP_CLAUSE_DECL (c);
4569 tree type = TREE_TYPE (d);
4570 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4571 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4572 const char *name = get_name (orig_var);
4573 if (TREE_CONSTANT (v))
4575 x = create_tmp_var_raw (type, name);
4576 gimple_add_tmp_var (x);
4577 TREE_ADDRESSABLE (x) = 1;
4578 x = build_fold_addr_expr_loc (clause_loc, x);
4580 else
4582 tree atmp
4583 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4584 tree t = maybe_lookup_decl (v, ctx);
4585 if (t)
4586 v = t;
4587 else
4588 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4589 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4590 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4591 TREE_TYPE (v), v,
4592 build_int_cst (TREE_TYPE (v), 1));
4593 t = fold_build2_loc (clause_loc, MULT_EXPR,
4594 TREE_TYPE (v), t,
4595 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4596 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4597 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4600 tree ptype = build_pointer_type (TREE_TYPE (type));
4601 x = fold_convert_loc (clause_loc, ptype, x);
4602 tree y = create_tmp_var (ptype, name);
4603 gimplify_assign (y, x, ilist);
4604 x = y;
4605 tree yb = y;
4607 if (!integer_zerop (bias))
4609 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4610 bias);
4611 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4613 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4614 pointer_sized_int_node, yb, bias);
4615 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4616 yb = create_tmp_var (ptype, name);
4617 gimplify_assign (yb, x, ilist);
4618 x = yb;
4621 d = TREE_OPERAND (d, 0);
4622 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4623 d = TREE_OPERAND (d, 0);
4624 if (TREE_CODE (d) == ADDR_EXPR)
4626 if (orig_var != var)
4628 gcc_assert (is_variable_sized (orig_var));
4629 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4631 gimplify_assign (new_var, x, ilist);
4632 tree new_orig_var = lookup_decl (orig_var, ctx);
4633 tree t = build_fold_indirect_ref (new_var);
4634 DECL_IGNORED_P (new_var) = 0;
4635 TREE_THIS_NOTRAP (t);
4636 SET_DECL_VALUE_EXPR (new_orig_var, t);
4637 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4639 else
4641 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4642 build_int_cst (ptype, 0));
4643 SET_DECL_VALUE_EXPR (new_var, x);
4644 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4647 else
4649 gcc_assert (orig_var == var);
4650 if (TREE_CODE (d) == INDIRECT_REF)
4652 x = create_tmp_var (ptype, name);
4653 TREE_ADDRESSABLE (x) = 1;
4654 gimplify_assign (x, yb, ilist);
4655 x = build_fold_addr_expr_loc (clause_loc, x);
4657 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4658 gimplify_assign (new_var, x, ilist);
4660 tree y1 = create_tmp_var (ptype, NULL);
4661 gimplify_assign (y1, y, ilist);
4662 tree i2 = NULL_TREE, y2 = NULL_TREE;
4663 tree body2 = NULL_TREE, end2 = NULL_TREE;
4664 tree y3 = NULL_TREE, y4 = NULL_TREE;
4665 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4667 y2 = create_tmp_var (ptype, NULL);
4668 gimplify_assign (y2, y, ilist);
4669 tree ref = build_outer_var_ref (var, ctx);
4670 /* For ref build_outer_var_ref already performs this. */
4671 if (TREE_CODE (d) == INDIRECT_REF)
4672 gcc_assert (is_reference (var));
4673 else if (TREE_CODE (d) == ADDR_EXPR)
4674 ref = build_fold_addr_expr (ref);
4675 else if (is_reference (var))
4676 ref = build_fold_addr_expr (ref);
4677 ref = fold_convert_loc (clause_loc, ptype, ref);
4678 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4679 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4681 y3 = create_tmp_var (ptype, NULL);
4682 gimplify_assign (y3, unshare_expr (ref), ilist);
4684 if (is_simd)
4686 y4 = create_tmp_var (ptype, NULL);
4687 gimplify_assign (y4, ref, dlist);
4690 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4691 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4692 tree body = create_artificial_label (UNKNOWN_LOCATION);
4693 tree end = create_artificial_label (UNKNOWN_LOCATION);
4694 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4695 if (y2)
4697 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4698 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4699 body2 = create_artificial_label (UNKNOWN_LOCATION);
4700 end2 = create_artificial_label (UNKNOWN_LOCATION);
4701 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4703 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4705 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4706 tree decl_placeholder
4707 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4708 SET_DECL_VALUE_EXPR (decl_placeholder,
4709 build_simple_mem_ref (y1));
4710 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4711 SET_DECL_VALUE_EXPR (placeholder,
4712 y3 ? build_simple_mem_ref (y3)
4713 : error_mark_node);
4714 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4715 x = lang_hooks.decls.omp_clause_default_ctor
4716 (c, build_simple_mem_ref (y1),
4717 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4718 if (x)
4719 gimplify_and_add (x, ilist);
4720 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4722 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4723 lower_omp (&tseq, ctx);
4724 gimple_seq_add_seq (ilist, tseq);
4726 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4727 if (is_simd)
4729 SET_DECL_VALUE_EXPR (decl_placeholder,
4730 build_simple_mem_ref (y2));
4731 SET_DECL_VALUE_EXPR (placeholder,
4732 build_simple_mem_ref (y4));
4733 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4734 lower_omp (&tseq, ctx);
4735 gimple_seq_add_seq (dlist, tseq);
4736 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4738 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4739 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4740 x = lang_hooks.decls.omp_clause_dtor
4741 (c, build_simple_mem_ref (y2));
4742 if (x)
4744 gimple_seq tseq = NULL;
4745 dtor = x;
4746 gimplify_stmt (&dtor, &tseq);
4747 gimple_seq_add_seq (dlist, tseq);
4750 else
4752 x = omp_reduction_init (c, TREE_TYPE (type));
4753 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4755 /* reduction(-:var) sums up the partial results, so it
4756 acts identically to reduction(+:var). */
4757 if (code == MINUS_EXPR)
4758 code = PLUS_EXPR;
4760 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4761 if (is_simd)
4763 x = build2 (code, TREE_TYPE (type),
4764 build_simple_mem_ref (y4),
4765 build_simple_mem_ref (y2));
4766 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4769 gimple *g
4770 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4771 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4772 gimple_seq_add_stmt (ilist, g);
4773 if (y3)
4775 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4776 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4777 gimple_seq_add_stmt (ilist, g);
4779 g = gimple_build_assign (i, PLUS_EXPR, i,
4780 build_int_cst (TREE_TYPE (i), 1));
4781 gimple_seq_add_stmt (ilist, g);
4782 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4783 gimple_seq_add_stmt (ilist, g);
4784 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4785 if (y2)
4787 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4788 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4789 gimple_seq_add_stmt (dlist, g);
4790 if (y4)
4792 g = gimple_build_assign
4793 (y4, POINTER_PLUS_EXPR, y4,
4794 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4795 gimple_seq_add_stmt (dlist, g);
4797 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4798 build_int_cst (TREE_TYPE (i2), 1));
4799 gimple_seq_add_stmt (dlist, g);
4800 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4801 gimple_seq_add_stmt (dlist, g);
4802 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4804 continue;
4806 else if (is_variable_sized (var))
4808 /* For variable sized types, we need to allocate the
4809 actual storage here. Call alloca and store the
4810 result in the pointer decl that we created elsewhere. */
4811 if (pass == 0)
4812 continue;
4814 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4816 gcall *stmt;
4817 tree tmp, atmp;
4819 ptr = DECL_VALUE_EXPR (new_var);
4820 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4821 ptr = TREE_OPERAND (ptr, 0);
4822 gcc_assert (DECL_P (ptr));
4823 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4825 /* void *tmp = __builtin_alloca */
4826 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4827 stmt = gimple_build_call (atmp, 2, x,
4828 size_int (DECL_ALIGN (var)));
4829 tmp = create_tmp_var_raw (ptr_type_node);
4830 gimple_add_tmp_var (tmp);
4831 gimple_call_set_lhs (stmt, tmp);
4833 gimple_seq_add_stmt (ilist, stmt);
4835 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4836 gimplify_assign (ptr, x, ilist);
4839 else if (is_reference (var))
4841 /* For references that are being privatized for Fortran,
4842 allocate new backing storage for the new pointer
4843 variable. This allows us to avoid changing all the
4844 code that expects a pointer to something that expects
4845 a direct variable. */
4846 if (pass == 0)
4847 continue;
4849 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4850 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4852 x = build_receiver_ref (var, false, ctx);
4853 x = build_fold_addr_expr_loc (clause_loc, x);
4855 else if (TREE_CONSTANT (x))
4857 /* For reduction in SIMD loop, defer adding the
4858 initialization of the reference, because if we decide
4859 to use SIMD array for it, the initilization could cause
4860 expansion ICE. */
4861 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4862 x = NULL_TREE;
4863 else
4865 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4866 get_name (var));
4867 gimple_add_tmp_var (x);
4868 TREE_ADDRESSABLE (x) = 1;
4869 x = build_fold_addr_expr_loc (clause_loc, x);
4872 else
4874 tree atmp
4875 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4876 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4877 tree al = size_int (TYPE_ALIGN (rtype));
4878 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4881 if (x)
4883 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4884 gimplify_assign (new_var, x, ilist);
4887 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4889 else if (c_kind == OMP_CLAUSE_REDUCTION
4890 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4892 if (pass == 0)
4893 continue;
4895 else if (pass != 0)
4896 continue;
4898 switch (OMP_CLAUSE_CODE (c))
4900 case OMP_CLAUSE_SHARED:
4901 /* Ignore shared directives in teams construct. */
4902 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4903 continue;
4904 /* Shared global vars are just accessed directly. */
4905 if (is_global_var (new_var))
4906 break;
4907 /* For taskloop firstprivate/lastprivate, represented
4908 as firstprivate and shared clause on the task, new_var
4909 is the firstprivate var. */
4910 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4911 break;
4912 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4913 needs to be delayed until after fixup_child_record_type so
4914 that we get the correct type during the dereference. */
4915 by_ref = use_pointer_for_field (var, ctx);
4916 x = build_receiver_ref (var, by_ref, ctx);
4917 SET_DECL_VALUE_EXPR (new_var, x);
4918 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4920 /* ??? If VAR is not passed by reference, and the variable
4921 hasn't been initialized yet, then we'll get a warning for
4922 the store into the omp_data_s structure. Ideally, we'd be
4923 able to notice this and not store anything at all, but
4924 we're generating code too early. Suppress the warning. */
4925 if (!by_ref)
4926 TREE_NO_WARNING (var) = 1;
4927 break;
4929 case OMP_CLAUSE_LASTPRIVATE:
4930 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4931 break;
4932 /* FALLTHRU */
4934 case OMP_CLAUSE_PRIVATE:
4935 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4936 x = build_outer_var_ref (var, ctx);
4937 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4939 if (is_task_ctx (ctx))
4940 x = build_receiver_ref (var, false, ctx);
4941 else
4942 x = build_outer_var_ref (var, ctx);
4944 else
4945 x = NULL;
4946 do_private:
4947 tree nx;
4948 nx = lang_hooks.decls.omp_clause_default_ctor
4949 (c, unshare_expr (new_var), x);
4950 if (is_simd)
4952 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4953 if ((TREE_ADDRESSABLE (new_var) || nx || y
4954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4955 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4956 idx, lane, ivar, lvar))
4958 if (nx)
4959 x = lang_hooks.decls.omp_clause_default_ctor
4960 (c, unshare_expr (ivar), x);
4961 if (nx && x)
4962 gimplify_and_add (x, &llist[0]);
4963 if (y)
4965 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4966 if (y)
4968 gimple_seq tseq = NULL;
4970 dtor = y;
4971 gimplify_stmt (&dtor, &tseq);
4972 gimple_seq_add_seq (&llist[1], tseq);
4975 break;
4978 if (nx)
4979 gimplify_and_add (nx, ilist);
4980 /* FALLTHRU */
4982 do_dtor:
4983 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4984 if (x)
4986 gimple_seq tseq = NULL;
4988 dtor = x;
4989 gimplify_stmt (&dtor, &tseq);
4990 gimple_seq_add_seq (dlist, tseq);
4992 break;
4994 case OMP_CLAUSE_LINEAR:
4995 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4996 goto do_firstprivate;
4997 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4998 x = NULL;
4999 else
5000 x = build_outer_var_ref (var, ctx);
5001 goto do_private;
5003 case OMP_CLAUSE_FIRSTPRIVATE:
5004 if (is_task_ctx (ctx))
5006 if (is_reference (var) || is_variable_sized (var))
5007 goto do_dtor;
5008 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5009 ctx))
5010 || use_pointer_for_field (var, NULL))
5012 x = build_receiver_ref (var, false, ctx);
5013 SET_DECL_VALUE_EXPR (new_var, x);
5014 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5015 goto do_dtor;
5018 do_firstprivate:
5019 x = build_outer_var_ref (var, ctx);
5020 if (is_simd)
5022 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5023 && gimple_omp_for_combined_into_p (ctx->stmt))
5025 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5026 tree stept = TREE_TYPE (t);
5027 tree ct = find_omp_clause (clauses,
5028 OMP_CLAUSE__LOOPTEMP_);
5029 gcc_assert (ct);
5030 tree l = OMP_CLAUSE_DECL (ct);
5031 tree n1 = fd->loop.n1;
5032 tree step = fd->loop.step;
5033 tree itype = TREE_TYPE (l);
5034 if (POINTER_TYPE_P (itype))
5035 itype = signed_type_for (itype);
5036 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5037 if (TYPE_UNSIGNED (itype)
5038 && fd->loop.cond_code == GT_EXPR)
5039 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5040 fold_build1 (NEGATE_EXPR, itype, l),
5041 fold_build1 (NEGATE_EXPR,
5042 itype, step));
5043 else
5044 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5045 t = fold_build2 (MULT_EXPR, stept,
5046 fold_convert (stept, l), t);
5048 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5050 x = lang_hooks.decls.omp_clause_linear_ctor
5051 (c, new_var, x, t);
5052 gimplify_and_add (x, ilist);
5053 goto do_dtor;
5056 if (POINTER_TYPE_P (TREE_TYPE (x)))
5057 x = fold_build2 (POINTER_PLUS_EXPR,
5058 TREE_TYPE (x), x, t);
5059 else
5060 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5063 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5064 || TREE_ADDRESSABLE (new_var))
5065 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5066 idx, lane, ivar, lvar))
5068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5070 tree iv = create_tmp_var (TREE_TYPE (new_var));
5071 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5072 gimplify_and_add (x, ilist);
5073 gimple_stmt_iterator gsi
5074 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5075 gassign *g
5076 = gimple_build_assign (unshare_expr (lvar), iv);
5077 gsi_insert_before_without_update (&gsi, g,
5078 GSI_SAME_STMT);
5079 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5080 enum tree_code code = PLUS_EXPR;
5081 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5082 code = POINTER_PLUS_EXPR;
5083 g = gimple_build_assign (iv, code, iv, t);
5084 gsi_insert_before_without_update (&gsi, g,
5085 GSI_SAME_STMT);
5086 break;
5088 x = lang_hooks.decls.omp_clause_copy_ctor
5089 (c, unshare_expr (ivar), x);
5090 gimplify_and_add (x, &llist[0]);
5091 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5092 if (x)
5094 gimple_seq tseq = NULL;
5096 dtor = x;
5097 gimplify_stmt (&dtor, &tseq);
5098 gimple_seq_add_seq (&llist[1], tseq);
5100 break;
5103 x = lang_hooks.decls.omp_clause_copy_ctor
5104 (c, unshare_expr (new_var), x);
5105 gimplify_and_add (x, ilist);
5106 goto do_dtor;
5108 case OMP_CLAUSE__LOOPTEMP_:
5109 gcc_assert (is_taskreg_ctx (ctx));
5110 x = build_outer_var_ref (var, ctx);
5111 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5112 gimplify_and_add (x, ilist);
5113 break;
5115 case OMP_CLAUSE_COPYIN:
5116 by_ref = use_pointer_for_field (var, NULL);
5117 x = build_receiver_ref (var, by_ref, ctx);
5118 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5119 append_to_statement_list (x, &copyin_seq);
5120 copyin_by_ref |= by_ref;
5121 break;
5123 case OMP_CLAUSE_REDUCTION:
5124 /* OpenACC reductions are initialized using the
5125 GOACC_REDUCTION internal function. */
5126 if (is_gimple_omp_oacc (ctx->stmt))
5127 break;
5128 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5130 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5131 gimple *tseq;
5132 x = build_outer_var_ref (var, ctx);
5134 if (is_reference (var)
5135 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5136 TREE_TYPE (x)))
5137 x = build_fold_addr_expr_loc (clause_loc, x);
5138 SET_DECL_VALUE_EXPR (placeholder, x);
5139 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5140 tree new_vard = new_var;
5141 if (is_reference (var))
5143 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5144 new_vard = TREE_OPERAND (new_var, 0);
5145 gcc_assert (DECL_P (new_vard));
5147 if (is_simd
5148 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5149 idx, lane, ivar, lvar))
5151 if (new_vard == new_var)
5153 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5154 SET_DECL_VALUE_EXPR (new_var, ivar);
5156 else
5158 SET_DECL_VALUE_EXPR (new_vard,
5159 build_fold_addr_expr (ivar));
5160 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5162 x = lang_hooks.decls.omp_clause_default_ctor
5163 (c, unshare_expr (ivar),
5164 build_outer_var_ref (var, ctx));
5165 if (x)
5166 gimplify_and_add (x, &llist[0]);
5167 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5169 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5170 lower_omp (&tseq, ctx);
5171 gimple_seq_add_seq (&llist[0], tseq);
5173 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5174 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5175 lower_omp (&tseq, ctx);
5176 gimple_seq_add_seq (&llist[1], tseq);
5177 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5178 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5179 if (new_vard == new_var)
5180 SET_DECL_VALUE_EXPR (new_var, lvar);
5181 else
5182 SET_DECL_VALUE_EXPR (new_vard,
5183 build_fold_addr_expr (lvar));
5184 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5185 if (x)
5187 tseq = NULL;
5188 dtor = x;
5189 gimplify_stmt (&dtor, &tseq);
5190 gimple_seq_add_seq (&llist[1], tseq);
5192 break;
5194 /* If this is a reference to constant size reduction var
5195 with placeholder, we haven't emitted the initializer
5196 for it because it is undesirable if SIMD arrays are used.
5197 But if they aren't used, we need to emit the deferred
5198 initialization now. */
5199 else if (is_reference (var) && is_simd)
5200 handle_simd_reference (clause_loc, new_vard, ilist);
5201 x = lang_hooks.decls.omp_clause_default_ctor
5202 (c, unshare_expr (new_var),
5203 build_outer_var_ref (var, ctx));
5204 if (x)
5205 gimplify_and_add (x, ilist);
5206 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5208 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5209 lower_omp (&tseq, ctx);
5210 gimple_seq_add_seq (ilist, tseq);
5212 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5213 if (is_simd)
5215 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5216 lower_omp (&tseq, ctx);
5217 gimple_seq_add_seq (dlist, tseq);
5218 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5220 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5221 goto do_dtor;
5223 else
5225 x = omp_reduction_init (c, TREE_TYPE (new_var));
5226 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5227 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5229 /* reduction(-:var) sums up the partial results, so it
5230 acts identically to reduction(+:var). */
5231 if (code == MINUS_EXPR)
5232 code = PLUS_EXPR;
5234 tree new_vard = new_var;
5235 if (is_simd && is_reference (var))
5237 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5238 new_vard = TREE_OPERAND (new_var, 0);
5239 gcc_assert (DECL_P (new_vard));
5241 if (is_simd
5242 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5243 idx, lane, ivar, lvar))
5245 tree ref = build_outer_var_ref (var, ctx);
5247 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5249 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5250 ref = build_outer_var_ref (var, ctx);
5251 gimplify_assign (ref, x, &llist[1]);
5253 if (new_vard != new_var)
5255 SET_DECL_VALUE_EXPR (new_vard,
5256 build_fold_addr_expr (lvar));
5257 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5260 else
5262 if (is_reference (var) && is_simd)
5263 handle_simd_reference (clause_loc, new_vard, ilist);
5264 gimplify_assign (new_var, x, ilist);
5265 if (is_simd)
5267 tree ref = build_outer_var_ref (var, ctx);
5269 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5270 ref = build_outer_var_ref (var, ctx);
5271 gimplify_assign (ref, x, dlist);
5275 break;
5277 default:
5278 gcc_unreachable ();
5283 if (lane)
5285 tree uid = create_tmp_var (ptr_type_node, "simduid");
5286 /* Don't want uninit warnings on simduid, it is always uninitialized,
5287 but we use it not for the value, but for the DECL_UID only. */
5288 TREE_NO_WARNING (uid) = 1;
5289 gimple *g
5290 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5291 gimple_call_set_lhs (g, lane);
5292 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5293 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5294 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5295 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5296 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5297 gimple_omp_for_set_clauses (ctx->stmt, c);
5298 g = gimple_build_assign (lane, INTEGER_CST,
5299 build_int_cst (unsigned_type_node, 0));
5300 gimple_seq_add_stmt (ilist, g);
5301 for (int i = 0; i < 2; i++)
5302 if (llist[i])
5304 tree vf = create_tmp_var (unsigned_type_node);
5305 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5306 gimple_call_set_lhs (g, vf);
5307 gimple_seq *seq = i == 0 ? ilist : dlist;
5308 gimple_seq_add_stmt (seq, g);
5309 tree t = build_int_cst (unsigned_type_node, 0);
5310 g = gimple_build_assign (idx, INTEGER_CST, t);
5311 gimple_seq_add_stmt (seq, g);
5312 tree body = create_artificial_label (UNKNOWN_LOCATION);
5313 tree header = create_artificial_label (UNKNOWN_LOCATION);
5314 tree end = create_artificial_label (UNKNOWN_LOCATION);
5315 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5316 gimple_seq_add_stmt (seq, gimple_build_label (body));
5317 gimple_seq_add_seq (seq, llist[i]);
5318 t = build_int_cst (unsigned_type_node, 1);
5319 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5320 gimple_seq_add_stmt (seq, g);
5321 gimple_seq_add_stmt (seq, gimple_build_label (header));
5322 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5323 gimple_seq_add_stmt (seq, g);
5324 gimple_seq_add_stmt (seq, gimple_build_label (end));
5328 /* The copyin sequence is not to be executed by the main thread, since
5329 that would result in self-copies. Perhaps not visible to scalars,
5330 but it certainly is to C++ operator=. */
5331 if (copyin_seq)
5333 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5335 x = build2 (NE_EXPR, boolean_type_node, x,
5336 build_int_cst (TREE_TYPE (x), 0));
5337 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5338 gimplify_and_add (x, ilist);
5341 /* If any copyin variable is passed by reference, we must ensure the
5342 master thread doesn't modify it before it is copied over in all
5343 threads. Similarly for variables in both firstprivate and
5344 lastprivate clauses we need to ensure the lastprivate copying
5345 happens after firstprivate copying in all threads. And similarly
5346 for UDRs if initializer expression refers to omp_orig. */
5347 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5349 /* Don't add any barrier for #pragma omp simd or
5350 #pragma omp distribute. */
5351 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5352 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5353 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5356 /* If max_vf is non-zero, then we can use only a vectorization factor
5357 up to the max_vf we chose. So stick it into the safelen clause. */
5358 if (max_vf)
5360 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5361 OMP_CLAUSE_SAFELEN);
5362 if (c == NULL_TREE
5363 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5364 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5365 max_vf) == 1))
5367 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5368 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5369 max_vf);
5370 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5371 gimple_omp_for_set_clauses (ctx->stmt, c);
5377 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5378 both parallel and workshare constructs. PREDICATE may be NULL if it's
5379 always true. */
5381 static void
5382 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5383 omp_context *ctx)
5385 tree x, c, label = NULL, orig_clauses = clauses;
5386 bool par_clauses = false;
5387 tree simduid = NULL, lastlane = NULL;
5389 /* Early exit if there are no lastprivate or linear clauses. */
5390 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5391 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5392 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5393 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5394 break;
5395 if (clauses == NULL)
5397 /* If this was a workshare clause, see if it had been combined
5398 with its parallel. In that case, look for the clauses on the
5399 parallel statement itself. */
5400 if (is_parallel_ctx (ctx))
5401 return;
5403 ctx = ctx->outer;
5404 if (ctx == NULL || !is_parallel_ctx (ctx))
5405 return;
5407 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5408 OMP_CLAUSE_LASTPRIVATE);
5409 if (clauses == NULL)
5410 return;
5411 par_clauses = true;
5414 if (predicate)
5416 gcond *stmt;
5417 tree label_true, arm1, arm2;
5419 label = create_artificial_label (UNKNOWN_LOCATION);
5420 label_true = create_artificial_label (UNKNOWN_LOCATION);
5421 arm1 = TREE_OPERAND (predicate, 0);
5422 arm2 = TREE_OPERAND (predicate, 1);
5423 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5424 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5425 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5426 label_true, label);
5427 gimple_seq_add_stmt (stmt_list, stmt);
5428 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5431 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5432 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5434 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5435 if (simduid)
5436 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5439 for (c = clauses; c ;)
5441 tree var, new_var;
5442 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5444 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5445 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5446 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5448 var = OMP_CLAUSE_DECL (c);
5449 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5450 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5451 && is_taskloop_ctx (ctx))
5453 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5454 new_var = lookup_decl (var, ctx->outer);
5456 else
5457 new_var = lookup_decl (var, ctx);
5459 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5461 tree val = DECL_VALUE_EXPR (new_var);
5462 if (TREE_CODE (val) == ARRAY_REF
5463 && VAR_P (TREE_OPERAND (val, 0))
5464 && lookup_attribute ("omp simd array",
5465 DECL_ATTRIBUTES (TREE_OPERAND (val,
5466 0))))
5468 if (lastlane == NULL)
5470 lastlane = create_tmp_var (unsigned_type_node);
5471 gcall *g
5472 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5473 2, simduid,
5474 TREE_OPERAND (val, 1));
5475 gimple_call_set_lhs (g, lastlane);
5476 gimple_seq_add_stmt (stmt_list, g);
5478 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5479 TREE_OPERAND (val, 0), lastlane,
5480 NULL_TREE, NULL_TREE);
5484 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5485 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5487 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5488 gimple_seq_add_seq (stmt_list,
5489 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5490 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5492 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5493 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5495 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5496 gimple_seq_add_seq (stmt_list,
5497 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5498 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5501 x = NULL_TREE;
5502 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5503 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5505 gcc_checking_assert (is_taskloop_ctx (ctx));
5506 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5507 ctx->outer->outer);
5508 if (is_global_var (ovar))
5509 x = ovar;
5511 if (!x)
5512 x = build_outer_var_ref (var, ctx, true);
5513 if (is_reference (var))
5514 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5515 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5516 gimplify_and_add (x, stmt_list);
5518 c = OMP_CLAUSE_CHAIN (c);
5519 if (c == NULL && !par_clauses)
5521 /* If this was a workshare clause, see if it had been combined
5522 with its parallel. In that case, continue looking for the
5523 clauses also on the parallel statement itself. */
5524 if (is_parallel_ctx (ctx))
5525 break;
5527 ctx = ctx->outer;
5528 if (ctx == NULL || !is_parallel_ctx (ctx))
5529 break;
5531 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5532 OMP_CLAUSE_LASTPRIVATE);
5533 par_clauses = true;
5537 if (label)
5538 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5541 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5542 (which might be a placeholder). INNER is true if this is an inner
5543 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5544 join markers. Generate the before-loop forking sequence in
5545 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5546 general form of these sequences is
5548 GOACC_REDUCTION_SETUP
5549 GOACC_FORK
5550 GOACC_REDUCTION_INIT
5552 GOACC_REDUCTION_FINI
5553 GOACC_JOIN
5554 GOACC_REDUCTION_TEARDOWN. */
5556 static void
5557 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5558 gcall *fork, gcall *join, gimple_seq *fork_seq,
5559 gimple_seq *join_seq, omp_context *ctx)
5561 gimple_seq before_fork = NULL;
5562 gimple_seq after_fork = NULL;
5563 gimple_seq before_join = NULL;
5564 gimple_seq after_join = NULL;
5565 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5566 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5567 unsigned offset = 0;
5569 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5572 tree orig = OMP_CLAUSE_DECL (c);
5573 tree var = maybe_lookup_decl (orig, ctx);
5574 tree ref_to_res = NULL_TREE;
5575 tree incoming, outgoing, v1, v2, v3;
5576 bool is_private = false;
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;
5590 incoming = outgoing = var;
5592 if (!inner)
5594 /* See if an outer construct also reduces this variable. */
5595 omp_context *outer = ctx;
5597 while (omp_context *probe = outer->outer)
5599 enum gimple_code type = gimple_code (probe->stmt);
5600 tree cls;
5602 switch (type)
5604 case GIMPLE_OMP_FOR:
5605 cls = gimple_omp_for_clauses (probe->stmt);
5606 break;
5608 case GIMPLE_OMP_TARGET:
5609 if (gimple_omp_target_kind (probe->stmt)
5610 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5611 goto do_lookup;
5613 cls = gimple_omp_target_clauses (probe->stmt);
5614 break;
5616 default:
5617 goto do_lookup;
5620 outer = probe;
5621 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5622 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5623 && orig == OMP_CLAUSE_DECL (cls))
5625 incoming = outgoing = lookup_decl (orig, probe);
5626 goto has_outer_reduction;
5628 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5629 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5630 && orig == OMP_CLAUSE_DECL (cls))
5632 is_private = true;
5633 goto do_lookup;
5637 do_lookup:
5638 /* This is the outermost construct with this reduction,
5639 see if there's a mapping for it. */
5640 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5641 && maybe_lookup_field (orig, outer) && !is_private)
5643 ref_to_res = build_receiver_ref (orig, false, outer);
5644 if (is_reference (orig))
5645 ref_to_res = build_simple_mem_ref (ref_to_res);
5647 tree type = TREE_TYPE (var);
5648 if (POINTER_TYPE_P (type))
5649 type = TREE_TYPE (type);
5651 outgoing = var;
5652 incoming = omp_reduction_init_op (loc, rcode, type);
5654 else if (ctx->outer)
5655 incoming = outgoing = lookup_decl (orig, ctx->outer);
5656 else
5657 incoming = outgoing = orig;
5659 has_outer_reduction:;
5662 if (!ref_to_res)
5663 ref_to_res = integer_zero_node;
5665 if (is_reference (orig))
5667 tree type = TREE_TYPE (var);
5668 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5670 if (!inner)
5672 tree x = create_tmp_var (TREE_TYPE (type), id);
5673 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5676 v1 = create_tmp_var (type, id);
5677 v2 = create_tmp_var (type, id);
5678 v3 = create_tmp_var (type, id);
5680 gimplify_assign (v1, var, fork_seq);
5681 gimplify_assign (v2, var, fork_seq);
5682 gimplify_assign (v3, var, fork_seq);
5684 var = build_simple_mem_ref (var);
5685 v1 = build_simple_mem_ref (v1);
5686 v2 = build_simple_mem_ref (v2);
5687 v3 = build_simple_mem_ref (v3);
5688 outgoing = build_simple_mem_ref (outgoing);
5690 if (!TREE_CONSTANT (incoming))
5691 incoming = build_simple_mem_ref (incoming);
5693 else
5694 v1 = v2 = v3 = var;
5696 /* Determine position in reduction buffer, which may be used
5697 by target. */
5698 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5699 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5700 offset = (offset + align - 1) & ~(align - 1);
5701 tree off = build_int_cst (sizetype, offset);
5702 offset += GET_MODE_SIZE (mode);
5704 if (!init_code)
5706 init_code = build_int_cst (integer_type_node,
5707 IFN_GOACC_REDUCTION_INIT);
5708 fini_code = build_int_cst (integer_type_node,
5709 IFN_GOACC_REDUCTION_FINI);
5710 setup_code = build_int_cst (integer_type_node,
5711 IFN_GOACC_REDUCTION_SETUP);
5712 teardown_code = build_int_cst (integer_type_node,
5713 IFN_GOACC_REDUCTION_TEARDOWN);
5716 tree setup_call
5717 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5718 TREE_TYPE (var), 6, setup_code,
5719 unshare_expr (ref_to_res),
5720 incoming, level, op, off);
5721 tree init_call
5722 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5723 TREE_TYPE (var), 6, init_code,
5724 unshare_expr (ref_to_res),
5725 v1, level, op, off);
5726 tree fini_call
5727 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5728 TREE_TYPE (var), 6, fini_code,
5729 unshare_expr (ref_to_res),
5730 v2, level, op, off);
5731 tree teardown_call
5732 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5733 TREE_TYPE (var), 6, teardown_code,
5734 ref_to_res, v3, level, op, off);
5736 gimplify_assign (v1, setup_call, &before_fork);
5737 gimplify_assign (v2, init_call, &after_fork);
5738 gimplify_assign (v3, fini_call, &before_join);
5739 gimplify_assign (outgoing, teardown_call, &after_join);
5742 /* Now stitch things together. */
5743 gimple_seq_add_seq (fork_seq, before_fork);
5744 if (fork)
5745 gimple_seq_add_stmt (fork_seq, fork);
5746 gimple_seq_add_seq (fork_seq, after_fork);
5748 gimple_seq_add_seq (join_seq, before_join);
5749 if (join)
5750 gimple_seq_add_stmt (join_seq, join);
5751 gimple_seq_add_seq (join_seq, after_join);
5754 /* Generate code to implement the REDUCTION clauses. */
5756 static void
5757 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5759 gimple_seq sub_seq = NULL;
5760 gimple *stmt;
5761 tree x, c;
5762 int count = 0;
5764 /* OpenACC loop reductions are handled elsewhere. */
5765 if (is_gimple_omp_oacc (ctx->stmt))
5766 return;
5768 /* SIMD reductions are handled in lower_rec_input_clauses. */
5769 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5770 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5771 return;
5773 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5774 update in that case, otherwise use a lock. */
5775 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5776 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5778 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5779 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5781 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5782 count = -1;
5783 break;
5785 count++;
5788 if (count == 0)
5789 return;
5791 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5793 tree var, ref, new_var, orig_var;
5794 enum tree_code code;
5795 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5797 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5798 continue;
5800 orig_var = var = OMP_CLAUSE_DECL (c);
5801 if (TREE_CODE (var) == MEM_REF)
5803 var = TREE_OPERAND (var, 0);
5804 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5805 var = TREE_OPERAND (var, 0);
5806 if (TREE_CODE (var) == INDIRECT_REF
5807 || TREE_CODE (var) == ADDR_EXPR)
5808 var = TREE_OPERAND (var, 0);
5809 orig_var = var;
5810 if (is_variable_sized (var))
5812 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5813 var = DECL_VALUE_EXPR (var);
5814 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5815 var = TREE_OPERAND (var, 0);
5816 gcc_assert (DECL_P (var));
5819 new_var = lookup_decl (var, ctx);
5820 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5821 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5822 ref = build_outer_var_ref (var, ctx);
5823 code = OMP_CLAUSE_REDUCTION_CODE (c);
5825 /* reduction(-:var) sums up the partial results, so it acts
5826 identically to reduction(+:var). */
5827 if (code == MINUS_EXPR)
5828 code = PLUS_EXPR;
5830 if (count == 1)
5832 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5834 addr = save_expr (addr);
5835 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5836 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5837 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5838 gimplify_and_add (x, stmt_seqp);
5839 return;
5841 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5843 tree d = OMP_CLAUSE_DECL (c);
5844 tree type = TREE_TYPE (d);
5845 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5846 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5847 tree ptype = build_pointer_type (TREE_TYPE (type));
5848 tree bias = TREE_OPERAND (d, 1);
5849 d = TREE_OPERAND (d, 0);
5850 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5852 tree b = TREE_OPERAND (d, 1);
5853 b = maybe_lookup_decl (b, ctx);
5854 if (b == NULL)
5856 b = TREE_OPERAND (d, 1);
5857 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5859 if (integer_zerop (bias))
5860 bias = b;
5861 else
5863 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5864 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5865 TREE_TYPE (b), b, bias);
5867 d = TREE_OPERAND (d, 0);
5869 /* For ref build_outer_var_ref already performs this, so
5870 only new_var needs a dereference. */
5871 if (TREE_CODE (d) == INDIRECT_REF)
5873 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5874 gcc_assert (is_reference (var) && var == orig_var);
5876 else if (TREE_CODE (d) == ADDR_EXPR)
5878 if (orig_var == var)
5880 new_var = build_fold_addr_expr (new_var);
5881 ref = build_fold_addr_expr (ref);
5884 else
5886 gcc_assert (orig_var == var);
5887 if (is_reference (var))
5888 ref = build_fold_addr_expr (ref);
5890 if (DECL_P (v))
5892 tree t = maybe_lookup_decl (v, ctx);
5893 if (t)
5894 v = t;
5895 else
5896 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5897 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5899 if (!integer_zerop (bias))
5901 bias = fold_convert_loc (clause_loc, sizetype, bias);
5902 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5903 TREE_TYPE (new_var), new_var,
5904 unshare_expr (bias));
5905 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5906 TREE_TYPE (ref), ref, bias);
5908 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5909 ref = fold_convert_loc (clause_loc, ptype, ref);
5910 tree m = create_tmp_var (ptype, NULL);
5911 gimplify_assign (m, new_var, stmt_seqp);
5912 new_var = m;
5913 m = create_tmp_var (ptype, NULL);
5914 gimplify_assign (m, ref, stmt_seqp);
5915 ref = m;
5916 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5917 tree body = create_artificial_label (UNKNOWN_LOCATION);
5918 tree end = create_artificial_label (UNKNOWN_LOCATION);
5919 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5920 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5921 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5922 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5924 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5925 tree decl_placeholder
5926 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5927 SET_DECL_VALUE_EXPR (placeholder, out);
5928 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5929 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5930 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5931 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5932 gimple_seq_add_seq (&sub_seq,
5933 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5934 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5935 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5936 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5938 else
5940 x = build2 (code, TREE_TYPE (out), out, priv);
5941 out = unshare_expr (out);
5942 gimplify_assign (out, x, &sub_seq);
5944 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5945 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5946 gimple_seq_add_stmt (&sub_seq, g);
5947 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5948 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5949 gimple_seq_add_stmt (&sub_seq, g);
5950 g = gimple_build_assign (i, PLUS_EXPR, i,
5951 build_int_cst (TREE_TYPE (i), 1));
5952 gimple_seq_add_stmt (&sub_seq, g);
5953 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5954 gimple_seq_add_stmt (&sub_seq, g);
5955 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5957 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5959 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5961 if (is_reference (var)
5962 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5963 TREE_TYPE (ref)))
5964 ref = build_fold_addr_expr_loc (clause_loc, ref);
5965 SET_DECL_VALUE_EXPR (placeholder, ref);
5966 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5967 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5968 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5969 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5970 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5972 else
5974 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5975 ref = build_outer_var_ref (var, ctx);
5976 gimplify_assign (ref, x, &sub_seq);
5980 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5982 gimple_seq_add_stmt (stmt_seqp, stmt);
5984 gimple_seq_add_seq (stmt_seqp, sub_seq);
5986 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5988 gimple_seq_add_stmt (stmt_seqp, stmt);
5992 /* Generate code to implement the COPYPRIVATE clauses. */
5994 static void
5995 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5996 omp_context *ctx)
5998 tree c;
6000 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6002 tree var, new_var, ref, x;
6003 bool by_ref;
6004 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6006 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6007 continue;
6009 var = OMP_CLAUSE_DECL (c);
6010 by_ref = use_pointer_for_field (var, NULL);
6012 ref = build_sender_ref (var, ctx);
6013 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6014 if (by_ref)
6016 x = build_fold_addr_expr_loc (clause_loc, new_var);
6017 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6019 gimplify_assign (ref, x, slist);
6021 ref = build_receiver_ref (var, false, ctx);
6022 if (by_ref)
6024 ref = fold_convert_loc (clause_loc,
6025 build_pointer_type (TREE_TYPE (new_var)),
6026 ref);
6027 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6029 if (is_reference (var))
6031 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6032 ref = build_simple_mem_ref_loc (clause_loc, ref);
6033 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6035 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6036 gimplify_and_add (x, rlist);
6041 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6042 and REDUCTION from the sender (aka parent) side. */
6044 static void
6045 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6046 omp_context *ctx)
6048 tree c, t;
6049 int ignored_looptemp = 0;
6050 bool is_taskloop = false;
6052 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6053 by GOMP_taskloop. */
6054 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6056 ignored_looptemp = 2;
6057 is_taskloop = true;
6060 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6062 tree val, ref, x, var;
6063 bool by_ref, do_in = false, do_out = false;
6064 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6066 switch (OMP_CLAUSE_CODE (c))
6068 case OMP_CLAUSE_PRIVATE:
6069 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6070 break;
6071 continue;
6072 case OMP_CLAUSE_FIRSTPRIVATE:
6073 case OMP_CLAUSE_COPYIN:
6074 case OMP_CLAUSE_LASTPRIVATE:
6075 case OMP_CLAUSE_REDUCTION:
6076 break;
6077 case OMP_CLAUSE_SHARED:
6078 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6079 break;
6080 continue;
6081 case OMP_CLAUSE__LOOPTEMP_:
6082 if (ignored_looptemp)
6084 ignored_looptemp--;
6085 continue;
6087 break;
6088 default:
6089 continue;
6092 val = OMP_CLAUSE_DECL (c);
6093 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6094 && TREE_CODE (val) == MEM_REF)
6096 val = TREE_OPERAND (val, 0);
6097 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6098 val = TREE_OPERAND (val, 0);
6099 if (TREE_CODE (val) == INDIRECT_REF
6100 || TREE_CODE (val) == ADDR_EXPR)
6101 val = TREE_OPERAND (val, 0);
6102 if (is_variable_sized (val))
6103 continue;
6106 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6107 outer taskloop region. */
6108 omp_context *ctx_for_o = ctx;
6109 if (is_taskloop
6110 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6111 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6112 ctx_for_o = ctx->outer;
6114 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6116 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6117 && is_global_var (var))
6118 continue;
6120 t = omp_member_access_dummy_var (var);
6121 if (t)
6123 var = DECL_VALUE_EXPR (var);
6124 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6125 if (o != t)
6126 var = unshare_and_remap (var, t, o);
6127 else
6128 var = unshare_expr (var);
6131 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6133 /* Handle taskloop firstprivate/lastprivate, where the
6134 lastprivate on GIMPLE_OMP_TASK is represented as
6135 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6136 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6137 x = omp_build_component_ref (ctx->sender_decl, f);
6138 if (use_pointer_for_field (val, ctx))
6139 var = build_fold_addr_expr (var);
6140 gimplify_assign (x, var, ilist);
6141 DECL_ABSTRACT_ORIGIN (f) = NULL;
6142 continue;
6145 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6146 || val == OMP_CLAUSE_DECL (c))
6147 && is_variable_sized (val))
6148 continue;
6149 by_ref = use_pointer_for_field (val, NULL);
6151 switch (OMP_CLAUSE_CODE (c))
6153 case OMP_CLAUSE_FIRSTPRIVATE:
6154 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6155 && !by_ref
6156 && is_task_ctx (ctx))
6157 TREE_NO_WARNING (var) = 1;
6158 do_in = true;
6159 break;
6161 case OMP_CLAUSE_PRIVATE:
6162 case OMP_CLAUSE_COPYIN:
6163 case OMP_CLAUSE__LOOPTEMP_:
6164 do_in = true;
6165 break;
6167 case OMP_CLAUSE_LASTPRIVATE:
6168 if (by_ref || is_reference (val))
6170 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6171 continue;
6172 do_in = true;
6174 else
6176 do_out = true;
6177 if (lang_hooks.decls.omp_private_outer_ref (val))
6178 do_in = true;
6180 break;
6182 case OMP_CLAUSE_REDUCTION:
6183 do_in = true;
6184 if (val == OMP_CLAUSE_DECL (c))
6185 do_out = !(by_ref || is_reference (val));
6186 else
6187 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6188 break;
6190 default:
6191 gcc_unreachable ();
6194 if (do_in)
6196 ref = build_sender_ref (val, ctx);
6197 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6198 gimplify_assign (ref, x, ilist);
6199 if (is_task_ctx (ctx))
6200 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6203 if (do_out)
6205 ref = build_sender_ref (val, ctx);
6206 gimplify_assign (var, ref, olist);
6211 /* Generate code to implement SHARED from the sender (aka parent)
6212 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6213 list things that got automatically shared. */
6215 static void
6216 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6218 tree var, ovar, nvar, t, f, x, record_type;
6220 if (ctx->record_type == NULL)
6221 return;
6223 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6224 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6226 ovar = DECL_ABSTRACT_ORIGIN (f);
6227 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6228 continue;
6230 nvar = maybe_lookup_decl (ovar, ctx);
6231 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6232 continue;
6234 /* If CTX is a nested parallel directive. Find the immediately
6235 enclosing parallel or workshare construct that contains a
6236 mapping for OVAR. */
6237 var = lookup_decl_in_outer_ctx (ovar, ctx);
6239 t = omp_member_access_dummy_var (var);
6240 if (t)
6242 var = DECL_VALUE_EXPR (var);
6243 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6244 if (o != t)
6245 var = unshare_and_remap (var, t, o);
6246 else
6247 var = unshare_expr (var);
6250 if (use_pointer_for_field (ovar, ctx))
6252 x = build_sender_ref (ovar, ctx);
6253 var = build_fold_addr_expr (var);
6254 gimplify_assign (x, var, ilist);
6256 else
6258 x = build_sender_ref (ovar, ctx);
6259 gimplify_assign (x, var, ilist);
6261 if (!TREE_READONLY (var)
6262 /* We don't need to receive a new reference to a result
6263 or parm decl. In fact we may not store to it as we will
6264 invalidate any pending RSO and generate wrong gimple
6265 during inlining. */
6266 && !((TREE_CODE (var) == RESULT_DECL
6267 || TREE_CODE (var) == PARM_DECL)
6268 && DECL_BY_REFERENCE (var)))
6270 x = build_sender_ref (ovar, ctx);
6271 gimplify_assign (var, x, olist);
6277 /* Emit an OpenACC head marker call, encapulating the partitioning and
6278 other information that must be processed by the target compiler.
6279 Return the maximum number of dimensions the associated loop might
6280 be partitioned over. */
6282 static unsigned
6283 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6284 gimple_seq *seq, omp_context *ctx)
6286 unsigned levels = 0;
6287 unsigned tag = 0;
6288 tree gang_static = NULL_TREE;
6289 auto_vec<tree, 5> args;
6291 args.quick_push (build_int_cst
6292 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6293 args.quick_push (ddvar);
6294 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6296 switch (OMP_CLAUSE_CODE (c))
6298 case OMP_CLAUSE_GANG:
6299 tag |= OLF_DIM_GANG;
6300 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6301 /* static:* is represented by -1, and we can ignore it, as
6302 scheduling is always static. */
6303 if (gang_static && integer_minus_onep (gang_static))
6304 gang_static = NULL_TREE;
6305 levels++;
6306 break;
6308 case OMP_CLAUSE_WORKER:
6309 tag |= OLF_DIM_WORKER;
6310 levels++;
6311 break;
6313 case OMP_CLAUSE_VECTOR:
6314 tag |= OLF_DIM_VECTOR;
6315 levels++;
6316 break;
6318 case OMP_CLAUSE_SEQ:
6319 tag |= OLF_SEQ;
6320 break;
6322 case OMP_CLAUSE_AUTO:
6323 tag |= OLF_AUTO;
6324 break;
6326 case OMP_CLAUSE_INDEPENDENT:
6327 tag |= OLF_INDEPENDENT;
6328 break;
6330 default:
6331 continue;
6335 if (gang_static)
6337 if (DECL_P (gang_static))
6338 gang_static = build_outer_var_ref (gang_static, ctx);
6339 tag |= OLF_GANG_STATIC;
6342 /* In a parallel region, loops are implicitly INDEPENDENT. */
6343 omp_context *tgt = enclosing_target_ctx (ctx);
6344 if (!tgt || is_oacc_parallel (tgt))
6345 tag |= OLF_INDEPENDENT;
6347 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6348 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6349 | OLF_SEQ)))
6350 tag |= OLF_AUTO;
6352 /* Ensure at least one level. */
6353 if (!levels)
6354 levels++;
6356 args.quick_push (build_int_cst (integer_type_node, levels));
6357 args.quick_push (build_int_cst (integer_type_node, tag));
6358 if (gang_static)
6359 args.quick_push (gang_static);
6361 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6362 gimple_set_location (call, loc);
6363 gimple_set_lhs (call, ddvar);
6364 gimple_seq_add_stmt (seq, call);
6366 return levels;
6369 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6370 partitioning level of the enclosed region. */
6372 static void
6373 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6374 tree tofollow, gimple_seq *seq)
6376 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6377 : IFN_UNIQUE_OACC_TAIL_MARK);
6378 tree marker = build_int_cst (integer_type_node, marker_kind);
6379 int nargs = 2 + (tofollow != NULL_TREE);
6380 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6381 marker, ddvar, tofollow);
6382 gimple_set_location (call, loc);
6383 gimple_set_lhs (call, ddvar);
6384 gimple_seq_add_stmt (seq, call);
6387 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6388 the loop clauses, from which we extract reductions. Initialize
6389 HEAD and TAIL. */
6391 static void
6392 lower_oacc_head_tail (location_t loc, tree clauses,
6393 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6395 bool inner = false;
6396 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6397 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6399 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6400 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6401 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6403 gcc_assert (count);
6404 for (unsigned done = 1; count; count--, done++)
6406 gimple_seq fork_seq = NULL;
6407 gimple_seq join_seq = NULL;
6409 tree place = build_int_cst (integer_type_node, -1);
6410 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6411 fork_kind, ddvar, place);
6412 gimple_set_location (fork, loc);
6413 gimple_set_lhs (fork, ddvar);
6415 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6416 join_kind, ddvar, place);
6417 gimple_set_location (join, loc);
6418 gimple_set_lhs (join, ddvar);
6420 /* Mark the beginning of this level sequence. */
6421 if (inner)
6422 lower_oacc_loop_marker (loc, ddvar, true,
6423 build_int_cst (integer_type_node, count),
6424 &fork_seq);
6425 lower_oacc_loop_marker (loc, ddvar, false,
6426 build_int_cst (integer_type_node, done),
6427 &join_seq);
6429 lower_oacc_reductions (loc, clauses, place, inner,
6430 fork, join, &fork_seq, &join_seq, ctx);
6432 /* Append this level to head. */
6433 gimple_seq_add_seq (head, fork_seq);
6434 /* Prepend it to tail. */
6435 gimple_seq_add_seq (&join_seq, *tail);
6436 *tail = join_seq;
6438 inner = true;
6441 /* Mark the end of the sequence. */
6442 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6443 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6446 /* A convenience function to build an empty GIMPLE_COND with just the
6447 condition. */
6449 static gcond *
6450 gimple_build_cond_empty (tree cond)
6452 enum tree_code pred_code;
6453 tree lhs, rhs;
6455 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6456 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6459 /* Return true if a parallel REGION is within a declare target function or
6460 within a target region and is not a part of a gridified target. */
6462 static bool
6463 parallel_needs_hsa_kernel_p (struct omp_region *region)
6465 bool indirect = false;
6466 for (region = region->outer; region; region = region->outer)
6468 if (region->type == GIMPLE_OMP_PARALLEL)
6469 indirect = true;
6470 else if (region->type == GIMPLE_OMP_TARGET)
6472 gomp_target *tgt_stmt
6473 = as_a <gomp_target *> (last_stmt (region->entry));
6475 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6476 OMP_CLAUSE__GRIDDIM_))
6477 return indirect;
6478 else
6479 return true;
6483 if (lookup_attribute ("omp declare target",
6484 DECL_ATTRIBUTES (current_function_decl)))
6485 return true;
6487 return false;
6490 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6491 bool = false);
6493 /* Build the function calls to GOMP_parallel_start etc to actually
6494 generate the parallel operation. REGION is the parallel region
6495 being expanded. BB is the block where to insert the code. WS_ARGS
6496 will be set if this is a call to a combined parallel+workshare
6497 construct, it contains the list of additional arguments needed by
6498 the workshare construct. */
6500 static void
6501 expand_parallel_call (struct omp_region *region, basic_block bb,
6502 gomp_parallel *entry_stmt,
6503 vec<tree, va_gc> *ws_args)
6505 tree t, t1, t2, val, cond, c, clauses, flags;
6506 gimple_stmt_iterator gsi;
6507 gimple *stmt;
6508 enum built_in_function start_ix;
6509 int start_ix2;
6510 location_t clause_loc;
6511 vec<tree, va_gc> *args;
6513 clauses = gimple_omp_parallel_clauses (entry_stmt);
6515 /* Determine what flavor of GOMP_parallel we will be
6516 emitting. */
6517 start_ix = BUILT_IN_GOMP_PARALLEL;
6518 if (is_combined_parallel (region))
6520 switch (region->inner->type)
6522 case GIMPLE_OMP_FOR:
6523 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6524 switch (region->inner->sched_kind)
6526 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6527 start_ix2 = 3;
6528 break;
6529 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6530 case OMP_CLAUSE_SCHEDULE_GUIDED:
6531 if (region->inner->sched_modifiers
6532 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6534 start_ix2 = 3 + region->inner->sched_kind;
6535 break;
6537 /* FALLTHRU */
6538 default:
6539 start_ix2 = region->inner->sched_kind;
6540 break;
6542 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6543 start_ix = (enum built_in_function) start_ix2;
6544 break;
6545 case GIMPLE_OMP_SECTIONS:
6546 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6547 break;
6548 default:
6549 gcc_unreachable ();
6553 /* By default, the value of NUM_THREADS is zero (selected at run time)
6554 and there is no conditional. */
6555 cond = NULL_TREE;
6556 val = build_int_cst (unsigned_type_node, 0);
6557 flags = build_int_cst (unsigned_type_node, 0);
6559 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6560 if (c)
6561 cond = OMP_CLAUSE_IF_EXPR (c);
6563 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6564 if (c)
6566 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6567 clause_loc = OMP_CLAUSE_LOCATION (c);
6569 else
6570 clause_loc = gimple_location (entry_stmt);
6572 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6573 if (c)
6574 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6576 /* Ensure 'val' is of the correct type. */
6577 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6579 /* If we found the clause 'if (cond)', build either
6580 (cond != 0) or (cond ? val : 1u). */
6581 if (cond)
6583 cond = gimple_boolify (cond);
6585 if (integer_zerop (val))
6586 val = fold_build2_loc (clause_loc,
6587 EQ_EXPR, unsigned_type_node, cond,
6588 build_int_cst (TREE_TYPE (cond), 0));
6589 else
6591 basic_block cond_bb, then_bb, else_bb;
6592 edge e, e_then, e_else;
6593 tree tmp_then, tmp_else, tmp_join, tmp_var;
6595 tmp_var = create_tmp_var (TREE_TYPE (val));
6596 if (gimple_in_ssa_p (cfun))
6598 tmp_then = make_ssa_name (tmp_var);
6599 tmp_else = make_ssa_name (tmp_var);
6600 tmp_join = make_ssa_name (tmp_var);
6602 else
6604 tmp_then = tmp_var;
6605 tmp_else = tmp_var;
6606 tmp_join = tmp_var;
6609 e = split_block_after_labels (bb);
6610 cond_bb = e->src;
6611 bb = e->dest;
6612 remove_edge (e);
6614 then_bb = create_empty_bb (cond_bb);
6615 else_bb = create_empty_bb (then_bb);
6616 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6617 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6619 stmt = gimple_build_cond_empty (cond);
6620 gsi = gsi_start_bb (cond_bb);
6621 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6623 gsi = gsi_start_bb (then_bb);
6624 expand_omp_build_assign (&gsi, tmp_then, val, true);
6626 gsi = gsi_start_bb (else_bb);
6627 expand_omp_build_assign (&gsi, tmp_else,
6628 build_int_cst (unsigned_type_node, 1),
6629 true);
6631 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6632 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6633 add_bb_to_loop (then_bb, cond_bb->loop_father);
6634 add_bb_to_loop (else_bb, cond_bb->loop_father);
6635 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6636 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6638 if (gimple_in_ssa_p (cfun))
6640 gphi *phi = create_phi_node (tmp_join, bb);
6641 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6642 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6645 val = tmp_join;
6648 gsi = gsi_start_bb (bb);
6649 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6650 false, GSI_CONTINUE_LINKING);
6653 gsi = gsi_last_bb (bb);
6654 t = gimple_omp_parallel_data_arg (entry_stmt);
6655 if (t == NULL)
6656 t1 = null_pointer_node;
6657 else
6658 t1 = build_fold_addr_expr (t);
6659 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6660 t2 = build_fold_addr_expr (child_fndecl);
6662 vec_alloc (args, 4 + vec_safe_length (ws_args));
6663 args->quick_push (t2);
6664 args->quick_push (t1);
6665 args->quick_push (val);
6666 if (ws_args)
6667 args->splice (*ws_args);
6668 args->quick_push (flags);
6670 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6671 builtin_decl_explicit (start_ix), args);
6673 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6674 false, GSI_CONTINUE_LINKING);
6676 if (hsa_gen_requested_p ()
6677 && parallel_needs_hsa_kernel_p (region))
6679 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6680 hsa_register_kernel (child_cnode);
6684 /* Insert a function call whose name is FUNC_NAME with the information from
6685 ENTRY_STMT into the basic_block BB. */
6687 static void
6688 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6689 vec <tree, va_gc> *ws_args)
6691 tree t, t1, t2;
6692 gimple_stmt_iterator gsi;
6693 vec <tree, va_gc> *args;
6695 gcc_assert (vec_safe_length (ws_args) == 2);
6696 tree func_name = (*ws_args)[0];
6697 tree grain = (*ws_args)[1];
6699 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6700 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6701 gcc_assert (count != NULL_TREE);
6702 count = OMP_CLAUSE_OPERAND (count, 0);
6704 gsi = gsi_last_bb (bb);
6705 t = gimple_omp_parallel_data_arg (entry_stmt);
6706 if (t == NULL)
6707 t1 = null_pointer_node;
6708 else
6709 t1 = build_fold_addr_expr (t);
6710 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6712 vec_alloc (args, 4);
6713 args->quick_push (t2);
6714 args->quick_push (t1);
6715 args->quick_push (count);
6716 args->quick_push (grain);
6717 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6719 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6720 GSI_CONTINUE_LINKING);
6723 /* Build the function call to GOMP_task to actually
6724 generate the task operation. BB is the block where to insert the code. */
6726 static void
6727 expand_task_call (struct omp_region *region, basic_block bb,
6728 gomp_task *entry_stmt)
6730 tree t1, t2, t3;
6731 gimple_stmt_iterator gsi;
6732 location_t loc = gimple_location (entry_stmt);
6734 tree clauses = gimple_omp_task_clauses (entry_stmt);
6736 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6737 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6738 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6739 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6740 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6741 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6743 unsigned int iflags
6744 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6745 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6746 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6748 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6749 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6750 tree num_tasks = NULL_TREE;
6751 bool ull = false;
6752 if (taskloop_p)
6754 gimple *g = last_stmt (region->outer->entry);
6755 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6756 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6757 struct omp_for_data fd;
6758 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6759 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6760 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6761 OMP_CLAUSE__LOOPTEMP_);
6762 startvar = OMP_CLAUSE_DECL (startvar);
6763 endvar = OMP_CLAUSE_DECL (endvar);
6764 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6765 if (fd.loop.cond_code == LT_EXPR)
6766 iflags |= GOMP_TASK_FLAG_UP;
6767 tree tclauses = gimple_omp_for_clauses (g);
6768 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6769 if (num_tasks)
6770 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6771 else
6773 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6774 if (num_tasks)
6776 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6777 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6779 else
6780 num_tasks = integer_zero_node;
6782 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6783 if (ifc == NULL_TREE)
6784 iflags |= GOMP_TASK_FLAG_IF;
6785 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6786 iflags |= GOMP_TASK_FLAG_NOGROUP;
6787 ull = fd.iter_type == long_long_unsigned_type_node;
6789 else if (priority)
6790 iflags |= GOMP_TASK_FLAG_PRIORITY;
6792 tree flags = build_int_cst (unsigned_type_node, iflags);
6794 tree cond = boolean_true_node;
6795 if (ifc)
6797 if (taskloop_p)
6799 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6800 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6801 build_int_cst (unsigned_type_node,
6802 GOMP_TASK_FLAG_IF),
6803 build_int_cst (unsigned_type_node, 0));
6804 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6805 flags, t);
6807 else
6808 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6811 if (finalc)
6813 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6814 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6815 build_int_cst (unsigned_type_node,
6816 GOMP_TASK_FLAG_FINAL),
6817 build_int_cst (unsigned_type_node, 0));
6818 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6820 if (depend)
6821 depend = OMP_CLAUSE_DECL (depend);
6822 else
6823 depend = build_int_cst (ptr_type_node, 0);
6824 if (priority)
6825 priority = fold_convert (integer_type_node,
6826 OMP_CLAUSE_PRIORITY_EXPR (priority));
6827 else
6828 priority = integer_zero_node;
6830 gsi = gsi_last_bb (bb);
6831 tree t = gimple_omp_task_data_arg (entry_stmt);
6832 if (t == NULL)
6833 t2 = null_pointer_node;
6834 else
6835 t2 = build_fold_addr_expr_loc (loc, t);
6836 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6837 t = gimple_omp_task_copy_fn (entry_stmt);
6838 if (t == NULL)
6839 t3 = null_pointer_node;
6840 else
6841 t3 = build_fold_addr_expr_loc (loc, t);
6843 if (taskloop_p)
6844 t = build_call_expr (ull
6845 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6846 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6847 11, t1, t2, t3,
6848 gimple_omp_task_arg_size (entry_stmt),
6849 gimple_omp_task_arg_align (entry_stmt), flags,
6850 num_tasks, priority, startvar, endvar, step);
6851 else
6852 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6853 9, t1, t2, t3,
6854 gimple_omp_task_arg_size (entry_stmt),
6855 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6856 depend, priority);
6858 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6859 false, GSI_CONTINUE_LINKING);
6863 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6864 catch handler and return it. This prevents programs from violating the
6865 structured block semantics with throws. */
6867 static gimple_seq
6868 maybe_catch_exception (gimple_seq body)
6870 gimple *g;
6871 tree decl;
6873 if (!flag_exceptions)
6874 return body;
6876 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6877 decl = lang_hooks.eh_protect_cleanup_actions ();
6878 else
6879 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6881 g = gimple_build_eh_must_not_throw (decl);
6882 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6883 GIMPLE_TRY_CATCH);
6885 return gimple_seq_alloc_with_stmt (g);
6888 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6890 static tree
6891 vec2chain (vec<tree, va_gc> *v)
6893 tree chain = NULL_TREE, t;
6894 unsigned ix;
6896 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6898 DECL_CHAIN (t) = chain;
6899 chain = t;
6902 return chain;
6906 /* Remove barriers in REGION->EXIT's block. Note that this is only
6907 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6908 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6909 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6910 removed. */
6912 static void
6913 remove_exit_barrier (struct omp_region *region)
6915 gimple_stmt_iterator gsi;
6916 basic_block exit_bb;
6917 edge_iterator ei;
6918 edge e;
6919 gimple *stmt;
6920 int any_addressable_vars = -1;
6922 exit_bb = region->exit;
6924 /* If the parallel region doesn't return, we don't have REGION->EXIT
6925 block at all. */
6926 if (! exit_bb)
6927 return;
6929 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6930 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6931 statements that can appear in between are extremely limited -- no
6932 memory operations at all. Here, we allow nothing at all, so the
6933 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6934 gsi = gsi_last_bb (exit_bb);
6935 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6936 gsi_prev (&gsi);
6937 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6938 return;
6940 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6942 gsi = gsi_last_bb (e->src);
6943 if (gsi_end_p (gsi))
6944 continue;
6945 stmt = gsi_stmt (gsi);
6946 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6947 && !gimple_omp_return_nowait_p (stmt))
6949 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6950 in many cases. If there could be tasks queued, the barrier
6951 might be needed to let the tasks run before some local
6952 variable of the parallel that the task uses as shared
6953 runs out of scope. The task can be spawned either
6954 from within current function (this would be easy to check)
6955 or from some function it calls and gets passed an address
6956 of such a variable. */
6957 if (any_addressable_vars < 0)
6959 gomp_parallel *parallel_stmt
6960 = as_a <gomp_parallel *> (last_stmt (region->entry));
6961 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6962 tree local_decls, block, decl;
6963 unsigned ix;
6965 any_addressable_vars = 0;
6966 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6967 if (TREE_ADDRESSABLE (decl))
6969 any_addressable_vars = 1;
6970 break;
6972 for (block = gimple_block (stmt);
6973 !any_addressable_vars
6974 && block
6975 && TREE_CODE (block) == BLOCK;
6976 block = BLOCK_SUPERCONTEXT (block))
6978 for (local_decls = BLOCK_VARS (block);
6979 local_decls;
6980 local_decls = DECL_CHAIN (local_decls))
6981 if (TREE_ADDRESSABLE (local_decls))
6983 any_addressable_vars = 1;
6984 break;
6986 if (block == gimple_block (parallel_stmt))
6987 break;
6990 if (!any_addressable_vars)
6991 gimple_omp_return_set_nowait (stmt);
6996 static void
6997 remove_exit_barriers (struct omp_region *region)
6999 if (region->type == GIMPLE_OMP_PARALLEL)
7000 remove_exit_barrier (region);
7002 if (region->inner)
7004 region = region->inner;
7005 remove_exit_barriers (region);
7006 while (region->next)
7008 region = region->next;
7009 remove_exit_barriers (region);
7014 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7015 calls. These can't be declared as const functions, but
7016 within one parallel body they are constant, so they can be
7017 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7018 which are declared const. Similarly for task body, except
7019 that in untied task omp_get_thread_num () can change at any task
7020 scheduling point. */
7022 static void
7023 optimize_omp_library_calls (gimple *entry_stmt)
7025 basic_block bb;
7026 gimple_stmt_iterator gsi;
7027 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7028 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7029 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7030 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7031 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7032 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7033 OMP_CLAUSE_UNTIED) != NULL);
7035 FOR_EACH_BB_FN (bb, cfun)
7036 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7038 gimple *call = gsi_stmt (gsi);
7039 tree decl;
7041 if (is_gimple_call (call)
7042 && (decl = gimple_call_fndecl (call))
7043 && DECL_EXTERNAL (decl)
7044 && TREE_PUBLIC (decl)
7045 && DECL_INITIAL (decl) == NULL)
7047 tree built_in;
7049 if (DECL_NAME (decl) == thr_num_id)
7051 /* In #pragma omp task untied omp_get_thread_num () can change
7052 during the execution of the task region. */
7053 if (untied_task)
7054 continue;
7055 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7057 else if (DECL_NAME (decl) == num_thr_id)
7058 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7059 else
7060 continue;
7062 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7063 || gimple_call_num_args (call) != 0)
7064 continue;
7066 if (flag_exceptions && !TREE_NOTHROW (decl))
7067 continue;
7069 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7070 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7071 TREE_TYPE (TREE_TYPE (built_in))))
7072 continue;
7074 gimple_call_set_fndecl (call, built_in);
7079 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7080 regimplified. */
7082 static tree
7083 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7085 tree t = *tp;
7087 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7088 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7089 return t;
7091 if (TREE_CODE (t) == ADDR_EXPR)
7092 recompute_tree_invariant_for_addr_expr (t);
7094 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7095 return NULL_TREE;
7098 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7100 static void
7101 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7102 bool after)
7104 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7105 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7106 !after, after ? GSI_CONTINUE_LINKING
7107 : GSI_SAME_STMT);
7108 gimple *stmt = gimple_build_assign (to, from);
7109 if (after)
7110 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7111 else
7112 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7113 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7114 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7116 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7117 gimple_regimplify_operands (stmt, &gsi);
7121 /* Expand the OpenMP parallel or task directive starting at REGION. */
7123 static void
7124 expand_omp_taskreg (struct omp_region *region)
7126 basic_block entry_bb, exit_bb, new_bb;
7127 struct function *child_cfun;
7128 tree child_fn, block, t;
7129 gimple_stmt_iterator gsi;
7130 gimple *entry_stmt, *stmt;
7131 edge e;
7132 vec<tree, va_gc> *ws_args;
7134 entry_stmt = last_stmt (region->entry);
7135 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7136 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7138 entry_bb = region->entry;
7139 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7140 exit_bb = region->cont;
7141 else
7142 exit_bb = region->exit;
7144 bool is_cilk_for
7145 = (flag_cilkplus
7146 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7147 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7148 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7150 if (is_cilk_for)
7151 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7152 and the inner statement contains the name of the built-in function
7153 and grain. */
7154 ws_args = region->inner->ws_args;
7155 else if (is_combined_parallel (region))
7156 ws_args = region->ws_args;
7157 else
7158 ws_args = NULL;
7160 if (child_cfun->cfg)
7162 /* Due to inlining, it may happen that we have already outlined
7163 the region, in which case all we need to do is make the
7164 sub-graph unreachable and emit the parallel call. */
7165 edge entry_succ_e, exit_succ_e;
7167 entry_succ_e = single_succ_edge (entry_bb);
7169 gsi = gsi_last_bb (entry_bb);
7170 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7171 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7172 gsi_remove (&gsi, true);
7174 new_bb = entry_bb;
7175 if (exit_bb)
7177 exit_succ_e = single_succ_edge (exit_bb);
7178 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7180 remove_edge_and_dominated_blocks (entry_succ_e);
7182 else
7184 unsigned srcidx, dstidx, num;
7186 /* If the parallel region needs data sent from the parent
7187 function, then the very first statement (except possible
7188 tree profile counter updates) of the parallel body
7189 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7190 &.OMP_DATA_O is passed as an argument to the child function,
7191 we need to replace it with the argument as seen by the child
7192 function.
7194 In most cases, this will end up being the identity assignment
7195 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7196 a function call that has been inlined, the original PARM_DECL
7197 .OMP_DATA_I may have been converted into a different local
7198 variable. In which case, we need to keep the assignment. */
7199 if (gimple_omp_taskreg_data_arg (entry_stmt))
7201 basic_block entry_succ_bb
7202 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7203 : FALLTHRU_EDGE (entry_bb)->dest;
7204 tree arg;
7205 gimple *parcopy_stmt = NULL;
7207 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7209 gimple *stmt;
7211 gcc_assert (!gsi_end_p (gsi));
7212 stmt = gsi_stmt (gsi);
7213 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7214 continue;
7216 if (gimple_num_ops (stmt) == 2)
7218 tree arg = gimple_assign_rhs1 (stmt);
7220 /* We're ignore the subcode because we're
7221 effectively doing a STRIP_NOPS. */
7223 if (TREE_CODE (arg) == ADDR_EXPR
7224 && TREE_OPERAND (arg, 0)
7225 == gimple_omp_taskreg_data_arg (entry_stmt))
7227 parcopy_stmt = stmt;
7228 break;
7233 gcc_assert (parcopy_stmt != NULL);
7234 arg = DECL_ARGUMENTS (child_fn);
7236 if (!gimple_in_ssa_p (cfun))
7238 if (gimple_assign_lhs (parcopy_stmt) == arg)
7239 gsi_remove (&gsi, true);
7240 else
7242 /* ?? Is setting the subcode really necessary ?? */
7243 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7244 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7247 else
7249 tree lhs = gimple_assign_lhs (parcopy_stmt);
7250 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7251 /* We'd like to set the rhs to the default def in the child_fn,
7252 but it's too early to create ssa names in the child_fn.
7253 Instead, we set the rhs to the parm. In
7254 move_sese_region_to_fn, we introduce a default def for the
7255 parm, map the parm to it's default def, and once we encounter
7256 this stmt, replace the parm with the default def. */
7257 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7258 update_stmt (parcopy_stmt);
7262 /* Declare local variables needed in CHILD_CFUN. */
7263 block = DECL_INITIAL (child_fn);
7264 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7265 /* The gimplifier could record temporaries in parallel/task block
7266 rather than in containing function's local_decls chain,
7267 which would mean cgraph missed finalizing them. Do it now. */
7268 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7269 if (TREE_CODE (t) == VAR_DECL
7270 && TREE_STATIC (t)
7271 && !DECL_EXTERNAL (t))
7272 varpool_node::finalize_decl (t);
7273 DECL_SAVED_TREE (child_fn) = NULL;
7274 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7275 gimple_set_body (child_fn, NULL);
7276 TREE_USED (block) = 1;
7278 /* Reset DECL_CONTEXT on function arguments. */
7279 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7280 DECL_CONTEXT (t) = child_fn;
7282 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7283 so that it can be moved to the child function. */
7284 gsi = gsi_last_bb (entry_bb);
7285 stmt = gsi_stmt (gsi);
7286 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7287 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7288 e = split_block (entry_bb, stmt);
7289 gsi_remove (&gsi, true);
7290 entry_bb = e->dest;
7291 edge e2 = NULL;
7292 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7293 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7294 else
7296 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7297 gcc_assert (e2->dest == region->exit);
7298 remove_edge (BRANCH_EDGE (entry_bb));
7299 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7300 gsi = gsi_last_bb (region->exit);
7301 gcc_assert (!gsi_end_p (gsi)
7302 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7303 gsi_remove (&gsi, true);
7306 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7307 if (exit_bb)
7309 gsi = gsi_last_bb (exit_bb);
7310 gcc_assert (!gsi_end_p (gsi)
7311 && (gimple_code (gsi_stmt (gsi))
7312 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7313 stmt = gimple_build_return (NULL);
7314 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7315 gsi_remove (&gsi, true);
7318 /* Move the parallel region into CHILD_CFUN. */
7320 if (gimple_in_ssa_p (cfun))
7322 init_tree_ssa (child_cfun);
7323 init_ssa_operands (child_cfun);
7324 child_cfun->gimple_df->in_ssa_p = true;
7325 block = NULL_TREE;
7327 else
7328 block = gimple_block (entry_stmt);
7330 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7331 if (exit_bb)
7332 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7333 if (e2)
7335 basic_block dest_bb = e2->dest;
7336 if (!exit_bb)
7337 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7338 remove_edge (e2);
7339 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7341 /* When the OMP expansion process cannot guarantee an up-to-date
7342 loop tree arrange for the child function to fixup loops. */
7343 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7344 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7346 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7347 num = vec_safe_length (child_cfun->local_decls);
7348 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7350 t = (*child_cfun->local_decls)[srcidx];
7351 if (DECL_CONTEXT (t) == cfun->decl)
7352 continue;
7353 if (srcidx != dstidx)
7354 (*child_cfun->local_decls)[dstidx] = t;
7355 dstidx++;
7357 if (dstidx != num)
7358 vec_safe_truncate (child_cfun->local_decls, dstidx);
7360 /* Inform the callgraph about the new function. */
7361 child_cfun->curr_properties = cfun->curr_properties;
7362 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7363 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7364 cgraph_node *node = cgraph_node::get_create (child_fn);
7365 node->parallelized_function = 1;
7366 cgraph_node::add_new_function (child_fn, true);
7368 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7369 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7371 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7372 fixed in a following pass. */
7373 push_cfun (child_cfun);
7374 if (need_asm)
7375 assign_assembler_name_if_neeeded (child_fn);
7377 if (optimize)
7378 optimize_omp_library_calls (entry_stmt);
7379 cgraph_edge::rebuild_edges ();
7381 /* Some EH regions might become dead, see PR34608. If
7382 pass_cleanup_cfg isn't the first pass to happen with the
7383 new child, these dead EH edges might cause problems.
7384 Clean them up now. */
7385 if (flag_exceptions)
7387 basic_block bb;
7388 bool changed = false;
7390 FOR_EACH_BB_FN (bb, cfun)
7391 changed |= gimple_purge_dead_eh_edges (bb);
7392 if (changed)
7393 cleanup_tree_cfg ();
7395 if (gimple_in_ssa_p (cfun))
7396 update_ssa (TODO_update_ssa);
7397 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7398 verify_loop_structure ();
7399 pop_cfun ();
7401 if (dump_file && !gimple_in_ssa_p (cfun))
7403 omp_any_child_fn_dumped = true;
7404 dump_function_header (dump_file, child_fn, dump_flags);
7405 dump_function_to_file (child_fn, dump_file, dump_flags);
7409 /* Emit a library call to launch the children threads. */
7410 if (is_cilk_for)
7411 expand_cilk_for_call (new_bb,
7412 as_a <gomp_parallel *> (entry_stmt), ws_args);
7413 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7414 expand_parallel_call (region, new_bb,
7415 as_a <gomp_parallel *> (entry_stmt), ws_args);
7416 else
7417 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7418 if (gimple_in_ssa_p (cfun))
7419 update_ssa (TODO_update_ssa_only_virtuals);
7422 /* Information about members of an OpenACC collapsed loop nest. */
7424 struct oacc_collapse
7426 tree base; /* Base value. */
7427 tree iters; /* Number of steps. */
7428 tree step; /* step size. */
7431 /* Helper for expand_oacc_for. Determine collapsed loop information.
7432 Fill in COUNTS array. Emit any initialization code before GSI.
7433 Return the calculated outer loop bound of BOUND_TYPE. */
7435 static tree
7436 expand_oacc_collapse_init (const struct omp_for_data *fd,
7437 gimple_stmt_iterator *gsi,
7438 oacc_collapse *counts, tree bound_type)
7440 tree total = build_int_cst (bound_type, 1);
7441 int ix;
7443 gcc_assert (integer_onep (fd->loop.step));
7444 gcc_assert (integer_zerop (fd->loop.n1));
7446 for (ix = 0; ix != fd->collapse; ix++)
7448 const omp_for_data_loop *loop = &fd->loops[ix];
7450 tree iter_type = TREE_TYPE (loop->v);
7451 tree diff_type = iter_type;
7452 tree plus_type = iter_type;
7454 gcc_assert (loop->cond_code == fd->loop.cond_code);
7456 if (POINTER_TYPE_P (iter_type))
7457 plus_type = sizetype;
7458 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7459 diff_type = signed_type_for (diff_type);
7461 tree b = loop->n1;
7462 tree e = loop->n2;
7463 tree s = loop->step;
7464 bool up = loop->cond_code == LT_EXPR;
7465 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7466 bool negating;
7467 tree expr;
7469 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7470 true, GSI_SAME_STMT);
7471 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7472 true, GSI_SAME_STMT);
7474 /* Convert the step, avoiding possible unsigned->signed overflow. */
7475 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7476 if (negating)
7477 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7478 s = fold_convert (diff_type, s);
7479 if (negating)
7480 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7481 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7482 true, GSI_SAME_STMT);
7484 /* Determine the range, avoiding possible unsigned->signed overflow. */
7485 negating = !up && TYPE_UNSIGNED (iter_type);
7486 expr = fold_build2 (MINUS_EXPR, plus_type,
7487 fold_convert (plus_type, negating ? b : e),
7488 fold_convert (plus_type, negating ? e : b));
7489 expr = fold_convert (diff_type, expr);
7490 if (negating)
7491 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7492 tree range = force_gimple_operand_gsi
7493 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7495 /* Determine number of iterations. */
7496 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7497 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7498 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7500 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7501 true, GSI_SAME_STMT);
7503 counts[ix].base = b;
7504 counts[ix].iters = iters;
7505 counts[ix].step = s;
7507 total = fold_build2 (MULT_EXPR, bound_type, total,
7508 fold_convert (bound_type, iters));
7511 return total;
7514 /* Emit initializers for collapsed loop members. IVAR is the outer
7515 loop iteration variable, from which collapsed loop iteration values
7516 are calculated. COUNTS array has been initialized by
7517 expand_oacc_collapse_inits. */
7519 static void
7520 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7521 gimple_stmt_iterator *gsi,
7522 const oacc_collapse *counts, tree ivar)
7524 tree ivar_type = TREE_TYPE (ivar);
7526 /* The most rapidly changing iteration variable is the innermost
7527 one. */
7528 for (int ix = fd->collapse; ix--;)
7530 const omp_for_data_loop *loop = &fd->loops[ix];
7531 const oacc_collapse *collapse = &counts[ix];
7532 tree iter_type = TREE_TYPE (loop->v);
7533 tree diff_type = TREE_TYPE (collapse->step);
7534 tree plus_type = iter_type;
7535 enum tree_code plus_code = PLUS_EXPR;
7536 tree expr;
7538 if (POINTER_TYPE_P (iter_type))
7540 plus_code = POINTER_PLUS_EXPR;
7541 plus_type = sizetype;
7544 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7545 fold_convert (ivar_type, collapse->iters));
7546 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7547 collapse->step);
7548 expr = fold_build2 (plus_code, iter_type, collapse->base,
7549 fold_convert (plus_type, expr));
7550 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7551 true, GSI_SAME_STMT);
7552 gassign *ass = gimple_build_assign (loop->v, expr);
7553 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7555 if (ix)
7557 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7558 fold_convert (ivar_type, collapse->iters));
7559 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7560 true, GSI_SAME_STMT);
7566 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7567 of the combined collapse > 1 loop constructs, generate code like:
7568 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7569 if (cond3 is <)
7570 adj = STEP3 - 1;
7571 else
7572 adj = STEP3 + 1;
7573 count3 = (adj + N32 - N31) / STEP3;
7574 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7575 if (cond2 is <)
7576 adj = STEP2 - 1;
7577 else
7578 adj = STEP2 + 1;
7579 count2 = (adj + N22 - N21) / STEP2;
7580 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7581 if (cond1 is <)
7582 adj = STEP1 - 1;
7583 else
7584 adj = STEP1 + 1;
7585 count1 = (adj + N12 - N11) / STEP1;
7586 count = count1 * count2 * count3;
7587 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7588 count = 0;
7589 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7590 of the combined loop constructs, just initialize COUNTS array
7591 from the _looptemp_ clauses. */
7593 /* NOTE: It *could* be better to moosh all of the BBs together,
7594 creating one larger BB with all the computation and the unexpected
7595 jump at the end. I.e.
7597 bool zero3, zero2, zero1, zero;
7599 zero3 = N32 c3 N31;
7600 count3 = (N32 - N31) /[cl] STEP3;
7601 zero2 = N22 c2 N21;
7602 count2 = (N22 - N21) /[cl] STEP2;
7603 zero1 = N12 c1 N11;
7604 count1 = (N12 - N11) /[cl] STEP1;
7605 zero = zero3 || zero2 || zero1;
7606 count = count1 * count2 * count3;
7607 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7609 After all, we expect the zero=false, and thus we expect to have to
7610 evaluate all of the comparison expressions, so short-circuiting
7611 oughtn't be a win. Since the condition isn't protecting a
7612 denominator, we're not concerned about divide-by-zero, so we can
7613 fully evaluate count even if a numerator turned out to be wrong.
7615 It seems like putting this all together would create much better
7616 scheduling opportunities, and less pressure on the chip's branch
7617 predictor. */
7619 static void
7620 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7621 basic_block &entry_bb, tree *counts,
7622 basic_block &zero_iter1_bb, int &first_zero_iter1,
7623 basic_block &zero_iter2_bb, int &first_zero_iter2,
7624 basic_block &l2_dom_bb)
7626 tree t, type = TREE_TYPE (fd->loop.v);
7627 edge e, ne;
7628 int i;
7630 /* Collapsed loops need work for expansion into SSA form. */
7631 gcc_assert (!gimple_in_ssa_p (cfun));
7633 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7634 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7636 gcc_assert (fd->ordered == 0);
7637 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7638 isn't supposed to be handled, as the inner loop doesn't
7639 use it. */
7640 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7641 OMP_CLAUSE__LOOPTEMP_);
7642 gcc_assert (innerc);
7643 for (i = 0; i < fd->collapse; i++)
7645 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7646 OMP_CLAUSE__LOOPTEMP_);
7647 gcc_assert (innerc);
7648 if (i)
7649 counts[i] = OMP_CLAUSE_DECL (innerc);
7650 else
7651 counts[0] = NULL_TREE;
7653 return;
7656 for (i = fd->collapse; i < fd->ordered; i++)
7658 tree itype = TREE_TYPE (fd->loops[i].v);
7659 counts[i] = NULL_TREE;
7660 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7661 fold_convert (itype, fd->loops[i].n1),
7662 fold_convert (itype, fd->loops[i].n2));
7663 if (t && integer_zerop (t))
7665 for (i = fd->collapse; i < fd->ordered; i++)
7666 counts[i] = build_int_cst (type, 0);
7667 break;
7670 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7672 tree itype = TREE_TYPE (fd->loops[i].v);
7674 if (i >= fd->collapse && counts[i])
7675 continue;
7676 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7677 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7678 fold_convert (itype, fd->loops[i].n1),
7679 fold_convert (itype, fd->loops[i].n2)))
7680 == NULL_TREE || !integer_onep (t)))
7682 gcond *cond_stmt;
7683 tree n1, n2;
7684 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7685 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7686 true, GSI_SAME_STMT);
7687 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7688 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7689 true, GSI_SAME_STMT);
7690 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7691 NULL_TREE, NULL_TREE);
7692 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7693 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7694 expand_omp_regimplify_p, NULL, NULL)
7695 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7696 expand_omp_regimplify_p, NULL, NULL))
7698 *gsi = gsi_for_stmt (cond_stmt);
7699 gimple_regimplify_operands (cond_stmt, gsi);
7701 e = split_block (entry_bb, cond_stmt);
7702 basic_block &zero_iter_bb
7703 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7704 int &first_zero_iter
7705 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7706 if (zero_iter_bb == NULL)
7708 gassign *assign_stmt;
7709 first_zero_iter = i;
7710 zero_iter_bb = create_empty_bb (entry_bb);
7711 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7712 *gsi = gsi_after_labels (zero_iter_bb);
7713 if (i < fd->collapse)
7714 assign_stmt = gimple_build_assign (fd->loop.n2,
7715 build_zero_cst (type));
7716 else
7718 counts[i] = create_tmp_reg (type, ".count");
7719 assign_stmt
7720 = gimple_build_assign (counts[i], build_zero_cst (type));
7722 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7723 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7724 entry_bb);
7726 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7727 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7728 e->flags = EDGE_TRUE_VALUE;
7729 e->probability = REG_BR_PROB_BASE - ne->probability;
7730 if (l2_dom_bb == NULL)
7731 l2_dom_bb = entry_bb;
7732 entry_bb = e->dest;
7733 *gsi = gsi_last_bb (entry_bb);
7736 if (POINTER_TYPE_P (itype))
7737 itype = signed_type_for (itype);
7738 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7739 ? -1 : 1));
7740 t = fold_build2 (PLUS_EXPR, itype,
7741 fold_convert (itype, fd->loops[i].step), t);
7742 t = fold_build2 (PLUS_EXPR, itype, t,
7743 fold_convert (itype, fd->loops[i].n2));
7744 t = fold_build2 (MINUS_EXPR, itype, t,
7745 fold_convert (itype, fd->loops[i].n1));
7746 /* ?? We could probably use CEIL_DIV_EXPR instead of
7747 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7748 generate the same code in the end because generically we
7749 don't know that the values involved must be negative for
7750 GT?? */
7751 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7752 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7753 fold_build1 (NEGATE_EXPR, itype, t),
7754 fold_build1 (NEGATE_EXPR, itype,
7755 fold_convert (itype,
7756 fd->loops[i].step)));
7757 else
7758 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7759 fold_convert (itype, fd->loops[i].step));
7760 t = fold_convert (type, t);
7761 if (TREE_CODE (t) == INTEGER_CST)
7762 counts[i] = t;
7763 else
7765 if (i < fd->collapse || i != first_zero_iter2)
7766 counts[i] = create_tmp_reg (type, ".count");
7767 expand_omp_build_assign (gsi, counts[i], t);
7769 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7771 if (i == 0)
7772 t = counts[0];
7773 else
7774 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7775 expand_omp_build_assign (gsi, fd->loop.n2, t);
7781 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7782 T = V;
7783 V3 = N31 + (T % count3) * STEP3;
7784 T = T / count3;
7785 V2 = N21 + (T % count2) * STEP2;
7786 T = T / count2;
7787 V1 = N11 + T * STEP1;
7788 if this loop doesn't have an inner loop construct combined with it.
7789 If it does have an inner loop construct combined with it and the
7790 iteration count isn't known constant, store values from counts array
7791 into its _looptemp_ temporaries instead. */
7793 static void
7794 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7795 tree *counts, gimple *inner_stmt, tree startvar)
7797 int i;
7798 if (gimple_omp_for_combined_p (fd->for_stmt))
7800 /* If fd->loop.n2 is constant, then no propagation of the counts
7801 is needed, they are constant. */
7802 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7803 return;
7805 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7806 ? gimple_omp_taskreg_clauses (inner_stmt)
7807 : gimple_omp_for_clauses (inner_stmt);
7808 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7809 isn't supposed to be handled, as the inner loop doesn't
7810 use it. */
7811 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7812 gcc_assert (innerc);
7813 for (i = 0; i < fd->collapse; i++)
7815 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7816 OMP_CLAUSE__LOOPTEMP_);
7817 gcc_assert (innerc);
7818 if (i)
7820 tree tem = OMP_CLAUSE_DECL (innerc);
7821 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7822 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7823 false, GSI_CONTINUE_LINKING);
7824 gassign *stmt = gimple_build_assign (tem, t);
7825 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7828 return;
7831 tree type = TREE_TYPE (fd->loop.v);
7832 tree tem = create_tmp_reg (type, ".tem");
7833 gassign *stmt = gimple_build_assign (tem, startvar);
7834 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7836 for (i = fd->collapse - 1; i >= 0; i--)
7838 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7839 itype = vtype;
7840 if (POINTER_TYPE_P (vtype))
7841 itype = signed_type_for (vtype);
7842 if (i != 0)
7843 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7844 else
7845 t = tem;
7846 t = fold_convert (itype, t);
7847 t = fold_build2 (MULT_EXPR, itype, t,
7848 fold_convert (itype, fd->loops[i].step));
7849 if (POINTER_TYPE_P (vtype))
7850 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7851 else
7852 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7853 t = force_gimple_operand_gsi (gsi, t,
7854 DECL_P (fd->loops[i].v)
7855 && TREE_ADDRESSABLE (fd->loops[i].v),
7856 NULL_TREE, false,
7857 GSI_CONTINUE_LINKING);
7858 stmt = gimple_build_assign (fd->loops[i].v, t);
7859 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7860 if (i != 0)
7862 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7863 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7864 false, GSI_CONTINUE_LINKING);
7865 stmt = gimple_build_assign (tem, t);
7866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7872 /* Helper function for expand_omp_for_*. Generate code like:
7873 L10:
7874 V3 += STEP3;
7875 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7876 L11:
7877 V3 = N31;
7878 V2 += STEP2;
7879 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7880 L12:
7881 V2 = N21;
7882 V1 += STEP1;
7883 goto BODY_BB; */
7885 static basic_block
7886 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7887 basic_block body_bb)
7889 basic_block last_bb, bb, collapse_bb = NULL;
7890 int i;
7891 gimple_stmt_iterator gsi;
7892 edge e;
7893 tree t;
7894 gimple *stmt;
7896 last_bb = cont_bb;
7897 for (i = fd->collapse - 1; i >= 0; i--)
7899 tree vtype = TREE_TYPE (fd->loops[i].v);
7901 bb = create_empty_bb (last_bb);
7902 add_bb_to_loop (bb, last_bb->loop_father);
7903 gsi = gsi_start_bb (bb);
7905 if (i < fd->collapse - 1)
7907 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7908 e->probability = REG_BR_PROB_BASE / 8;
7910 t = fd->loops[i + 1].n1;
7911 t = force_gimple_operand_gsi (&gsi, t,
7912 DECL_P (fd->loops[i + 1].v)
7913 && TREE_ADDRESSABLE (fd->loops[i
7914 + 1].v),
7915 NULL_TREE, false,
7916 GSI_CONTINUE_LINKING);
7917 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7918 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7920 else
7921 collapse_bb = bb;
7923 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7925 if (POINTER_TYPE_P (vtype))
7926 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7927 else
7928 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7929 t = force_gimple_operand_gsi (&gsi, t,
7930 DECL_P (fd->loops[i].v)
7931 && TREE_ADDRESSABLE (fd->loops[i].v),
7932 NULL_TREE, false, GSI_CONTINUE_LINKING);
7933 stmt = gimple_build_assign (fd->loops[i].v, t);
7934 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7936 if (i > 0)
7938 t = fd->loops[i].n2;
7939 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7940 false, GSI_CONTINUE_LINKING);
7941 tree v = fd->loops[i].v;
7942 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7943 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7944 false, GSI_CONTINUE_LINKING);
7945 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7946 stmt = gimple_build_cond_empty (t);
7947 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7948 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7949 e->probability = REG_BR_PROB_BASE * 7 / 8;
7951 else
7952 make_edge (bb, body_bb, EDGE_FALLTHRU);
7953 last_bb = bb;
7956 return collapse_bb;
7960 /* Expand #pragma omp ordered depend(source). */
7962 static void
7963 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7964 tree *counts, location_t loc)
7966 enum built_in_function source_ix
7967 = fd->iter_type == long_integer_type_node
7968 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7969 gimple *g
7970 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7971 build_fold_addr_expr (counts[fd->ordered]));
7972 gimple_set_location (g, loc);
7973 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7976 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7978 static void
7979 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7980 tree *counts, tree c, location_t loc)
7982 auto_vec<tree, 10> args;
7983 enum built_in_function sink_ix
7984 = fd->iter_type == long_integer_type_node
7985 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7986 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7987 int i;
7988 gimple_stmt_iterator gsi2 = *gsi;
7989 bool warned_step = false;
7991 for (i = 0; i < fd->ordered; i++)
7993 off = TREE_PURPOSE (deps);
7994 if (!integer_zerop (off))
7996 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7997 || fd->loops[i].cond_code == GT_EXPR);
7998 bool forward = fd->loops[i].cond_code == LT_EXPR;
7999 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8000 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8001 "lexically later iteration");
8002 break;
8004 deps = TREE_CHAIN (deps);
8006 /* If all offsets corresponding to the collapsed loops are zero,
8007 this depend clause can be ignored. FIXME: but there is still a
8008 flush needed. We need to emit one __sync_synchronize () for it
8009 though (perhaps conditionally)? Solve this together with the
8010 conservative dependence folding optimization.
8011 if (i >= fd->collapse)
8012 return; */
8014 deps = OMP_CLAUSE_DECL (c);
8015 gsi_prev (&gsi2);
8016 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8017 edge e2 = split_block_after_labels (e1->dest);
8019 *gsi = gsi_after_labels (e1->dest);
8020 for (i = 0; i < fd->ordered; i++)
8022 tree itype = TREE_TYPE (fd->loops[i].v);
8023 if (POINTER_TYPE_P (itype))
8024 itype = sizetype;
8025 if (i)
8026 deps = TREE_CHAIN (deps);
8027 off = TREE_PURPOSE (deps);
8028 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8030 if (integer_zerop (off))
8031 t = boolean_true_node;
8032 else
8034 tree a;
8035 tree co = fold_convert_loc (loc, itype, off);
8036 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8038 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8039 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8040 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8041 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8042 co);
8044 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8045 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8046 fd->loops[i].v, co);
8047 else
8048 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8049 fd->loops[i].v, co);
8050 if (fd->loops[i].cond_code == LT_EXPR)
8052 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8053 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8054 fd->loops[i].n1);
8055 else
8056 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8057 fd->loops[i].n2);
8059 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8060 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8061 fd->loops[i].n2);
8062 else
8063 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8064 fd->loops[i].n1);
8066 if (cond)
8067 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8068 else
8069 cond = t;
8071 off = fold_convert_loc (loc, itype, off);
8073 if (fd->loops[i].cond_code == LT_EXPR
8074 ? !integer_onep (fd->loops[i].step)
8075 : !integer_minus_onep (fd->loops[i].step))
8077 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8078 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8079 fold_build1_loc (loc, NEGATE_EXPR, itype,
8080 s));
8081 else
8082 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8083 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8084 build_int_cst (itype, 0));
8085 if (integer_zerop (t) && !warned_step)
8087 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8088 "in the iteration space");
8089 warned_step = true;
8091 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8092 cond, t);
8095 if (i <= fd->collapse - 1 && fd->collapse > 1)
8096 t = fd->loop.v;
8097 else if (counts[i])
8098 t = counts[i];
8099 else
8101 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8102 fd->loops[i].v, fd->loops[i].n1);
8103 t = fold_convert_loc (loc, fd->iter_type, t);
8105 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8106 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8107 fold_build1_loc (loc, NEGATE_EXPR, itype,
8108 s));
8109 else
8110 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8111 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8112 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8113 off = fold_convert_loc (loc, fd->iter_type, off);
8114 if (i <= fd->collapse - 1 && fd->collapse > 1)
8116 if (i)
8117 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8118 off);
8119 if (i < fd->collapse - 1)
8121 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8122 counts[i]);
8123 continue;
8126 off = unshare_expr (off);
8127 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8128 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8129 true, GSI_SAME_STMT);
8130 args.safe_push (t);
8132 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8133 gimple_set_location (g, loc);
8134 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8136 *gsi = gsi_last_bb (e1->src);
8137 cond = unshare_expr (cond);
8138 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8139 GSI_CONTINUE_LINKING);
8140 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8141 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8142 e3->probability = REG_BR_PROB_BASE / 8;
8143 e1->probability = REG_BR_PROB_BASE - e3->probability;
8144 e1->flags = EDGE_TRUE_VALUE;
8145 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8147 *gsi = gsi_after_labels (e2->dest);
8150 /* Expand all #pragma omp ordered depend(source) and
8151 #pragma omp ordered depend(sink:...) constructs in the current
8152 #pragma omp for ordered(n) region. */
8154 static void
8155 expand_omp_ordered_source_sink (struct omp_region *region,
8156 struct omp_for_data *fd, tree *counts,
8157 basic_block cont_bb)
8159 struct omp_region *inner;
8160 int i;
8161 for (i = fd->collapse - 1; i < fd->ordered; i++)
8162 if (i == fd->collapse - 1 && fd->collapse > 1)
8163 counts[i] = NULL_TREE;
8164 else if (i >= fd->collapse && !cont_bb)
8165 counts[i] = build_zero_cst (fd->iter_type);
8166 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8167 && integer_onep (fd->loops[i].step))
8168 counts[i] = NULL_TREE;
8169 else
8170 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8171 tree atype
8172 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8173 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8174 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8176 for (inner = region->inner; inner; inner = inner->next)
8177 if (inner->type == GIMPLE_OMP_ORDERED)
8179 gomp_ordered *ord_stmt = inner->ord_stmt;
8180 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8181 location_t loc = gimple_location (ord_stmt);
8182 tree c;
8183 for (c = gimple_omp_ordered_clauses (ord_stmt);
8184 c; c = OMP_CLAUSE_CHAIN (c))
8185 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8186 break;
8187 if (c)
8188 expand_omp_ordered_source (&gsi, fd, counts, loc);
8189 for (c = gimple_omp_ordered_clauses (ord_stmt);
8190 c; c = OMP_CLAUSE_CHAIN (c))
8191 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8192 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8193 gsi_remove (&gsi, true);
8197 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8198 collapsed. */
8200 static basic_block
8201 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8202 basic_block cont_bb, basic_block body_bb,
8203 bool ordered_lastprivate)
8205 if (fd->ordered == fd->collapse)
8206 return cont_bb;
8208 if (!cont_bb)
8210 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8211 for (int i = fd->collapse; i < fd->ordered; i++)
8213 tree type = TREE_TYPE (fd->loops[i].v);
8214 tree n1 = fold_convert (type, fd->loops[i].n1);
8215 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8216 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8217 size_int (i - fd->collapse + 1),
8218 NULL_TREE, NULL_TREE);
8219 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8221 return NULL;
8224 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8226 tree t, type = TREE_TYPE (fd->loops[i].v);
8227 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8228 expand_omp_build_assign (&gsi, fd->loops[i].v,
8229 fold_convert (type, fd->loops[i].n1));
8230 if (counts[i])
8231 expand_omp_build_assign (&gsi, counts[i],
8232 build_zero_cst (fd->iter_type));
8233 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8234 size_int (i - fd->collapse + 1),
8235 NULL_TREE, NULL_TREE);
8236 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8237 if (!gsi_end_p (gsi))
8238 gsi_prev (&gsi);
8239 else
8240 gsi = gsi_last_bb (body_bb);
8241 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8242 basic_block new_body = e1->dest;
8243 if (body_bb == cont_bb)
8244 cont_bb = new_body;
8245 edge e2 = NULL;
8246 basic_block new_header;
8247 if (EDGE_COUNT (cont_bb->preds) > 0)
8249 gsi = gsi_last_bb (cont_bb);
8250 if (POINTER_TYPE_P (type))
8251 t = fold_build_pointer_plus (fd->loops[i].v,
8252 fold_convert (sizetype,
8253 fd->loops[i].step));
8254 else
8255 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8256 fold_convert (type, fd->loops[i].step));
8257 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8258 if (counts[i])
8260 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8261 build_int_cst (fd->iter_type, 1));
8262 expand_omp_build_assign (&gsi, counts[i], t);
8263 t = counts[i];
8265 else
8267 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8268 fd->loops[i].v, fd->loops[i].n1);
8269 t = fold_convert (fd->iter_type, t);
8270 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8271 true, GSI_SAME_STMT);
8273 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8274 size_int (i - fd->collapse + 1),
8275 NULL_TREE, NULL_TREE);
8276 expand_omp_build_assign (&gsi, aref, t);
8277 gsi_prev (&gsi);
8278 e2 = split_block (cont_bb, gsi_stmt (gsi));
8279 new_header = e2->dest;
8281 else
8282 new_header = cont_bb;
8283 gsi = gsi_after_labels (new_header);
8284 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8285 true, GSI_SAME_STMT);
8286 tree n2
8287 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8288 true, NULL_TREE, true, GSI_SAME_STMT);
8289 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8290 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8291 edge e3 = split_block (new_header, gsi_stmt (gsi));
8292 cont_bb = e3->dest;
8293 remove_edge (e1);
8294 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8295 e3->flags = EDGE_FALSE_VALUE;
8296 e3->probability = REG_BR_PROB_BASE / 8;
8297 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8298 e1->probability = REG_BR_PROB_BASE - e3->probability;
8300 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8301 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8303 if (e2)
8305 struct loop *loop = alloc_loop ();
8306 loop->header = new_header;
8307 loop->latch = e2->src;
8308 add_loop (loop, body_bb->loop_father);
8312 /* If there are any lastprivate clauses and it is possible some loops
8313 might have zero iterations, ensure all the decls are initialized,
8314 otherwise we could crash evaluating C++ class iterators with lastprivate
8315 clauses. */
8316 bool need_inits = false;
8317 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8318 if (need_inits)
8320 tree type = TREE_TYPE (fd->loops[i].v);
8321 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8322 expand_omp_build_assign (&gsi, fd->loops[i].v,
8323 fold_convert (type, fd->loops[i].n1));
8325 else
8327 tree type = TREE_TYPE (fd->loops[i].v);
8328 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8329 boolean_type_node,
8330 fold_convert (type, fd->loops[i].n1),
8331 fold_convert (type, fd->loops[i].n2));
8332 if (!integer_onep (this_cond))
8333 need_inits = true;
8336 return cont_bb;
8340 /* A subroutine of expand_omp_for. Generate code for a parallel
8341 loop with any schedule. Given parameters:
8343 for (V = N1; V cond N2; V += STEP) BODY;
8345 where COND is "<" or ">", we generate pseudocode
8347 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8348 if (more) goto L0; else goto L3;
8350 V = istart0;
8351 iend = iend0;
8353 BODY;
8354 V += STEP;
8355 if (V cond iend) goto L1; else goto L2;
8357 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8360 If this is a combined omp parallel loop, instead of the call to
8361 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8362 If this is gimple_omp_for_combined_p loop, then instead of assigning
8363 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8364 inner GIMPLE_OMP_FOR and V += STEP; and
8365 if (V cond iend) goto L1; else goto L2; are removed.
8367 For collapsed loops, given parameters:
8368 collapse(3)
8369 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8370 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8371 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8372 BODY;
8374 we generate pseudocode
8376 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8377 if (cond3 is <)
8378 adj = STEP3 - 1;
8379 else
8380 adj = STEP3 + 1;
8381 count3 = (adj + N32 - N31) / STEP3;
8382 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8383 if (cond2 is <)
8384 adj = STEP2 - 1;
8385 else
8386 adj = STEP2 + 1;
8387 count2 = (adj + N22 - N21) / STEP2;
8388 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8389 if (cond1 is <)
8390 adj = STEP1 - 1;
8391 else
8392 adj = STEP1 + 1;
8393 count1 = (adj + N12 - N11) / STEP1;
8394 count = count1 * count2 * count3;
8395 goto Z1;
8397 count = 0;
8399 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8400 if (more) goto L0; else goto L3;
8402 V = istart0;
8403 T = V;
8404 V3 = N31 + (T % count3) * STEP3;
8405 T = T / count3;
8406 V2 = N21 + (T % count2) * STEP2;
8407 T = T / count2;
8408 V1 = N11 + T * STEP1;
8409 iend = iend0;
8411 BODY;
8412 V += 1;
8413 if (V < iend) goto L10; else goto L2;
8414 L10:
8415 V3 += STEP3;
8416 if (V3 cond3 N32) goto L1; else goto L11;
8417 L11:
8418 V3 = N31;
8419 V2 += STEP2;
8420 if (V2 cond2 N22) goto L1; else goto L12;
8421 L12:
8422 V2 = N21;
8423 V1 += STEP1;
8424 goto L1;
8426 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8431 static void
8432 expand_omp_for_generic (struct omp_region *region,
8433 struct omp_for_data *fd,
8434 enum built_in_function start_fn,
8435 enum built_in_function next_fn,
8436 gimple *inner_stmt)
8438 tree type, istart0, iend0, iend;
8439 tree t, vmain, vback, bias = NULL_TREE;
8440 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8441 basic_block l2_bb = NULL, l3_bb = NULL;
8442 gimple_stmt_iterator gsi;
8443 gassign *assign_stmt;
8444 bool in_combined_parallel = is_combined_parallel (region);
8445 bool broken_loop = region->cont == NULL;
8446 edge e, ne;
8447 tree *counts = NULL;
8448 int i;
8449 bool ordered_lastprivate = false;
8451 gcc_assert (!broken_loop || !in_combined_parallel);
8452 gcc_assert (fd->iter_type == long_integer_type_node
8453 || !in_combined_parallel);
8455 entry_bb = region->entry;
8456 cont_bb = region->cont;
8457 collapse_bb = NULL;
8458 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8459 gcc_assert (broken_loop
8460 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8461 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8462 l1_bb = single_succ (l0_bb);
8463 if (!broken_loop)
8465 l2_bb = create_empty_bb (cont_bb);
8466 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8467 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8468 == l1_bb));
8469 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8471 else
8472 l2_bb = NULL;
8473 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8474 exit_bb = region->exit;
8476 gsi = gsi_last_bb (entry_bb);
8478 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8479 if (fd->ordered
8480 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8481 OMP_CLAUSE_LASTPRIVATE))
8482 ordered_lastprivate = false;
8483 if (fd->collapse > 1 || fd->ordered)
8485 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8486 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8488 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8489 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8490 zero_iter1_bb, first_zero_iter1,
8491 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8493 if (zero_iter1_bb)
8495 /* Some counts[i] vars might be uninitialized if
8496 some loop has zero iterations. But the body shouldn't
8497 be executed in that case, so just avoid uninit warnings. */
8498 for (i = first_zero_iter1;
8499 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8500 if (SSA_VAR_P (counts[i]))
8501 TREE_NO_WARNING (counts[i]) = 1;
8502 gsi_prev (&gsi);
8503 e = split_block (entry_bb, gsi_stmt (gsi));
8504 entry_bb = e->dest;
8505 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8506 gsi = gsi_last_bb (entry_bb);
8507 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8508 get_immediate_dominator (CDI_DOMINATORS,
8509 zero_iter1_bb));
8511 if (zero_iter2_bb)
8513 /* Some counts[i] vars might be uninitialized if
8514 some loop has zero iterations. But the body shouldn't
8515 be executed in that case, so just avoid uninit warnings. */
8516 for (i = first_zero_iter2; i < fd->ordered; i++)
8517 if (SSA_VAR_P (counts[i]))
8518 TREE_NO_WARNING (counts[i]) = 1;
8519 if (zero_iter1_bb)
8520 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8521 else
8523 gsi_prev (&gsi);
8524 e = split_block (entry_bb, gsi_stmt (gsi));
8525 entry_bb = e->dest;
8526 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8527 gsi = gsi_last_bb (entry_bb);
8528 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8529 get_immediate_dominator
8530 (CDI_DOMINATORS, zero_iter2_bb));
8533 if (fd->collapse == 1)
8535 counts[0] = fd->loop.n2;
8536 fd->loop = fd->loops[0];
8540 type = TREE_TYPE (fd->loop.v);
8541 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8542 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8543 TREE_ADDRESSABLE (istart0) = 1;
8544 TREE_ADDRESSABLE (iend0) = 1;
8546 /* See if we need to bias by LLONG_MIN. */
8547 if (fd->iter_type == long_long_unsigned_type_node
8548 && TREE_CODE (type) == INTEGER_TYPE
8549 && !TYPE_UNSIGNED (type)
8550 && fd->ordered == 0)
8552 tree n1, n2;
8554 if (fd->loop.cond_code == LT_EXPR)
8556 n1 = fd->loop.n1;
8557 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8559 else
8561 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8562 n2 = fd->loop.n1;
8564 if (TREE_CODE (n1) != INTEGER_CST
8565 || TREE_CODE (n2) != INTEGER_CST
8566 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8567 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8570 gimple_stmt_iterator gsif = gsi;
8571 gsi_prev (&gsif);
8573 tree arr = NULL_TREE;
8574 if (in_combined_parallel)
8576 gcc_assert (fd->ordered == 0);
8577 /* In a combined parallel loop, emit a call to
8578 GOMP_loop_foo_next. */
8579 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8580 build_fold_addr_expr (istart0),
8581 build_fold_addr_expr (iend0));
8583 else
8585 tree t0, t1, t2, t3, t4;
8586 /* If this is not a combined parallel loop, emit a call to
8587 GOMP_loop_foo_start in ENTRY_BB. */
8588 t4 = build_fold_addr_expr (iend0);
8589 t3 = build_fold_addr_expr (istart0);
8590 if (fd->ordered)
8592 t0 = build_int_cst (unsigned_type_node,
8593 fd->ordered - fd->collapse + 1);
8594 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8595 fd->ordered
8596 - fd->collapse + 1),
8597 ".omp_counts");
8598 DECL_NAMELESS (arr) = 1;
8599 TREE_ADDRESSABLE (arr) = 1;
8600 TREE_STATIC (arr) = 1;
8601 vec<constructor_elt, va_gc> *v;
8602 vec_alloc (v, fd->ordered - fd->collapse + 1);
8603 int idx;
8605 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8607 tree c;
8608 if (idx == 0 && fd->collapse > 1)
8609 c = fd->loop.n2;
8610 else
8611 c = counts[idx + fd->collapse - 1];
8612 tree purpose = size_int (idx);
8613 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8614 if (TREE_CODE (c) != INTEGER_CST)
8615 TREE_STATIC (arr) = 0;
8618 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8619 if (!TREE_STATIC (arr))
8620 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8621 void_type_node, arr),
8622 true, NULL_TREE, true, GSI_SAME_STMT);
8623 t1 = build_fold_addr_expr (arr);
8624 t2 = NULL_TREE;
8626 else
8628 t2 = fold_convert (fd->iter_type, fd->loop.step);
8629 t1 = fd->loop.n2;
8630 t0 = fd->loop.n1;
8631 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8633 tree innerc
8634 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8635 OMP_CLAUSE__LOOPTEMP_);
8636 gcc_assert (innerc);
8637 t0 = OMP_CLAUSE_DECL (innerc);
8638 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8639 OMP_CLAUSE__LOOPTEMP_);
8640 gcc_assert (innerc);
8641 t1 = OMP_CLAUSE_DECL (innerc);
8643 if (POINTER_TYPE_P (TREE_TYPE (t0))
8644 && TYPE_PRECISION (TREE_TYPE (t0))
8645 != TYPE_PRECISION (fd->iter_type))
8647 /* Avoid casting pointers to integer of a different size. */
8648 tree itype = signed_type_for (type);
8649 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8650 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8652 else
8654 t1 = fold_convert (fd->iter_type, t1);
8655 t0 = fold_convert (fd->iter_type, t0);
8657 if (bias)
8659 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8660 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8663 if (fd->iter_type == long_integer_type_node || fd->ordered)
8665 if (fd->chunk_size)
8667 t = fold_convert (fd->iter_type, fd->chunk_size);
8668 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8669 if (fd->ordered)
8670 t = build_call_expr (builtin_decl_explicit (start_fn),
8671 5, t0, t1, t, t3, t4);
8672 else
8673 t = build_call_expr (builtin_decl_explicit (start_fn),
8674 6, t0, t1, t2, t, t3, t4);
8676 else if (fd->ordered)
8677 t = build_call_expr (builtin_decl_explicit (start_fn),
8678 4, t0, t1, t3, t4);
8679 else
8680 t = build_call_expr (builtin_decl_explicit (start_fn),
8681 5, t0, t1, t2, t3, t4);
8683 else
8685 tree t5;
8686 tree c_bool_type;
8687 tree bfn_decl;
8689 /* The GOMP_loop_ull_*start functions have additional boolean
8690 argument, true for < loops and false for > loops.
8691 In Fortran, the C bool type can be different from
8692 boolean_type_node. */
8693 bfn_decl = builtin_decl_explicit (start_fn);
8694 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8695 t5 = build_int_cst (c_bool_type,
8696 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8697 if (fd->chunk_size)
8699 tree bfn_decl = builtin_decl_explicit (start_fn);
8700 t = fold_convert (fd->iter_type, fd->chunk_size);
8701 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8702 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8704 else
8705 t = build_call_expr (builtin_decl_explicit (start_fn),
8706 6, t5, t0, t1, t2, t3, t4);
8709 if (TREE_TYPE (t) != boolean_type_node)
8710 t = fold_build2 (NE_EXPR, boolean_type_node,
8711 t, build_int_cst (TREE_TYPE (t), 0));
8712 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8713 true, GSI_SAME_STMT);
8714 if (arr && !TREE_STATIC (arr))
8716 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8717 TREE_THIS_VOLATILE (clobber) = 1;
8718 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8719 GSI_SAME_STMT);
8721 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8723 /* Remove the GIMPLE_OMP_FOR statement. */
8724 gsi_remove (&gsi, true);
8726 if (gsi_end_p (gsif))
8727 gsif = gsi_after_labels (gsi_bb (gsif));
8728 gsi_next (&gsif);
8730 /* Iteration setup for sequential loop goes in L0_BB. */
8731 tree startvar = fd->loop.v;
8732 tree endvar = NULL_TREE;
8734 if (gimple_omp_for_combined_p (fd->for_stmt))
8736 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8737 && gimple_omp_for_kind (inner_stmt)
8738 == GF_OMP_FOR_KIND_SIMD);
8739 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8740 OMP_CLAUSE__LOOPTEMP_);
8741 gcc_assert (innerc);
8742 startvar = OMP_CLAUSE_DECL (innerc);
8743 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8744 OMP_CLAUSE__LOOPTEMP_);
8745 gcc_assert (innerc);
8746 endvar = OMP_CLAUSE_DECL (innerc);
8749 gsi = gsi_start_bb (l0_bb);
8750 t = istart0;
8751 if (fd->ordered && fd->collapse == 1)
8752 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8753 fold_convert (fd->iter_type, fd->loop.step));
8754 else if (bias)
8755 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8756 if (fd->ordered && fd->collapse == 1)
8758 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8759 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8760 fd->loop.n1, fold_convert (sizetype, t));
8761 else
8763 t = fold_convert (TREE_TYPE (startvar), t);
8764 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8765 fd->loop.n1, t);
8768 else
8770 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8771 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8772 t = fold_convert (TREE_TYPE (startvar), t);
8774 t = force_gimple_operand_gsi (&gsi, t,
8775 DECL_P (startvar)
8776 && TREE_ADDRESSABLE (startvar),
8777 NULL_TREE, false, GSI_CONTINUE_LINKING);
8778 assign_stmt = gimple_build_assign (startvar, t);
8779 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8781 t = iend0;
8782 if (fd->ordered && fd->collapse == 1)
8783 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8784 fold_convert (fd->iter_type, fd->loop.step));
8785 else if (bias)
8786 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8787 if (fd->ordered && fd->collapse == 1)
8789 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8790 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8791 fd->loop.n1, fold_convert (sizetype, t));
8792 else
8794 t = fold_convert (TREE_TYPE (startvar), t);
8795 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8796 fd->loop.n1, t);
8799 else
8801 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8802 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8803 t = fold_convert (TREE_TYPE (startvar), t);
8805 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8806 false, GSI_CONTINUE_LINKING);
8807 if (endvar)
8809 assign_stmt = gimple_build_assign (endvar, iend);
8810 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8811 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8812 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8813 else
8814 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8815 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8817 /* Handle linear clause adjustments. */
8818 tree itercnt = NULL_TREE;
8819 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8820 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8821 c; c = OMP_CLAUSE_CHAIN (c))
8822 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8823 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8825 tree d = OMP_CLAUSE_DECL (c);
8826 bool is_ref = is_reference (d);
8827 tree t = d, a, dest;
8828 if (is_ref)
8829 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8830 tree type = TREE_TYPE (t);
8831 if (POINTER_TYPE_P (type))
8832 type = sizetype;
8833 dest = unshare_expr (t);
8834 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8835 expand_omp_build_assign (&gsif, v, t);
8836 if (itercnt == NULL_TREE)
8838 itercnt = startvar;
8839 tree n1 = fd->loop.n1;
8840 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8842 itercnt
8843 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8844 itercnt);
8845 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8847 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8848 itercnt, n1);
8849 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8850 itercnt, fd->loop.step);
8851 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8852 NULL_TREE, false,
8853 GSI_CONTINUE_LINKING);
8855 a = fold_build2 (MULT_EXPR, type,
8856 fold_convert (type, itercnt),
8857 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8858 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8859 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8860 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8861 false, GSI_CONTINUE_LINKING);
8862 assign_stmt = gimple_build_assign (dest, t);
8863 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8865 if (fd->collapse > 1)
8866 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8868 if (fd->ordered)
8870 /* Until now, counts array contained number of iterations or
8871 variable containing it for ith loop. From now on, we need
8872 those counts only for collapsed loops, and only for the 2nd
8873 till the last collapsed one. Move those one element earlier,
8874 we'll use counts[fd->collapse - 1] for the first source/sink
8875 iteration counter and so on and counts[fd->ordered]
8876 as the array holding the current counter values for
8877 depend(source). */
8878 if (fd->collapse > 1)
8879 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8880 if (broken_loop)
8882 int i;
8883 for (i = fd->collapse; i < fd->ordered; i++)
8885 tree type = TREE_TYPE (fd->loops[i].v);
8886 tree this_cond
8887 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8888 fold_convert (type, fd->loops[i].n1),
8889 fold_convert (type, fd->loops[i].n2));
8890 if (!integer_onep (this_cond))
8891 break;
8893 if (i < fd->ordered)
8895 cont_bb
8896 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8897 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8898 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8899 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8900 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8901 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8902 make_edge (cont_bb, l1_bb, 0);
8903 l2_bb = create_empty_bb (cont_bb);
8904 broken_loop = false;
8907 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8908 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8909 ordered_lastprivate);
8910 if (counts[fd->collapse - 1])
8912 gcc_assert (fd->collapse == 1);
8913 gsi = gsi_last_bb (l0_bb);
8914 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8915 istart0, true);
8916 gsi = gsi_last_bb (cont_bb);
8917 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8918 build_int_cst (fd->iter_type, 1));
8919 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8920 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8921 size_zero_node, NULL_TREE, NULL_TREE);
8922 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8923 t = counts[fd->collapse - 1];
8925 else if (fd->collapse > 1)
8926 t = fd->loop.v;
8927 else
8929 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8930 fd->loops[0].v, fd->loops[0].n1);
8931 t = fold_convert (fd->iter_type, t);
8933 gsi = gsi_last_bb (l0_bb);
8934 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8935 size_zero_node, NULL_TREE, NULL_TREE);
8936 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8937 false, GSI_CONTINUE_LINKING);
8938 expand_omp_build_assign (&gsi, aref, t, true);
8941 if (!broken_loop)
8943 /* Code to control the increment and predicate for the sequential
8944 loop goes in the CONT_BB. */
8945 gsi = gsi_last_bb (cont_bb);
8946 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8947 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8948 vmain = gimple_omp_continue_control_use (cont_stmt);
8949 vback = gimple_omp_continue_control_def (cont_stmt);
8951 if (!gimple_omp_for_combined_p (fd->for_stmt))
8953 if (POINTER_TYPE_P (type))
8954 t = fold_build_pointer_plus (vmain, fd->loop.step);
8955 else
8956 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8957 t = force_gimple_operand_gsi (&gsi, t,
8958 DECL_P (vback)
8959 && TREE_ADDRESSABLE (vback),
8960 NULL_TREE, true, GSI_SAME_STMT);
8961 assign_stmt = gimple_build_assign (vback, t);
8962 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8964 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8966 if (fd->collapse > 1)
8967 t = fd->loop.v;
8968 else
8970 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8971 fd->loops[0].v, fd->loops[0].n1);
8972 t = fold_convert (fd->iter_type, t);
8974 tree aref = build4 (ARRAY_REF, fd->iter_type,
8975 counts[fd->ordered], size_zero_node,
8976 NULL_TREE, NULL_TREE);
8977 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8978 true, GSI_SAME_STMT);
8979 expand_omp_build_assign (&gsi, aref, t);
8982 t = build2 (fd->loop.cond_code, boolean_type_node,
8983 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8984 iend);
8985 gcond *cond_stmt = gimple_build_cond_empty (t);
8986 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8989 /* Remove GIMPLE_OMP_CONTINUE. */
8990 gsi_remove (&gsi, true);
8992 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8993 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8995 /* Emit code to get the next parallel iteration in L2_BB. */
8996 gsi = gsi_start_bb (l2_bb);
8998 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8999 build_fold_addr_expr (istart0),
9000 build_fold_addr_expr (iend0));
9001 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9002 false, GSI_CONTINUE_LINKING);
9003 if (TREE_TYPE (t) != boolean_type_node)
9004 t = fold_build2 (NE_EXPR, boolean_type_node,
9005 t, build_int_cst (TREE_TYPE (t), 0));
9006 gcond *cond_stmt = gimple_build_cond_empty (t);
9007 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9010 /* Add the loop cleanup function. */
9011 gsi = gsi_last_bb (exit_bb);
9012 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9013 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9014 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9015 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9016 else
9017 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9018 gcall *call_stmt = gimple_build_call (t, 0);
9019 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9020 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9021 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9022 if (fd->ordered)
9024 tree arr = counts[fd->ordered];
9025 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9026 TREE_THIS_VOLATILE (clobber) = 1;
9027 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9028 GSI_SAME_STMT);
9030 gsi_remove (&gsi, true);
9032 /* Connect the new blocks. */
9033 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9034 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9036 if (!broken_loop)
9038 gimple_seq phis;
9040 e = find_edge (cont_bb, l3_bb);
9041 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9043 phis = phi_nodes (l3_bb);
9044 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9046 gimple *phi = gsi_stmt (gsi);
9047 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9048 PHI_ARG_DEF_FROM_EDGE (phi, e));
9050 remove_edge (e);
9052 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9053 e = find_edge (cont_bb, l1_bb);
9054 if (e == NULL)
9056 e = BRANCH_EDGE (cont_bb);
9057 gcc_assert (single_succ (e->dest) == l1_bb);
9059 if (gimple_omp_for_combined_p (fd->for_stmt))
9061 remove_edge (e);
9062 e = NULL;
9064 else if (fd->collapse > 1)
9066 remove_edge (e);
9067 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9069 else
9070 e->flags = EDGE_TRUE_VALUE;
9071 if (e)
9073 e->probability = REG_BR_PROB_BASE * 7 / 8;
9074 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9076 else
9078 e = find_edge (cont_bb, l2_bb);
9079 e->flags = EDGE_FALLTHRU;
9081 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9083 if (gimple_in_ssa_p (cfun))
9085 /* Add phis to the outer loop that connect to the phis in the inner,
9086 original loop, and move the loop entry value of the inner phi to
9087 the loop entry value of the outer phi. */
9088 gphi_iterator psi;
9089 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9091 source_location locus;
9092 gphi *nphi;
9093 gphi *exit_phi = psi.phi ();
9095 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9096 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9098 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9099 edge latch_to_l1 = find_edge (latch, l1_bb);
9100 gphi *inner_phi
9101 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9103 tree t = gimple_phi_result (exit_phi);
9104 tree new_res = copy_ssa_name (t, NULL);
9105 nphi = create_phi_node (new_res, l0_bb);
9107 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9108 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9109 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9110 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9111 add_phi_arg (nphi, t, entry_to_l0, locus);
9113 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9114 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9116 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9120 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9121 recompute_dominator (CDI_DOMINATORS, l2_bb));
9122 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9123 recompute_dominator (CDI_DOMINATORS, l3_bb));
9124 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9125 recompute_dominator (CDI_DOMINATORS, l0_bb));
9126 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9127 recompute_dominator (CDI_DOMINATORS, l1_bb));
9129 /* We enter expand_omp_for_generic with a loop. This original loop may
9130 have its own loop struct, or it may be part of an outer loop struct
9131 (which may be the fake loop). */
9132 struct loop *outer_loop = entry_bb->loop_father;
9133 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9135 add_bb_to_loop (l2_bb, outer_loop);
9137 /* We've added a new loop around the original loop. Allocate the
9138 corresponding loop struct. */
9139 struct loop *new_loop = alloc_loop ();
9140 new_loop->header = l0_bb;
9141 new_loop->latch = l2_bb;
9142 add_loop (new_loop, outer_loop);
9144 /* Allocate a loop structure for the original loop unless we already
9145 had one. */
9146 if (!orig_loop_has_loop_struct
9147 && !gimple_omp_for_combined_p (fd->for_stmt))
9149 struct loop *orig_loop = alloc_loop ();
9150 orig_loop->header = l1_bb;
9151 /* The loop may have multiple latches. */
9152 add_loop (orig_loop, new_loop);
9158 /* A subroutine of expand_omp_for. Generate code for a parallel
9159 loop with static schedule and no specified chunk size. Given
9160 parameters:
9162 for (V = N1; V cond N2; V += STEP) BODY;
9164 where COND is "<" or ">", we generate pseudocode
9166 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9167 if (cond is <)
9168 adj = STEP - 1;
9169 else
9170 adj = STEP + 1;
9171 if ((__typeof (V)) -1 > 0 && cond is >)
9172 n = -(adj + N2 - N1) / -STEP;
9173 else
9174 n = (adj + N2 - N1) / STEP;
9175 q = n / nthreads;
9176 tt = n % nthreads;
9177 if (threadid < tt) goto L3; else goto L4;
9179 tt = 0;
9180 q = q + 1;
9182 s0 = q * threadid + tt;
9183 e0 = s0 + q;
9184 V = s0 * STEP + N1;
9185 if (s0 >= e0) goto L2; else goto L0;
9187 e = e0 * STEP + N1;
9189 BODY;
9190 V += STEP;
9191 if (V cond e) goto L1;
9195 static void
9196 expand_omp_for_static_nochunk (struct omp_region *region,
9197 struct omp_for_data *fd,
9198 gimple *inner_stmt)
9200 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9201 tree type, itype, vmain, vback;
9202 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9203 basic_block body_bb, cont_bb, collapse_bb = NULL;
9204 basic_block fin_bb;
9205 gimple_stmt_iterator gsi;
9206 edge ep;
9207 bool broken_loop = region->cont == NULL;
9208 tree *counts = NULL;
9209 tree n1, n2, step;
9211 itype = type = TREE_TYPE (fd->loop.v);
9212 if (POINTER_TYPE_P (type))
9213 itype = signed_type_for (type);
9215 entry_bb = region->entry;
9216 cont_bb = region->cont;
9217 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9218 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9219 gcc_assert (broken_loop
9220 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9221 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9222 body_bb = single_succ (seq_start_bb);
9223 if (!broken_loop)
9225 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9226 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9227 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9229 exit_bb = region->exit;
9231 /* Iteration space partitioning goes in ENTRY_BB. */
9232 gsi = gsi_last_bb (entry_bb);
9233 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9235 if (fd->collapse > 1)
9237 int first_zero_iter = -1, dummy = -1;
9238 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9240 counts = XALLOCAVEC (tree, fd->collapse);
9241 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9242 fin_bb, first_zero_iter,
9243 dummy_bb, dummy, l2_dom_bb);
9244 t = NULL_TREE;
9246 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9247 t = integer_one_node;
9248 else
9249 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9250 fold_convert (type, fd->loop.n1),
9251 fold_convert (type, fd->loop.n2));
9252 if (fd->collapse == 1
9253 && TYPE_UNSIGNED (type)
9254 && (t == NULL_TREE || !integer_onep (t)))
9256 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9257 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9258 true, GSI_SAME_STMT);
9259 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9260 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9261 true, GSI_SAME_STMT);
9262 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9263 NULL_TREE, NULL_TREE);
9264 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9265 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9266 expand_omp_regimplify_p, NULL, NULL)
9267 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9268 expand_omp_regimplify_p, NULL, NULL))
9270 gsi = gsi_for_stmt (cond_stmt);
9271 gimple_regimplify_operands (cond_stmt, &gsi);
9273 ep = split_block (entry_bb, cond_stmt);
9274 ep->flags = EDGE_TRUE_VALUE;
9275 entry_bb = ep->dest;
9276 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9277 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9278 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9279 if (gimple_in_ssa_p (cfun))
9281 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9282 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9283 !gsi_end_p (gpi); gsi_next (&gpi))
9285 gphi *phi = gpi.phi ();
9286 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9287 ep, UNKNOWN_LOCATION);
9290 gsi = gsi_last_bb (entry_bb);
9293 switch (gimple_omp_for_kind (fd->for_stmt))
9295 case GF_OMP_FOR_KIND_FOR:
9296 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9297 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9298 break;
9299 case GF_OMP_FOR_KIND_DISTRIBUTE:
9300 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9301 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9302 break;
9303 default:
9304 gcc_unreachable ();
9306 nthreads = build_call_expr (nthreads, 0);
9307 nthreads = fold_convert (itype, nthreads);
9308 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9309 true, GSI_SAME_STMT);
9310 threadid = build_call_expr (threadid, 0);
9311 threadid = fold_convert (itype, threadid);
9312 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9313 true, GSI_SAME_STMT);
9315 n1 = fd->loop.n1;
9316 n2 = fd->loop.n2;
9317 step = fd->loop.step;
9318 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9320 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9321 OMP_CLAUSE__LOOPTEMP_);
9322 gcc_assert (innerc);
9323 n1 = OMP_CLAUSE_DECL (innerc);
9324 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9325 OMP_CLAUSE__LOOPTEMP_);
9326 gcc_assert (innerc);
9327 n2 = OMP_CLAUSE_DECL (innerc);
9329 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9330 true, NULL_TREE, true, GSI_SAME_STMT);
9331 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9332 true, NULL_TREE, true, GSI_SAME_STMT);
9333 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9334 true, NULL_TREE, true, GSI_SAME_STMT);
9336 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9337 t = fold_build2 (PLUS_EXPR, itype, step, t);
9338 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9339 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9340 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9341 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9342 fold_build1 (NEGATE_EXPR, itype, t),
9343 fold_build1 (NEGATE_EXPR, itype, step));
9344 else
9345 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9346 t = fold_convert (itype, t);
9347 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9349 q = create_tmp_reg (itype, "q");
9350 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9351 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9352 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9354 tt = create_tmp_reg (itype, "tt");
9355 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9356 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9357 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9359 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9360 gcond *cond_stmt = gimple_build_cond_empty (t);
9361 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9363 second_bb = split_block (entry_bb, cond_stmt)->dest;
9364 gsi = gsi_last_bb (second_bb);
9365 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9367 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9368 GSI_SAME_STMT);
9369 gassign *assign_stmt
9370 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9371 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9373 third_bb = split_block (second_bb, assign_stmt)->dest;
9374 gsi = gsi_last_bb (third_bb);
9375 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9377 t = build2 (MULT_EXPR, itype, q, threadid);
9378 t = build2 (PLUS_EXPR, itype, t, tt);
9379 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9381 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9382 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9384 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9385 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9387 /* Remove the GIMPLE_OMP_FOR statement. */
9388 gsi_remove (&gsi, true);
9390 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9391 gsi = gsi_start_bb (seq_start_bb);
9393 tree startvar = fd->loop.v;
9394 tree endvar = NULL_TREE;
9396 if (gimple_omp_for_combined_p (fd->for_stmt))
9398 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9399 ? gimple_omp_parallel_clauses (inner_stmt)
9400 : gimple_omp_for_clauses (inner_stmt);
9401 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9402 gcc_assert (innerc);
9403 startvar = OMP_CLAUSE_DECL (innerc);
9404 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9405 OMP_CLAUSE__LOOPTEMP_);
9406 gcc_assert (innerc);
9407 endvar = OMP_CLAUSE_DECL (innerc);
9408 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9409 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9411 int i;
9412 for (i = 1; i < fd->collapse; i++)
9414 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9415 OMP_CLAUSE__LOOPTEMP_);
9416 gcc_assert (innerc);
9418 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9419 OMP_CLAUSE__LOOPTEMP_);
9420 if (innerc)
9422 /* If needed (distribute parallel for with lastprivate),
9423 propagate down the total number of iterations. */
9424 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9425 fd->loop.n2);
9426 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9427 GSI_CONTINUE_LINKING);
9428 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9429 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9433 t = fold_convert (itype, s0);
9434 t = fold_build2 (MULT_EXPR, itype, t, step);
9435 if (POINTER_TYPE_P (type))
9436 t = fold_build_pointer_plus (n1, t);
9437 else
9438 t = fold_build2 (PLUS_EXPR, type, t, n1);
9439 t = fold_convert (TREE_TYPE (startvar), t);
9440 t = force_gimple_operand_gsi (&gsi, t,
9441 DECL_P (startvar)
9442 && TREE_ADDRESSABLE (startvar),
9443 NULL_TREE, false, GSI_CONTINUE_LINKING);
9444 assign_stmt = gimple_build_assign (startvar, t);
9445 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9447 t = fold_convert (itype, e0);
9448 t = fold_build2 (MULT_EXPR, itype, t, step);
9449 if (POINTER_TYPE_P (type))
9450 t = fold_build_pointer_plus (n1, t);
9451 else
9452 t = fold_build2 (PLUS_EXPR, type, t, n1);
9453 t = fold_convert (TREE_TYPE (startvar), t);
9454 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9455 false, GSI_CONTINUE_LINKING);
9456 if (endvar)
9458 assign_stmt = gimple_build_assign (endvar, e);
9459 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9460 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9461 assign_stmt = gimple_build_assign (fd->loop.v, e);
9462 else
9463 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9464 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9466 /* Handle linear clause adjustments. */
9467 tree itercnt = NULL_TREE;
9468 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9469 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9470 c; c = OMP_CLAUSE_CHAIN (c))
9471 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9472 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9474 tree d = OMP_CLAUSE_DECL (c);
9475 bool is_ref = is_reference (d);
9476 tree t = d, a, dest;
9477 if (is_ref)
9478 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9479 if (itercnt == NULL_TREE)
9481 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9483 itercnt = fold_build2 (MINUS_EXPR, itype,
9484 fold_convert (itype, n1),
9485 fold_convert (itype, fd->loop.n1));
9486 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9487 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9488 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9489 NULL_TREE, false,
9490 GSI_CONTINUE_LINKING);
9492 else
9493 itercnt = s0;
9495 tree type = TREE_TYPE (t);
9496 if (POINTER_TYPE_P (type))
9497 type = sizetype;
9498 a = fold_build2 (MULT_EXPR, type,
9499 fold_convert (type, itercnt),
9500 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9501 dest = unshare_expr (t);
9502 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9503 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9504 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9505 false, GSI_CONTINUE_LINKING);
9506 assign_stmt = gimple_build_assign (dest, t);
9507 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9509 if (fd->collapse > 1)
9510 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9512 if (!broken_loop)
9514 /* The code controlling the sequential loop replaces the
9515 GIMPLE_OMP_CONTINUE. */
9516 gsi = gsi_last_bb (cont_bb);
9517 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9518 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9519 vmain = gimple_omp_continue_control_use (cont_stmt);
9520 vback = gimple_omp_continue_control_def (cont_stmt);
9522 if (!gimple_omp_for_combined_p (fd->for_stmt))
9524 if (POINTER_TYPE_P (type))
9525 t = fold_build_pointer_plus (vmain, step);
9526 else
9527 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9528 t = force_gimple_operand_gsi (&gsi, t,
9529 DECL_P (vback)
9530 && TREE_ADDRESSABLE (vback),
9531 NULL_TREE, true, GSI_SAME_STMT);
9532 assign_stmt = gimple_build_assign (vback, t);
9533 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9535 t = build2 (fd->loop.cond_code, boolean_type_node,
9536 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9537 ? t : vback, e);
9538 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9541 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9542 gsi_remove (&gsi, true);
9544 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9545 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9548 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9549 gsi = gsi_last_bb (exit_bb);
9550 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9552 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9553 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9555 gsi_remove (&gsi, true);
9557 /* Connect all the blocks. */
9558 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9559 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9560 ep = find_edge (entry_bb, second_bb);
9561 ep->flags = EDGE_TRUE_VALUE;
9562 ep->probability = REG_BR_PROB_BASE / 4;
9563 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9564 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9566 if (!broken_loop)
9568 ep = find_edge (cont_bb, body_bb);
9569 if (ep == NULL)
9571 ep = BRANCH_EDGE (cont_bb);
9572 gcc_assert (single_succ (ep->dest) == body_bb);
9574 if (gimple_omp_for_combined_p (fd->for_stmt))
9576 remove_edge (ep);
9577 ep = NULL;
9579 else if (fd->collapse > 1)
9581 remove_edge (ep);
9582 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9584 else
9585 ep->flags = EDGE_TRUE_VALUE;
9586 find_edge (cont_bb, fin_bb)->flags
9587 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9590 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9591 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9592 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9594 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9595 recompute_dominator (CDI_DOMINATORS, body_bb));
9596 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9597 recompute_dominator (CDI_DOMINATORS, fin_bb));
9599 struct loop *loop = body_bb->loop_father;
9600 if (loop != entry_bb->loop_father)
9602 gcc_assert (loop->header == body_bb);
9603 gcc_assert (broken_loop
9604 || loop->latch == region->cont
9605 || single_pred (loop->latch) == region->cont);
9606 return;
9609 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9611 loop = alloc_loop ();
9612 loop->header = body_bb;
9613 if (collapse_bb == NULL)
9614 loop->latch = cont_bb;
9615 add_loop (loop, body_bb->loop_father);
9619 /* Return phi in E->DEST with ARG on edge E. */
9621 static gphi *
9622 find_phi_with_arg_on_edge (tree arg, edge e)
9624 basic_block bb = e->dest;
9626 for (gphi_iterator gpi = gsi_start_phis (bb);
9627 !gsi_end_p (gpi);
9628 gsi_next (&gpi))
9630 gphi *phi = gpi.phi ();
9631 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9632 return phi;
9635 return NULL;
9638 /* A subroutine of expand_omp_for. Generate code for a parallel
9639 loop with static schedule and a specified chunk size. Given
9640 parameters:
9642 for (V = N1; V cond N2; V += STEP) BODY;
9644 where COND is "<" or ">", we generate pseudocode
9646 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9647 if (cond is <)
9648 adj = STEP - 1;
9649 else
9650 adj = STEP + 1;
9651 if ((__typeof (V)) -1 > 0 && cond is >)
9652 n = -(adj + N2 - N1) / -STEP;
9653 else
9654 n = (adj + N2 - N1) / STEP;
9655 trip = 0;
9656 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9657 here so that V is defined
9658 if the loop is not entered
9660 s0 = (trip * nthreads + threadid) * CHUNK;
9661 e0 = min(s0 + CHUNK, n);
9662 if (s0 < n) goto L1; else goto L4;
9664 V = s0 * STEP + N1;
9665 e = e0 * STEP + N1;
9667 BODY;
9668 V += STEP;
9669 if (V cond e) goto L2; else goto L3;
9671 trip += 1;
9672 goto L0;
9676 static void
9677 expand_omp_for_static_chunk (struct omp_region *region,
9678 struct omp_for_data *fd, gimple *inner_stmt)
9680 tree n, s0, e0, e, t;
9681 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9682 tree type, itype, vmain, vback, vextra;
9683 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9684 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9685 gimple_stmt_iterator gsi;
9686 edge se;
9687 bool broken_loop = region->cont == NULL;
9688 tree *counts = NULL;
9689 tree n1, n2, step;
9691 itype = type = TREE_TYPE (fd->loop.v);
9692 if (POINTER_TYPE_P (type))
9693 itype = signed_type_for (type);
9695 entry_bb = region->entry;
9696 se = split_block (entry_bb, last_stmt (entry_bb));
9697 entry_bb = se->src;
9698 iter_part_bb = se->dest;
9699 cont_bb = region->cont;
9700 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9701 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9702 gcc_assert (broken_loop
9703 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9704 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9705 body_bb = single_succ (seq_start_bb);
9706 if (!broken_loop)
9708 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9709 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9710 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9711 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9713 exit_bb = region->exit;
9715 /* Trip and adjustment setup goes in ENTRY_BB. */
9716 gsi = gsi_last_bb (entry_bb);
9717 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9719 if (fd->collapse > 1)
9721 int first_zero_iter = -1, dummy = -1;
9722 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9724 counts = XALLOCAVEC (tree, fd->collapse);
9725 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9726 fin_bb, first_zero_iter,
9727 dummy_bb, dummy, l2_dom_bb);
9728 t = NULL_TREE;
9730 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9731 t = integer_one_node;
9732 else
9733 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9734 fold_convert (type, fd->loop.n1),
9735 fold_convert (type, fd->loop.n2));
9736 if (fd->collapse == 1
9737 && TYPE_UNSIGNED (type)
9738 && (t == NULL_TREE || !integer_onep (t)))
9740 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9741 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9742 true, GSI_SAME_STMT);
9743 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9744 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9745 true, GSI_SAME_STMT);
9746 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9747 NULL_TREE, NULL_TREE);
9748 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9749 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9750 expand_omp_regimplify_p, NULL, NULL)
9751 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9752 expand_omp_regimplify_p, NULL, NULL))
9754 gsi = gsi_for_stmt (cond_stmt);
9755 gimple_regimplify_operands (cond_stmt, &gsi);
9757 se = split_block (entry_bb, cond_stmt);
9758 se->flags = EDGE_TRUE_VALUE;
9759 entry_bb = se->dest;
9760 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9761 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9762 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9763 if (gimple_in_ssa_p (cfun))
9765 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9766 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9767 !gsi_end_p (gpi); gsi_next (&gpi))
9769 gphi *phi = gpi.phi ();
9770 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9771 se, UNKNOWN_LOCATION);
9774 gsi = gsi_last_bb (entry_bb);
9777 switch (gimple_omp_for_kind (fd->for_stmt))
9779 case GF_OMP_FOR_KIND_FOR:
9780 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9781 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9782 break;
9783 case GF_OMP_FOR_KIND_DISTRIBUTE:
9784 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9785 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9786 break;
9787 default:
9788 gcc_unreachable ();
9790 nthreads = build_call_expr (nthreads, 0);
9791 nthreads = fold_convert (itype, nthreads);
9792 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9793 true, GSI_SAME_STMT);
9794 threadid = build_call_expr (threadid, 0);
9795 threadid = fold_convert (itype, threadid);
9796 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9797 true, GSI_SAME_STMT);
9799 n1 = fd->loop.n1;
9800 n2 = fd->loop.n2;
9801 step = fd->loop.step;
9802 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9804 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9805 OMP_CLAUSE__LOOPTEMP_);
9806 gcc_assert (innerc);
9807 n1 = OMP_CLAUSE_DECL (innerc);
9808 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9809 OMP_CLAUSE__LOOPTEMP_);
9810 gcc_assert (innerc);
9811 n2 = OMP_CLAUSE_DECL (innerc);
9813 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9814 true, NULL_TREE, true, GSI_SAME_STMT);
9815 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9816 true, NULL_TREE, true, GSI_SAME_STMT);
9817 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9818 true, NULL_TREE, true, GSI_SAME_STMT);
9819 tree chunk_size = fold_convert (itype, fd->chunk_size);
9820 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9821 chunk_size
9822 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9823 GSI_SAME_STMT);
9825 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9826 t = fold_build2 (PLUS_EXPR, itype, step, t);
9827 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9828 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9829 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9830 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9831 fold_build1 (NEGATE_EXPR, itype, t),
9832 fold_build1 (NEGATE_EXPR, itype, step));
9833 else
9834 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9835 t = fold_convert (itype, t);
9836 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9837 true, GSI_SAME_STMT);
9839 trip_var = create_tmp_reg (itype, ".trip");
9840 if (gimple_in_ssa_p (cfun))
9842 trip_init = make_ssa_name (trip_var);
9843 trip_main = make_ssa_name (trip_var);
9844 trip_back = make_ssa_name (trip_var);
9846 else
9848 trip_init = trip_var;
9849 trip_main = trip_var;
9850 trip_back = trip_var;
9853 gassign *assign_stmt
9854 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9855 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9857 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9858 t = fold_build2 (MULT_EXPR, itype, t, step);
9859 if (POINTER_TYPE_P (type))
9860 t = fold_build_pointer_plus (n1, t);
9861 else
9862 t = fold_build2 (PLUS_EXPR, type, t, n1);
9863 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9864 true, GSI_SAME_STMT);
9866 /* Remove the GIMPLE_OMP_FOR. */
9867 gsi_remove (&gsi, true);
9869 gimple_stmt_iterator gsif = gsi;
9871 /* Iteration space partitioning goes in ITER_PART_BB. */
9872 gsi = gsi_last_bb (iter_part_bb);
9874 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9875 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9876 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9877 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9878 false, GSI_CONTINUE_LINKING);
9880 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9881 t = fold_build2 (MIN_EXPR, itype, t, n);
9882 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9883 false, GSI_CONTINUE_LINKING);
9885 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9886 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9888 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9889 gsi = gsi_start_bb (seq_start_bb);
9891 tree startvar = fd->loop.v;
9892 tree endvar = NULL_TREE;
9894 if (gimple_omp_for_combined_p (fd->for_stmt))
9896 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9897 ? gimple_omp_parallel_clauses (inner_stmt)
9898 : gimple_omp_for_clauses (inner_stmt);
9899 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9900 gcc_assert (innerc);
9901 startvar = OMP_CLAUSE_DECL (innerc);
9902 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9903 OMP_CLAUSE__LOOPTEMP_);
9904 gcc_assert (innerc);
9905 endvar = OMP_CLAUSE_DECL (innerc);
9906 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9907 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9909 int i;
9910 for (i = 1; i < fd->collapse; i++)
9912 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9913 OMP_CLAUSE__LOOPTEMP_);
9914 gcc_assert (innerc);
9916 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9917 OMP_CLAUSE__LOOPTEMP_);
9918 if (innerc)
9920 /* If needed (distribute parallel for with lastprivate),
9921 propagate down the total number of iterations. */
9922 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9923 fd->loop.n2);
9924 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9925 GSI_CONTINUE_LINKING);
9926 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9927 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9932 t = fold_convert (itype, s0);
9933 t = fold_build2 (MULT_EXPR, itype, t, step);
9934 if (POINTER_TYPE_P (type))
9935 t = fold_build_pointer_plus (n1, t);
9936 else
9937 t = fold_build2 (PLUS_EXPR, type, t, n1);
9938 t = fold_convert (TREE_TYPE (startvar), t);
9939 t = force_gimple_operand_gsi (&gsi, t,
9940 DECL_P (startvar)
9941 && TREE_ADDRESSABLE (startvar),
9942 NULL_TREE, false, GSI_CONTINUE_LINKING);
9943 assign_stmt = gimple_build_assign (startvar, t);
9944 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9946 t = fold_convert (itype, e0);
9947 t = fold_build2 (MULT_EXPR, itype, t, step);
9948 if (POINTER_TYPE_P (type))
9949 t = fold_build_pointer_plus (n1, t);
9950 else
9951 t = fold_build2 (PLUS_EXPR, type, t, n1);
9952 t = fold_convert (TREE_TYPE (startvar), t);
9953 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9954 false, GSI_CONTINUE_LINKING);
9955 if (endvar)
9957 assign_stmt = gimple_build_assign (endvar, e);
9958 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9959 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9960 assign_stmt = gimple_build_assign (fd->loop.v, e);
9961 else
9962 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9963 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965 /* Handle linear clause adjustments. */
9966 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9967 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9968 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9969 c; c = OMP_CLAUSE_CHAIN (c))
9970 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9971 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9973 tree d = OMP_CLAUSE_DECL (c);
9974 bool is_ref = is_reference (d);
9975 tree t = d, a, dest;
9976 if (is_ref)
9977 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9978 tree type = TREE_TYPE (t);
9979 if (POINTER_TYPE_P (type))
9980 type = sizetype;
9981 dest = unshare_expr (t);
9982 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9983 expand_omp_build_assign (&gsif, v, t);
9984 if (itercnt == NULL_TREE)
9986 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9988 itercntbias
9989 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9990 fold_convert (itype, fd->loop.n1));
9991 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9992 itercntbias, step);
9993 itercntbias
9994 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9995 NULL_TREE, true,
9996 GSI_SAME_STMT);
9997 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9998 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9999 NULL_TREE, false,
10000 GSI_CONTINUE_LINKING);
10002 else
10003 itercnt = s0;
10005 a = fold_build2 (MULT_EXPR, type,
10006 fold_convert (type, itercnt),
10007 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10008 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10009 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10010 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10011 false, GSI_CONTINUE_LINKING);
10012 assign_stmt = gimple_build_assign (dest, t);
10013 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10015 if (fd->collapse > 1)
10016 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10018 if (!broken_loop)
10020 /* The code controlling the sequential loop goes in CONT_BB,
10021 replacing the GIMPLE_OMP_CONTINUE. */
10022 gsi = gsi_last_bb (cont_bb);
10023 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10024 vmain = gimple_omp_continue_control_use (cont_stmt);
10025 vback = gimple_omp_continue_control_def (cont_stmt);
10027 if (!gimple_omp_for_combined_p (fd->for_stmt))
10029 if (POINTER_TYPE_P (type))
10030 t = fold_build_pointer_plus (vmain, step);
10031 else
10032 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10033 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10034 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10035 true, GSI_SAME_STMT);
10036 assign_stmt = gimple_build_assign (vback, t);
10037 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10039 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10040 t = build2 (EQ_EXPR, boolean_type_node,
10041 build_int_cst (itype, 0),
10042 build_int_cst (itype, 1));
10043 else
10044 t = build2 (fd->loop.cond_code, boolean_type_node,
10045 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10046 ? t : vback, e);
10047 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10050 /* Remove GIMPLE_OMP_CONTINUE. */
10051 gsi_remove (&gsi, true);
10053 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10054 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10056 /* Trip update code goes into TRIP_UPDATE_BB. */
10057 gsi = gsi_start_bb (trip_update_bb);
10059 t = build_int_cst (itype, 1);
10060 t = build2 (PLUS_EXPR, itype, trip_main, t);
10061 assign_stmt = gimple_build_assign (trip_back, t);
10062 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10065 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10066 gsi = gsi_last_bb (exit_bb);
10067 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10069 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10070 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10072 gsi_remove (&gsi, true);
10074 /* Connect the new blocks. */
10075 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10076 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10078 if (!broken_loop)
10080 se = find_edge (cont_bb, body_bb);
10081 if (se == NULL)
10083 se = BRANCH_EDGE (cont_bb);
10084 gcc_assert (single_succ (se->dest) == body_bb);
10086 if (gimple_omp_for_combined_p (fd->for_stmt))
10088 remove_edge (se);
10089 se = NULL;
10091 else if (fd->collapse > 1)
10093 remove_edge (se);
10094 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10096 else
10097 se->flags = EDGE_TRUE_VALUE;
10098 find_edge (cont_bb, trip_update_bb)->flags
10099 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10101 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10104 if (gimple_in_ssa_p (cfun))
10106 gphi_iterator psi;
10107 gphi *phi;
10108 edge re, ene;
10109 edge_var_map *vm;
10110 size_t i;
10112 gcc_assert (fd->collapse == 1 && !broken_loop);
10114 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10115 remove arguments of the phi nodes in fin_bb. We need to create
10116 appropriate phi nodes in iter_part_bb instead. */
10117 se = find_edge (iter_part_bb, fin_bb);
10118 re = single_succ_edge (trip_update_bb);
10119 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10120 ene = single_succ_edge (entry_bb);
10122 psi = gsi_start_phis (fin_bb);
10123 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10124 gsi_next (&psi), ++i)
10126 gphi *nphi;
10127 source_location locus;
10129 phi = psi.phi ();
10130 t = gimple_phi_result (phi);
10131 gcc_assert (t == redirect_edge_var_map_result (vm));
10133 if (!single_pred_p (fin_bb))
10134 t = copy_ssa_name (t, phi);
10136 nphi = create_phi_node (t, iter_part_bb);
10138 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10139 locus = gimple_phi_arg_location_from_edge (phi, se);
10141 /* A special case -- fd->loop.v is not yet computed in
10142 iter_part_bb, we need to use vextra instead. */
10143 if (t == fd->loop.v)
10144 t = vextra;
10145 add_phi_arg (nphi, t, ene, locus);
10146 locus = redirect_edge_var_map_location (vm);
10147 tree back_arg = redirect_edge_var_map_def (vm);
10148 add_phi_arg (nphi, back_arg, re, locus);
10149 edge ce = find_edge (cont_bb, body_bb);
10150 if (ce == NULL)
10152 ce = BRANCH_EDGE (cont_bb);
10153 gcc_assert (single_succ (ce->dest) == body_bb);
10154 ce = single_succ_edge (ce->dest);
10156 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10157 gcc_assert (inner_loop_phi != NULL);
10158 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10159 find_edge (seq_start_bb, body_bb), locus);
10161 if (!single_pred_p (fin_bb))
10162 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10164 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10165 redirect_edge_var_map_clear (re);
10166 if (single_pred_p (fin_bb))
10167 while (1)
10169 psi = gsi_start_phis (fin_bb);
10170 if (gsi_end_p (psi))
10171 break;
10172 remove_phi_node (&psi, false);
10175 /* Make phi node for trip. */
10176 phi = create_phi_node (trip_main, iter_part_bb);
10177 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10178 UNKNOWN_LOCATION);
10179 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10180 UNKNOWN_LOCATION);
10183 if (!broken_loop)
10184 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10185 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10186 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10187 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10188 recompute_dominator (CDI_DOMINATORS, fin_bb));
10189 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10190 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10191 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10192 recompute_dominator (CDI_DOMINATORS, body_bb));
10194 if (!broken_loop)
10196 struct loop *loop = body_bb->loop_father;
10197 struct loop *trip_loop = alloc_loop ();
10198 trip_loop->header = iter_part_bb;
10199 trip_loop->latch = trip_update_bb;
10200 add_loop (trip_loop, iter_part_bb->loop_father);
10202 if (loop != entry_bb->loop_father)
10204 gcc_assert (loop->header == body_bb);
10205 gcc_assert (loop->latch == region->cont
10206 || single_pred (loop->latch) == region->cont);
10207 trip_loop->inner = loop;
10208 return;
10211 if (!gimple_omp_for_combined_p (fd->for_stmt))
10213 loop = alloc_loop ();
10214 loop->header = body_bb;
10215 if (collapse_bb == NULL)
10216 loop->latch = cont_bb;
10217 add_loop (loop, trip_loop);
10222 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10223 Given parameters:
10224 for (V = N1; V cond N2; V += STEP) BODY;
10226 where COND is "<" or ">" or "!=", we generate pseudocode
10228 for (ind_var = low; ind_var < high; ind_var++)
10230 V = n1 + (ind_var * STEP)
10232 <BODY>
10235 In the above pseudocode, low and high are function parameters of the
10236 child function. In the function below, we are inserting a temp.
10237 variable that will be making a call to two OMP functions that will not be
10238 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10239 with _Cilk_for). These functions are replaced with low and high
10240 by the function that handles taskreg. */
10243 static void
10244 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10246 bool broken_loop = region->cont == NULL;
10247 basic_block entry_bb = region->entry;
10248 basic_block cont_bb = region->cont;
10250 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10251 gcc_assert (broken_loop
10252 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10253 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10254 basic_block l1_bb, l2_bb;
10256 if (!broken_loop)
10258 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10259 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10260 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10261 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10263 else
10265 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10266 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10267 l2_bb = single_succ (l1_bb);
10269 basic_block exit_bb = region->exit;
10270 basic_block l2_dom_bb = NULL;
10272 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10274 /* Below statements until the "tree high_val = ..." are pseudo statements
10275 used to pass information to be used by expand_omp_taskreg.
10276 low_val and high_val will be replaced by the __low and __high
10277 parameter from the child function.
10279 The call_exprs part is a place-holder, it is mainly used
10280 to distinctly identify to the top-level part that this is
10281 where we should put low and high (reasoning given in header
10282 comment). */
10284 tree child_fndecl
10285 = gimple_omp_parallel_child_fn (
10286 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10287 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10288 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10290 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10291 high_val = t;
10292 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10293 low_val = t;
10295 gcc_assert (low_val && high_val);
10297 tree type = TREE_TYPE (low_val);
10298 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10299 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10301 /* Not needed in SSA form right now. */
10302 gcc_assert (!gimple_in_ssa_p (cfun));
10303 if (l2_dom_bb == NULL)
10304 l2_dom_bb = l1_bb;
10306 tree n1 = low_val;
10307 tree n2 = high_val;
10309 gimple *stmt = gimple_build_assign (ind_var, n1);
10311 /* Replace the GIMPLE_OMP_FOR statement. */
10312 gsi_replace (&gsi, stmt, true);
10314 if (!broken_loop)
10316 /* Code to control the increment goes in the CONT_BB. */
10317 gsi = gsi_last_bb (cont_bb);
10318 stmt = gsi_stmt (gsi);
10319 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10320 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10321 build_one_cst (type));
10323 /* Replace GIMPLE_OMP_CONTINUE. */
10324 gsi_replace (&gsi, stmt, true);
10327 /* Emit the condition in L1_BB. */
10328 gsi = gsi_after_labels (l1_bb);
10329 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10330 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10331 fd->loop.step);
10332 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10333 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10334 fd->loop.n1, fold_convert (sizetype, t));
10335 else
10336 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10337 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10338 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10339 expand_omp_build_assign (&gsi, fd->loop.v, t);
10341 /* The condition is always '<' since the runtime will fill in the low
10342 and high values. */
10343 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10344 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10346 /* Remove GIMPLE_OMP_RETURN. */
10347 gsi = gsi_last_bb (exit_bb);
10348 gsi_remove (&gsi, true);
10350 /* Connect the new blocks. */
10351 remove_edge (FALLTHRU_EDGE (entry_bb));
10353 edge e, ne;
10354 if (!broken_loop)
10356 remove_edge (BRANCH_EDGE (entry_bb));
10357 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10359 e = BRANCH_EDGE (l1_bb);
10360 ne = FALLTHRU_EDGE (l1_bb);
10361 e->flags = EDGE_TRUE_VALUE;
10363 else
10365 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10367 ne = single_succ_edge (l1_bb);
10368 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10371 ne->flags = EDGE_FALSE_VALUE;
10372 e->probability = REG_BR_PROB_BASE * 7 / 8;
10373 ne->probability = REG_BR_PROB_BASE / 8;
10375 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10376 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10377 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10379 if (!broken_loop)
10381 struct loop *loop = alloc_loop ();
10382 loop->header = l1_bb;
10383 loop->latch = cont_bb;
10384 add_loop (loop, l1_bb->loop_father);
10385 loop->safelen = INT_MAX;
10388 /* Pick the correct library function based on the precision of the
10389 induction variable type. */
10390 tree lib_fun = NULL_TREE;
10391 if (TYPE_PRECISION (type) == 32)
10392 lib_fun = cilk_for_32_fndecl;
10393 else if (TYPE_PRECISION (type) == 64)
10394 lib_fun = cilk_for_64_fndecl;
10395 else
10396 gcc_unreachable ();
10398 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10400 /* WS_ARGS contains the library function flavor to call:
10401 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10402 user-defined grain value. If the user does not define one, then zero
10403 is passed in by the parser. */
10404 vec_alloc (region->ws_args, 2);
10405 region->ws_args->quick_push (lib_fun);
10406 region->ws_args->quick_push (fd->chunk_size);
10409 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10410 loop. Given parameters:
10412 for (V = N1; V cond N2; V += STEP) BODY;
10414 where COND is "<" or ">", we generate pseudocode
10416 V = N1;
10417 goto L1;
10419 BODY;
10420 V += STEP;
10422 if (V cond N2) goto L0; else goto L2;
10425 For collapsed loops, given parameters:
10426 collapse(3)
10427 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10428 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10429 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10430 BODY;
10432 we generate pseudocode
10434 if (cond3 is <)
10435 adj = STEP3 - 1;
10436 else
10437 adj = STEP3 + 1;
10438 count3 = (adj + N32 - N31) / STEP3;
10439 if (cond2 is <)
10440 adj = STEP2 - 1;
10441 else
10442 adj = STEP2 + 1;
10443 count2 = (adj + N22 - N21) / STEP2;
10444 if (cond1 is <)
10445 adj = STEP1 - 1;
10446 else
10447 adj = STEP1 + 1;
10448 count1 = (adj + N12 - N11) / STEP1;
10449 count = count1 * count2 * count3;
10450 V = 0;
10451 V1 = N11;
10452 V2 = N21;
10453 V3 = N31;
10454 goto L1;
10456 BODY;
10457 V += 1;
10458 V3 += STEP3;
10459 V2 += (V3 cond3 N32) ? 0 : STEP2;
10460 V3 = (V3 cond3 N32) ? V3 : N31;
10461 V1 += (V2 cond2 N22) ? 0 : STEP1;
10462 V2 = (V2 cond2 N22) ? V2 : N21;
10464 if (V < count) goto L0; else goto L2;
10469 static void
10470 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10472 tree type, t;
10473 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10474 gimple_stmt_iterator gsi;
10475 gimple *stmt;
10476 gcond *cond_stmt;
10477 bool broken_loop = region->cont == NULL;
10478 edge e, ne;
10479 tree *counts = NULL;
10480 int i;
10481 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10482 OMP_CLAUSE_SAFELEN);
10483 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10484 OMP_CLAUSE__SIMDUID_);
10485 tree n1, n2;
10487 type = TREE_TYPE (fd->loop.v);
10488 entry_bb = region->entry;
10489 cont_bb = region->cont;
10490 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10491 gcc_assert (broken_loop
10492 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10493 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10494 if (!broken_loop)
10496 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10497 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10498 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10499 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10501 else
10503 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10504 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10505 l2_bb = single_succ (l1_bb);
10507 exit_bb = region->exit;
10508 l2_dom_bb = NULL;
10510 gsi = gsi_last_bb (entry_bb);
10512 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10513 /* Not needed in SSA form right now. */
10514 gcc_assert (!gimple_in_ssa_p (cfun));
10515 if (fd->collapse > 1)
10517 int first_zero_iter = -1, dummy = -1;
10518 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10520 counts = XALLOCAVEC (tree, fd->collapse);
10521 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10522 zero_iter_bb, first_zero_iter,
10523 dummy_bb, dummy, l2_dom_bb);
10525 if (l2_dom_bb == NULL)
10526 l2_dom_bb = l1_bb;
10528 n1 = fd->loop.n1;
10529 n2 = fd->loop.n2;
10530 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10532 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10533 OMP_CLAUSE__LOOPTEMP_);
10534 gcc_assert (innerc);
10535 n1 = OMP_CLAUSE_DECL (innerc);
10536 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10537 OMP_CLAUSE__LOOPTEMP_);
10538 gcc_assert (innerc);
10539 n2 = OMP_CLAUSE_DECL (innerc);
10540 expand_omp_build_assign (&gsi, fd->loop.v,
10541 fold_convert (type, n1));
10542 if (fd->collapse > 1)
10544 gsi_prev (&gsi);
10545 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10546 gsi_next (&gsi);
10549 else
10551 expand_omp_build_assign (&gsi, fd->loop.v,
10552 fold_convert (type, fd->loop.n1));
10553 if (fd->collapse > 1)
10554 for (i = 0; i < fd->collapse; i++)
10556 tree itype = TREE_TYPE (fd->loops[i].v);
10557 if (POINTER_TYPE_P (itype))
10558 itype = signed_type_for (itype);
10559 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10560 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10564 /* Remove the GIMPLE_OMP_FOR statement. */
10565 gsi_remove (&gsi, true);
10567 if (!broken_loop)
10569 /* Code to control the increment goes in the CONT_BB. */
10570 gsi = gsi_last_bb (cont_bb);
10571 stmt = gsi_stmt (gsi);
10572 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10574 if (POINTER_TYPE_P (type))
10575 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10576 else
10577 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10578 expand_omp_build_assign (&gsi, fd->loop.v, t);
10580 if (fd->collapse > 1)
10582 i = fd->collapse - 1;
10583 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10585 t = fold_convert (sizetype, fd->loops[i].step);
10586 t = fold_build_pointer_plus (fd->loops[i].v, t);
10588 else
10590 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10591 fd->loops[i].step);
10592 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10593 fd->loops[i].v, t);
10595 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10597 for (i = fd->collapse - 1; i > 0; i--)
10599 tree itype = TREE_TYPE (fd->loops[i].v);
10600 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10601 if (POINTER_TYPE_P (itype2))
10602 itype2 = signed_type_for (itype2);
10603 t = build3 (COND_EXPR, itype2,
10604 build2 (fd->loops[i].cond_code, boolean_type_node,
10605 fd->loops[i].v,
10606 fold_convert (itype, fd->loops[i].n2)),
10607 build_int_cst (itype2, 0),
10608 fold_convert (itype2, fd->loops[i - 1].step));
10609 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10610 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10611 else
10612 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10613 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10615 t = build3 (COND_EXPR, itype,
10616 build2 (fd->loops[i].cond_code, boolean_type_node,
10617 fd->loops[i].v,
10618 fold_convert (itype, fd->loops[i].n2)),
10619 fd->loops[i].v,
10620 fold_convert (itype, fd->loops[i].n1));
10621 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10625 /* Remove GIMPLE_OMP_CONTINUE. */
10626 gsi_remove (&gsi, true);
10629 /* Emit the condition in L1_BB. */
10630 gsi = gsi_start_bb (l1_bb);
10632 t = fold_convert (type, n2);
10633 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10634 false, GSI_CONTINUE_LINKING);
10635 tree v = fd->loop.v;
10636 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10637 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10638 false, GSI_CONTINUE_LINKING);
10639 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10640 cond_stmt = gimple_build_cond_empty (t);
10641 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10642 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10643 NULL, NULL)
10644 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10645 NULL, NULL))
10647 gsi = gsi_for_stmt (cond_stmt);
10648 gimple_regimplify_operands (cond_stmt, &gsi);
10651 /* Remove GIMPLE_OMP_RETURN. */
10652 gsi = gsi_last_bb (exit_bb);
10653 gsi_remove (&gsi, true);
10655 /* Connect the new blocks. */
10656 remove_edge (FALLTHRU_EDGE (entry_bb));
10658 if (!broken_loop)
10660 remove_edge (BRANCH_EDGE (entry_bb));
10661 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10663 e = BRANCH_EDGE (l1_bb);
10664 ne = FALLTHRU_EDGE (l1_bb);
10665 e->flags = EDGE_TRUE_VALUE;
10667 else
10669 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10671 ne = single_succ_edge (l1_bb);
10672 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10675 ne->flags = EDGE_FALSE_VALUE;
10676 e->probability = REG_BR_PROB_BASE * 7 / 8;
10677 ne->probability = REG_BR_PROB_BASE / 8;
10679 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10680 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10681 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10683 if (!broken_loop)
10685 struct loop *loop = alloc_loop ();
10686 loop->header = l1_bb;
10687 loop->latch = cont_bb;
10688 add_loop (loop, l1_bb->loop_father);
10689 if (safelen == NULL_TREE)
10690 loop->safelen = INT_MAX;
10691 else
10693 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10694 if (TREE_CODE (safelen) != INTEGER_CST)
10695 loop->safelen = 0;
10696 else if (!tree_fits_uhwi_p (safelen)
10697 || tree_to_uhwi (safelen) > INT_MAX)
10698 loop->safelen = INT_MAX;
10699 else
10700 loop->safelen = tree_to_uhwi (safelen);
10701 if (loop->safelen == 1)
10702 loop->safelen = 0;
10704 if (simduid)
10706 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10707 cfun->has_simduid_loops = true;
10709 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10710 the loop. */
10711 if ((flag_tree_loop_vectorize
10712 || (!global_options_set.x_flag_tree_loop_vectorize
10713 && !global_options_set.x_flag_tree_vectorize))
10714 && flag_tree_loop_optimize
10715 && loop->safelen > 1)
10717 loop->force_vectorize = true;
10718 cfun->has_force_vectorize_loops = true;
10721 else if (simduid)
10722 cfun->has_simduid_loops = true;
10725 /* Taskloop construct is represented after gimplification with
10726 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10727 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10728 which should just compute all the needed loop temporaries
10729 for GIMPLE_OMP_TASK. */
10731 static void
10732 expand_omp_taskloop_for_outer (struct omp_region *region,
10733 struct omp_for_data *fd,
10734 gimple *inner_stmt)
10736 tree type, bias = NULL_TREE;
10737 basic_block entry_bb, cont_bb, exit_bb;
10738 gimple_stmt_iterator gsi;
10739 gassign *assign_stmt;
10740 tree *counts = NULL;
10741 int i;
10743 gcc_assert (inner_stmt);
10744 gcc_assert (region->cont);
10745 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10746 && gimple_omp_task_taskloop_p (inner_stmt));
10747 type = TREE_TYPE (fd->loop.v);
10749 /* See if we need to bias by LLONG_MIN. */
10750 if (fd->iter_type == long_long_unsigned_type_node
10751 && TREE_CODE (type) == INTEGER_TYPE
10752 && !TYPE_UNSIGNED (type))
10754 tree n1, n2;
10756 if (fd->loop.cond_code == LT_EXPR)
10758 n1 = fd->loop.n1;
10759 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10761 else
10763 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10764 n2 = fd->loop.n1;
10766 if (TREE_CODE (n1) != INTEGER_CST
10767 || TREE_CODE (n2) != INTEGER_CST
10768 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10769 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10772 entry_bb = region->entry;
10773 cont_bb = region->cont;
10774 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10775 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10776 exit_bb = region->exit;
10778 gsi = gsi_last_bb (entry_bb);
10779 gimple *for_stmt = gsi_stmt (gsi);
10780 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10781 if (fd->collapse > 1)
10783 int first_zero_iter = -1, dummy = -1;
10784 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10786 counts = XALLOCAVEC (tree, fd->collapse);
10787 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10788 zero_iter_bb, first_zero_iter,
10789 dummy_bb, dummy, l2_dom_bb);
10791 if (zero_iter_bb)
10793 /* Some counts[i] vars might be uninitialized if
10794 some loop has zero iterations. But the body shouldn't
10795 be executed in that case, so just avoid uninit warnings. */
10796 for (i = first_zero_iter; i < fd->collapse; i++)
10797 if (SSA_VAR_P (counts[i]))
10798 TREE_NO_WARNING (counts[i]) = 1;
10799 gsi_prev (&gsi);
10800 edge e = split_block (entry_bb, gsi_stmt (gsi));
10801 entry_bb = e->dest;
10802 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10803 gsi = gsi_last_bb (entry_bb);
10804 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10805 get_immediate_dominator (CDI_DOMINATORS,
10806 zero_iter_bb));
10810 tree t0, t1;
10811 t1 = fd->loop.n2;
10812 t0 = fd->loop.n1;
10813 if (POINTER_TYPE_P (TREE_TYPE (t0))
10814 && TYPE_PRECISION (TREE_TYPE (t0))
10815 != TYPE_PRECISION (fd->iter_type))
10817 /* Avoid casting pointers to integer of a different size. */
10818 tree itype = signed_type_for (type);
10819 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10820 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10822 else
10824 t1 = fold_convert (fd->iter_type, t1);
10825 t0 = fold_convert (fd->iter_type, t0);
10827 if (bias)
10829 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10830 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10833 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10834 OMP_CLAUSE__LOOPTEMP_);
10835 gcc_assert (innerc);
10836 tree startvar = OMP_CLAUSE_DECL (innerc);
10837 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10838 gcc_assert (innerc);
10839 tree endvar = OMP_CLAUSE_DECL (innerc);
10840 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10842 gcc_assert (innerc);
10843 for (i = 1; i < fd->collapse; i++)
10845 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10846 OMP_CLAUSE__LOOPTEMP_);
10847 gcc_assert (innerc);
10849 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10850 OMP_CLAUSE__LOOPTEMP_);
10851 if (innerc)
10853 /* If needed (inner taskloop has lastprivate clause), propagate
10854 down the total number of iterations. */
10855 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10856 NULL_TREE, false,
10857 GSI_CONTINUE_LINKING);
10858 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10859 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10863 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10864 GSI_CONTINUE_LINKING);
10865 assign_stmt = gimple_build_assign (startvar, t0);
10866 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10868 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10869 GSI_CONTINUE_LINKING);
10870 assign_stmt = gimple_build_assign (endvar, t1);
10871 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10872 if (fd->collapse > 1)
10873 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10875 /* Remove the GIMPLE_OMP_FOR statement. */
10876 gsi = gsi_for_stmt (for_stmt);
10877 gsi_remove (&gsi, true);
10879 gsi = gsi_last_bb (cont_bb);
10880 gsi_remove (&gsi, true);
10882 gsi = gsi_last_bb (exit_bb);
10883 gsi_remove (&gsi, true);
10885 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10886 remove_edge (BRANCH_EDGE (entry_bb));
10887 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10888 remove_edge (BRANCH_EDGE (cont_bb));
10889 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10890 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10891 recompute_dominator (CDI_DOMINATORS, region->entry));
10894 /* Taskloop construct is represented after gimplification with
10895 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10896 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10897 GOMP_taskloop{,_ull} function arranges for each task to be given just
10898 a single range of iterations. */
10900 static void
10901 expand_omp_taskloop_for_inner (struct omp_region *region,
10902 struct omp_for_data *fd,
10903 gimple *inner_stmt)
10905 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10906 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10907 basic_block fin_bb;
10908 gimple_stmt_iterator gsi;
10909 edge ep;
10910 bool broken_loop = region->cont == NULL;
10911 tree *counts = NULL;
10912 tree n1, n2, step;
10914 itype = type = TREE_TYPE (fd->loop.v);
10915 if (POINTER_TYPE_P (type))
10916 itype = signed_type_for (type);
10918 /* See if we need to bias by LLONG_MIN. */
10919 if (fd->iter_type == long_long_unsigned_type_node
10920 && TREE_CODE (type) == INTEGER_TYPE
10921 && !TYPE_UNSIGNED (type))
10923 tree n1, n2;
10925 if (fd->loop.cond_code == LT_EXPR)
10927 n1 = fd->loop.n1;
10928 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10930 else
10932 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10933 n2 = fd->loop.n1;
10935 if (TREE_CODE (n1) != INTEGER_CST
10936 || TREE_CODE (n2) != INTEGER_CST
10937 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10938 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10941 entry_bb = region->entry;
10942 cont_bb = region->cont;
10943 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10944 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10945 gcc_assert (broken_loop
10946 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10947 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10948 if (!broken_loop)
10950 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10951 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10953 exit_bb = region->exit;
10955 /* Iteration space partitioning goes in ENTRY_BB. */
10956 gsi = gsi_last_bb (entry_bb);
10957 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10959 if (fd->collapse > 1)
10961 int first_zero_iter = -1, dummy = -1;
10962 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10964 counts = XALLOCAVEC (tree, fd->collapse);
10965 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10966 fin_bb, first_zero_iter,
10967 dummy_bb, dummy, l2_dom_bb);
10968 t = NULL_TREE;
10970 else
10971 t = integer_one_node;
10973 step = fd->loop.step;
10974 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10975 OMP_CLAUSE__LOOPTEMP_);
10976 gcc_assert (innerc);
10977 n1 = OMP_CLAUSE_DECL (innerc);
10978 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10979 gcc_assert (innerc);
10980 n2 = OMP_CLAUSE_DECL (innerc);
10981 if (bias)
10983 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10984 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10986 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10987 true, NULL_TREE, true, GSI_SAME_STMT);
10988 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10989 true, NULL_TREE, true, GSI_SAME_STMT);
10990 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10991 true, NULL_TREE, true, GSI_SAME_STMT);
10993 tree startvar = fd->loop.v;
10994 tree endvar = NULL_TREE;
10996 if (gimple_omp_for_combined_p (fd->for_stmt))
10998 tree clauses = gimple_omp_for_clauses (inner_stmt);
10999 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11000 gcc_assert (innerc);
11001 startvar = OMP_CLAUSE_DECL (innerc);
11002 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11003 OMP_CLAUSE__LOOPTEMP_);
11004 gcc_assert (innerc);
11005 endvar = OMP_CLAUSE_DECL (innerc);
11007 t = fold_convert (TREE_TYPE (startvar), n1);
11008 t = force_gimple_operand_gsi (&gsi, t,
11009 DECL_P (startvar)
11010 && TREE_ADDRESSABLE (startvar),
11011 NULL_TREE, false, GSI_CONTINUE_LINKING);
11012 gimple *assign_stmt = gimple_build_assign (startvar, t);
11013 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11015 t = fold_convert (TREE_TYPE (startvar), n2);
11016 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11017 false, GSI_CONTINUE_LINKING);
11018 if (endvar)
11020 assign_stmt = gimple_build_assign (endvar, e);
11021 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11022 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11023 assign_stmt = gimple_build_assign (fd->loop.v, e);
11024 else
11025 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11026 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11028 if (fd->collapse > 1)
11029 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11031 if (!broken_loop)
11033 /* The code controlling the sequential loop replaces the
11034 GIMPLE_OMP_CONTINUE. */
11035 gsi = gsi_last_bb (cont_bb);
11036 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11037 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11038 vmain = gimple_omp_continue_control_use (cont_stmt);
11039 vback = gimple_omp_continue_control_def (cont_stmt);
11041 if (!gimple_omp_for_combined_p (fd->for_stmt))
11043 if (POINTER_TYPE_P (type))
11044 t = fold_build_pointer_plus (vmain, step);
11045 else
11046 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11047 t = force_gimple_operand_gsi (&gsi, t,
11048 DECL_P (vback)
11049 && TREE_ADDRESSABLE (vback),
11050 NULL_TREE, true, GSI_SAME_STMT);
11051 assign_stmt = gimple_build_assign (vback, t);
11052 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11054 t = build2 (fd->loop.cond_code, boolean_type_node,
11055 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11056 ? t : vback, e);
11057 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11060 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11061 gsi_remove (&gsi, true);
11063 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11064 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11067 /* Remove the GIMPLE_OMP_FOR statement. */
11068 gsi = gsi_for_stmt (fd->for_stmt);
11069 gsi_remove (&gsi, true);
11071 /* Remove the GIMPLE_OMP_RETURN statement. */
11072 gsi = gsi_last_bb (exit_bb);
11073 gsi_remove (&gsi, true);
11075 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11076 if (!broken_loop)
11077 remove_edge (BRANCH_EDGE (entry_bb));
11078 else
11080 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11081 region->outer->cont = NULL;
11084 /* Connect all the blocks. */
11085 if (!broken_loop)
11087 ep = find_edge (cont_bb, body_bb);
11088 if (gimple_omp_for_combined_p (fd->for_stmt))
11090 remove_edge (ep);
11091 ep = NULL;
11093 else if (fd->collapse > 1)
11095 remove_edge (ep);
11096 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11098 else
11099 ep->flags = EDGE_TRUE_VALUE;
11100 find_edge (cont_bb, fin_bb)->flags
11101 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11104 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11105 recompute_dominator (CDI_DOMINATORS, body_bb));
11106 if (!broken_loop)
11107 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11108 recompute_dominator (CDI_DOMINATORS, fin_bb));
11110 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11112 struct loop *loop = alloc_loop ();
11113 loop->header = body_bb;
11114 if (collapse_bb == NULL)
11115 loop->latch = cont_bb;
11116 add_loop (loop, body_bb->loop_father);
11120 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11121 partitioned loop. The lowering here is abstracted, in that the
11122 loop parameters are passed through internal functions, which are
11123 further lowered by oacc_device_lower, once we get to the target
11124 compiler. The loop is of the form:
11126 for (V = B; V LTGT E; V += S) {BODY}
11128 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11129 (constant 0 for no chunking) and we will have a GWV partitioning
11130 mask, specifying dimensions over which the loop is to be
11131 partitioned (see note below). We generate code that looks like:
11133 <entry_bb> [incoming FALL->body, BRANCH->exit]
11134 typedef signedintify (typeof (V)) T; // underlying signed integral type
11135 T range = E - B;
11136 T chunk_no = 0;
11137 T DIR = LTGT == '<' ? +1 : -1;
11138 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11139 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11141 <head_bb> [created by splitting end of entry_bb]
11142 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11143 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11144 if (!(offset LTGT bound)) goto bottom_bb;
11146 <body_bb> [incoming]
11147 V = B + offset;
11148 {BODY}
11150 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11151 offset += step;
11152 if (offset LTGT bound) goto body_bb; [*]
11154 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11155 chunk_no++;
11156 if (chunk < chunk_max) goto head_bb;
11158 <exit_bb> [incoming]
11159 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11161 [*] Needed if V live at end of loop
11163 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11164 transition, and will be specified by a more general mechanism shortly.
11167 static void
11168 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11170 tree v = fd->loop.v;
11171 enum tree_code cond_code = fd->loop.cond_code;
11172 enum tree_code plus_code = PLUS_EXPR;
11174 tree chunk_size = integer_minus_one_node;
11175 tree gwv = integer_zero_node;
11176 tree iter_type = TREE_TYPE (v);
11177 tree diff_type = iter_type;
11178 tree plus_type = iter_type;
11179 struct oacc_collapse *counts = NULL;
11181 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11182 == GF_OMP_FOR_KIND_OACC_LOOP);
11183 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11184 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11186 if (POINTER_TYPE_P (iter_type))
11188 plus_code = POINTER_PLUS_EXPR;
11189 plus_type = sizetype;
11191 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11192 diff_type = signed_type_for (diff_type);
11194 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11195 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11196 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11197 basic_block bottom_bb = NULL;
11199 /* entry_bb has two sucessors; the branch edge is to the exit
11200 block, fallthrough edge to body. */
11201 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11202 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11204 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11205 body_bb, or to a block whose only successor is the body_bb. Its
11206 fallthrough successor is the final block (same as the branch
11207 successor of the entry_bb). */
11208 if (cont_bb)
11210 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11211 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11213 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11214 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11216 else
11217 gcc_assert (!gimple_in_ssa_p (cfun));
11219 /* The exit block only has entry_bb and cont_bb as predecessors. */
11220 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11222 tree chunk_no;
11223 tree chunk_max = NULL_TREE;
11224 tree bound, offset;
11225 tree step = create_tmp_var (diff_type, ".step");
11226 bool up = cond_code == LT_EXPR;
11227 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11228 bool chunking = !gimple_in_ssa_p (cfun);;
11229 bool negating;
11231 /* SSA instances. */
11232 tree offset_incr = NULL_TREE;
11233 tree offset_init = NULL_TREE;
11235 gimple_stmt_iterator gsi;
11236 gassign *ass;
11237 gcall *call;
11238 gimple *stmt;
11239 tree expr;
11240 location_t loc;
11241 edge split, be, fte;
11243 /* Split the end of entry_bb to create head_bb. */
11244 split = split_block (entry_bb, last_stmt (entry_bb));
11245 basic_block head_bb = split->dest;
11246 entry_bb = split->src;
11248 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11249 gsi = gsi_last_bb (entry_bb);
11250 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11251 loc = gimple_location (for_stmt);
11253 if (gimple_in_ssa_p (cfun))
11255 offset_init = gimple_omp_for_index (for_stmt, 0);
11256 gcc_assert (integer_zerop (fd->loop.n1));
11257 /* The SSA parallelizer does gang parallelism. */
11258 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11261 if (fd->collapse > 1)
11263 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11264 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11265 TREE_TYPE (fd->loop.n2));
11267 if (SSA_VAR_P (fd->loop.n2))
11269 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11270 true, GSI_SAME_STMT);
11271 ass = gimple_build_assign (fd->loop.n2, total);
11272 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11277 tree b = fd->loop.n1;
11278 tree e = fd->loop.n2;
11279 tree s = fd->loop.step;
11281 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11282 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11284 /* Convert the step, avoiding possible unsigned->signed overflow. */
11285 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11286 if (negating)
11287 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11288 s = fold_convert (diff_type, s);
11289 if (negating)
11290 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11291 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11293 if (!chunking)
11294 chunk_size = integer_zero_node;
11295 expr = fold_convert (diff_type, chunk_size);
11296 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11297 NULL_TREE, true, GSI_SAME_STMT);
11298 /* Determine the range, avoiding possible unsigned->signed overflow. */
11299 negating = !up && TYPE_UNSIGNED (iter_type);
11300 expr = fold_build2 (MINUS_EXPR, plus_type,
11301 fold_convert (plus_type, negating ? b : e),
11302 fold_convert (plus_type, negating ? e : b));
11303 expr = fold_convert (diff_type, expr);
11304 if (negating)
11305 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11306 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11307 NULL_TREE, true, GSI_SAME_STMT);
11309 chunk_no = build_int_cst (diff_type, 0);
11310 if (chunking)
11312 gcc_assert (!gimple_in_ssa_p (cfun));
11314 expr = chunk_no;
11315 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11316 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11318 ass = gimple_build_assign (chunk_no, expr);
11319 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11321 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11322 build_int_cst (integer_type_node,
11323 IFN_GOACC_LOOP_CHUNKS),
11324 dir, range, s, chunk_size, gwv);
11325 gimple_call_set_lhs (call, chunk_max);
11326 gimple_set_location (call, loc);
11327 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11329 else
11330 chunk_size = chunk_no;
11332 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11333 build_int_cst (integer_type_node,
11334 IFN_GOACC_LOOP_STEP),
11335 dir, range, s, chunk_size, gwv);
11336 gimple_call_set_lhs (call, step);
11337 gimple_set_location (call, loc);
11338 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11340 /* Remove the GIMPLE_OMP_FOR. */
11341 gsi_remove (&gsi, true);
11343 /* Fixup edges from head_bb */
11344 be = BRANCH_EDGE (head_bb);
11345 fte = FALLTHRU_EDGE (head_bb);
11346 be->flags |= EDGE_FALSE_VALUE;
11347 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11349 basic_block body_bb = fte->dest;
11351 if (gimple_in_ssa_p (cfun))
11353 gsi = gsi_last_bb (cont_bb);
11354 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11356 offset = gimple_omp_continue_control_use (cont_stmt);
11357 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11359 else
11361 offset = create_tmp_var (diff_type, ".offset");
11362 offset_init = offset_incr = offset;
11364 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11366 /* Loop offset & bound go into head_bb. */
11367 gsi = gsi_start_bb (head_bb);
11369 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11370 build_int_cst (integer_type_node,
11371 IFN_GOACC_LOOP_OFFSET),
11372 dir, range, s,
11373 chunk_size, gwv, chunk_no);
11374 gimple_call_set_lhs (call, offset_init);
11375 gimple_set_location (call, loc);
11376 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11378 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11379 build_int_cst (integer_type_node,
11380 IFN_GOACC_LOOP_BOUND),
11381 dir, range, s,
11382 chunk_size, gwv, offset_init);
11383 gimple_call_set_lhs (call, bound);
11384 gimple_set_location (call, loc);
11385 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11387 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11388 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11389 GSI_CONTINUE_LINKING);
11391 /* V assignment goes into body_bb. */
11392 if (!gimple_in_ssa_p (cfun))
11394 gsi = gsi_start_bb (body_bb);
11396 expr = build2 (plus_code, iter_type, b,
11397 fold_convert (plus_type, offset));
11398 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11399 true, GSI_SAME_STMT);
11400 ass = gimple_build_assign (v, expr);
11401 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11402 if (fd->collapse > 1)
11403 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11406 /* Loop increment goes into cont_bb. If this is not a loop, we
11407 will have spawned threads as if it was, and each one will
11408 execute one iteration. The specification is not explicit about
11409 whether such constructs are ill-formed or not, and they can
11410 occur, especially when noreturn routines are involved. */
11411 if (cont_bb)
11413 gsi = gsi_last_bb (cont_bb);
11414 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11415 loc = gimple_location (cont_stmt);
11417 /* Increment offset. */
11418 if (gimple_in_ssa_p (cfun))
11419 expr= build2 (plus_code, iter_type, offset,
11420 fold_convert (plus_type, step));
11421 else
11422 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11423 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11424 true, GSI_SAME_STMT);
11425 ass = gimple_build_assign (offset_incr, expr);
11426 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11427 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11428 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11430 /* Remove the GIMPLE_OMP_CONTINUE. */
11431 gsi_remove (&gsi, true);
11433 /* Fixup edges from cont_bb */
11434 be = BRANCH_EDGE (cont_bb);
11435 fte = FALLTHRU_EDGE (cont_bb);
11436 be->flags |= EDGE_TRUE_VALUE;
11437 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11439 if (chunking)
11441 /* Split the beginning of exit_bb to make bottom_bb. We
11442 need to insert a nop at the start, because splitting is
11443 after a stmt, not before. */
11444 gsi = gsi_start_bb (exit_bb);
11445 stmt = gimple_build_nop ();
11446 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11447 split = split_block (exit_bb, stmt);
11448 bottom_bb = split->src;
11449 exit_bb = split->dest;
11450 gsi = gsi_last_bb (bottom_bb);
11452 /* Chunk increment and test goes into bottom_bb. */
11453 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11454 build_int_cst (diff_type, 1));
11455 ass = gimple_build_assign (chunk_no, expr);
11456 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11458 /* Chunk test at end of bottom_bb. */
11459 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11460 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11461 GSI_CONTINUE_LINKING);
11463 /* Fixup edges from bottom_bb. */
11464 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11465 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11469 gsi = gsi_last_bb (exit_bb);
11470 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11471 loc = gimple_location (gsi_stmt (gsi));
11473 if (!gimple_in_ssa_p (cfun))
11475 /* Insert the final value of V, in case it is live. This is the
11476 value for the only thread that survives past the join. */
11477 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11478 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11479 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11480 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11481 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11482 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11483 true, GSI_SAME_STMT);
11484 ass = gimple_build_assign (v, expr);
11485 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11488 /* Remove the OMP_RETURN. */
11489 gsi_remove (&gsi, true);
11491 if (cont_bb)
11493 /* We now have one or two nested loops. Update the loop
11494 structures. */
11495 struct loop *parent = entry_bb->loop_father;
11496 struct loop *body = body_bb->loop_father;
11498 if (chunking)
11500 struct loop *chunk_loop = alloc_loop ();
11501 chunk_loop->header = head_bb;
11502 chunk_loop->latch = bottom_bb;
11503 add_loop (chunk_loop, parent);
11504 parent = chunk_loop;
11506 else if (parent != body)
11508 gcc_assert (body->header == body_bb);
11509 gcc_assert (body->latch == cont_bb
11510 || single_pred (body->latch) == cont_bb);
11511 parent = NULL;
11514 if (parent)
11516 struct loop *body_loop = alloc_loop ();
11517 body_loop->header = body_bb;
11518 body_loop->latch = cont_bb;
11519 add_loop (body_loop, parent);
11524 /* Expand the OMP loop defined by REGION. */
11526 static void
11527 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11529 struct omp_for_data fd;
11530 struct omp_for_data_loop *loops;
11532 loops
11533 = (struct omp_for_data_loop *)
11534 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11535 * sizeof (struct omp_for_data_loop));
11536 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11537 &fd, loops);
11538 region->sched_kind = fd.sched_kind;
11539 region->sched_modifiers = fd.sched_modifiers;
11541 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11542 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11543 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11544 if (region->cont)
11546 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11547 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11548 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11550 else
11551 /* If there isn't a continue then this is a degerate case where
11552 the introduction of abnormal edges during lowering will prevent
11553 original loops from being detected. Fix that up. */
11554 loops_state_set (LOOPS_NEED_FIXUP);
11556 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11557 expand_omp_simd (region, &fd);
11558 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11559 expand_cilk_for (region, &fd);
11560 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11562 gcc_assert (!inner_stmt);
11563 expand_oacc_for (region, &fd);
11565 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11567 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11568 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11569 else
11570 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11572 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11573 && !fd.have_ordered)
11575 if (fd.chunk_size == NULL)
11576 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11577 else
11578 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11580 else
11582 int fn_index, start_ix, next_ix;
11584 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11585 == GF_OMP_FOR_KIND_FOR);
11586 if (fd.chunk_size == NULL
11587 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11588 fd.chunk_size = integer_zero_node;
11589 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11590 switch (fd.sched_kind)
11592 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11593 fn_index = 3;
11594 break;
11595 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11596 case OMP_CLAUSE_SCHEDULE_GUIDED:
11597 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11598 && !fd.ordered
11599 && !fd.have_ordered)
11601 fn_index = 3 + fd.sched_kind;
11602 break;
11604 /* FALLTHRU */
11605 default:
11606 fn_index = fd.sched_kind;
11607 break;
11609 if (!fd.ordered)
11610 fn_index += fd.have_ordered * 6;
11611 if (fd.ordered)
11612 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11613 else
11614 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11615 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11616 if (fd.iter_type == long_long_unsigned_type_node)
11618 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11619 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11620 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11621 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11623 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11624 (enum built_in_function) next_ix, inner_stmt);
11627 if (gimple_in_ssa_p (cfun))
11628 update_ssa (TODO_update_ssa_only_virtuals);
11632 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11634 v = GOMP_sections_start (n);
11636 switch (v)
11638 case 0:
11639 goto L2;
11640 case 1:
11641 section 1;
11642 goto L1;
11643 case 2:
11645 case n:
11647 default:
11648 abort ();
11651 v = GOMP_sections_next ();
11652 goto L0;
11654 reduction;
11656 If this is a combined parallel sections, replace the call to
11657 GOMP_sections_start with call to GOMP_sections_next. */
11659 static void
11660 expand_omp_sections (struct omp_region *region)
11662 tree t, u, vin = NULL, vmain, vnext, l2;
11663 unsigned len;
11664 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11665 gimple_stmt_iterator si, switch_si;
11666 gomp_sections *sections_stmt;
11667 gimple *stmt;
11668 gomp_continue *cont;
11669 edge_iterator ei;
11670 edge e;
11671 struct omp_region *inner;
11672 unsigned i, casei;
11673 bool exit_reachable = region->cont != NULL;
11675 gcc_assert (region->exit != NULL);
11676 entry_bb = region->entry;
11677 l0_bb = single_succ (entry_bb);
11678 l1_bb = region->cont;
11679 l2_bb = region->exit;
11680 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11681 l2 = gimple_block_label (l2_bb);
11682 else
11684 /* This can happen if there are reductions. */
11685 len = EDGE_COUNT (l0_bb->succs);
11686 gcc_assert (len > 0);
11687 e = EDGE_SUCC (l0_bb, len - 1);
11688 si = gsi_last_bb (e->dest);
11689 l2 = NULL_TREE;
11690 if (gsi_end_p (si)
11691 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11692 l2 = gimple_block_label (e->dest);
11693 else
11694 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11696 si = gsi_last_bb (e->dest);
11697 if (gsi_end_p (si)
11698 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11700 l2 = gimple_block_label (e->dest);
11701 break;
11705 if (exit_reachable)
11706 default_bb = create_empty_bb (l1_bb->prev_bb);
11707 else
11708 default_bb = create_empty_bb (l0_bb);
11710 /* We will build a switch() with enough cases for all the
11711 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11712 and a default case to abort if something goes wrong. */
11713 len = EDGE_COUNT (l0_bb->succs);
11715 /* Use vec::quick_push on label_vec throughout, since we know the size
11716 in advance. */
11717 auto_vec<tree> label_vec (len);
11719 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11720 GIMPLE_OMP_SECTIONS statement. */
11721 si = gsi_last_bb (entry_bb);
11722 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11723 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11724 vin = gimple_omp_sections_control (sections_stmt);
11725 if (!is_combined_parallel (region))
11727 /* If we are not inside a combined parallel+sections region,
11728 call GOMP_sections_start. */
11729 t = build_int_cst (unsigned_type_node, len - 1);
11730 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11731 stmt = gimple_build_call (u, 1, t);
11733 else
11735 /* Otherwise, call GOMP_sections_next. */
11736 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11737 stmt = gimple_build_call (u, 0);
11739 gimple_call_set_lhs (stmt, vin);
11740 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11741 gsi_remove (&si, true);
11743 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11744 L0_BB. */
11745 switch_si = gsi_last_bb (l0_bb);
11746 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11747 if (exit_reachable)
11749 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11750 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11751 vmain = gimple_omp_continue_control_use (cont);
11752 vnext = gimple_omp_continue_control_def (cont);
11754 else
11756 vmain = vin;
11757 vnext = NULL_TREE;
11760 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11761 label_vec.quick_push (t);
11762 i = 1;
11764 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11765 for (inner = region->inner, casei = 1;
11766 inner;
11767 inner = inner->next, i++, casei++)
11769 basic_block s_entry_bb, s_exit_bb;
11771 /* Skip optional reduction region. */
11772 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11774 --i;
11775 --casei;
11776 continue;
11779 s_entry_bb = inner->entry;
11780 s_exit_bb = inner->exit;
11782 t = gimple_block_label (s_entry_bb);
11783 u = build_int_cst (unsigned_type_node, casei);
11784 u = build_case_label (u, NULL, t);
11785 label_vec.quick_push (u);
11787 si = gsi_last_bb (s_entry_bb);
11788 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11789 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11790 gsi_remove (&si, true);
11791 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11793 if (s_exit_bb == NULL)
11794 continue;
11796 si = gsi_last_bb (s_exit_bb);
11797 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11798 gsi_remove (&si, true);
11800 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11803 /* Error handling code goes in DEFAULT_BB. */
11804 t = gimple_block_label (default_bb);
11805 u = build_case_label (NULL, NULL, t);
11806 make_edge (l0_bb, default_bb, 0);
11807 add_bb_to_loop (default_bb, current_loops->tree_root);
11809 stmt = gimple_build_switch (vmain, u, label_vec);
11810 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11811 gsi_remove (&switch_si, true);
11813 si = gsi_start_bb (default_bb);
11814 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11815 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11817 if (exit_reachable)
11819 tree bfn_decl;
11821 /* Code to get the next section goes in L1_BB. */
11822 si = gsi_last_bb (l1_bb);
11823 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11825 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11826 stmt = gimple_build_call (bfn_decl, 0);
11827 gimple_call_set_lhs (stmt, vnext);
11828 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11829 gsi_remove (&si, true);
11831 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11834 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11835 si = gsi_last_bb (l2_bb);
11836 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11837 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11838 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11839 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11840 else
11841 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11842 stmt = gimple_build_call (t, 0);
11843 if (gimple_omp_return_lhs (gsi_stmt (si)))
11844 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11845 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11846 gsi_remove (&si, true);
11848 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11852 /* Expand code for an OpenMP single directive. We've already expanded
11853 much of the code, here we simply place the GOMP_barrier call. */
11855 static void
11856 expand_omp_single (struct omp_region *region)
11858 basic_block entry_bb, exit_bb;
11859 gimple_stmt_iterator si;
11861 entry_bb = region->entry;
11862 exit_bb = region->exit;
11864 si = gsi_last_bb (entry_bb);
11865 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11866 gsi_remove (&si, true);
11867 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11869 si = gsi_last_bb (exit_bb);
11870 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11872 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11873 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11875 gsi_remove (&si, true);
11876 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11880 /* Generic expansion for OpenMP synchronization directives: master,
11881 ordered and critical. All we need to do here is remove the entry
11882 and exit markers for REGION. */
11884 static void
11885 expand_omp_synch (struct omp_region *region)
11887 basic_block entry_bb, exit_bb;
11888 gimple_stmt_iterator si;
11890 entry_bb = region->entry;
11891 exit_bb = region->exit;
11893 si = gsi_last_bb (entry_bb);
11894 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11895 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11896 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11897 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11898 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11899 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11900 gsi_remove (&si, true);
11901 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11903 if (exit_bb)
11905 si = gsi_last_bb (exit_bb);
11906 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11907 gsi_remove (&si, true);
11908 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11912 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11913 operation as a normal volatile load. */
11915 static bool
11916 expand_omp_atomic_load (basic_block load_bb, tree addr,
11917 tree loaded_val, int index)
11919 enum built_in_function tmpbase;
11920 gimple_stmt_iterator gsi;
11921 basic_block store_bb;
11922 location_t loc;
11923 gimple *stmt;
11924 tree decl, call, type, itype;
11926 gsi = gsi_last_bb (load_bb);
11927 stmt = gsi_stmt (gsi);
11928 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11929 loc = gimple_location (stmt);
11931 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11932 is smaller than word size, then expand_atomic_load assumes that the load
11933 is atomic. We could avoid the builtin entirely in this case. */
11935 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11936 decl = builtin_decl_explicit (tmpbase);
11937 if (decl == NULL_TREE)
11938 return false;
11940 type = TREE_TYPE (loaded_val);
11941 itype = TREE_TYPE (TREE_TYPE (decl));
11943 call = build_call_expr_loc (loc, decl, 2, addr,
11944 build_int_cst (NULL,
11945 gimple_omp_atomic_seq_cst_p (stmt)
11946 ? MEMMODEL_SEQ_CST
11947 : MEMMODEL_RELAXED));
11948 if (!useless_type_conversion_p (type, itype))
11949 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11950 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11952 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11953 gsi_remove (&gsi, true);
11955 store_bb = single_succ (load_bb);
11956 gsi = gsi_last_bb (store_bb);
11957 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11958 gsi_remove (&gsi, true);
11960 if (gimple_in_ssa_p (cfun))
11961 update_ssa (TODO_update_ssa_no_phi);
11963 return true;
11966 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11967 operation as a normal volatile store. */
11969 static bool
11970 expand_omp_atomic_store (basic_block load_bb, tree addr,
11971 tree loaded_val, tree stored_val, int index)
11973 enum built_in_function tmpbase;
11974 gimple_stmt_iterator gsi;
11975 basic_block store_bb = single_succ (load_bb);
11976 location_t loc;
11977 gimple *stmt;
11978 tree decl, call, type, itype;
11979 machine_mode imode;
11980 bool exchange;
11982 gsi = gsi_last_bb (load_bb);
11983 stmt = gsi_stmt (gsi);
11984 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11986 /* If the load value is needed, then this isn't a store but an exchange. */
11987 exchange = gimple_omp_atomic_need_value_p (stmt);
11989 gsi = gsi_last_bb (store_bb);
11990 stmt = gsi_stmt (gsi);
11991 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11992 loc = gimple_location (stmt);
11994 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11995 is smaller than word size, then expand_atomic_store assumes that the store
11996 is atomic. We could avoid the builtin entirely in this case. */
11998 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11999 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12000 decl = builtin_decl_explicit (tmpbase);
12001 if (decl == NULL_TREE)
12002 return false;
12004 type = TREE_TYPE (stored_val);
12006 /* Dig out the type of the function's second argument. */
12007 itype = TREE_TYPE (decl);
12008 itype = TYPE_ARG_TYPES (itype);
12009 itype = TREE_CHAIN (itype);
12010 itype = TREE_VALUE (itype);
12011 imode = TYPE_MODE (itype);
12013 if (exchange && !can_atomic_exchange_p (imode, true))
12014 return false;
12016 if (!useless_type_conversion_p (itype, type))
12017 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12018 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12019 build_int_cst (NULL,
12020 gimple_omp_atomic_seq_cst_p (stmt)
12021 ? MEMMODEL_SEQ_CST
12022 : MEMMODEL_RELAXED));
12023 if (exchange)
12025 if (!useless_type_conversion_p (type, itype))
12026 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12027 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12030 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12031 gsi_remove (&gsi, true);
12033 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12034 gsi = gsi_last_bb (load_bb);
12035 gsi_remove (&gsi, true);
12037 if (gimple_in_ssa_p (cfun))
12038 update_ssa (TODO_update_ssa_no_phi);
12040 return true;
12043 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12044 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12045 size of the data type, and thus usable to find the index of the builtin
12046 decl. Returns false if the expression is not of the proper form. */
12048 static bool
12049 expand_omp_atomic_fetch_op (basic_block load_bb,
12050 tree addr, tree loaded_val,
12051 tree stored_val, int index)
12053 enum built_in_function oldbase, newbase, tmpbase;
12054 tree decl, itype, call;
12055 tree lhs, rhs;
12056 basic_block store_bb = single_succ (load_bb);
12057 gimple_stmt_iterator gsi;
12058 gimple *stmt;
12059 location_t loc;
12060 enum tree_code code;
12061 bool need_old, need_new;
12062 machine_mode imode;
12063 bool seq_cst;
12065 /* We expect to find the following sequences:
12067 load_bb:
12068 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12070 store_bb:
12071 val = tmp OP something; (or: something OP tmp)
12072 GIMPLE_OMP_STORE (val)
12074 ???FIXME: Allow a more flexible sequence.
12075 Perhaps use data flow to pick the statements.
12079 gsi = gsi_after_labels (store_bb);
12080 stmt = gsi_stmt (gsi);
12081 loc = gimple_location (stmt);
12082 if (!is_gimple_assign (stmt))
12083 return false;
12084 gsi_next (&gsi);
12085 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12086 return false;
12087 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12088 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12089 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12090 gcc_checking_assert (!need_old || !need_new);
12092 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12093 return false;
12095 /* Check for one of the supported fetch-op operations. */
12096 code = gimple_assign_rhs_code (stmt);
12097 switch (code)
12099 case PLUS_EXPR:
12100 case POINTER_PLUS_EXPR:
12101 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12102 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12103 break;
12104 case MINUS_EXPR:
12105 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12106 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12107 break;
12108 case BIT_AND_EXPR:
12109 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12110 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12111 break;
12112 case BIT_IOR_EXPR:
12113 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12114 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12115 break;
12116 case BIT_XOR_EXPR:
12117 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12118 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12119 break;
12120 default:
12121 return false;
12124 /* Make sure the expression is of the proper form. */
12125 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12126 rhs = gimple_assign_rhs2 (stmt);
12127 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12128 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12129 rhs = gimple_assign_rhs1 (stmt);
12130 else
12131 return false;
12133 tmpbase = ((enum built_in_function)
12134 ((need_new ? newbase : oldbase) + index + 1));
12135 decl = builtin_decl_explicit (tmpbase);
12136 if (decl == NULL_TREE)
12137 return false;
12138 itype = TREE_TYPE (TREE_TYPE (decl));
12139 imode = TYPE_MODE (itype);
12141 /* We could test all of the various optabs involved, but the fact of the
12142 matter is that (with the exception of i486 vs i586 and xadd) all targets
12143 that support any atomic operaton optab also implements compare-and-swap.
12144 Let optabs.c take care of expanding any compare-and-swap loop. */
12145 if (!can_compare_and_swap_p (imode, true))
12146 return false;
12148 gsi = gsi_last_bb (load_bb);
12149 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12151 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12152 It only requires that the operation happen atomically. Thus we can
12153 use the RELAXED memory model. */
12154 call = build_call_expr_loc (loc, decl, 3, addr,
12155 fold_convert_loc (loc, itype, rhs),
12156 build_int_cst (NULL,
12157 seq_cst ? MEMMODEL_SEQ_CST
12158 : MEMMODEL_RELAXED));
12160 if (need_old || need_new)
12162 lhs = need_old ? loaded_val : stored_val;
12163 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12164 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12166 else
12167 call = fold_convert_loc (loc, void_type_node, call);
12168 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12169 gsi_remove (&gsi, true);
12171 gsi = gsi_last_bb (store_bb);
12172 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12173 gsi_remove (&gsi, true);
12174 gsi = gsi_last_bb (store_bb);
12175 stmt = gsi_stmt (gsi);
12176 gsi_remove (&gsi, true);
12178 if (gimple_in_ssa_p (cfun))
12180 release_defs (stmt);
12181 update_ssa (TODO_update_ssa_no_phi);
12184 return true;
12187 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12189 oldval = *addr;
12190 repeat:
12191 newval = rhs; // with oldval replacing *addr in rhs
12192 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12193 if (oldval != newval)
12194 goto repeat;
12196 INDEX is log2 of the size of the data type, and thus usable to find the
12197 index of the builtin decl. */
12199 static bool
12200 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12201 tree addr, tree loaded_val, tree stored_val,
12202 int index)
12204 tree loadedi, storedi, initial, new_storedi, old_vali;
12205 tree type, itype, cmpxchg, iaddr;
12206 gimple_stmt_iterator si;
12207 basic_block loop_header = single_succ (load_bb);
12208 gimple *phi, *stmt;
12209 edge e;
12210 enum built_in_function fncode;
12212 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12213 order to use the RELAXED memory model effectively. */
12214 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12215 + index + 1);
12216 cmpxchg = builtin_decl_explicit (fncode);
12217 if (cmpxchg == NULL_TREE)
12218 return false;
12219 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12220 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12222 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12223 return false;
12225 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12226 si = gsi_last_bb (load_bb);
12227 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12229 /* For floating-point values, we'll need to view-convert them to integers
12230 so that we can perform the atomic compare and swap. Simplify the
12231 following code by always setting up the "i"ntegral variables. */
12232 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12234 tree iaddr_val;
12236 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12237 true));
12238 iaddr_val
12239 = force_gimple_operand_gsi (&si,
12240 fold_convert (TREE_TYPE (iaddr), addr),
12241 false, NULL_TREE, true, GSI_SAME_STMT);
12242 stmt = gimple_build_assign (iaddr, iaddr_val);
12243 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12244 loadedi = create_tmp_var (itype);
12245 if (gimple_in_ssa_p (cfun))
12246 loadedi = make_ssa_name (loadedi);
12248 else
12250 iaddr = addr;
12251 loadedi = loaded_val;
12254 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12255 tree loaddecl = builtin_decl_explicit (fncode);
12256 if (loaddecl)
12257 initial
12258 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12259 build_call_expr (loaddecl, 2, iaddr,
12260 build_int_cst (NULL_TREE,
12261 MEMMODEL_RELAXED)));
12262 else
12263 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12264 build_int_cst (TREE_TYPE (iaddr), 0));
12266 initial
12267 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12268 GSI_SAME_STMT);
12270 /* Move the value to the LOADEDI temporary. */
12271 if (gimple_in_ssa_p (cfun))
12273 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12274 phi = create_phi_node (loadedi, loop_header);
12275 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12276 initial);
12278 else
12279 gsi_insert_before (&si,
12280 gimple_build_assign (loadedi, initial),
12281 GSI_SAME_STMT);
12282 if (loadedi != loaded_val)
12284 gimple_stmt_iterator gsi2;
12285 tree x;
12287 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12288 gsi2 = gsi_start_bb (loop_header);
12289 if (gimple_in_ssa_p (cfun))
12291 gassign *stmt;
12292 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12293 true, GSI_SAME_STMT);
12294 stmt = gimple_build_assign (loaded_val, x);
12295 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12297 else
12299 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12300 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12301 true, GSI_SAME_STMT);
12304 gsi_remove (&si, true);
12306 si = gsi_last_bb (store_bb);
12307 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12309 if (iaddr == addr)
12310 storedi = stored_val;
12311 else
12312 storedi =
12313 force_gimple_operand_gsi (&si,
12314 build1 (VIEW_CONVERT_EXPR, itype,
12315 stored_val), true, NULL_TREE, true,
12316 GSI_SAME_STMT);
12318 /* Build the compare&swap statement. */
12319 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12320 new_storedi = force_gimple_operand_gsi (&si,
12321 fold_convert (TREE_TYPE (loadedi),
12322 new_storedi),
12323 true, NULL_TREE,
12324 true, GSI_SAME_STMT);
12326 if (gimple_in_ssa_p (cfun))
12327 old_vali = loadedi;
12328 else
12330 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12331 stmt = gimple_build_assign (old_vali, loadedi);
12332 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12334 stmt = gimple_build_assign (loadedi, new_storedi);
12335 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12338 /* Note that we always perform the comparison as an integer, even for
12339 floating point. This allows the atomic operation to properly
12340 succeed even with NaNs and -0.0. */
12341 stmt = gimple_build_cond_empty
12342 (build2 (NE_EXPR, boolean_type_node,
12343 new_storedi, old_vali));
12344 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12346 /* Update cfg. */
12347 e = single_succ_edge (store_bb);
12348 e->flags &= ~EDGE_FALLTHRU;
12349 e->flags |= EDGE_FALSE_VALUE;
12351 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12353 /* Copy the new value to loadedi (we already did that before the condition
12354 if we are not in SSA). */
12355 if (gimple_in_ssa_p (cfun))
12357 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12358 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12361 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12362 gsi_remove (&si, true);
12364 struct loop *loop = alloc_loop ();
12365 loop->header = loop_header;
12366 loop->latch = store_bb;
12367 add_loop (loop, loop_header->loop_father);
12369 if (gimple_in_ssa_p (cfun))
12370 update_ssa (TODO_update_ssa_no_phi);
12372 return true;
12375 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12377 GOMP_atomic_start ();
12378 *addr = rhs;
12379 GOMP_atomic_end ();
12381 The result is not globally atomic, but works so long as all parallel
12382 references are within #pragma omp atomic directives. According to
12383 responses received from omp@openmp.org, appears to be within spec.
12384 Which makes sense, since that's how several other compilers handle
12385 this situation as well.
12386 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12387 expanding. STORED_VAL is the operand of the matching
12388 GIMPLE_OMP_ATOMIC_STORE.
12390 We replace
12391 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12392 loaded_val = *addr;
12394 and replace
12395 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12396 *addr = stored_val;
12399 static bool
12400 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12401 tree addr, tree loaded_val, tree stored_val)
12403 gimple_stmt_iterator si;
12404 gassign *stmt;
12405 tree t;
12407 si = gsi_last_bb (load_bb);
12408 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12410 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12411 t = build_call_expr (t, 0);
12412 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12414 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12415 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12416 gsi_remove (&si, true);
12418 si = gsi_last_bb (store_bb);
12419 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12421 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12422 stored_val);
12423 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12425 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12426 t = build_call_expr (t, 0);
12427 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12428 gsi_remove (&si, true);
12430 if (gimple_in_ssa_p (cfun))
12431 update_ssa (TODO_update_ssa_no_phi);
12432 return true;
12435 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12436 using expand_omp_atomic_fetch_op. If it failed, we try to
12437 call expand_omp_atomic_pipeline, and if it fails too, the
12438 ultimate fallback is wrapping the operation in a mutex
12439 (expand_omp_atomic_mutex). REGION is the atomic region built
12440 by build_omp_regions_1(). */
12442 static void
12443 expand_omp_atomic (struct omp_region *region)
12445 basic_block load_bb = region->entry, store_bb = region->exit;
12446 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12447 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12448 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12449 tree addr = gimple_omp_atomic_load_rhs (load);
12450 tree stored_val = gimple_omp_atomic_store_val (store);
12451 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12452 HOST_WIDE_INT index;
12454 /* Make sure the type is one of the supported sizes. */
12455 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12456 index = exact_log2 (index);
12457 if (index >= 0 && index <= 4)
12459 unsigned int align = TYPE_ALIGN_UNIT (type);
12461 /* __sync builtins require strict data alignment. */
12462 if (exact_log2 (align) >= index)
12464 /* Atomic load. */
12465 if (loaded_val == stored_val
12466 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12467 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12468 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12469 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12470 return;
12472 /* Atomic store. */
12473 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12474 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12475 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12476 && store_bb == single_succ (load_bb)
12477 && first_stmt (store_bb) == store
12478 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12479 stored_val, index))
12480 return;
12482 /* When possible, use specialized atomic update functions. */
12483 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12484 && store_bb == single_succ (load_bb)
12485 && expand_omp_atomic_fetch_op (load_bb, addr,
12486 loaded_val, stored_val, index))
12487 return;
12489 /* If we don't have specialized __sync builtins, try and implement
12490 as a compare and swap loop. */
12491 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12492 loaded_val, stored_val, index))
12493 return;
12497 /* The ultimate fallback is wrapping the operation in a mutex. */
12498 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12502 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12503 macro on gomp-constants.h. We do not check for overflow. */
12505 static tree
12506 oacc_launch_pack (unsigned code, tree device, unsigned op)
12508 tree res;
12510 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12511 if (device)
12513 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12514 device, build_int_cst (unsigned_type_node,
12515 GOMP_LAUNCH_DEVICE_SHIFT));
12516 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12518 return res;
12521 /* Look for compute grid dimension clauses and convert to an attribute
12522 attached to FN. This permits the target-side code to (a) massage
12523 the dimensions, (b) emit that data and (c) optimize. Non-constant
12524 dimensions are pushed onto ARGS.
12526 The attribute value is a TREE_LIST. A set of dimensions is
12527 represented as a list of INTEGER_CST. Those that are runtime
12528 exprs are represented as an INTEGER_CST of zero.
12530 TOOO. Normally the attribute will just contain a single such list. If
12531 however it contains a list of lists, this will represent the use of
12532 device_type. Each member of the outer list is an assoc list of
12533 dimensions, keyed by the device type. The first entry will be the
12534 default. Well, that's the plan. */
12536 #define OACC_FN_ATTRIB "oacc function"
12538 /* Replace any existing oacc fn attribute with updated dimensions. */
12540 void
12541 replace_oacc_fn_attrib (tree fn, tree dims)
12543 tree ident = get_identifier (OACC_FN_ATTRIB);
12544 tree attribs = DECL_ATTRIBUTES (fn);
12546 /* If we happen to be present as the first attrib, drop it. */
12547 if (attribs && TREE_PURPOSE (attribs) == ident)
12548 attribs = TREE_CHAIN (attribs);
12549 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12552 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12553 function attribute. Push any that are non-constant onto the ARGS
12554 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12555 true, if these are for a kernels region offload function. */
12557 void
12558 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12560 /* Must match GOMP_DIM ordering. */
12561 static const omp_clause_code ids[]
12562 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12563 OMP_CLAUSE_VECTOR_LENGTH };
12564 unsigned ix;
12565 tree dims[GOMP_DIM_MAX];
12566 tree attr = NULL_TREE;
12567 unsigned non_const = 0;
12569 for (ix = GOMP_DIM_MAX; ix--;)
12571 tree clause = find_omp_clause (clauses, ids[ix]);
12572 tree dim = NULL_TREE;
12574 if (clause)
12575 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12576 dims[ix] = dim;
12577 if (dim && TREE_CODE (dim) != INTEGER_CST)
12579 dim = integer_zero_node;
12580 non_const |= GOMP_DIM_MASK (ix);
12582 attr = tree_cons (NULL_TREE, dim, attr);
12583 /* Note kernelness with TREE_PUBLIC. */
12584 if (is_kernel)
12585 TREE_PUBLIC (attr) = 1;
12588 replace_oacc_fn_attrib (fn, attr);
12590 if (non_const)
12592 /* Push a dynamic argument set. */
12593 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12594 NULL_TREE, non_const));
12595 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12596 if (non_const & GOMP_DIM_MASK (ix))
12597 args->safe_push (dims[ix]);
12601 /* Process the routine's dimension clauess to generate an attribute
12602 value. Issue diagnostics as appropriate. We default to SEQ
12603 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12604 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12605 can have a loop partitioned on it. non-zero indicates
12606 yes, zero indicates no. By construction once a non-zero has been
12607 reached, further inner dimensions must also be non-zero. We set
12608 TREE_VALUE to zero for the dimensions that may be partitioned and
12609 1 for the other ones -- if a loop is (erroneously) spawned at
12610 an outer level, we don't want to try and partition it. */
12612 tree
12613 build_oacc_routine_dims (tree clauses)
12615 /* Must match GOMP_DIM ordering. */
12616 static const omp_clause_code ids[] =
12617 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12618 int ix;
12619 int level = -1;
12621 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12622 for (ix = GOMP_DIM_MAX + 1; ix--;)
12623 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12625 if (level >= 0)
12626 error_at (OMP_CLAUSE_LOCATION (clauses),
12627 "multiple loop axes specified for routine");
12628 level = ix;
12629 break;
12632 /* Default to SEQ. */
12633 if (level < 0)
12634 level = GOMP_DIM_MAX;
12636 tree dims = NULL_TREE;
12638 for (ix = GOMP_DIM_MAX; ix--;)
12639 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12640 build_int_cst (integer_type_node, ix < level), dims);
12642 return dims;
12645 /* Retrieve the oacc function attrib and return it. Non-oacc
12646 functions will return NULL. */
12648 tree
12649 get_oacc_fn_attrib (tree fn)
12651 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12654 /* Return true if this oacc fn attrib is for a kernels offload
12655 region. We use the TREE_PUBLIC flag of each dimension -- only
12656 need to check the first one. */
12658 bool
12659 oacc_fn_attrib_kernels_p (tree attr)
12661 return TREE_PUBLIC (TREE_VALUE (attr));
12664 /* Return level at which oacc routine may spawn a partitioned loop, or
12665 -1 if it is not a routine (i.e. is an offload fn). */
12667 static int
12668 oacc_fn_attrib_level (tree attr)
12670 tree pos = TREE_VALUE (attr);
12672 if (!TREE_PURPOSE (pos))
12673 return -1;
12675 int ix = 0;
12676 for (ix = 0; ix != GOMP_DIM_MAX;
12677 ix++, pos = TREE_CHAIN (pos))
12678 if (!integer_zerop (TREE_PURPOSE (pos)))
12679 break;
12681 return ix;
12684 /* Extract an oacc execution dimension from FN. FN must be an
12685 offloaded function or routine that has already had its execution
12686 dimensions lowered to the target-specific values. */
12689 get_oacc_fn_dim_size (tree fn, int axis)
12691 tree attrs = get_oacc_fn_attrib (fn);
12693 gcc_assert (axis < GOMP_DIM_MAX);
12695 tree dims = TREE_VALUE (attrs);
12696 while (axis--)
12697 dims = TREE_CHAIN (dims);
12699 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12701 return size;
12704 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12705 IFN_GOACC_DIM_SIZE call. */
12708 get_oacc_ifn_dim_arg (const gimple *stmt)
12710 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12711 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12712 tree arg = gimple_call_arg (stmt, 0);
12713 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12715 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12716 return (int) axis;
12719 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12720 at REGION_EXIT. */
12722 static void
12723 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12724 basic_block region_exit)
12726 struct loop *outer = region_entry->loop_father;
12727 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12729 /* Don't parallelize the kernels region if it contains more than one outer
12730 loop. */
12731 unsigned int nr_outer_loops = 0;
12732 struct loop *single_outer = NULL;
12733 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12735 gcc_assert (loop_outer (loop) == outer);
12737 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12738 continue;
12740 if (region_exit != NULL
12741 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12742 continue;
12744 nr_outer_loops++;
12745 single_outer = loop;
12747 if (nr_outer_loops != 1)
12748 return;
12750 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12751 if (loop->next)
12752 return;
12754 /* Mark the loops in the region. */
12755 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12756 loop->in_oacc_kernels_region = true;
12759 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12761 struct GTY(()) grid_launch_attributes_trees
12763 tree kernel_dim_array_type;
12764 tree kernel_lattrs_dimnum_decl;
12765 tree kernel_lattrs_grid_decl;
12766 tree kernel_lattrs_group_decl;
12767 tree kernel_launch_attributes_type;
12770 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12772 /* Create types used to pass kernel launch attributes to target. */
12774 static void
12775 grid_create_kernel_launch_attr_types (void)
12777 if (grid_attr_trees)
12778 return;
12779 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12781 tree dim_arr_index_type
12782 = build_index_type (build_int_cst (integer_type_node, 2));
12783 grid_attr_trees->kernel_dim_array_type
12784 = build_array_type (uint32_type_node, dim_arr_index_type);
12786 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12787 grid_attr_trees->kernel_lattrs_dimnum_decl
12788 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12789 uint32_type_node);
12790 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12792 grid_attr_trees->kernel_lattrs_grid_decl
12793 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12794 grid_attr_trees->kernel_dim_array_type);
12795 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12796 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12797 grid_attr_trees->kernel_lattrs_group_decl
12798 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12799 grid_attr_trees->kernel_dim_array_type);
12800 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12801 = grid_attr_trees->kernel_lattrs_grid_decl;
12802 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12803 "__gomp_kernel_launch_attributes",
12804 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12807 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12808 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12809 of type uint32_type_node. */
12811 static void
12812 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12813 tree fld_decl, int index, tree value)
12815 tree ref = build4 (ARRAY_REF, uint32_type_node,
12816 build3 (COMPONENT_REF,
12817 grid_attr_trees->kernel_dim_array_type,
12818 range_var, fld_decl, NULL_TREE),
12819 build_int_cst (integer_type_node, index),
12820 NULL_TREE, NULL_TREE);
12821 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12824 /* Return a tree representation of a pointer to a structure with grid and
12825 work-group size information. Statements filling that information will be
12826 inserted before GSI, TGT_STMT is the target statement which has the
12827 necessary information in it. */
12829 static tree
12830 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12831 gomp_target *tgt_stmt)
12833 grid_create_kernel_launch_attr_types ();
12834 tree u32_one = build_one_cst (uint32_type_node);
12835 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12836 "__kernel_launch_attrs");
12838 unsigned max_dim = 0;
12839 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12840 clause;
12841 clause = OMP_CLAUSE_CHAIN (clause))
12843 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12844 continue;
12846 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12847 max_dim = MAX (dim, max_dim);
12849 grid_insert_store_range_dim (gsi, lattrs,
12850 grid_attr_trees->kernel_lattrs_grid_decl,
12851 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12852 grid_insert_store_range_dim (gsi, lattrs,
12853 grid_attr_trees->kernel_lattrs_group_decl,
12854 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12857 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12858 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12859 /* At this moment we cannot gridify a loop with a collapse clause. */
12860 /* TODO: Adjust when we support bigger collapse. */
12861 gcc_assert (max_dim == 0);
12862 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12863 TREE_ADDRESSABLE (lattrs) = 1;
12864 return build_fold_addr_expr (lattrs);
12867 /* Build target argument identifier from the DEVICE identifier, value
12868 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12870 static tree
12871 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12873 tree t = build_int_cst (integer_type_node, device);
12874 if (subseqent_param)
12875 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12876 build_int_cst (integer_type_node,
12877 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12878 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12879 build_int_cst (integer_type_node, id));
12880 return t;
12883 /* Like above but return it in type that can be directly stored as an element
12884 of the argument array. */
12886 static tree
12887 get_target_argument_identifier (int device, bool subseqent_param, int id)
12889 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12890 return fold_convert (ptr_type_node, t);
12893 /* Return a target argument consisting of DEVICE identifier, value identifier
12894 ID, and the actual VALUE. */
12896 static tree
12897 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12898 tree value)
12900 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12901 fold_convert (integer_type_node, value),
12902 build_int_cst (unsigned_type_node,
12903 GOMP_TARGET_ARG_VALUE_SHIFT));
12904 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12905 get_target_argument_identifier_1 (device, false, id));
12906 t = fold_convert (ptr_type_node, t);
12907 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12910 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12911 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12912 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12913 arguments. */
12915 static void
12916 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12917 int id, tree value, vec <tree> *args)
12919 if (tree_fits_shwi_p (value)
12920 && tree_to_shwi (value) > -(1 << 15)
12921 && tree_to_shwi (value) < (1 << 15))
12922 args->quick_push (get_target_argument_value (gsi, device, id, value));
12923 else
12925 args->quick_push (get_target_argument_identifier (device, true, id));
12926 value = fold_convert (ptr_type_node, value);
12927 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12928 GSI_SAME_STMT);
12929 args->quick_push (value);
12933 /* Create an array of arguments that is then passed to GOMP_target. */
12935 static tree
12936 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12938 auto_vec <tree, 6> args;
12939 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12940 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12941 if (c)
12942 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12943 else
12944 t = integer_minus_one_node;
12945 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12946 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12948 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12949 if (c)
12950 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12951 else
12952 t = integer_minus_one_node;
12953 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12954 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12955 &args);
12957 /* Add HSA-specific grid sizes, if available. */
12958 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12959 OMP_CLAUSE__GRIDDIM_))
12961 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12962 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12963 args.quick_push (t);
12964 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12967 /* Produce more, perhaps device specific, arguments here. */
12969 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12970 args.length () + 1),
12971 ".omp_target_args");
12972 for (unsigned i = 0; i < args.length (); i++)
12974 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12975 build_int_cst (integer_type_node, i),
12976 NULL_TREE, NULL_TREE);
12977 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12978 GSI_SAME_STMT);
12980 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12981 build_int_cst (integer_type_node, args.length ()),
12982 NULL_TREE, NULL_TREE);
12983 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12984 GSI_SAME_STMT);
12985 TREE_ADDRESSABLE (argarray) = 1;
12986 return build_fold_addr_expr (argarray);
12989 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12991 static void
12992 expand_omp_target (struct omp_region *region)
12994 basic_block entry_bb, exit_bb, new_bb;
12995 struct function *child_cfun;
12996 tree child_fn, block, t;
12997 gimple_stmt_iterator gsi;
12998 gomp_target *entry_stmt;
12999 gimple *stmt;
13000 edge e;
13001 bool offloaded, data_region;
13003 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13004 new_bb = region->entry;
13006 offloaded = is_gimple_omp_offloaded (entry_stmt);
13007 switch (gimple_omp_target_kind (entry_stmt))
13009 case GF_OMP_TARGET_KIND_REGION:
13010 case GF_OMP_TARGET_KIND_UPDATE:
13011 case GF_OMP_TARGET_KIND_ENTER_DATA:
13012 case GF_OMP_TARGET_KIND_EXIT_DATA:
13013 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13014 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13015 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13016 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13017 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13018 data_region = false;
13019 break;
13020 case GF_OMP_TARGET_KIND_DATA:
13021 case GF_OMP_TARGET_KIND_OACC_DATA:
13022 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13023 data_region = true;
13024 break;
13025 default:
13026 gcc_unreachable ();
13029 child_fn = NULL_TREE;
13030 child_cfun = NULL;
13031 if (offloaded)
13033 child_fn = gimple_omp_target_child_fn (entry_stmt);
13034 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13037 /* Supported by expand_omp_taskreg, but not here. */
13038 if (child_cfun != NULL)
13039 gcc_checking_assert (!child_cfun->cfg);
13040 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13042 entry_bb = region->entry;
13043 exit_bb = region->exit;
13045 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13046 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13048 if (offloaded)
13050 unsigned srcidx, dstidx, num;
13052 /* If the offloading region needs data sent from the parent
13053 function, then the very first statement (except possible
13054 tree profile counter updates) of the offloading body
13055 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13056 &.OMP_DATA_O is passed as an argument to the child function,
13057 we need to replace it with the argument as seen by the child
13058 function.
13060 In most cases, this will end up being the identity assignment
13061 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13062 a function call that has been inlined, the original PARM_DECL
13063 .OMP_DATA_I may have been converted into a different local
13064 variable. In which case, we need to keep the assignment. */
13065 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13066 if (data_arg)
13068 basic_block entry_succ_bb = single_succ (entry_bb);
13069 gimple_stmt_iterator gsi;
13070 tree arg;
13071 gimple *tgtcopy_stmt = NULL;
13072 tree sender = TREE_VEC_ELT (data_arg, 0);
13074 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13076 gcc_assert (!gsi_end_p (gsi));
13077 stmt = gsi_stmt (gsi);
13078 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13079 continue;
13081 if (gimple_num_ops (stmt) == 2)
13083 tree arg = gimple_assign_rhs1 (stmt);
13085 /* We're ignoring the subcode because we're
13086 effectively doing a STRIP_NOPS. */
13088 if (TREE_CODE (arg) == ADDR_EXPR
13089 && TREE_OPERAND (arg, 0) == sender)
13091 tgtcopy_stmt = stmt;
13092 break;
13097 gcc_assert (tgtcopy_stmt != NULL);
13098 arg = DECL_ARGUMENTS (child_fn);
13100 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13101 gsi_remove (&gsi, true);
13104 /* Declare local variables needed in CHILD_CFUN. */
13105 block = DECL_INITIAL (child_fn);
13106 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13107 /* The gimplifier could record temporaries in the offloading block
13108 rather than in containing function's local_decls chain,
13109 which would mean cgraph missed finalizing them. Do it now. */
13110 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13111 if (TREE_CODE (t) == VAR_DECL
13112 && TREE_STATIC (t)
13113 && !DECL_EXTERNAL (t))
13114 varpool_node::finalize_decl (t);
13115 DECL_SAVED_TREE (child_fn) = NULL;
13116 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13117 gimple_set_body (child_fn, NULL);
13118 TREE_USED (block) = 1;
13120 /* Reset DECL_CONTEXT on function arguments. */
13121 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13122 DECL_CONTEXT (t) = child_fn;
13124 /* Split ENTRY_BB at GIMPLE_*,
13125 so that it can be moved to the child function. */
13126 gsi = gsi_last_bb (entry_bb);
13127 stmt = gsi_stmt (gsi);
13128 gcc_assert (stmt
13129 && gimple_code (stmt) == gimple_code (entry_stmt));
13130 e = split_block (entry_bb, stmt);
13131 gsi_remove (&gsi, true);
13132 entry_bb = e->dest;
13133 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13135 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13136 if (exit_bb)
13138 gsi = gsi_last_bb (exit_bb);
13139 gcc_assert (!gsi_end_p (gsi)
13140 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13141 stmt = gimple_build_return (NULL);
13142 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13143 gsi_remove (&gsi, true);
13146 /* Move the offloading region into CHILD_CFUN. */
13148 block = gimple_block (entry_stmt);
13150 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13151 if (exit_bb)
13152 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13153 /* When the OMP expansion process cannot guarantee an up-to-date
13154 loop tree arrange for the child function to fixup loops. */
13155 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13156 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13158 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13159 num = vec_safe_length (child_cfun->local_decls);
13160 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13162 t = (*child_cfun->local_decls)[srcidx];
13163 if (DECL_CONTEXT (t) == cfun->decl)
13164 continue;
13165 if (srcidx != dstidx)
13166 (*child_cfun->local_decls)[dstidx] = t;
13167 dstidx++;
13169 if (dstidx != num)
13170 vec_safe_truncate (child_cfun->local_decls, dstidx);
13172 /* Inform the callgraph about the new function. */
13173 child_cfun->curr_properties = cfun->curr_properties;
13174 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13175 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13176 cgraph_node *node = cgraph_node::get_create (child_fn);
13177 node->parallelized_function = 1;
13178 cgraph_node::add_new_function (child_fn, true);
13180 /* Add the new function to the offload table. */
13181 if (ENABLE_OFFLOADING)
13182 vec_safe_push (offload_funcs, child_fn);
13184 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13185 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13187 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13188 fixed in a following pass. */
13189 push_cfun (child_cfun);
13190 if (need_asm)
13191 assign_assembler_name_if_neeeded (child_fn);
13192 cgraph_edge::rebuild_edges ();
13194 /* Some EH regions might become dead, see PR34608. If
13195 pass_cleanup_cfg isn't the first pass to happen with the
13196 new child, these dead EH edges might cause problems.
13197 Clean them up now. */
13198 if (flag_exceptions)
13200 basic_block bb;
13201 bool changed = false;
13203 FOR_EACH_BB_FN (bb, cfun)
13204 changed |= gimple_purge_dead_eh_edges (bb);
13205 if (changed)
13206 cleanup_tree_cfg ();
13208 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13209 verify_loop_structure ();
13210 pop_cfun ();
13212 if (dump_file && !gimple_in_ssa_p (cfun))
13214 omp_any_child_fn_dumped = true;
13215 dump_function_header (dump_file, child_fn, dump_flags);
13216 dump_function_to_file (child_fn, dump_file, dump_flags);
13220 /* Emit a library call to launch the offloading region, or do data
13221 transfers. */
13222 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13223 enum built_in_function start_ix;
13224 location_t clause_loc;
13225 unsigned int flags_i = 0;
13226 bool oacc_kernels_p = false;
13228 switch (gimple_omp_target_kind (entry_stmt))
13230 case GF_OMP_TARGET_KIND_REGION:
13231 start_ix = BUILT_IN_GOMP_TARGET;
13232 break;
13233 case GF_OMP_TARGET_KIND_DATA:
13234 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13235 break;
13236 case GF_OMP_TARGET_KIND_UPDATE:
13237 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13238 break;
13239 case GF_OMP_TARGET_KIND_ENTER_DATA:
13240 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13241 break;
13242 case GF_OMP_TARGET_KIND_EXIT_DATA:
13243 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13244 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13245 break;
13246 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13247 oacc_kernels_p = true;
13248 /* FALLTHROUGH */
13249 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13250 start_ix = BUILT_IN_GOACC_PARALLEL;
13251 break;
13252 case GF_OMP_TARGET_KIND_OACC_DATA:
13253 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13254 start_ix = BUILT_IN_GOACC_DATA_START;
13255 break;
13256 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13257 start_ix = BUILT_IN_GOACC_UPDATE;
13258 break;
13259 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13260 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13261 break;
13262 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13263 start_ix = BUILT_IN_GOACC_DECLARE;
13264 break;
13265 default:
13266 gcc_unreachable ();
13269 clauses = gimple_omp_target_clauses (entry_stmt);
13271 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13272 library choose) and there is no conditional. */
13273 cond = NULL_TREE;
13274 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13276 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13277 if (c)
13278 cond = OMP_CLAUSE_IF_EXPR (c);
13280 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13281 if (c)
13283 /* Even if we pass it to all library function calls, it is currently only
13284 defined/used for the OpenMP target ones. */
13285 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13286 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13287 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13288 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13290 device = OMP_CLAUSE_DEVICE_ID (c);
13291 clause_loc = OMP_CLAUSE_LOCATION (c);
13293 else
13294 clause_loc = gimple_location (entry_stmt);
13296 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13297 if (c)
13298 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13300 /* Ensure 'device' is of the correct type. */
13301 device = fold_convert_loc (clause_loc, integer_type_node, device);
13303 /* If we found the clause 'if (cond)', build
13304 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13305 if (cond)
13307 cond = gimple_boolify (cond);
13309 basic_block cond_bb, then_bb, else_bb;
13310 edge e;
13311 tree tmp_var;
13313 tmp_var = create_tmp_var (TREE_TYPE (device));
13314 if (offloaded)
13315 e = split_block_after_labels (new_bb);
13316 else
13318 gsi = gsi_last_bb (new_bb);
13319 gsi_prev (&gsi);
13320 e = split_block (new_bb, gsi_stmt (gsi));
13322 cond_bb = e->src;
13323 new_bb = e->dest;
13324 remove_edge (e);
13326 then_bb = create_empty_bb (cond_bb);
13327 else_bb = create_empty_bb (then_bb);
13328 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13329 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13331 stmt = gimple_build_cond_empty (cond);
13332 gsi = gsi_last_bb (cond_bb);
13333 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13335 gsi = gsi_start_bb (then_bb);
13336 stmt = gimple_build_assign (tmp_var, device);
13337 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13339 gsi = gsi_start_bb (else_bb);
13340 stmt = gimple_build_assign (tmp_var,
13341 build_int_cst (integer_type_node,
13342 GOMP_DEVICE_HOST_FALLBACK));
13343 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13345 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13346 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13347 add_bb_to_loop (then_bb, cond_bb->loop_father);
13348 add_bb_to_loop (else_bb, cond_bb->loop_father);
13349 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13350 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13352 device = tmp_var;
13353 gsi = gsi_last_bb (new_bb);
13355 else
13357 gsi = gsi_last_bb (new_bb);
13358 device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
13359 true, GSI_SAME_STMT);
13362 t = gimple_omp_target_data_arg (entry_stmt);
13363 if (t == NULL)
13365 t1 = size_zero_node;
13366 t2 = build_zero_cst (ptr_type_node);
13367 t3 = t2;
13368 t4 = t2;
13370 else
13372 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13373 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13374 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13375 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13376 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13379 gimple *g;
13380 bool tagging = false;
13381 /* The maximum number used by any start_ix, without varargs. */
13382 auto_vec<tree, 11> args;
13383 args.quick_push (device);
13384 if (offloaded)
13385 args.quick_push (build_fold_addr_expr (child_fn));
13386 args.quick_push (t1);
13387 args.quick_push (t2);
13388 args.quick_push (t3);
13389 args.quick_push (t4);
13390 switch (start_ix)
13392 case BUILT_IN_GOACC_DATA_START:
13393 case BUILT_IN_GOACC_DECLARE:
13394 case BUILT_IN_GOMP_TARGET_DATA:
13395 break;
13396 case BUILT_IN_GOMP_TARGET:
13397 case BUILT_IN_GOMP_TARGET_UPDATE:
13398 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13399 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13400 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13401 if (c)
13402 depend = OMP_CLAUSE_DECL (c);
13403 else
13404 depend = build_int_cst (ptr_type_node, 0);
13405 args.quick_push (depend);
13406 if (start_ix == BUILT_IN_GOMP_TARGET)
13407 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13408 break;
13409 case BUILT_IN_GOACC_PARALLEL:
13411 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13412 tagging = true;
13414 /* FALLTHRU */
13415 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13416 case BUILT_IN_GOACC_UPDATE:
13418 tree t_async = NULL_TREE;
13420 /* If present, use the value specified by the respective
13421 clause, making sure that is of the correct type. */
13422 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13423 if (c)
13424 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13425 integer_type_node,
13426 OMP_CLAUSE_ASYNC_EXPR (c));
13427 else if (!tagging)
13428 /* Default values for t_async. */
13429 t_async = fold_convert_loc (gimple_location (entry_stmt),
13430 integer_type_node,
13431 build_int_cst (integer_type_node,
13432 GOMP_ASYNC_SYNC));
13433 if (tagging && t_async)
13435 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13437 if (TREE_CODE (t_async) == INTEGER_CST)
13439 /* See if we can pack the async arg in to the tag's
13440 operand. */
13441 i_async = TREE_INT_CST_LOW (t_async);
13442 if (i_async < GOMP_LAUNCH_OP_MAX)
13443 t_async = NULL_TREE;
13444 else
13445 i_async = GOMP_LAUNCH_OP_MAX;
13447 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13448 i_async));
13450 if (t_async)
13451 args.safe_push (t_async);
13453 /* Save the argument index, and ... */
13454 unsigned t_wait_idx = args.length ();
13455 unsigned num_waits = 0;
13456 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13457 if (!tagging || c)
13458 /* ... push a placeholder. */
13459 args.safe_push (integer_zero_node);
13461 for (; c; c = OMP_CLAUSE_CHAIN (c))
13462 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13464 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13465 integer_type_node,
13466 OMP_CLAUSE_WAIT_EXPR (c)));
13467 num_waits++;
13470 if (!tagging || num_waits)
13472 tree len;
13474 /* Now that we know the number, update the placeholder. */
13475 if (tagging)
13476 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13477 else
13478 len = build_int_cst (integer_type_node, num_waits);
13479 len = fold_convert_loc (gimple_location (entry_stmt),
13480 unsigned_type_node, len);
13481 args[t_wait_idx] = len;
13484 break;
13485 default:
13486 gcc_unreachable ();
13488 if (tagging)
13489 /* Push terminal marker - zero. */
13490 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13492 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13493 gimple_set_location (g, gimple_location (entry_stmt));
13494 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13495 if (!offloaded)
13497 g = gsi_stmt (gsi);
13498 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13499 gsi_remove (&gsi, true);
13501 if (data_region && region->exit)
13503 gsi = gsi_last_bb (region->exit);
13504 g = gsi_stmt (gsi);
13505 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13506 gsi_remove (&gsi, true);
13510 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13511 variable derived from the thread number. */
13513 static void
13514 grid_expand_omp_for_loop (struct omp_region *kfor)
13516 tree t, threadid;
13517 tree type, itype;
13518 gimple_stmt_iterator gsi;
13519 tree n1, step;
13520 struct omp_for_data fd;
13522 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13523 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13524 == GF_OMP_FOR_KIND_GRID_LOOP);
13525 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13527 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13528 gcc_assert (kfor->cont);
13529 extract_omp_for_data (for_stmt, &fd, NULL);
13531 itype = type = TREE_TYPE (fd.loop.v);
13532 if (POINTER_TYPE_P (type))
13533 itype = signed_type_for (type);
13535 gsi = gsi_start_bb (body_bb);
13537 n1 = fd.loop.n1;
13538 step = fd.loop.step;
13539 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13540 true, NULL_TREE, true, GSI_SAME_STMT);
13541 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13542 true, NULL_TREE, true, GSI_SAME_STMT);
13543 threadid = build_call_expr (builtin_decl_explicit
13544 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13545 threadid = fold_convert (itype, threadid);
13546 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13547 true, GSI_SAME_STMT);
13549 tree startvar = fd.loop.v;
13550 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13551 if (POINTER_TYPE_P (type))
13552 t = fold_build_pointer_plus (n1, t);
13553 else
13554 t = fold_build2 (PLUS_EXPR, type, t, n1);
13555 t = fold_convert (type, t);
13556 t = force_gimple_operand_gsi (&gsi, t,
13557 DECL_P (startvar)
13558 && TREE_ADDRESSABLE (startvar),
13559 NULL_TREE, true, GSI_SAME_STMT);
13560 gassign *assign_stmt = gimple_build_assign (startvar, t);
13561 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13563 /* Remove the omp for statement */
13564 gsi = gsi_last_bb (kfor->entry);
13565 gsi_remove (&gsi, true);
13567 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13568 gsi = gsi_last_bb (kfor->cont);
13569 gcc_assert (!gsi_end_p (gsi)
13570 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13571 gsi_remove (&gsi, true);
13573 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13574 gsi = gsi_last_bb (kfor->exit);
13575 gcc_assert (!gsi_end_p (gsi)
13576 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13577 gsi_remove (&gsi, true);
13579 /* Fixup the much simpler CFG. */
13580 remove_edge (find_edge (kfor->cont, body_bb));
13582 if (kfor->cont != body_bb)
13583 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13584 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13587 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13588 argument_decls. */
13590 struct grid_arg_decl_map
13592 tree old_arg;
13593 tree new_arg;
13596 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13597 pertaining to kernel function. */
13599 static tree
13600 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13602 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13603 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13604 tree t = *tp;
13606 if (t == adm->old_arg)
13607 *tp = adm->new_arg;
13608 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13609 return NULL_TREE;
13612 static void expand_omp (struct omp_region *region);
13614 /* If TARGET region contains a kernel body for loop, remove its region from the
13615 TARGET and expand it in GPGPU kernel fashion. */
13617 static void
13618 grid_expand_target_grid_body (struct omp_region *target)
13620 if (!hsa_gen_requested_p ())
13621 return;
13623 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13624 struct omp_region **pp;
13626 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13627 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13628 break;
13630 struct omp_region *gpukernel = *pp;
13632 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13633 if (!gpukernel)
13635 /* HSA cannot handle OACC stuff. */
13636 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13637 return;
13638 gcc_checking_assert (orig_child_fndecl);
13639 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13640 OMP_CLAUSE__GRIDDIM_));
13641 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13643 hsa_register_kernel (n);
13644 return;
13647 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13648 OMP_CLAUSE__GRIDDIM_));
13649 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13650 *pp = gpukernel->next;
13651 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13652 if ((*pp)->type == GIMPLE_OMP_FOR)
13653 break;
13655 struct omp_region *kfor = *pp;
13656 gcc_assert (kfor);
13657 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13658 == GF_OMP_FOR_KIND_GRID_LOOP);
13659 *pp = kfor->next;
13660 if (kfor->inner)
13661 expand_omp (kfor->inner);
13662 if (gpukernel->inner)
13663 expand_omp (gpukernel->inner);
13665 tree kern_fndecl = copy_node (orig_child_fndecl);
13666 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13667 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13668 tree tgtblock = gimple_block (tgt_stmt);
13669 tree fniniblock = make_node (BLOCK);
13670 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13671 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13672 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13673 DECL_INITIAL (kern_fndecl) = fniniblock;
13674 push_struct_function (kern_fndecl);
13675 cfun->function_end_locus = gimple_location (tgt_stmt);
13676 init_tree_ssa (cfun);
13677 pop_cfun ();
13679 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13680 gcc_assert (!DECL_CHAIN (old_parm_decl));
13681 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13682 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13683 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13684 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13685 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13686 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13687 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13688 kern_cfun->curr_properties = cfun->curr_properties;
13690 remove_edge (BRANCH_EDGE (kfor->entry));
13691 grid_expand_omp_for_loop (kfor);
13693 /* Remove the omp for statement */
13694 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13695 gsi_remove (&gsi, true);
13696 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13697 return. */
13698 gsi = gsi_last_bb (gpukernel->exit);
13699 gcc_assert (!gsi_end_p (gsi)
13700 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13701 gimple *ret_stmt = gimple_build_return (NULL);
13702 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13703 gsi_remove (&gsi, true);
13705 /* Statements in the first BB in the target construct have been produced by
13706 target lowering and must be copied inside the GPUKERNEL, with the two
13707 exceptions of the first OMP statement and the OMP_DATA assignment
13708 statement. */
13709 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13710 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13711 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13712 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13713 !gsi_end_p (tsi); gsi_next (&tsi))
13715 gimple *stmt = gsi_stmt (tsi);
13716 if (is_gimple_omp (stmt))
13717 break;
13718 if (sender
13719 && is_gimple_assign (stmt)
13720 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13721 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13722 continue;
13723 gimple *copy = gimple_copy (stmt);
13724 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13725 gimple_set_block (copy, fniniblock);
13728 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13729 gpukernel->exit, inside_block);
13731 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13732 kcn->mark_force_output ();
13733 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13735 hsa_register_kernel (kcn, orig_child);
13737 cgraph_node::add_new_function (kern_fndecl, true);
13738 push_cfun (kern_cfun);
13739 cgraph_edge::rebuild_edges ();
13741 /* Re-map any mention of the PARM_DECL of the original function to the
13742 PARM_DECL of the new one.
13744 TODO: It would be great if lowering produced references into the GPU
13745 kernel decl straight away and we did not have to do this. */
13746 struct grid_arg_decl_map adm;
13747 adm.old_arg = old_parm_decl;
13748 adm.new_arg = new_parm_decl;
13749 basic_block bb;
13750 FOR_EACH_BB_FN (bb, kern_cfun)
13752 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13754 gimple *stmt = gsi_stmt (gsi);
13755 struct walk_stmt_info wi;
13756 memset (&wi, 0, sizeof (wi));
13757 wi.info = &adm;
13758 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13761 pop_cfun ();
13763 return;
13766 /* Expand the parallel region tree rooted at REGION. Expansion
13767 proceeds in depth-first order. Innermost regions are expanded
13768 first. This way, parallel regions that require a new function to
13769 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13770 internal dependencies in their body. */
13772 static void
13773 expand_omp (struct omp_region *region)
13775 omp_any_child_fn_dumped = false;
13776 while (region)
13778 location_t saved_location;
13779 gimple *inner_stmt = NULL;
13781 /* First, determine whether this is a combined parallel+workshare
13782 region. */
13783 if (region->type == GIMPLE_OMP_PARALLEL)
13784 determine_parallel_type (region);
13785 else if (region->type == GIMPLE_OMP_TARGET)
13786 grid_expand_target_grid_body (region);
13788 if (region->type == GIMPLE_OMP_FOR
13789 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13790 inner_stmt = last_stmt (region->inner->entry);
13792 if (region->inner)
13793 expand_omp (region->inner);
13795 saved_location = input_location;
13796 if (gimple_has_location (last_stmt (region->entry)))
13797 input_location = gimple_location (last_stmt (region->entry));
13799 switch (region->type)
13801 case GIMPLE_OMP_PARALLEL:
13802 case GIMPLE_OMP_TASK:
13803 expand_omp_taskreg (region);
13804 break;
13806 case GIMPLE_OMP_FOR:
13807 expand_omp_for (region, inner_stmt);
13808 break;
13810 case GIMPLE_OMP_SECTIONS:
13811 expand_omp_sections (region);
13812 break;
13814 case GIMPLE_OMP_SECTION:
13815 /* Individual omp sections are handled together with their
13816 parent GIMPLE_OMP_SECTIONS region. */
13817 break;
13819 case GIMPLE_OMP_SINGLE:
13820 expand_omp_single (region);
13821 break;
13823 case GIMPLE_OMP_ORDERED:
13825 gomp_ordered *ord_stmt
13826 = as_a <gomp_ordered *> (last_stmt (region->entry));
13827 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13828 OMP_CLAUSE_DEPEND))
13830 /* We'll expand these when expanding corresponding
13831 worksharing region with ordered(n) clause. */
13832 gcc_assert (region->outer
13833 && region->outer->type == GIMPLE_OMP_FOR);
13834 region->ord_stmt = ord_stmt;
13835 break;
13838 /* FALLTHRU */
13839 case GIMPLE_OMP_MASTER:
13840 case GIMPLE_OMP_TASKGROUP:
13841 case GIMPLE_OMP_CRITICAL:
13842 case GIMPLE_OMP_TEAMS:
13843 expand_omp_synch (region);
13844 break;
13846 case GIMPLE_OMP_ATOMIC_LOAD:
13847 expand_omp_atomic (region);
13848 break;
13850 case GIMPLE_OMP_TARGET:
13851 expand_omp_target (region);
13852 break;
13854 default:
13855 gcc_unreachable ();
13858 input_location = saved_location;
13859 region = region->next;
13861 if (omp_any_child_fn_dumped)
13863 if (dump_file)
13864 dump_function_header (dump_file, current_function_decl, dump_flags);
13865 omp_any_child_fn_dumped = false;
13870 /* Helper for build_omp_regions. Scan the dominator tree starting at
13871 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13872 true, the function ends once a single tree is built (otherwise, whole
13873 forest of OMP constructs may be built). */
13875 static void
13876 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13877 bool single_tree)
13879 gimple_stmt_iterator gsi;
13880 gimple *stmt;
13881 basic_block son;
13883 gsi = gsi_last_bb (bb);
13884 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13886 struct omp_region *region;
13887 enum gimple_code code;
13889 stmt = gsi_stmt (gsi);
13890 code = gimple_code (stmt);
13891 if (code == GIMPLE_OMP_RETURN)
13893 /* STMT is the return point out of region PARENT. Mark it
13894 as the exit point and make PARENT the immediately
13895 enclosing region. */
13896 gcc_assert (parent);
13897 region = parent;
13898 region->exit = bb;
13899 parent = parent->outer;
13901 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13903 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13904 GIMPLE_OMP_RETURN, but matches with
13905 GIMPLE_OMP_ATOMIC_LOAD. */
13906 gcc_assert (parent);
13907 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13908 region = parent;
13909 region->exit = bb;
13910 parent = parent->outer;
13912 else if (code == GIMPLE_OMP_CONTINUE)
13914 gcc_assert (parent);
13915 parent->cont = bb;
13917 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13919 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13920 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13922 else
13924 region = new_omp_region (bb, code, parent);
13925 /* Otherwise... */
13926 if (code == GIMPLE_OMP_TARGET)
13928 switch (gimple_omp_target_kind (stmt))
13930 case GF_OMP_TARGET_KIND_REGION:
13931 case GF_OMP_TARGET_KIND_DATA:
13932 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13933 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13934 case GF_OMP_TARGET_KIND_OACC_DATA:
13935 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13936 break;
13937 case GF_OMP_TARGET_KIND_UPDATE:
13938 case GF_OMP_TARGET_KIND_ENTER_DATA:
13939 case GF_OMP_TARGET_KIND_EXIT_DATA:
13940 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13941 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13942 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13943 /* ..., other than for those stand-alone directives... */
13944 region = NULL;
13945 break;
13946 default:
13947 gcc_unreachable ();
13950 else if (code == GIMPLE_OMP_ORDERED
13951 && find_omp_clause (gimple_omp_ordered_clauses
13952 (as_a <gomp_ordered *> (stmt)),
13953 OMP_CLAUSE_DEPEND))
13954 /* #pragma omp ordered depend is also just a stand-alone
13955 directive. */
13956 region = NULL;
13957 /* ..., this directive becomes the parent for a new region. */
13958 if (region)
13959 parent = region;
13963 if (single_tree && !parent)
13964 return;
13966 for (son = first_dom_son (CDI_DOMINATORS, bb);
13967 son;
13968 son = next_dom_son (CDI_DOMINATORS, son))
13969 build_omp_regions_1 (son, parent, single_tree);
13972 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13973 root_omp_region. */
13975 static void
13976 build_omp_regions_root (basic_block root)
13978 gcc_assert (root_omp_region == NULL);
13979 build_omp_regions_1 (root, NULL, true);
13980 gcc_assert (root_omp_region != NULL);
13983 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13985 void
13986 omp_expand_local (basic_block head)
13988 build_omp_regions_root (head);
13989 if (dump_file && (dump_flags & TDF_DETAILS))
13991 fprintf (dump_file, "\nOMP region tree\n\n");
13992 dump_omp_region (dump_file, root_omp_region, 0);
13993 fprintf (dump_file, "\n");
13996 remove_exit_barriers (root_omp_region);
13997 expand_omp (root_omp_region);
13999 free_omp_regions ();
14002 /* Scan the CFG and build a tree of OMP regions. Return the root of
14003 the OMP region tree. */
14005 static void
14006 build_omp_regions (void)
14008 gcc_assert (root_omp_region == NULL);
14009 calculate_dominance_info (CDI_DOMINATORS);
14010 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14013 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14015 static unsigned int
14016 execute_expand_omp (void)
14018 build_omp_regions ();
14020 if (!root_omp_region)
14021 return 0;
14023 if (dump_file)
14025 fprintf (dump_file, "\nOMP region tree\n\n");
14026 dump_omp_region (dump_file, root_omp_region, 0);
14027 fprintf (dump_file, "\n");
14030 remove_exit_barriers (root_omp_region);
14032 expand_omp (root_omp_region);
14034 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14035 verify_loop_structure ();
14036 cleanup_tree_cfg ();
14038 free_omp_regions ();
14040 return 0;
14043 /* OMP expansion -- the default pass, run before creation of SSA form. */
14045 namespace {
14047 const pass_data pass_data_expand_omp =
14049 GIMPLE_PASS, /* type */
14050 "ompexp", /* name */
14051 OPTGROUP_NONE, /* optinfo_flags */
14052 TV_NONE, /* tv_id */
14053 PROP_gimple_any, /* properties_required */
14054 PROP_gimple_eomp, /* properties_provided */
14055 0, /* properties_destroyed */
14056 0, /* todo_flags_start */
14057 0, /* todo_flags_finish */
14060 class pass_expand_omp : public gimple_opt_pass
14062 public:
14063 pass_expand_omp (gcc::context *ctxt)
14064 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14067 /* opt_pass methods: */
14068 virtual unsigned int execute (function *)
14070 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14071 || flag_openmp_simd != 0)
14072 && !seen_error ());
14074 /* This pass always runs, to provide PROP_gimple_eomp.
14075 But often, there is nothing to do. */
14076 if (!gate)
14077 return 0;
14079 return execute_expand_omp ();
14082 }; // class pass_expand_omp
14084 } // anon namespace
14086 gimple_opt_pass *
14087 make_pass_expand_omp (gcc::context *ctxt)
14089 return new pass_expand_omp (ctxt);
14092 namespace {
14094 const pass_data pass_data_expand_omp_ssa =
14096 GIMPLE_PASS, /* type */
14097 "ompexpssa", /* name */
14098 OPTGROUP_NONE, /* optinfo_flags */
14099 TV_NONE, /* tv_id */
14100 PROP_cfg | PROP_ssa, /* properties_required */
14101 PROP_gimple_eomp, /* properties_provided */
14102 0, /* properties_destroyed */
14103 0, /* todo_flags_start */
14104 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14107 class pass_expand_omp_ssa : public gimple_opt_pass
14109 public:
14110 pass_expand_omp_ssa (gcc::context *ctxt)
14111 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14114 /* opt_pass methods: */
14115 virtual bool gate (function *fun)
14117 return !(fun->curr_properties & PROP_gimple_eomp);
14119 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14120 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14122 }; // class pass_expand_omp_ssa
14124 } // anon namespace
14126 gimple_opt_pass *
14127 make_pass_expand_omp_ssa (gcc::context *ctxt)
14129 return new pass_expand_omp_ssa (ctxt);
14132 /* Routines to lower OMP directives into OMP-GIMPLE. */
14134 /* If ctx is a worksharing context inside of a cancellable parallel
14135 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14136 and conditional branch to parallel's cancel_label to handle
14137 cancellation in the implicit barrier. */
14139 static void
14140 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14142 gimple *omp_return = gimple_seq_last_stmt (*body);
14143 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14144 if (gimple_omp_return_nowait_p (omp_return))
14145 return;
14146 if (ctx->outer
14147 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14148 && ctx->outer->cancellable)
14150 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14151 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14152 tree lhs = create_tmp_var (c_bool_type);
14153 gimple_omp_return_set_lhs (omp_return, lhs);
14154 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14155 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14156 fold_convert (c_bool_type,
14157 boolean_false_node),
14158 ctx->outer->cancel_label, fallthru_label);
14159 gimple_seq_add_stmt (body, g);
14160 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14164 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14165 CTX is the enclosing OMP context for the current statement. */
14167 static void
14168 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14170 tree block, control;
14171 gimple_stmt_iterator tgsi;
14172 gomp_sections *stmt;
14173 gimple *t;
14174 gbind *new_stmt, *bind;
14175 gimple_seq ilist, dlist, olist, new_body;
14177 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14179 push_gimplify_context ();
14181 dlist = NULL;
14182 ilist = NULL;
14183 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14184 &ilist, &dlist, ctx, NULL);
14186 new_body = gimple_omp_body (stmt);
14187 gimple_omp_set_body (stmt, NULL);
14188 tgsi = gsi_start (new_body);
14189 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14191 omp_context *sctx;
14192 gimple *sec_start;
14194 sec_start = gsi_stmt (tgsi);
14195 sctx = maybe_lookup_ctx (sec_start);
14196 gcc_assert (sctx);
14198 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14199 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14200 GSI_CONTINUE_LINKING);
14201 gimple_omp_set_body (sec_start, NULL);
14203 if (gsi_one_before_end_p (tgsi))
14205 gimple_seq l = NULL;
14206 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14207 &l, ctx);
14208 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14209 gimple_omp_section_set_last (sec_start);
14212 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14213 GSI_CONTINUE_LINKING);
14216 block = make_node (BLOCK);
14217 bind = gimple_build_bind (NULL, new_body, block);
14219 olist = NULL;
14220 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14222 block = make_node (BLOCK);
14223 new_stmt = gimple_build_bind (NULL, NULL, block);
14224 gsi_replace (gsi_p, new_stmt, true);
14226 pop_gimplify_context (new_stmt);
14227 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14228 BLOCK_VARS (block) = gimple_bind_vars (bind);
14229 if (BLOCK_VARS (block))
14230 TREE_USED (block) = 1;
14232 new_body = NULL;
14233 gimple_seq_add_seq (&new_body, ilist);
14234 gimple_seq_add_stmt (&new_body, stmt);
14235 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14236 gimple_seq_add_stmt (&new_body, bind);
14238 control = create_tmp_var (unsigned_type_node, ".section");
14239 t = gimple_build_omp_continue (control, control);
14240 gimple_omp_sections_set_control (stmt, control);
14241 gimple_seq_add_stmt (&new_body, t);
14243 gimple_seq_add_seq (&new_body, olist);
14244 if (ctx->cancellable)
14245 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14246 gimple_seq_add_seq (&new_body, dlist);
14248 new_body = maybe_catch_exception (new_body);
14250 t = gimple_build_omp_return
14251 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14252 OMP_CLAUSE_NOWAIT));
14253 gimple_seq_add_stmt (&new_body, t);
14254 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14256 gimple_bind_set_body (new_stmt, new_body);
14260 /* A subroutine of lower_omp_single. Expand the simple form of
14261 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14263 if (GOMP_single_start ())
14264 BODY;
14265 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14267 FIXME. It may be better to delay expanding the logic of this until
14268 pass_expand_omp. The expanded logic may make the job more difficult
14269 to a synchronization analysis pass. */
14271 static void
14272 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14274 location_t loc = gimple_location (single_stmt);
14275 tree tlabel = create_artificial_label (loc);
14276 tree flabel = create_artificial_label (loc);
14277 gimple *call, *cond;
14278 tree lhs, decl;
14280 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14281 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14282 call = gimple_build_call (decl, 0);
14283 gimple_call_set_lhs (call, lhs);
14284 gimple_seq_add_stmt (pre_p, call);
14286 cond = gimple_build_cond (EQ_EXPR, lhs,
14287 fold_convert_loc (loc, TREE_TYPE (lhs),
14288 boolean_true_node),
14289 tlabel, flabel);
14290 gimple_seq_add_stmt (pre_p, cond);
14291 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14292 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14293 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14297 /* A subroutine of lower_omp_single. Expand the simple form of
14298 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14300 #pragma omp single copyprivate (a, b, c)
14302 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14305 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14307 BODY;
14308 copyout.a = a;
14309 copyout.b = b;
14310 copyout.c = c;
14311 GOMP_single_copy_end (&copyout);
14313 else
14315 a = copyout_p->a;
14316 b = copyout_p->b;
14317 c = copyout_p->c;
14319 GOMP_barrier ();
14322 FIXME. It may be better to delay expanding the logic of this until
14323 pass_expand_omp. The expanded logic may make the job more difficult
14324 to a synchronization analysis pass. */
14326 static void
14327 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14328 omp_context *ctx)
14330 tree ptr_type, t, l0, l1, l2, bfn_decl;
14331 gimple_seq copyin_seq;
14332 location_t loc = gimple_location (single_stmt);
14334 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14336 ptr_type = build_pointer_type (ctx->record_type);
14337 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14339 l0 = create_artificial_label (loc);
14340 l1 = create_artificial_label (loc);
14341 l2 = create_artificial_label (loc);
14343 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14344 t = build_call_expr_loc (loc, bfn_decl, 0);
14345 t = fold_convert_loc (loc, ptr_type, t);
14346 gimplify_assign (ctx->receiver_decl, t, pre_p);
14348 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14349 build_int_cst (ptr_type, 0));
14350 t = build3 (COND_EXPR, void_type_node, t,
14351 build_and_jump (&l0), build_and_jump (&l1));
14352 gimplify_and_add (t, pre_p);
14354 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14356 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14358 copyin_seq = NULL;
14359 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14360 &copyin_seq, ctx);
14362 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14363 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14364 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14365 gimplify_and_add (t, pre_p);
14367 t = build_and_jump (&l2);
14368 gimplify_and_add (t, pre_p);
14370 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14372 gimple_seq_add_seq (pre_p, copyin_seq);
14374 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14378 /* Expand code for an OpenMP single directive. */
14380 static void
14381 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14383 tree block;
14384 gimple *t;
14385 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14386 gbind *bind;
14387 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14389 push_gimplify_context ();
14391 block = make_node (BLOCK);
14392 bind = gimple_build_bind (NULL, NULL, block);
14393 gsi_replace (gsi_p, bind, true);
14394 bind_body = NULL;
14395 dlist = NULL;
14396 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14397 &bind_body, &dlist, ctx, NULL);
14398 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14400 gimple_seq_add_stmt (&bind_body, single_stmt);
14402 if (ctx->record_type)
14403 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14404 else
14405 lower_omp_single_simple (single_stmt, &bind_body);
14407 gimple_omp_set_body (single_stmt, NULL);
14409 gimple_seq_add_seq (&bind_body, dlist);
14411 bind_body = maybe_catch_exception (bind_body);
14413 t = gimple_build_omp_return
14414 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14415 OMP_CLAUSE_NOWAIT));
14416 gimple_seq_add_stmt (&bind_body_tail, t);
14417 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14418 if (ctx->record_type)
14420 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14421 tree clobber = build_constructor (ctx->record_type, NULL);
14422 TREE_THIS_VOLATILE (clobber) = 1;
14423 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14424 clobber), GSI_SAME_STMT);
14426 gimple_seq_add_seq (&bind_body, bind_body_tail);
14427 gimple_bind_set_body (bind, bind_body);
14429 pop_gimplify_context (bind);
14431 gimple_bind_append_vars (bind, ctx->block_vars);
14432 BLOCK_VARS (block) = ctx->block_vars;
14433 if (BLOCK_VARS (block))
14434 TREE_USED (block) = 1;
14438 /* Expand code for an OpenMP master directive. */
14440 static void
14441 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14443 tree block, lab = NULL, x, bfn_decl;
14444 gimple *stmt = gsi_stmt (*gsi_p);
14445 gbind *bind;
14446 location_t loc = gimple_location (stmt);
14447 gimple_seq tseq;
14449 push_gimplify_context ();
14451 block = make_node (BLOCK);
14452 bind = gimple_build_bind (NULL, NULL, block);
14453 gsi_replace (gsi_p, bind, true);
14454 gimple_bind_add_stmt (bind, stmt);
14456 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14457 x = build_call_expr_loc (loc, bfn_decl, 0);
14458 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14459 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14460 tseq = NULL;
14461 gimplify_and_add (x, &tseq);
14462 gimple_bind_add_seq (bind, tseq);
14464 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14465 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14466 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14467 gimple_omp_set_body (stmt, NULL);
14469 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14471 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14473 pop_gimplify_context (bind);
14475 gimple_bind_append_vars (bind, ctx->block_vars);
14476 BLOCK_VARS (block) = ctx->block_vars;
14480 /* Expand code for an OpenMP taskgroup directive. */
14482 static void
14483 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14485 gimple *stmt = gsi_stmt (*gsi_p);
14486 gcall *x;
14487 gbind *bind;
14488 tree block = make_node (BLOCK);
14490 bind = gimple_build_bind (NULL, NULL, block);
14491 gsi_replace (gsi_p, bind, true);
14492 gimple_bind_add_stmt (bind, stmt);
14494 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14496 gimple_bind_add_stmt (bind, x);
14498 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14499 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14500 gimple_omp_set_body (stmt, NULL);
14502 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14504 gimple_bind_append_vars (bind, ctx->block_vars);
14505 BLOCK_VARS (block) = ctx->block_vars;
14509 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14511 static void
14512 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14513 omp_context *ctx)
14515 struct omp_for_data fd;
14516 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14517 return;
14519 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14520 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14521 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14522 if (!fd.ordered)
14523 return;
14525 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14526 tree c = gimple_omp_ordered_clauses (ord_stmt);
14527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14528 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14530 /* Merge depend clauses from multiple adjacent
14531 #pragma omp ordered depend(sink:...) constructs
14532 into one #pragma omp ordered depend(sink:...), so that
14533 we can optimize them together. */
14534 gimple_stmt_iterator gsi = *gsi_p;
14535 gsi_next (&gsi);
14536 while (!gsi_end_p (gsi))
14538 gimple *stmt = gsi_stmt (gsi);
14539 if (is_gimple_debug (stmt)
14540 || gimple_code (stmt) == GIMPLE_NOP)
14542 gsi_next (&gsi);
14543 continue;
14545 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14546 break;
14547 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14548 c = gimple_omp_ordered_clauses (ord_stmt2);
14549 if (c == NULL_TREE
14550 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14551 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14552 break;
14553 while (*list_p)
14554 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14555 *list_p = c;
14556 gsi_remove (&gsi, true);
14560 /* Canonicalize sink dependence clauses into one folded clause if
14561 possible.
14563 The basic algorithm is to create a sink vector whose first
14564 element is the GCD of all the first elements, and whose remaining
14565 elements are the minimum of the subsequent columns.
14567 We ignore dependence vectors whose first element is zero because
14568 such dependencies are known to be executed by the same thread.
14570 We take into account the direction of the loop, so a minimum
14571 becomes a maximum if the loop is iterating forwards. We also
14572 ignore sink clauses where the loop direction is unknown, or where
14573 the offsets are clearly invalid because they are not a multiple
14574 of the loop increment.
14576 For example:
14578 #pragma omp for ordered(2)
14579 for (i=0; i < N; ++i)
14580 for (j=0; j < M; ++j)
14582 #pragma omp ordered \
14583 depend(sink:i-8,j-2) \
14584 depend(sink:i,j-1) \ // Completely ignored because i+0.
14585 depend(sink:i-4,j-3) \
14586 depend(sink:i-6,j-4)
14587 #pragma omp ordered depend(source)
14590 Folded clause is:
14592 depend(sink:-gcd(8,4,6),-min(2,3,4))
14593 -or-
14594 depend(sink:-2,-2)
14597 /* FIXME: Computing GCD's where the first element is zero is
14598 non-trivial in the presence of collapsed loops. Do this later. */
14599 if (fd.collapse > 1)
14600 return;
14602 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14603 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14604 tree folded_dep = NULL_TREE;
14605 /* TRUE if the first dimension's offset is negative. */
14606 bool neg_offset_p = false;
14608 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14609 unsigned int i;
14610 while ((c = *list_p) != NULL)
14612 bool remove = false;
14614 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14615 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14616 goto next_ordered_clause;
14618 tree vec;
14619 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14620 vec && TREE_CODE (vec) == TREE_LIST;
14621 vec = TREE_CHAIN (vec), ++i)
14623 gcc_assert (i < len);
14625 /* extract_omp_for_data has canonicalized the condition. */
14626 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14627 || fd.loops[i].cond_code == GT_EXPR);
14628 bool forward = fd.loops[i].cond_code == LT_EXPR;
14629 bool maybe_lexically_later = true;
14631 /* While the committee makes up its mind, bail if we have any
14632 non-constant steps. */
14633 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14634 goto lower_omp_ordered_ret;
14636 tree itype = TREE_TYPE (TREE_VALUE (vec));
14637 if (POINTER_TYPE_P (itype))
14638 itype = sizetype;
14639 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14640 TYPE_PRECISION (itype),
14641 TYPE_SIGN (itype));
14643 /* Ignore invalid offsets that are not multiples of the step. */
14644 if (!wi::multiple_of_p
14645 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14646 UNSIGNED))
14648 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14649 "ignoring sink clause with offset that is not "
14650 "a multiple of the loop step");
14651 remove = true;
14652 goto next_ordered_clause;
14655 /* Calculate the first dimension. The first dimension of
14656 the folded dependency vector is the GCD of the first
14657 elements, while ignoring any first elements whose offset
14658 is 0. */
14659 if (i == 0)
14661 /* Ignore dependence vectors whose first dimension is 0. */
14662 if (offset == 0)
14664 remove = true;
14665 goto next_ordered_clause;
14667 else
14669 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14671 error_at (OMP_CLAUSE_LOCATION (c),
14672 "first offset must be in opposite direction "
14673 "of loop iterations");
14674 goto lower_omp_ordered_ret;
14676 if (forward)
14677 offset = -offset;
14678 neg_offset_p = forward;
14679 /* Initialize the first time around. */
14680 if (folded_dep == NULL_TREE)
14682 folded_dep = c;
14683 folded_deps[0] = offset;
14685 else
14686 folded_deps[0] = wi::gcd (folded_deps[0],
14687 offset, UNSIGNED);
14690 /* Calculate minimum for the remaining dimensions. */
14691 else
14693 folded_deps[len + i - 1] = offset;
14694 if (folded_dep == c)
14695 folded_deps[i] = offset;
14696 else if (maybe_lexically_later
14697 && !wi::eq_p (folded_deps[i], offset))
14699 if (forward ^ wi::gts_p (folded_deps[i], offset))
14701 unsigned int j;
14702 folded_dep = c;
14703 for (j = 1; j <= i; j++)
14704 folded_deps[j] = folded_deps[len + j - 1];
14706 else
14707 maybe_lexically_later = false;
14711 gcc_assert (i == len);
14713 remove = true;
14715 next_ordered_clause:
14716 if (remove)
14717 *list_p = OMP_CLAUSE_CHAIN (c);
14718 else
14719 list_p = &OMP_CLAUSE_CHAIN (c);
14722 if (folded_dep)
14724 if (neg_offset_p)
14725 folded_deps[0] = -folded_deps[0];
14727 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14728 if (POINTER_TYPE_P (itype))
14729 itype = sizetype;
14731 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14732 = wide_int_to_tree (itype, folded_deps[0]);
14733 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14734 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14737 lower_omp_ordered_ret:
14739 /* Ordered without clauses is #pragma omp threads, while we want
14740 a nop instead if we remove all clauses. */
14741 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14742 gsi_replace (gsi_p, gimple_build_nop (), true);
14746 /* Expand code for an OpenMP ordered directive. */
14748 static void
14749 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14751 tree block;
14752 gimple *stmt = gsi_stmt (*gsi_p);
14753 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14754 gcall *x;
14755 gbind *bind;
14756 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14757 OMP_CLAUSE_SIMD);
14758 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14759 OMP_CLAUSE_THREADS);
14761 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14762 OMP_CLAUSE_DEPEND))
14764 /* FIXME: This is needs to be moved to the expansion to verify various
14765 conditions only testable on cfg with dominators computed, and also
14766 all the depend clauses to be merged still might need to be available
14767 for the runtime checks. */
14768 if (0)
14769 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14770 return;
14773 push_gimplify_context ();
14775 block = make_node (BLOCK);
14776 bind = gimple_build_bind (NULL, NULL, block);
14777 gsi_replace (gsi_p, bind, true);
14778 gimple_bind_add_stmt (bind, stmt);
14780 if (simd)
14782 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14783 build_int_cst (NULL_TREE, threads));
14784 cfun->has_simduid_loops = true;
14786 else
14787 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14789 gimple_bind_add_stmt (bind, x);
14791 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14792 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14793 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14794 gimple_omp_set_body (stmt, NULL);
14796 if (simd)
14797 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14798 build_int_cst (NULL_TREE, threads));
14799 else
14800 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14802 gimple_bind_add_stmt (bind, x);
14804 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14806 pop_gimplify_context (bind);
14808 gimple_bind_append_vars (bind, ctx->block_vars);
14809 BLOCK_VARS (block) = gimple_bind_vars (bind);
14813 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14814 substitution of a couple of function calls. But in the NAMED case,
14815 requires that languages coordinate a symbol name. It is therefore
14816 best put here in common code. */
14818 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14820 static void
14821 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14823 tree block;
14824 tree name, lock, unlock;
14825 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14826 gbind *bind;
14827 location_t loc = gimple_location (stmt);
14828 gimple_seq tbody;
14830 name = gimple_omp_critical_name (stmt);
14831 if (name)
14833 tree decl;
14835 if (!critical_name_mutexes)
14836 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14838 tree *n = critical_name_mutexes->get (name);
14839 if (n == NULL)
14841 char *new_str;
14843 decl = create_tmp_var_raw (ptr_type_node);
14845 new_str = ACONCAT ((".gomp_critical_user_",
14846 IDENTIFIER_POINTER (name), NULL));
14847 DECL_NAME (decl) = get_identifier (new_str);
14848 TREE_PUBLIC (decl) = 1;
14849 TREE_STATIC (decl) = 1;
14850 DECL_COMMON (decl) = 1;
14851 DECL_ARTIFICIAL (decl) = 1;
14852 DECL_IGNORED_P (decl) = 1;
14854 varpool_node::finalize_decl (decl);
14856 critical_name_mutexes->put (name, decl);
14858 else
14859 decl = *n;
14861 /* If '#pragma omp critical' is inside offloaded region or
14862 inside function marked as offloadable, the symbol must be
14863 marked as offloadable too. */
14864 omp_context *octx;
14865 if (cgraph_node::get (current_function_decl)->offloadable)
14866 varpool_node::get_create (decl)->offloadable = 1;
14867 else
14868 for (octx = ctx->outer; octx; octx = octx->outer)
14869 if (is_gimple_omp_offloaded (octx->stmt))
14871 varpool_node::get_create (decl)->offloadable = 1;
14872 break;
14875 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14876 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14878 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14879 unlock = build_call_expr_loc (loc, unlock, 1,
14880 build_fold_addr_expr_loc (loc, decl));
14882 else
14884 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14885 lock = build_call_expr_loc (loc, lock, 0);
14887 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14888 unlock = build_call_expr_loc (loc, unlock, 0);
14891 push_gimplify_context ();
14893 block = make_node (BLOCK);
14894 bind = gimple_build_bind (NULL, NULL, block);
14895 gsi_replace (gsi_p, bind, true);
14896 gimple_bind_add_stmt (bind, stmt);
14898 tbody = gimple_bind_body (bind);
14899 gimplify_and_add (lock, &tbody);
14900 gimple_bind_set_body (bind, tbody);
14902 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14903 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14904 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14905 gimple_omp_set_body (stmt, NULL);
14907 tbody = gimple_bind_body (bind);
14908 gimplify_and_add (unlock, &tbody);
14909 gimple_bind_set_body (bind, tbody);
14911 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14913 pop_gimplify_context (bind);
14914 gimple_bind_append_vars (bind, ctx->block_vars);
14915 BLOCK_VARS (block) = gimple_bind_vars (bind);
14919 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14920 for a lastprivate clause. Given a loop control predicate of (V
14921 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14922 is appended to *DLIST, iterator initialization is appended to
14923 *BODY_P. */
14925 static void
14926 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14927 gimple_seq *dlist, struct omp_context *ctx)
14929 tree clauses, cond, vinit;
14930 enum tree_code cond_code;
14931 gimple_seq stmts;
14933 cond_code = fd->loop.cond_code;
14934 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14936 /* When possible, use a strict equality expression. This can let VRP
14937 type optimizations deduce the value and remove a copy. */
14938 if (tree_fits_shwi_p (fd->loop.step))
14940 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14941 if (step == 1 || step == -1)
14942 cond_code = EQ_EXPR;
14945 tree n2 = fd->loop.n2;
14946 if (fd->collapse > 1
14947 && TREE_CODE (n2) != INTEGER_CST
14948 && gimple_omp_for_combined_into_p (fd->for_stmt))
14950 struct omp_context *taskreg_ctx = NULL;
14951 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14953 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14954 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14955 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14957 if (gimple_omp_for_combined_into_p (gfor))
14959 gcc_assert (ctx->outer->outer
14960 && is_parallel_ctx (ctx->outer->outer));
14961 taskreg_ctx = ctx->outer->outer;
14963 else
14965 struct omp_for_data outer_fd;
14966 extract_omp_for_data (gfor, &outer_fd, NULL);
14967 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14970 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14971 taskreg_ctx = ctx->outer->outer;
14973 else if (is_taskreg_ctx (ctx->outer))
14974 taskreg_ctx = ctx->outer;
14975 if (taskreg_ctx)
14977 int i;
14978 tree innerc
14979 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14980 OMP_CLAUSE__LOOPTEMP_);
14981 gcc_assert (innerc);
14982 for (i = 0; i < fd->collapse; i++)
14984 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14985 OMP_CLAUSE__LOOPTEMP_);
14986 gcc_assert (innerc);
14988 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14989 OMP_CLAUSE__LOOPTEMP_);
14990 if (innerc)
14991 n2 = fold_convert (TREE_TYPE (n2),
14992 lookup_decl (OMP_CLAUSE_DECL (innerc),
14993 taskreg_ctx));
14996 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14998 clauses = gimple_omp_for_clauses (fd->for_stmt);
14999 stmts = NULL;
15000 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15001 if (!gimple_seq_empty_p (stmts))
15003 gimple_seq_add_seq (&stmts, *dlist);
15004 *dlist = stmts;
15006 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15007 vinit = fd->loop.n1;
15008 if (cond_code == EQ_EXPR
15009 && tree_fits_shwi_p (fd->loop.n2)
15010 && ! integer_zerop (fd->loop.n2))
15011 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15012 else
15013 vinit = unshare_expr (vinit);
15015 /* Initialize the iterator variable, so that threads that don't execute
15016 any iterations don't execute the lastprivate clauses by accident. */
15017 gimplify_assign (fd->loop.v, vinit, body_p);
15022 /* Lower code for an OMP loop directive. */
15024 static void
15025 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15027 tree *rhs_p, block;
15028 struct omp_for_data fd, *fdp = NULL;
15029 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15030 gbind *new_stmt;
15031 gimple_seq omp_for_body, body, dlist;
15032 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15033 size_t i;
15035 push_gimplify_context ();
15037 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15039 block = make_node (BLOCK);
15040 new_stmt = gimple_build_bind (NULL, NULL, block);
15041 /* Replace at gsi right away, so that 'stmt' is no member
15042 of a sequence anymore as we're going to add to a different
15043 one below. */
15044 gsi_replace (gsi_p, new_stmt, true);
15046 /* Move declaration of temporaries in the loop body before we make
15047 it go away. */
15048 omp_for_body = gimple_omp_body (stmt);
15049 if (!gimple_seq_empty_p (omp_for_body)
15050 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15052 gbind *inner_bind
15053 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15054 tree vars = gimple_bind_vars (inner_bind);
15055 gimple_bind_append_vars (new_stmt, vars);
15056 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15057 keep them on the inner_bind and it's block. */
15058 gimple_bind_set_vars (inner_bind, NULL_TREE);
15059 if (gimple_bind_block (inner_bind))
15060 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15063 if (gimple_omp_for_combined_into_p (stmt))
15065 extract_omp_for_data (stmt, &fd, NULL);
15066 fdp = &fd;
15068 /* We need two temporaries with fd.loop.v type (istart/iend)
15069 and then (fd.collapse - 1) temporaries with the same
15070 type for count2 ... countN-1 vars if not constant. */
15071 size_t count = 2;
15072 tree type = fd.iter_type;
15073 if (fd.collapse > 1
15074 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15075 count += fd.collapse - 1;
15076 bool taskreg_for
15077 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15078 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15079 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15080 tree clauses = *pc;
15081 if (taskreg_for)
15082 outerc
15083 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15084 OMP_CLAUSE__LOOPTEMP_);
15085 for (i = 0; i < count; i++)
15087 tree temp;
15088 if (taskreg_for)
15090 gcc_assert (outerc);
15091 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15092 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15093 OMP_CLAUSE__LOOPTEMP_);
15095 else
15097 temp = create_tmp_var (type);
15098 insert_decl_map (&ctx->outer->cb, temp, temp);
15100 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15101 OMP_CLAUSE_DECL (*pc) = temp;
15102 pc = &OMP_CLAUSE_CHAIN (*pc);
15104 *pc = clauses;
15107 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15108 dlist = NULL;
15109 body = NULL;
15110 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15111 fdp);
15112 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15114 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15116 /* Lower the header expressions. At this point, we can assume that
15117 the header is of the form:
15119 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15121 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15122 using the .omp_data_s mapping, if needed. */
15123 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15125 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15126 if (!is_gimple_min_invariant (*rhs_p))
15127 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15129 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15130 if (!is_gimple_min_invariant (*rhs_p))
15131 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15133 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15134 if (!is_gimple_min_invariant (*rhs_p))
15135 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15138 /* Once lowered, extract the bounds and clauses. */
15139 extract_omp_for_data (stmt, &fd, NULL);
15141 if (is_gimple_omp_oacc (ctx->stmt)
15142 && !ctx_in_oacc_kernels_region (ctx))
15143 lower_oacc_head_tail (gimple_location (stmt),
15144 gimple_omp_for_clauses (stmt),
15145 &oacc_head, &oacc_tail, ctx);
15147 /* Add OpenACC partitioning and reduction markers just before the loop */
15148 if (oacc_head)
15149 gimple_seq_add_seq (&body, oacc_head);
15151 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15153 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15154 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15155 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15156 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15158 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15159 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15160 OMP_CLAUSE_LINEAR_STEP (c)
15161 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15162 ctx);
15165 if (!gimple_omp_for_grid_phony (stmt))
15166 gimple_seq_add_stmt (&body, stmt);
15167 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15169 if (!gimple_omp_for_grid_phony (stmt))
15170 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15171 fd.loop.v));
15173 /* After the loop, add exit clauses. */
15174 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15176 if (ctx->cancellable)
15177 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15179 gimple_seq_add_seq (&body, dlist);
15181 body = maybe_catch_exception (body);
15183 if (!gimple_omp_for_grid_phony (stmt))
15185 /* Region exit marker goes at the end of the loop body. */
15186 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15187 maybe_add_implicit_barrier_cancel (ctx, &body);
15190 /* Add OpenACC joining and reduction markers just after the loop. */
15191 if (oacc_tail)
15192 gimple_seq_add_seq (&body, oacc_tail);
15194 pop_gimplify_context (new_stmt);
15196 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15197 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15198 if (BLOCK_VARS (block))
15199 TREE_USED (block) = 1;
15201 gimple_bind_set_body (new_stmt, body);
15202 gimple_omp_set_body (stmt, NULL);
15203 gimple_omp_for_set_pre_body (stmt, NULL);
15206 /* Callback for walk_stmts. Check if the current statement only contains
15207 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15209 static tree
15210 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15211 bool *handled_ops_p,
15212 struct walk_stmt_info *wi)
15214 int *info = (int *) wi->info;
15215 gimple *stmt = gsi_stmt (*gsi_p);
15217 *handled_ops_p = true;
15218 switch (gimple_code (stmt))
15220 WALK_SUBSTMTS;
15222 case GIMPLE_OMP_FOR:
15223 case GIMPLE_OMP_SECTIONS:
15224 *info = *info == 0 ? 1 : -1;
15225 break;
15226 default:
15227 *info = -1;
15228 break;
15230 return NULL;
15233 struct omp_taskcopy_context
15235 /* This field must be at the beginning, as we do "inheritance": Some
15236 callback functions for tree-inline.c (e.g., omp_copy_decl)
15237 receive a copy_body_data pointer that is up-casted to an
15238 omp_context pointer. */
15239 copy_body_data cb;
15240 omp_context *ctx;
15243 static tree
15244 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15246 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15248 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15249 return create_tmp_var (TREE_TYPE (var));
15251 return var;
15254 static tree
15255 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15257 tree name, new_fields = NULL, type, f;
15259 type = lang_hooks.types.make_type (RECORD_TYPE);
15260 name = DECL_NAME (TYPE_NAME (orig_type));
15261 name = build_decl (gimple_location (tcctx->ctx->stmt),
15262 TYPE_DECL, name, type);
15263 TYPE_NAME (type) = name;
15265 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15267 tree new_f = copy_node (f);
15268 DECL_CONTEXT (new_f) = type;
15269 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15270 TREE_CHAIN (new_f) = new_fields;
15271 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15272 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15273 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15274 &tcctx->cb, NULL);
15275 new_fields = new_f;
15276 tcctx->cb.decl_map->put (f, new_f);
15278 TYPE_FIELDS (type) = nreverse (new_fields);
15279 layout_type (type);
15280 return type;
15283 /* Create task copyfn. */
15285 static void
15286 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15288 struct function *child_cfun;
15289 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15290 tree record_type, srecord_type, bind, list;
15291 bool record_needs_remap = false, srecord_needs_remap = false;
15292 splay_tree_node n;
15293 struct omp_taskcopy_context tcctx;
15294 location_t loc = gimple_location (task_stmt);
15296 child_fn = gimple_omp_task_copy_fn (task_stmt);
15297 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15298 gcc_assert (child_cfun->cfg == NULL);
15299 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15301 /* Reset DECL_CONTEXT on function arguments. */
15302 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15303 DECL_CONTEXT (t) = child_fn;
15305 /* Populate the function. */
15306 push_gimplify_context ();
15307 push_cfun (child_cfun);
15309 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15310 TREE_SIDE_EFFECTS (bind) = 1;
15311 list = NULL;
15312 DECL_SAVED_TREE (child_fn) = bind;
15313 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15315 /* Remap src and dst argument types if needed. */
15316 record_type = ctx->record_type;
15317 srecord_type = ctx->srecord_type;
15318 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15319 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15321 record_needs_remap = true;
15322 break;
15324 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15325 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15327 srecord_needs_remap = true;
15328 break;
15331 if (record_needs_remap || srecord_needs_remap)
15333 memset (&tcctx, '\0', sizeof (tcctx));
15334 tcctx.cb.src_fn = ctx->cb.src_fn;
15335 tcctx.cb.dst_fn = child_fn;
15336 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15337 gcc_checking_assert (tcctx.cb.src_node);
15338 tcctx.cb.dst_node = tcctx.cb.src_node;
15339 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15340 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15341 tcctx.cb.eh_lp_nr = 0;
15342 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15343 tcctx.cb.decl_map = new hash_map<tree, tree>;
15344 tcctx.ctx = ctx;
15346 if (record_needs_remap)
15347 record_type = task_copyfn_remap_type (&tcctx, record_type);
15348 if (srecord_needs_remap)
15349 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15351 else
15352 tcctx.cb.decl_map = NULL;
15354 arg = DECL_ARGUMENTS (child_fn);
15355 TREE_TYPE (arg) = build_pointer_type (record_type);
15356 sarg = DECL_CHAIN (arg);
15357 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15359 /* First pass: initialize temporaries used in record_type and srecord_type
15360 sizes and field offsets. */
15361 if (tcctx.cb.decl_map)
15362 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15363 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15365 tree *p;
15367 decl = OMP_CLAUSE_DECL (c);
15368 p = tcctx.cb.decl_map->get (decl);
15369 if (p == NULL)
15370 continue;
15371 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15372 sf = (tree) n->value;
15373 sf = *tcctx.cb.decl_map->get (sf);
15374 src = build_simple_mem_ref_loc (loc, sarg);
15375 src = omp_build_component_ref (src, sf);
15376 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15377 append_to_statement_list (t, &list);
15380 /* Second pass: copy shared var pointers and copy construct non-VLA
15381 firstprivate vars. */
15382 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15383 switch (OMP_CLAUSE_CODE (c))
15385 splay_tree_key key;
15386 case OMP_CLAUSE_SHARED:
15387 decl = OMP_CLAUSE_DECL (c);
15388 key = (splay_tree_key) decl;
15389 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15390 key = (splay_tree_key) &DECL_UID (decl);
15391 n = splay_tree_lookup (ctx->field_map, key);
15392 if (n == NULL)
15393 break;
15394 f = (tree) n->value;
15395 if (tcctx.cb.decl_map)
15396 f = *tcctx.cb.decl_map->get (f);
15397 n = splay_tree_lookup (ctx->sfield_map, key);
15398 sf = (tree) n->value;
15399 if (tcctx.cb.decl_map)
15400 sf = *tcctx.cb.decl_map->get (sf);
15401 src = build_simple_mem_ref_loc (loc, sarg);
15402 src = omp_build_component_ref (src, sf);
15403 dst = build_simple_mem_ref_loc (loc, arg);
15404 dst = omp_build_component_ref (dst, f);
15405 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15406 append_to_statement_list (t, &list);
15407 break;
15408 case OMP_CLAUSE_FIRSTPRIVATE:
15409 decl = OMP_CLAUSE_DECL (c);
15410 if (is_variable_sized (decl))
15411 break;
15412 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15413 if (n == NULL)
15414 break;
15415 f = (tree) n->value;
15416 if (tcctx.cb.decl_map)
15417 f = *tcctx.cb.decl_map->get (f);
15418 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15419 if (n != NULL)
15421 sf = (tree) n->value;
15422 if (tcctx.cb.decl_map)
15423 sf = *tcctx.cb.decl_map->get (sf);
15424 src = build_simple_mem_ref_loc (loc, sarg);
15425 src = omp_build_component_ref (src, sf);
15426 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15427 src = build_simple_mem_ref_loc (loc, src);
15429 else
15430 src = decl;
15431 dst = build_simple_mem_ref_loc (loc, arg);
15432 dst = omp_build_component_ref (dst, f);
15433 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15434 append_to_statement_list (t, &list);
15435 break;
15436 case OMP_CLAUSE_PRIVATE:
15437 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15438 break;
15439 decl = OMP_CLAUSE_DECL (c);
15440 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15441 f = (tree) n->value;
15442 if (tcctx.cb.decl_map)
15443 f = *tcctx.cb.decl_map->get (f);
15444 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15445 if (n != NULL)
15447 sf = (tree) n->value;
15448 if (tcctx.cb.decl_map)
15449 sf = *tcctx.cb.decl_map->get (sf);
15450 src = build_simple_mem_ref_loc (loc, sarg);
15451 src = omp_build_component_ref (src, sf);
15452 if (use_pointer_for_field (decl, NULL))
15453 src = build_simple_mem_ref_loc (loc, src);
15455 else
15456 src = decl;
15457 dst = build_simple_mem_ref_loc (loc, arg);
15458 dst = omp_build_component_ref (dst, f);
15459 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15460 append_to_statement_list (t, &list);
15461 break;
15462 default:
15463 break;
15466 /* Last pass: handle VLA firstprivates. */
15467 if (tcctx.cb.decl_map)
15468 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15471 tree ind, ptr, df;
15473 decl = OMP_CLAUSE_DECL (c);
15474 if (!is_variable_sized (decl))
15475 continue;
15476 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15477 if (n == NULL)
15478 continue;
15479 f = (tree) n->value;
15480 f = *tcctx.cb.decl_map->get (f);
15481 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15482 ind = DECL_VALUE_EXPR (decl);
15483 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15484 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15485 n = splay_tree_lookup (ctx->sfield_map,
15486 (splay_tree_key) TREE_OPERAND (ind, 0));
15487 sf = (tree) n->value;
15488 sf = *tcctx.cb.decl_map->get (sf);
15489 src = build_simple_mem_ref_loc (loc, sarg);
15490 src = omp_build_component_ref (src, sf);
15491 src = build_simple_mem_ref_loc (loc, src);
15492 dst = build_simple_mem_ref_loc (loc, arg);
15493 dst = omp_build_component_ref (dst, f);
15494 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15495 append_to_statement_list (t, &list);
15496 n = splay_tree_lookup (ctx->field_map,
15497 (splay_tree_key) TREE_OPERAND (ind, 0));
15498 df = (tree) n->value;
15499 df = *tcctx.cb.decl_map->get (df);
15500 ptr = build_simple_mem_ref_loc (loc, arg);
15501 ptr = omp_build_component_ref (ptr, df);
15502 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15503 build_fold_addr_expr_loc (loc, dst));
15504 append_to_statement_list (t, &list);
15507 t = build1 (RETURN_EXPR, void_type_node, NULL);
15508 append_to_statement_list (t, &list);
15510 if (tcctx.cb.decl_map)
15511 delete tcctx.cb.decl_map;
15512 pop_gimplify_context (NULL);
15513 BIND_EXPR_BODY (bind) = list;
15514 pop_cfun ();
15517 static void
15518 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15520 tree c, clauses;
15521 gimple *g;
15522 size_t n_in = 0, n_out = 0, idx = 2, i;
15524 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15525 gcc_assert (clauses);
15526 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15528 switch (OMP_CLAUSE_DEPEND_KIND (c))
15530 case OMP_CLAUSE_DEPEND_IN:
15531 n_in++;
15532 break;
15533 case OMP_CLAUSE_DEPEND_OUT:
15534 case OMP_CLAUSE_DEPEND_INOUT:
15535 n_out++;
15536 break;
15537 case OMP_CLAUSE_DEPEND_SOURCE:
15538 case OMP_CLAUSE_DEPEND_SINK:
15539 /* FALLTHRU */
15540 default:
15541 gcc_unreachable ();
15543 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15544 tree array = create_tmp_var (type);
15545 TREE_ADDRESSABLE (array) = 1;
15546 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15547 NULL_TREE);
15548 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15549 gimple_seq_add_stmt (iseq, g);
15550 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15551 NULL_TREE);
15552 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15553 gimple_seq_add_stmt (iseq, g);
15554 for (i = 0; i < 2; i++)
15556 if ((i ? n_in : n_out) == 0)
15557 continue;
15558 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15559 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15560 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15562 tree t = OMP_CLAUSE_DECL (c);
15563 t = fold_convert (ptr_type_node, t);
15564 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15565 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15566 NULL_TREE, NULL_TREE);
15567 g = gimple_build_assign (r, t);
15568 gimple_seq_add_stmt (iseq, g);
15571 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15572 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15573 OMP_CLAUSE_CHAIN (c) = *pclauses;
15574 *pclauses = c;
15575 tree clobber = build_constructor (type, NULL);
15576 TREE_THIS_VOLATILE (clobber) = 1;
15577 g = gimple_build_assign (array, clobber);
15578 gimple_seq_add_stmt (oseq, g);
15581 /* Lower the OpenMP parallel or task directive in the current statement
15582 in GSI_P. CTX holds context information for the directive. */
15584 static void
15585 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15587 tree clauses;
15588 tree child_fn, t;
15589 gimple *stmt = gsi_stmt (*gsi_p);
15590 gbind *par_bind, *bind, *dep_bind = NULL;
15591 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15592 location_t loc = gimple_location (stmt);
15594 clauses = gimple_omp_taskreg_clauses (stmt);
15595 par_bind
15596 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15597 par_body = gimple_bind_body (par_bind);
15598 child_fn = ctx->cb.dst_fn;
15599 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15600 && !gimple_omp_parallel_combined_p (stmt))
15602 struct walk_stmt_info wi;
15603 int ws_num = 0;
15605 memset (&wi, 0, sizeof (wi));
15606 wi.info = &ws_num;
15607 wi.val_only = true;
15608 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15609 if (ws_num == 1)
15610 gimple_omp_parallel_set_combined_p (stmt, true);
15612 gimple_seq dep_ilist = NULL;
15613 gimple_seq dep_olist = NULL;
15614 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15615 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15617 push_gimplify_context ();
15618 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15619 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15620 &dep_ilist, &dep_olist);
15623 if (ctx->srecord_type)
15624 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15626 push_gimplify_context ();
15628 par_olist = NULL;
15629 par_ilist = NULL;
15630 par_rlist = NULL;
15631 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15632 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15633 if (phony_construct && ctx->record_type)
15635 gcc_checking_assert (!ctx->receiver_decl);
15636 ctx->receiver_decl = create_tmp_var
15637 (build_reference_type (ctx->record_type), ".omp_rec");
15639 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15640 lower_omp (&par_body, ctx);
15641 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15642 lower_reduction_clauses (clauses, &par_rlist, ctx);
15644 /* Declare all the variables created by mapping and the variables
15645 declared in the scope of the parallel body. */
15646 record_vars_into (ctx->block_vars, child_fn);
15647 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15649 if (ctx->record_type)
15651 ctx->sender_decl
15652 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15653 : ctx->record_type, ".omp_data_o");
15654 DECL_NAMELESS (ctx->sender_decl) = 1;
15655 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15656 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15659 olist = NULL;
15660 ilist = NULL;
15661 lower_send_clauses (clauses, &ilist, &olist, ctx);
15662 lower_send_shared_vars (&ilist, &olist, ctx);
15664 if (ctx->record_type)
15666 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15667 TREE_THIS_VOLATILE (clobber) = 1;
15668 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15669 clobber));
15672 /* Once all the expansions are done, sequence all the different
15673 fragments inside gimple_omp_body. */
15675 new_body = NULL;
15677 if (ctx->record_type)
15679 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15680 /* fixup_child_record_type might have changed receiver_decl's type. */
15681 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15682 gimple_seq_add_stmt (&new_body,
15683 gimple_build_assign (ctx->receiver_decl, t));
15686 gimple_seq_add_seq (&new_body, par_ilist);
15687 gimple_seq_add_seq (&new_body, par_body);
15688 gimple_seq_add_seq (&new_body, par_rlist);
15689 if (ctx->cancellable)
15690 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15691 gimple_seq_add_seq (&new_body, par_olist);
15692 new_body = maybe_catch_exception (new_body);
15693 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15694 gimple_seq_add_stmt (&new_body,
15695 gimple_build_omp_continue (integer_zero_node,
15696 integer_zero_node));
15697 if (!phony_construct)
15699 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15700 gimple_omp_set_body (stmt, new_body);
15703 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15704 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15705 gimple_bind_add_seq (bind, ilist);
15706 if (!phony_construct)
15707 gimple_bind_add_stmt (bind, stmt);
15708 else
15709 gimple_bind_add_seq (bind, new_body);
15710 gimple_bind_add_seq (bind, olist);
15712 pop_gimplify_context (NULL);
15714 if (dep_bind)
15716 gimple_bind_add_seq (dep_bind, dep_ilist);
15717 gimple_bind_add_stmt (dep_bind, bind);
15718 gimple_bind_add_seq (dep_bind, dep_olist);
15719 pop_gimplify_context (dep_bind);
15723 /* Lower the GIMPLE_OMP_TARGET in the current statement
15724 in GSI_P. CTX holds context information for the directive. */
15726 static void
15727 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15729 tree clauses;
15730 tree child_fn, t, c;
15731 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15732 gbind *tgt_bind, *bind, *dep_bind = NULL;
15733 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15734 location_t loc = gimple_location (stmt);
15735 bool offloaded, data_region;
15736 unsigned int map_cnt = 0;
15738 offloaded = is_gimple_omp_offloaded (stmt);
15739 switch (gimple_omp_target_kind (stmt))
15741 case GF_OMP_TARGET_KIND_REGION:
15742 case GF_OMP_TARGET_KIND_UPDATE:
15743 case GF_OMP_TARGET_KIND_ENTER_DATA:
15744 case GF_OMP_TARGET_KIND_EXIT_DATA:
15745 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15746 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15747 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15748 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15749 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15750 data_region = false;
15751 break;
15752 case GF_OMP_TARGET_KIND_DATA:
15753 case GF_OMP_TARGET_KIND_OACC_DATA:
15754 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15755 data_region = true;
15756 break;
15757 default:
15758 gcc_unreachable ();
15761 clauses = gimple_omp_target_clauses (stmt);
15763 gimple_seq dep_ilist = NULL;
15764 gimple_seq dep_olist = NULL;
15765 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15767 push_gimplify_context ();
15768 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15769 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15770 &dep_ilist, &dep_olist);
15773 tgt_bind = NULL;
15774 tgt_body = NULL;
15775 if (offloaded)
15777 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15778 tgt_body = gimple_bind_body (tgt_bind);
15780 else if (data_region)
15781 tgt_body = gimple_omp_body (stmt);
15782 child_fn = ctx->cb.dst_fn;
15784 push_gimplify_context ();
15785 fplist = NULL;
15787 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15788 switch (OMP_CLAUSE_CODE (c))
15790 tree var, x;
15792 default:
15793 break;
15794 case OMP_CLAUSE_MAP:
15795 #if CHECKING_P
15796 /* First check what we're prepared to handle in the following. */
15797 switch (OMP_CLAUSE_MAP_KIND (c))
15799 case GOMP_MAP_ALLOC:
15800 case GOMP_MAP_TO:
15801 case GOMP_MAP_FROM:
15802 case GOMP_MAP_TOFROM:
15803 case GOMP_MAP_POINTER:
15804 case GOMP_MAP_TO_PSET:
15805 case GOMP_MAP_DELETE:
15806 case GOMP_MAP_RELEASE:
15807 case GOMP_MAP_ALWAYS_TO:
15808 case GOMP_MAP_ALWAYS_FROM:
15809 case GOMP_MAP_ALWAYS_TOFROM:
15810 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15811 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15812 case GOMP_MAP_STRUCT:
15813 case GOMP_MAP_ALWAYS_POINTER:
15814 break;
15815 case GOMP_MAP_FORCE_ALLOC:
15816 case GOMP_MAP_FORCE_TO:
15817 case GOMP_MAP_FORCE_FROM:
15818 case GOMP_MAP_FORCE_TOFROM:
15819 case GOMP_MAP_FORCE_PRESENT:
15820 case GOMP_MAP_FORCE_DEVICEPTR:
15821 case GOMP_MAP_DEVICE_RESIDENT:
15822 case GOMP_MAP_LINK:
15823 gcc_assert (is_gimple_omp_oacc (stmt));
15824 break;
15825 default:
15826 gcc_unreachable ();
15828 #endif
15829 /* FALLTHRU */
15830 case OMP_CLAUSE_TO:
15831 case OMP_CLAUSE_FROM:
15832 oacc_firstprivate:
15833 var = OMP_CLAUSE_DECL (c);
15834 if (!DECL_P (var))
15836 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15837 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15838 && (OMP_CLAUSE_MAP_KIND (c)
15839 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15840 map_cnt++;
15841 continue;
15844 if (DECL_SIZE (var)
15845 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15847 tree var2 = DECL_VALUE_EXPR (var);
15848 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15849 var2 = TREE_OPERAND (var2, 0);
15850 gcc_assert (DECL_P (var2));
15851 var = var2;
15854 if (offloaded
15855 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15856 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15857 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15859 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15861 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15862 && varpool_node::get_create (var)->offloadable)
15863 continue;
15865 tree type = build_pointer_type (TREE_TYPE (var));
15866 tree new_var = lookup_decl (var, ctx);
15867 x = create_tmp_var_raw (type, get_name (new_var));
15868 gimple_add_tmp_var (x);
15869 x = build_simple_mem_ref (x);
15870 SET_DECL_VALUE_EXPR (new_var, x);
15871 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15873 continue;
15876 if (!maybe_lookup_field (var, ctx))
15877 continue;
15879 /* Don't remap oacc parallel reduction variables, because the
15880 intermediate result must be local to each gang. */
15881 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15882 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15884 x = build_receiver_ref (var, true, ctx);
15885 tree new_var = lookup_decl (var, ctx);
15887 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15888 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15889 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15890 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15891 x = build_simple_mem_ref (x);
15892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15894 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15895 if (is_reference (new_var))
15897 /* Create a local object to hold the instance
15898 value. */
15899 tree type = TREE_TYPE (TREE_TYPE (new_var));
15900 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15901 tree inst = create_tmp_var (type, id);
15902 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15903 x = build_fold_addr_expr (inst);
15905 gimplify_assign (new_var, x, &fplist);
15907 else if (DECL_P (new_var))
15909 SET_DECL_VALUE_EXPR (new_var, x);
15910 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15912 else
15913 gcc_unreachable ();
15915 map_cnt++;
15916 break;
15918 case OMP_CLAUSE_FIRSTPRIVATE:
15919 if (is_oacc_parallel (ctx))
15920 goto oacc_firstprivate;
15921 map_cnt++;
15922 var = OMP_CLAUSE_DECL (c);
15923 if (!is_reference (var)
15924 && !is_gimple_reg_type (TREE_TYPE (var)))
15926 tree new_var = lookup_decl (var, ctx);
15927 if (is_variable_sized (var))
15929 tree pvar = DECL_VALUE_EXPR (var);
15930 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15931 pvar = TREE_OPERAND (pvar, 0);
15932 gcc_assert (DECL_P (pvar));
15933 tree new_pvar = lookup_decl (pvar, ctx);
15934 x = build_fold_indirect_ref (new_pvar);
15935 TREE_THIS_NOTRAP (x) = 1;
15937 else
15938 x = build_receiver_ref (var, true, ctx);
15939 SET_DECL_VALUE_EXPR (new_var, x);
15940 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15942 break;
15944 case OMP_CLAUSE_PRIVATE:
15945 if (is_gimple_omp_oacc (ctx->stmt))
15946 break;
15947 var = OMP_CLAUSE_DECL (c);
15948 if (is_variable_sized (var))
15950 tree new_var = lookup_decl (var, ctx);
15951 tree pvar = DECL_VALUE_EXPR (var);
15952 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15953 pvar = TREE_OPERAND (pvar, 0);
15954 gcc_assert (DECL_P (pvar));
15955 tree new_pvar = lookup_decl (pvar, ctx);
15956 x = build_fold_indirect_ref (new_pvar);
15957 TREE_THIS_NOTRAP (x) = 1;
15958 SET_DECL_VALUE_EXPR (new_var, x);
15959 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15961 break;
15963 case OMP_CLAUSE_USE_DEVICE_PTR:
15964 case OMP_CLAUSE_IS_DEVICE_PTR:
15965 var = OMP_CLAUSE_DECL (c);
15966 map_cnt++;
15967 if (is_variable_sized (var))
15969 tree new_var = lookup_decl (var, ctx);
15970 tree pvar = DECL_VALUE_EXPR (var);
15971 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15972 pvar = TREE_OPERAND (pvar, 0);
15973 gcc_assert (DECL_P (pvar));
15974 tree new_pvar = lookup_decl (pvar, ctx);
15975 x = build_fold_indirect_ref (new_pvar);
15976 TREE_THIS_NOTRAP (x) = 1;
15977 SET_DECL_VALUE_EXPR (new_var, x);
15978 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15980 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15982 tree new_var = lookup_decl (var, ctx);
15983 tree type = build_pointer_type (TREE_TYPE (var));
15984 x = create_tmp_var_raw (type, get_name (new_var));
15985 gimple_add_tmp_var (x);
15986 x = build_simple_mem_ref (x);
15987 SET_DECL_VALUE_EXPR (new_var, x);
15988 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15990 else
15992 tree new_var = lookup_decl (var, ctx);
15993 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15994 gimple_add_tmp_var (x);
15995 SET_DECL_VALUE_EXPR (new_var, x);
15996 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15998 break;
16001 if (offloaded)
16003 target_nesting_level++;
16004 lower_omp (&tgt_body, ctx);
16005 target_nesting_level--;
16007 else if (data_region)
16008 lower_omp (&tgt_body, ctx);
16010 if (offloaded)
16012 /* Declare all the variables created by mapping and the variables
16013 declared in the scope of the target body. */
16014 record_vars_into (ctx->block_vars, child_fn);
16015 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16018 olist = NULL;
16019 ilist = NULL;
16020 if (ctx->record_type)
16022 ctx->sender_decl
16023 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16024 DECL_NAMELESS (ctx->sender_decl) = 1;
16025 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16026 t = make_tree_vec (3);
16027 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16028 TREE_VEC_ELT (t, 1)
16029 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16030 ".omp_data_sizes");
16031 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16032 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16033 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16034 tree tkind_type = short_unsigned_type_node;
16035 int talign_shift = 8;
16036 TREE_VEC_ELT (t, 2)
16037 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16038 ".omp_data_kinds");
16039 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16040 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16041 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16042 gimple_omp_target_set_data_arg (stmt, t);
16044 vec<constructor_elt, va_gc> *vsize;
16045 vec<constructor_elt, va_gc> *vkind;
16046 vec_alloc (vsize, map_cnt);
16047 vec_alloc (vkind, map_cnt);
16048 unsigned int map_idx = 0;
16050 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16051 switch (OMP_CLAUSE_CODE (c))
16053 tree ovar, nc, s, purpose, var, x, type;
16054 unsigned int talign;
16056 default:
16057 break;
16059 case OMP_CLAUSE_MAP:
16060 case OMP_CLAUSE_TO:
16061 case OMP_CLAUSE_FROM:
16062 oacc_firstprivate_map:
16063 nc = c;
16064 ovar = OMP_CLAUSE_DECL (c);
16065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16066 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16067 || (OMP_CLAUSE_MAP_KIND (c)
16068 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16069 break;
16070 if (!DECL_P (ovar))
16072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16073 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16075 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16076 == get_base_address (ovar));
16077 nc = OMP_CLAUSE_CHAIN (c);
16078 ovar = OMP_CLAUSE_DECL (nc);
16080 else
16082 tree x = build_sender_ref (ovar, ctx);
16083 tree v
16084 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16085 gimplify_assign (x, v, &ilist);
16086 nc = NULL_TREE;
16089 else
16091 if (DECL_SIZE (ovar)
16092 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16094 tree ovar2 = DECL_VALUE_EXPR (ovar);
16095 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16096 ovar2 = TREE_OPERAND (ovar2, 0);
16097 gcc_assert (DECL_P (ovar2));
16098 ovar = ovar2;
16100 if (!maybe_lookup_field (ovar, ctx))
16101 continue;
16104 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16105 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16106 talign = DECL_ALIGN_UNIT (ovar);
16107 if (nc)
16109 var = lookup_decl_in_outer_ctx (ovar, ctx);
16110 x = build_sender_ref (ovar, ctx);
16112 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16113 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16114 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16115 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16117 gcc_assert (offloaded);
16118 tree avar
16119 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16120 mark_addressable (avar);
16121 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16122 talign = DECL_ALIGN_UNIT (avar);
16123 avar = build_fold_addr_expr (avar);
16124 gimplify_assign (x, avar, &ilist);
16126 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16128 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16129 if (!is_reference (var))
16131 if (is_gimple_reg (var)
16132 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16133 TREE_NO_WARNING (var) = 1;
16134 var = build_fold_addr_expr (var);
16136 else
16137 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16138 gimplify_assign (x, var, &ilist);
16140 else if (is_gimple_reg (var))
16142 gcc_assert (offloaded);
16143 tree avar = create_tmp_var (TREE_TYPE (var));
16144 mark_addressable (avar);
16145 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16146 if (GOMP_MAP_COPY_TO_P (map_kind)
16147 || map_kind == GOMP_MAP_POINTER
16148 || map_kind == GOMP_MAP_TO_PSET
16149 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16151 /* If we need to initialize a temporary
16152 with VAR because it is not addressable, and
16153 the variable hasn't been initialized yet, then
16154 we'll get a warning for the store to avar.
16155 Don't warn in that case, the mapping might
16156 be implicit. */
16157 TREE_NO_WARNING (var) = 1;
16158 gimplify_assign (avar, var, &ilist);
16160 avar = build_fold_addr_expr (avar);
16161 gimplify_assign (x, avar, &ilist);
16162 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16163 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16164 && !TYPE_READONLY (TREE_TYPE (var)))
16166 x = unshare_expr (x);
16167 x = build_simple_mem_ref (x);
16168 gimplify_assign (var, x, &olist);
16171 else
16173 var = build_fold_addr_expr (var);
16174 gimplify_assign (x, var, &ilist);
16177 s = NULL_TREE;
16178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16180 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16181 s = TREE_TYPE (ovar);
16182 if (TREE_CODE (s) == REFERENCE_TYPE)
16183 s = TREE_TYPE (s);
16184 s = TYPE_SIZE_UNIT (s);
16186 else
16187 s = OMP_CLAUSE_SIZE (c);
16188 if (s == NULL_TREE)
16189 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16190 s = fold_convert (size_type_node, s);
16191 purpose = size_int (map_idx++);
16192 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16193 if (TREE_CODE (s) != INTEGER_CST)
16194 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16196 unsigned HOST_WIDE_INT tkind, tkind_zero;
16197 switch (OMP_CLAUSE_CODE (c))
16199 case OMP_CLAUSE_MAP:
16200 tkind = OMP_CLAUSE_MAP_KIND (c);
16201 tkind_zero = tkind;
16202 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16203 switch (tkind)
16205 case GOMP_MAP_ALLOC:
16206 case GOMP_MAP_TO:
16207 case GOMP_MAP_FROM:
16208 case GOMP_MAP_TOFROM:
16209 case GOMP_MAP_ALWAYS_TO:
16210 case GOMP_MAP_ALWAYS_FROM:
16211 case GOMP_MAP_ALWAYS_TOFROM:
16212 case GOMP_MAP_RELEASE:
16213 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16214 break;
16215 case GOMP_MAP_DELETE:
16216 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16217 default:
16218 break;
16220 if (tkind_zero != tkind)
16222 if (integer_zerop (s))
16223 tkind = tkind_zero;
16224 else if (integer_nonzerop (s))
16225 tkind_zero = tkind;
16227 break;
16228 case OMP_CLAUSE_FIRSTPRIVATE:
16229 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16230 tkind = GOMP_MAP_TO;
16231 tkind_zero = tkind;
16232 break;
16233 case OMP_CLAUSE_TO:
16234 tkind = GOMP_MAP_TO;
16235 tkind_zero = tkind;
16236 break;
16237 case OMP_CLAUSE_FROM:
16238 tkind = GOMP_MAP_FROM;
16239 tkind_zero = tkind;
16240 break;
16241 default:
16242 gcc_unreachable ();
16244 gcc_checking_assert (tkind
16245 < (HOST_WIDE_INT_C (1U) << talign_shift));
16246 gcc_checking_assert (tkind_zero
16247 < (HOST_WIDE_INT_C (1U) << talign_shift));
16248 talign = ceil_log2 (talign);
16249 tkind |= talign << talign_shift;
16250 tkind_zero |= talign << talign_shift;
16251 gcc_checking_assert (tkind
16252 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16253 gcc_checking_assert (tkind_zero
16254 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16255 if (tkind == tkind_zero)
16256 x = build_int_cstu (tkind_type, tkind);
16257 else
16259 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16260 x = build3 (COND_EXPR, tkind_type,
16261 fold_build2 (EQ_EXPR, boolean_type_node,
16262 unshare_expr (s), size_zero_node),
16263 build_int_cstu (tkind_type, tkind_zero),
16264 build_int_cstu (tkind_type, tkind));
16266 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16267 if (nc && nc != c)
16268 c = nc;
16269 break;
16271 case OMP_CLAUSE_FIRSTPRIVATE:
16272 if (is_oacc_parallel (ctx))
16273 goto oacc_firstprivate_map;
16274 ovar = OMP_CLAUSE_DECL (c);
16275 if (is_reference (ovar))
16276 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16277 else
16278 talign = DECL_ALIGN_UNIT (ovar);
16279 var = lookup_decl_in_outer_ctx (ovar, ctx);
16280 x = build_sender_ref (ovar, ctx);
16281 tkind = GOMP_MAP_FIRSTPRIVATE;
16282 type = TREE_TYPE (ovar);
16283 if (is_reference (ovar))
16284 type = TREE_TYPE (type);
16285 if ((INTEGRAL_TYPE_P (type)
16286 && TYPE_PRECISION (type) <= POINTER_SIZE)
16287 || TREE_CODE (type) == POINTER_TYPE)
16289 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16290 tree t = var;
16291 if (is_reference (var))
16292 t = build_simple_mem_ref (var);
16293 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16294 TREE_NO_WARNING (var) = 1;
16295 if (TREE_CODE (type) != POINTER_TYPE)
16296 t = fold_convert (pointer_sized_int_node, t);
16297 t = fold_convert (TREE_TYPE (x), t);
16298 gimplify_assign (x, t, &ilist);
16300 else if (is_reference (var))
16301 gimplify_assign (x, var, &ilist);
16302 else if (is_gimple_reg (var))
16304 tree avar = create_tmp_var (TREE_TYPE (var));
16305 mark_addressable (avar);
16306 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16307 TREE_NO_WARNING (var) = 1;
16308 gimplify_assign (avar, var, &ilist);
16309 avar = build_fold_addr_expr (avar);
16310 gimplify_assign (x, avar, &ilist);
16312 else
16314 var = build_fold_addr_expr (var);
16315 gimplify_assign (x, var, &ilist);
16317 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16318 s = size_int (0);
16319 else if (is_reference (var))
16320 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16321 else
16322 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16323 s = fold_convert (size_type_node, s);
16324 purpose = size_int (map_idx++);
16325 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16326 if (TREE_CODE (s) != INTEGER_CST)
16327 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16329 gcc_checking_assert (tkind
16330 < (HOST_WIDE_INT_C (1U) << talign_shift));
16331 talign = ceil_log2 (talign);
16332 tkind |= talign << talign_shift;
16333 gcc_checking_assert (tkind
16334 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16335 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16336 build_int_cstu (tkind_type, tkind));
16337 break;
16339 case OMP_CLAUSE_USE_DEVICE_PTR:
16340 case OMP_CLAUSE_IS_DEVICE_PTR:
16341 ovar = OMP_CLAUSE_DECL (c);
16342 var = lookup_decl_in_outer_ctx (ovar, ctx);
16343 x = build_sender_ref (ovar, ctx);
16344 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16345 tkind = GOMP_MAP_USE_DEVICE_PTR;
16346 else
16347 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16348 type = TREE_TYPE (ovar);
16349 if (TREE_CODE (type) == ARRAY_TYPE)
16350 var = build_fold_addr_expr (var);
16351 else
16353 if (is_reference (ovar))
16355 type = TREE_TYPE (type);
16356 if (TREE_CODE (type) != ARRAY_TYPE)
16357 var = build_simple_mem_ref (var);
16358 var = fold_convert (TREE_TYPE (x), var);
16361 gimplify_assign (x, var, &ilist);
16362 s = size_int (0);
16363 purpose = size_int (map_idx++);
16364 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16365 gcc_checking_assert (tkind
16366 < (HOST_WIDE_INT_C (1U) << talign_shift));
16367 gcc_checking_assert (tkind
16368 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16369 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16370 build_int_cstu (tkind_type, tkind));
16371 break;
16374 gcc_assert (map_idx == map_cnt);
16376 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16377 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16378 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16379 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16380 for (int i = 1; i <= 2; i++)
16381 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16383 gimple_seq initlist = NULL;
16384 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16385 TREE_VEC_ELT (t, i)),
16386 &initlist, true, NULL_TREE);
16387 gimple_seq_add_seq (&ilist, initlist);
16389 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16390 NULL);
16391 TREE_THIS_VOLATILE (clobber) = 1;
16392 gimple_seq_add_stmt (&olist,
16393 gimple_build_assign (TREE_VEC_ELT (t, i),
16394 clobber));
16397 tree clobber = build_constructor (ctx->record_type, NULL);
16398 TREE_THIS_VOLATILE (clobber) = 1;
16399 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16400 clobber));
16403 /* Once all the expansions are done, sequence all the different
16404 fragments inside gimple_omp_body. */
16406 new_body = NULL;
16408 if (offloaded
16409 && ctx->record_type)
16411 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16412 /* fixup_child_record_type might have changed receiver_decl's type. */
16413 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16414 gimple_seq_add_stmt (&new_body,
16415 gimple_build_assign (ctx->receiver_decl, t));
16417 gimple_seq_add_seq (&new_body, fplist);
16419 if (offloaded || data_region)
16421 tree prev = NULL_TREE;
16422 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16423 switch (OMP_CLAUSE_CODE (c))
16425 tree var, x;
16426 default:
16427 break;
16428 case OMP_CLAUSE_FIRSTPRIVATE:
16429 if (is_gimple_omp_oacc (ctx->stmt))
16430 break;
16431 var = OMP_CLAUSE_DECL (c);
16432 if (is_reference (var)
16433 || is_gimple_reg_type (TREE_TYPE (var)))
16435 tree new_var = lookup_decl (var, ctx);
16436 tree type;
16437 type = TREE_TYPE (var);
16438 if (is_reference (var))
16439 type = TREE_TYPE (type);
16440 if ((INTEGRAL_TYPE_P (type)
16441 && TYPE_PRECISION (type) <= POINTER_SIZE)
16442 || TREE_CODE (type) == POINTER_TYPE)
16444 x = build_receiver_ref (var, false, ctx);
16445 if (TREE_CODE (type) != POINTER_TYPE)
16446 x = fold_convert (pointer_sized_int_node, x);
16447 x = fold_convert (type, x);
16448 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16449 fb_rvalue);
16450 if (is_reference (var))
16452 tree v = create_tmp_var_raw (type, get_name (var));
16453 gimple_add_tmp_var (v);
16454 TREE_ADDRESSABLE (v) = 1;
16455 gimple_seq_add_stmt (&new_body,
16456 gimple_build_assign (v, x));
16457 x = build_fold_addr_expr (v);
16459 gimple_seq_add_stmt (&new_body,
16460 gimple_build_assign (new_var, x));
16462 else
16464 x = build_receiver_ref (var, !is_reference (var), ctx);
16465 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16466 fb_rvalue);
16467 gimple_seq_add_stmt (&new_body,
16468 gimple_build_assign (new_var, x));
16471 else if (is_variable_sized (var))
16473 tree pvar = DECL_VALUE_EXPR (var);
16474 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16475 pvar = TREE_OPERAND (pvar, 0);
16476 gcc_assert (DECL_P (pvar));
16477 tree new_var = lookup_decl (pvar, ctx);
16478 x = build_receiver_ref (var, false, ctx);
16479 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16480 gimple_seq_add_stmt (&new_body,
16481 gimple_build_assign (new_var, x));
16483 break;
16484 case OMP_CLAUSE_PRIVATE:
16485 if (is_gimple_omp_oacc (ctx->stmt))
16486 break;
16487 var = OMP_CLAUSE_DECL (c);
16488 if (is_reference (var))
16490 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16491 tree new_var = lookup_decl (var, ctx);
16492 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16493 if (TREE_CONSTANT (x))
16495 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16496 get_name (var));
16497 gimple_add_tmp_var (x);
16498 TREE_ADDRESSABLE (x) = 1;
16499 x = build_fold_addr_expr_loc (clause_loc, x);
16501 else
16502 break;
16504 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16505 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16506 gimple_seq_add_stmt (&new_body,
16507 gimple_build_assign (new_var, x));
16509 break;
16510 case OMP_CLAUSE_USE_DEVICE_PTR:
16511 case OMP_CLAUSE_IS_DEVICE_PTR:
16512 var = OMP_CLAUSE_DECL (c);
16513 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16514 x = build_sender_ref (var, ctx);
16515 else
16516 x = build_receiver_ref (var, false, ctx);
16517 if (is_variable_sized (var))
16519 tree pvar = DECL_VALUE_EXPR (var);
16520 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16521 pvar = TREE_OPERAND (pvar, 0);
16522 gcc_assert (DECL_P (pvar));
16523 tree new_var = lookup_decl (pvar, ctx);
16524 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16525 gimple_seq_add_stmt (&new_body,
16526 gimple_build_assign (new_var, x));
16528 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16530 tree new_var = lookup_decl (var, ctx);
16531 new_var = DECL_VALUE_EXPR (new_var);
16532 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16533 new_var = TREE_OPERAND (new_var, 0);
16534 gcc_assert (DECL_P (new_var));
16535 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16536 gimple_seq_add_stmt (&new_body,
16537 gimple_build_assign (new_var, x));
16539 else
16541 tree type = TREE_TYPE (var);
16542 tree new_var = lookup_decl (var, ctx);
16543 if (is_reference (var))
16545 type = TREE_TYPE (type);
16546 if (TREE_CODE (type) != ARRAY_TYPE)
16548 tree v = create_tmp_var_raw (type, get_name (var));
16549 gimple_add_tmp_var (v);
16550 TREE_ADDRESSABLE (v) = 1;
16551 x = fold_convert (type, x);
16552 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16553 fb_rvalue);
16554 gimple_seq_add_stmt (&new_body,
16555 gimple_build_assign (v, x));
16556 x = build_fold_addr_expr (v);
16559 new_var = DECL_VALUE_EXPR (new_var);
16560 x = fold_convert (TREE_TYPE (new_var), x);
16561 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16562 gimple_seq_add_stmt (&new_body,
16563 gimple_build_assign (new_var, x));
16565 break;
16567 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16568 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16569 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16570 or references to VLAs. */
16571 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16572 switch (OMP_CLAUSE_CODE (c))
16574 tree var;
16575 default:
16576 break;
16577 case OMP_CLAUSE_MAP:
16578 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16579 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16581 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16582 HOST_WIDE_INT offset = 0;
16583 gcc_assert (prev);
16584 var = OMP_CLAUSE_DECL (c);
16585 if (DECL_P (var)
16586 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16587 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16588 ctx))
16589 && varpool_node::get_create (var)->offloadable)
16590 break;
16591 if (TREE_CODE (var) == INDIRECT_REF
16592 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16593 var = TREE_OPERAND (var, 0);
16594 if (TREE_CODE (var) == COMPONENT_REF)
16596 var = get_addr_base_and_unit_offset (var, &offset);
16597 gcc_assert (var != NULL_TREE && DECL_P (var));
16599 else if (DECL_SIZE (var)
16600 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16602 tree var2 = DECL_VALUE_EXPR (var);
16603 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16604 var2 = TREE_OPERAND (var2, 0);
16605 gcc_assert (DECL_P (var2));
16606 var = var2;
16608 tree new_var = lookup_decl (var, ctx), x;
16609 tree type = TREE_TYPE (new_var);
16610 bool is_ref;
16611 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16612 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16613 == COMPONENT_REF))
16615 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16616 is_ref = true;
16617 new_var = build2 (MEM_REF, type,
16618 build_fold_addr_expr (new_var),
16619 build_int_cst (build_pointer_type (type),
16620 offset));
16622 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16624 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16625 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16626 new_var = build2 (MEM_REF, type,
16627 build_fold_addr_expr (new_var),
16628 build_int_cst (build_pointer_type (type),
16629 offset));
16631 else
16632 is_ref = is_reference (var);
16633 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16634 is_ref = false;
16635 bool ref_to_array = false;
16636 if (is_ref)
16638 type = TREE_TYPE (type);
16639 if (TREE_CODE (type) == ARRAY_TYPE)
16641 type = build_pointer_type (type);
16642 ref_to_array = true;
16645 else if (TREE_CODE (type) == ARRAY_TYPE)
16647 tree decl2 = DECL_VALUE_EXPR (new_var);
16648 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16649 decl2 = TREE_OPERAND (decl2, 0);
16650 gcc_assert (DECL_P (decl2));
16651 new_var = decl2;
16652 type = TREE_TYPE (new_var);
16654 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16655 x = fold_convert_loc (clause_loc, type, x);
16656 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16658 tree bias = OMP_CLAUSE_SIZE (c);
16659 if (DECL_P (bias))
16660 bias = lookup_decl (bias, ctx);
16661 bias = fold_convert_loc (clause_loc, sizetype, bias);
16662 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16663 bias);
16664 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16665 TREE_TYPE (x), x, bias);
16667 if (ref_to_array)
16668 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16669 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16670 if (is_ref && !ref_to_array)
16672 tree t = create_tmp_var_raw (type, get_name (var));
16673 gimple_add_tmp_var (t);
16674 TREE_ADDRESSABLE (t) = 1;
16675 gimple_seq_add_stmt (&new_body,
16676 gimple_build_assign (t, x));
16677 x = build_fold_addr_expr_loc (clause_loc, t);
16679 gimple_seq_add_stmt (&new_body,
16680 gimple_build_assign (new_var, x));
16681 prev = NULL_TREE;
16683 else if (OMP_CLAUSE_CHAIN (c)
16684 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16685 == OMP_CLAUSE_MAP
16686 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16687 == GOMP_MAP_FIRSTPRIVATE_POINTER
16688 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16689 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16690 prev = c;
16691 break;
16692 case OMP_CLAUSE_PRIVATE:
16693 var = OMP_CLAUSE_DECL (c);
16694 if (is_variable_sized (var))
16696 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16697 tree new_var = lookup_decl (var, ctx);
16698 tree pvar = DECL_VALUE_EXPR (var);
16699 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16700 pvar = TREE_OPERAND (pvar, 0);
16701 gcc_assert (DECL_P (pvar));
16702 tree new_pvar = lookup_decl (pvar, ctx);
16703 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16704 tree al = size_int (DECL_ALIGN (var));
16705 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16706 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16707 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16708 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16709 gimple_seq_add_stmt (&new_body,
16710 gimple_build_assign (new_pvar, x));
16712 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16714 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16715 tree new_var = lookup_decl (var, ctx);
16716 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16717 if (TREE_CONSTANT (x))
16718 break;
16719 else
16721 tree atmp
16722 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16723 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16724 tree al = size_int (TYPE_ALIGN (rtype));
16725 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16728 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16729 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16730 gimple_seq_add_stmt (&new_body,
16731 gimple_build_assign (new_var, x));
16733 break;
16736 gimple_seq fork_seq = NULL;
16737 gimple_seq join_seq = NULL;
16739 if (is_oacc_parallel (ctx))
16741 /* If there are reductions on the offloaded region itself, treat
16742 them as a dummy GANG loop. */
16743 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16745 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16746 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16749 gimple_seq_add_seq (&new_body, fork_seq);
16750 gimple_seq_add_seq (&new_body, tgt_body);
16751 gimple_seq_add_seq (&new_body, join_seq);
16753 if (offloaded)
16754 new_body = maybe_catch_exception (new_body);
16756 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16757 gimple_omp_set_body (stmt, new_body);
16760 bind = gimple_build_bind (NULL, NULL,
16761 tgt_bind ? gimple_bind_block (tgt_bind)
16762 : NULL_TREE);
16763 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16764 gimple_bind_add_seq (bind, ilist);
16765 gimple_bind_add_stmt (bind, stmt);
16766 gimple_bind_add_seq (bind, olist);
16768 pop_gimplify_context (NULL);
16770 if (dep_bind)
16772 gimple_bind_add_seq (dep_bind, dep_ilist);
16773 gimple_bind_add_stmt (dep_bind, bind);
16774 gimple_bind_add_seq (dep_bind, dep_olist);
16775 pop_gimplify_context (dep_bind);
16779 /* Expand code for an OpenMP teams directive. */
16781 static void
16782 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16784 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16785 push_gimplify_context ();
16787 tree block = make_node (BLOCK);
16788 gbind *bind = gimple_build_bind (NULL, NULL, block);
16789 gsi_replace (gsi_p, bind, true);
16790 gimple_seq bind_body = NULL;
16791 gimple_seq dlist = NULL;
16792 gimple_seq olist = NULL;
16794 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16795 OMP_CLAUSE_NUM_TEAMS);
16796 if (num_teams == NULL_TREE)
16797 num_teams = build_int_cst (unsigned_type_node, 0);
16798 else
16800 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16801 num_teams = fold_convert (unsigned_type_node, num_teams);
16802 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16804 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16805 OMP_CLAUSE_THREAD_LIMIT);
16806 if (thread_limit == NULL_TREE)
16807 thread_limit = build_int_cst (unsigned_type_node, 0);
16808 else
16810 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16811 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16812 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16813 fb_rvalue);
16816 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16817 &bind_body, &dlist, ctx, NULL);
16818 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16819 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16820 if (!gimple_omp_teams_grid_phony (teams_stmt))
16822 gimple_seq_add_stmt (&bind_body, teams_stmt);
16823 location_t loc = gimple_location (teams_stmt);
16824 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16825 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16826 gimple_set_location (call, loc);
16827 gimple_seq_add_stmt (&bind_body, call);
16830 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16831 gimple_omp_set_body (teams_stmt, NULL);
16832 gimple_seq_add_seq (&bind_body, olist);
16833 gimple_seq_add_seq (&bind_body, dlist);
16834 if (!gimple_omp_teams_grid_phony (teams_stmt))
16835 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16836 gimple_bind_set_body (bind, bind_body);
16838 pop_gimplify_context (bind);
16840 gimple_bind_append_vars (bind, ctx->block_vars);
16841 BLOCK_VARS (block) = ctx->block_vars;
16842 if (BLOCK_VARS (block))
16843 TREE_USED (block) = 1;
16846 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16848 static void
16849 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16851 gimple *stmt = gsi_stmt (*gsi_p);
16852 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16853 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16854 gimple_build_omp_return (false));
16858 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16859 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16860 of OMP context, but with task_shared_vars set. */
16862 static tree
16863 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16864 void *data)
16866 tree t = *tp;
16868 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16869 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16870 return t;
16872 if (task_shared_vars
16873 && DECL_P (t)
16874 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16875 return t;
16877 /* If a global variable has been privatized, TREE_CONSTANT on
16878 ADDR_EXPR might be wrong. */
16879 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16880 recompute_tree_invariant_for_addr_expr (t);
16882 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16883 return NULL_TREE;
16886 /* Data to be communicated between lower_omp_regimplify_operands and
16887 lower_omp_regimplify_operands_p. */
16889 struct lower_omp_regimplify_operands_data
16891 omp_context *ctx;
16892 vec<tree> *decls;
16895 /* Helper function for lower_omp_regimplify_operands. Find
16896 omp_member_access_dummy_var vars and adjust temporarily their
16897 DECL_VALUE_EXPRs if needed. */
16899 static tree
16900 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16901 void *data)
16903 tree t = omp_member_access_dummy_var (*tp);
16904 if (t)
16906 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16907 lower_omp_regimplify_operands_data *ldata
16908 = (lower_omp_regimplify_operands_data *) wi->info;
16909 tree o = maybe_lookup_decl (t, ldata->ctx);
16910 if (o != t)
16912 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16913 ldata->decls->safe_push (*tp);
16914 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16915 SET_DECL_VALUE_EXPR (*tp, v);
16918 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16919 return NULL_TREE;
16922 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16923 of omp_member_access_dummy_var vars during regimplification. */
16925 static void
16926 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16927 gimple_stmt_iterator *gsi_p)
16929 auto_vec<tree, 10> decls;
16930 if (ctx)
16932 struct walk_stmt_info wi;
16933 memset (&wi, '\0', sizeof (wi));
16934 struct lower_omp_regimplify_operands_data data;
16935 data.ctx = ctx;
16936 data.decls = &decls;
16937 wi.info = &data;
16938 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16940 gimple_regimplify_operands (stmt, gsi_p);
16941 while (!decls.is_empty ())
16943 tree t = decls.pop ();
16944 tree v = decls.pop ();
16945 SET_DECL_VALUE_EXPR (t, v);
16949 static void
16950 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16952 gimple *stmt = gsi_stmt (*gsi_p);
16953 struct walk_stmt_info wi;
16954 gcall *call_stmt;
16956 if (gimple_has_location (stmt))
16957 input_location = gimple_location (stmt);
16959 if (task_shared_vars)
16960 memset (&wi, '\0', sizeof (wi));
16962 /* If we have issued syntax errors, avoid doing any heavy lifting.
16963 Just replace the OMP directives with a NOP to avoid
16964 confusing RTL expansion. */
16965 if (seen_error () && is_gimple_omp (stmt))
16967 gsi_replace (gsi_p, gimple_build_nop (), true);
16968 return;
16971 switch (gimple_code (stmt))
16973 case GIMPLE_COND:
16975 gcond *cond_stmt = as_a <gcond *> (stmt);
16976 if ((ctx || task_shared_vars)
16977 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16978 lower_omp_regimplify_p,
16979 ctx ? NULL : &wi, NULL)
16980 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16981 lower_omp_regimplify_p,
16982 ctx ? NULL : &wi, NULL)))
16983 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16985 break;
16986 case GIMPLE_CATCH:
16987 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16988 break;
16989 case GIMPLE_EH_FILTER:
16990 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16991 break;
16992 case GIMPLE_TRY:
16993 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16994 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16995 break;
16996 case GIMPLE_TRANSACTION:
16997 lower_omp (gimple_transaction_body_ptr (
16998 as_a <gtransaction *> (stmt)),
16999 ctx);
17000 break;
17001 case GIMPLE_BIND:
17002 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17003 break;
17004 case GIMPLE_OMP_PARALLEL:
17005 case GIMPLE_OMP_TASK:
17006 ctx = maybe_lookup_ctx (stmt);
17007 gcc_assert (ctx);
17008 if (ctx->cancellable)
17009 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17010 lower_omp_taskreg (gsi_p, ctx);
17011 break;
17012 case GIMPLE_OMP_FOR:
17013 ctx = maybe_lookup_ctx (stmt);
17014 gcc_assert (ctx);
17015 if (ctx->cancellable)
17016 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17017 lower_omp_for (gsi_p, ctx);
17018 break;
17019 case GIMPLE_OMP_SECTIONS:
17020 ctx = maybe_lookup_ctx (stmt);
17021 gcc_assert (ctx);
17022 if (ctx->cancellable)
17023 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17024 lower_omp_sections (gsi_p, ctx);
17025 break;
17026 case GIMPLE_OMP_SINGLE:
17027 ctx = maybe_lookup_ctx (stmt);
17028 gcc_assert (ctx);
17029 lower_omp_single (gsi_p, ctx);
17030 break;
17031 case GIMPLE_OMP_MASTER:
17032 ctx = maybe_lookup_ctx (stmt);
17033 gcc_assert (ctx);
17034 lower_omp_master (gsi_p, ctx);
17035 break;
17036 case GIMPLE_OMP_TASKGROUP:
17037 ctx = maybe_lookup_ctx (stmt);
17038 gcc_assert (ctx);
17039 lower_omp_taskgroup (gsi_p, ctx);
17040 break;
17041 case GIMPLE_OMP_ORDERED:
17042 ctx = maybe_lookup_ctx (stmt);
17043 gcc_assert (ctx);
17044 lower_omp_ordered (gsi_p, ctx);
17045 break;
17046 case GIMPLE_OMP_CRITICAL:
17047 ctx = maybe_lookup_ctx (stmt);
17048 gcc_assert (ctx);
17049 lower_omp_critical (gsi_p, ctx);
17050 break;
17051 case GIMPLE_OMP_ATOMIC_LOAD:
17052 if ((ctx || task_shared_vars)
17053 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17054 as_a <gomp_atomic_load *> (stmt)),
17055 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17056 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17057 break;
17058 case GIMPLE_OMP_TARGET:
17059 ctx = maybe_lookup_ctx (stmt);
17060 gcc_assert (ctx);
17061 lower_omp_target (gsi_p, ctx);
17062 break;
17063 case GIMPLE_OMP_TEAMS:
17064 ctx = maybe_lookup_ctx (stmt);
17065 gcc_assert (ctx);
17066 lower_omp_teams (gsi_p, ctx);
17067 break;
17068 case GIMPLE_OMP_GRID_BODY:
17069 ctx = maybe_lookup_ctx (stmt);
17070 gcc_assert (ctx);
17071 lower_omp_grid_body (gsi_p, ctx);
17072 break;
17073 case GIMPLE_CALL:
17074 tree fndecl;
17075 call_stmt = as_a <gcall *> (stmt);
17076 fndecl = gimple_call_fndecl (call_stmt);
17077 if (fndecl
17078 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17079 switch (DECL_FUNCTION_CODE (fndecl))
17081 case BUILT_IN_GOMP_BARRIER:
17082 if (ctx == NULL)
17083 break;
17084 /* FALLTHRU */
17085 case BUILT_IN_GOMP_CANCEL:
17086 case BUILT_IN_GOMP_CANCELLATION_POINT:
17087 omp_context *cctx;
17088 cctx = ctx;
17089 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17090 cctx = cctx->outer;
17091 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17092 if (!cctx->cancellable)
17094 if (DECL_FUNCTION_CODE (fndecl)
17095 == BUILT_IN_GOMP_CANCELLATION_POINT)
17097 stmt = gimple_build_nop ();
17098 gsi_replace (gsi_p, stmt, false);
17100 break;
17102 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17104 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17105 gimple_call_set_fndecl (call_stmt, fndecl);
17106 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17108 tree lhs;
17109 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17110 gimple_call_set_lhs (call_stmt, lhs);
17111 tree fallthru_label;
17112 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17113 gimple *g;
17114 g = gimple_build_label (fallthru_label);
17115 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17116 g = gimple_build_cond (NE_EXPR, lhs,
17117 fold_convert (TREE_TYPE (lhs),
17118 boolean_false_node),
17119 cctx->cancel_label, fallthru_label);
17120 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17121 break;
17122 default:
17123 break;
17125 /* FALLTHRU */
17126 default:
17127 if ((ctx || task_shared_vars)
17128 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17129 ctx ? NULL : &wi))
17131 /* Just remove clobbers, this should happen only if we have
17132 "privatized" local addressable variables in SIMD regions,
17133 the clobber isn't needed in that case and gimplifying address
17134 of the ARRAY_REF into a pointer and creating MEM_REF based
17135 clobber would create worse code than we get with the clobber
17136 dropped. */
17137 if (gimple_clobber_p (stmt))
17139 gsi_replace (gsi_p, gimple_build_nop (), true);
17140 break;
17142 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17144 break;
17148 static void
17149 lower_omp (gimple_seq *body, omp_context *ctx)
17151 location_t saved_location = input_location;
17152 gimple_stmt_iterator gsi;
17153 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17154 lower_omp_1 (&gsi, ctx);
17155 /* During gimplification, we haven't folded statments inside offloading
17156 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17157 if (target_nesting_level || taskreg_nesting_level)
17158 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17159 fold_stmt (&gsi);
17160 input_location = saved_location;
17163 /* Returen true if STMT is an assignment of a register-type into a local
17164 VAR_DECL. */
17166 static bool
17167 grid_reg_assignment_to_local_var_p (gimple *stmt)
17169 gassign *assign = dyn_cast <gassign *> (stmt);
17170 if (!assign)
17171 return false;
17172 tree lhs = gimple_assign_lhs (assign);
17173 if (TREE_CODE (lhs) != VAR_DECL
17174 || !is_gimple_reg_type (TREE_TYPE (lhs))
17175 || is_global_var (lhs))
17176 return false;
17177 return true;
17180 /* Return true if all statements in SEQ are assignments to local register-type
17181 variables. */
17183 static bool
17184 grid_seq_only_contains_local_assignments (gimple_seq seq)
17186 if (!seq)
17187 return true;
17189 gimple_stmt_iterator gsi;
17190 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17191 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17192 return false;
17193 return true;
17196 /* Scan statements in SEQ and call itself recursively on any bind. If during
17197 whole search only assignments to register-type local variables and one
17198 single OMP statement is encountered, return true, otherwise return false.
17199 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17200 are used for dumping a note about a failure. */
17202 static bool
17203 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17204 const char *name, gimple **ret)
17206 gimple_stmt_iterator gsi;
17207 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17209 gimple *stmt = gsi_stmt (gsi);
17211 if (grid_reg_assignment_to_local_var_p (stmt))
17212 continue;
17213 if (gbind *bind = dyn_cast <gbind *> (stmt))
17215 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17216 target_loc, name, ret))
17217 return false;
17219 else if (is_gimple_omp (stmt))
17221 if (*ret)
17223 if (dump_enabled_p ())
17224 dump_printf_loc (MSG_NOTE, target_loc,
17225 "Will not turn target construct into a simple "
17226 "GPGPU kernel because %s construct contains "
17227 "multiple OpenMP constructs\n", name);
17228 return false;
17230 *ret = stmt;
17232 else
17234 if (dump_enabled_p ())
17235 dump_printf_loc (MSG_NOTE, target_loc,
17236 "Will not turn target construct into a simple "
17237 "GPGPU kernel because %s construct contains "
17238 "a complex statement\n", name);
17239 return false;
17242 return true;
17245 /* Scan statements in SEQ and make sure that it and any binds in it contain
17246 only assignments to local register-type variables and one OMP construct. If
17247 so, return that construct, otherwise return NULL. If dumping is enabled and
17248 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17249 failure. */
17251 static gimple *
17252 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17253 const char *name)
17255 if (!seq)
17257 if (dump_enabled_p ())
17258 dump_printf_loc (MSG_NOTE, target_loc,
17259 "Will not turn target construct into a simple "
17260 "GPGPU kernel because %s construct has empty "
17261 "body\n",
17262 name);
17263 return NULL;
17266 gimple *ret = NULL;
17267 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17269 if (!ret && dump_enabled_p ())
17270 dump_printf_loc (MSG_NOTE, target_loc,
17271 "Will not turn target construct into a simple "
17272 "GPGPU kernel because %s construct does not contain"
17273 "any other OpenMP construct\n", name);
17274 return ret;
17276 else
17277 return NULL;
17280 /* Walker function looking for statements there is no point gridifying (and for
17281 noreturn function calls which we cannot do). Return non-NULL if such a
17282 function is found. */
17284 static tree
17285 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17286 bool *handled_ops_p,
17287 struct walk_stmt_info *wi)
17289 *handled_ops_p = false;
17290 gimple *stmt = gsi_stmt (*gsi);
17291 switch (gimple_code (stmt))
17293 case GIMPLE_CALL:
17294 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17296 *handled_ops_p = true;
17297 wi->info = stmt;
17298 return error_mark_node;
17300 break;
17302 /* We may reduce the following list if we find a way to implement the
17303 clauses, but now there is no point trying further. */
17304 case GIMPLE_OMP_CRITICAL:
17305 case GIMPLE_OMP_TASKGROUP:
17306 case GIMPLE_OMP_TASK:
17307 case GIMPLE_OMP_SECTION:
17308 case GIMPLE_OMP_SECTIONS:
17309 case GIMPLE_OMP_SECTIONS_SWITCH:
17310 case GIMPLE_OMP_TARGET:
17311 case GIMPLE_OMP_ORDERED:
17312 *handled_ops_p = true;
17313 wi->info = stmt;
17314 return error_mark_node;
17316 case GIMPLE_OMP_FOR:
17317 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17318 && gimple_omp_for_combined_into_p (stmt))
17320 *handled_ops_p = true;
17321 wi->info = stmt;
17322 return error_mark_node;
17324 break;
17326 default:
17327 break;
17329 return NULL;
17333 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17334 kernel, return true, otherwise return false. In the case of success, also
17335 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17336 none. */
17338 static bool
17339 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17341 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17342 return false;
17344 location_t tloc = gimple_location (target);
17345 gimple *stmt
17346 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17347 tloc, "target");
17348 if (!stmt)
17349 return false;
17350 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17351 tree group_size = NULL;
17352 if (!teams)
17354 dump_printf_loc (MSG_NOTE, tloc,
17355 "Will not turn target construct into a simple "
17356 "GPGPU kernel because it does not have a sole teams "
17357 "construct in it.\n");
17358 return false;
17361 tree clauses = gimple_omp_teams_clauses (teams);
17362 while (clauses)
17364 switch (OMP_CLAUSE_CODE (clauses))
17366 case OMP_CLAUSE_NUM_TEAMS:
17367 if (dump_enabled_p ())
17368 dump_printf_loc (MSG_NOTE, tloc,
17369 "Will not turn target construct into a "
17370 "gridified GPGPU kernel because we cannot "
17371 "handle num_teams clause of teams "
17372 "construct\n ");
17373 return false;
17375 case OMP_CLAUSE_REDUCTION:
17376 if (dump_enabled_p ())
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a "
17379 "gridified GPGPU kernel because a reduction "
17380 "clause is present\n ");
17381 return false;
17383 case OMP_CLAUSE_LASTPRIVATE:
17384 if (dump_enabled_p ())
17385 dump_printf_loc (MSG_NOTE, tloc,
17386 "Will not turn target construct into a "
17387 "gridified GPGPU kernel because a lastprivate "
17388 "clause is present\n ");
17389 return false;
17391 case OMP_CLAUSE_THREAD_LIMIT:
17392 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17393 break;
17395 default:
17396 break;
17398 clauses = OMP_CLAUSE_CHAIN (clauses);
17401 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17402 "teams");
17403 if (!stmt)
17404 return false;
17405 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17406 if (!dist)
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a simple "
17410 "GPGPU kernel because the teams construct does not have "
17411 "a sole distribute construct in it.\n");
17412 return false;
17415 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17416 if (!gimple_omp_for_combined_p (dist))
17418 if (dump_enabled_p ())
17419 dump_printf_loc (MSG_NOTE, tloc,
17420 "Will not turn target construct into a gridified GPGPU "
17421 "kernel because we cannot handle a standalone "
17422 "distribute construct\n ");
17423 return false;
17425 if (dist->collapse > 1)
17427 if (dump_enabled_p ())
17428 dump_printf_loc (MSG_NOTE, tloc,
17429 "Will not turn target construct into a gridified GPGPU "
17430 "kernel because the distribute construct contains "
17431 "collapse clause\n");
17432 return false;
17434 struct omp_for_data fd;
17435 extract_omp_for_data (dist, &fd, NULL);
17436 if (fd.chunk_size)
17438 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17440 if (dump_enabled_p ())
17441 dump_printf_loc (MSG_NOTE, tloc,
17442 "Will not turn target construct into a "
17443 "gridified GPGPU kernel because the teams "
17444 "thread limit is different from distribute "
17445 "schedule chunk\n");
17446 return false;
17448 group_size = fd.chunk_size;
17450 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17451 "distribute");
17452 gomp_parallel *par;
17453 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17454 return false;
17456 clauses = gimple_omp_parallel_clauses (par);
17457 while (clauses)
17459 switch (OMP_CLAUSE_CODE (clauses))
17461 case OMP_CLAUSE_NUM_THREADS:
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE, tloc,
17464 "Will not turn target construct into a gridified"
17465 "GPGPU kernel because there is a num_threads "
17466 "clause of the parallel construct\n");
17467 return false;
17469 case OMP_CLAUSE_REDUCTION:
17470 if (dump_enabled_p ())
17471 dump_printf_loc (MSG_NOTE, tloc,
17472 "Will not turn target construct into a "
17473 "gridified GPGPU kernel because a reduction "
17474 "clause is present\n ");
17475 return false;
17477 case OMP_CLAUSE_LASTPRIVATE:
17478 if (dump_enabled_p ())
17479 dump_printf_loc (MSG_NOTE, tloc,
17480 "Will not turn target construct into a "
17481 "gridified GPGPU kernel because a lastprivate "
17482 "clause is present\n ");
17483 return false;
17485 default:
17486 break;
17488 clauses = OMP_CLAUSE_CHAIN (clauses);
17491 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17492 "parallel");
17493 gomp_for *gfor;
17494 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17495 return false;
17497 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17499 if (dump_enabled_p ())
17500 dump_printf_loc (MSG_NOTE, tloc,
17501 "Will not turn target construct into a gridified GPGPU "
17502 "kernel because the inner loop is not a simple for "
17503 "loop\n");
17504 return false;
17506 if (gfor->collapse > 1)
17508 if (dump_enabled_p ())
17509 dump_printf_loc (MSG_NOTE, tloc,
17510 "Will not turn target construct into a gridified GPGPU "
17511 "kernel because the inner loop contains collapse "
17512 "clause\n");
17513 return false;
17516 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17518 if (dump_enabled_p ())
17519 dump_printf_loc (MSG_NOTE, tloc,
17520 "Will not turn target construct into a gridified GPGPU "
17521 "kernel because the inner loop pre_body contains"
17522 "a complex instruction\n");
17523 return false;
17526 clauses = gimple_omp_for_clauses (gfor);
17527 while (clauses)
17529 switch (OMP_CLAUSE_CODE (clauses))
17531 case OMP_CLAUSE_SCHEDULE:
17532 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17534 if (dump_enabled_p ())
17535 dump_printf_loc (MSG_NOTE, tloc,
17536 "Will not turn target construct into a "
17537 "gridified GPGPU kernel because the inner "
17538 "loop has a non-automatic scheduling clause\n");
17539 return false;
17541 break;
17543 case OMP_CLAUSE_REDUCTION:
17544 if (dump_enabled_p ())
17545 dump_printf_loc (MSG_NOTE, tloc,
17546 "Will not turn target construct into a "
17547 "gridified GPGPU kernel because a reduction "
17548 "clause is present\n ");
17549 return false;
17551 case OMP_CLAUSE_LASTPRIVATE:
17552 if (dump_enabled_p ())
17553 dump_printf_loc (MSG_NOTE, tloc,
17554 "Will not turn target construct into a "
17555 "gridified GPGPU kernel because a lastprivate "
17556 "clause is present\n ");
17557 return false;
17559 default:
17560 break;
17562 clauses = OMP_CLAUSE_CHAIN (clauses);
17565 struct walk_stmt_info wi;
17566 memset (&wi, 0, sizeof (wi));
17567 if (walk_gimple_seq (gimple_omp_body (gfor),
17568 grid_find_ungridifiable_statement,
17569 NULL, &wi))
17571 gimple *bad = (gimple *) wi.info;
17572 if (dump_enabled_p ())
17574 if (is_gimple_call (bad))
17575 dump_printf_loc (MSG_NOTE, tloc,
17576 "Will not turn target construct into a gridified "
17577 " GPGPU kernel because the inner loop contains "
17578 "call to a noreturn function\n");
17579 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17580 dump_printf_loc (MSG_NOTE, tloc,
17581 "Will not turn target construct into a gridified "
17582 " GPGPU kernel because the inner loop contains "
17583 "a simd construct\n");
17584 else
17585 dump_printf_loc (MSG_NOTE, tloc,
17586 "Will not turn target construct into a gridified "
17587 "GPGPU kernel because the inner loop contains "
17588 "statement %s which cannot be transformed\n",
17589 gimple_code_name[(int) gimple_code (bad)]);
17591 return false;
17594 *group_size_p = group_size;
17595 return true;
17598 /* Operand walker, used to remap pre-body declarations according to a hash map
17599 provided in DATA. */
17601 static tree
17602 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17604 tree t = *tp;
17606 if (DECL_P (t) || TYPE_P (t))
17607 *walk_subtrees = 0;
17608 else
17609 *walk_subtrees = 1;
17611 if (TREE_CODE (t) == VAR_DECL)
17613 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17614 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17615 tree *repl = declmap->get (t);
17616 if (repl)
17617 *tp = *repl;
17619 return NULL_TREE;
17622 /* Copy leading register-type assignments to local variables in SRC to just
17623 before DST, Creating temporaries, adjusting mapping of operands in WI and
17624 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17625 Return the first statement that does not conform to
17626 grid_reg_assignment_to_local_var_p or NULL. */
17628 static gimple *
17629 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17630 gbind *tgt_bind, struct walk_stmt_info *wi)
17632 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17633 gimple_stmt_iterator gsi;
17634 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17636 gimple *stmt = gsi_stmt (gsi);
17637 if (gbind *bind = dyn_cast <gbind *> (stmt))
17639 gimple *r = grid_copy_leading_local_assignments
17640 (gimple_bind_body (bind), dst, tgt_bind, wi);
17641 if (r)
17642 return r;
17643 else
17644 continue;
17646 if (!grid_reg_assignment_to_local_var_p (stmt))
17647 return stmt;
17648 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17649 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17650 TREE_TYPE (lhs));
17651 DECL_CONTEXT (repl) = current_function_decl;
17652 gimple_bind_append_vars (tgt_bind, repl);
17654 declmap->put (lhs, repl);
17655 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17656 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17657 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17659 return NULL;
17662 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17663 components, mark them as part of kernel and return the inner loop, and copy
17664 assignment leading to them just before DST, remapping them using WI and
17665 adding new temporaries to TGT_BIND. */
17667 static gomp_for *
17668 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17669 gbind *tgt_bind, struct walk_stmt_info *wi)
17671 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17672 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17673 gcc_assert (teams);
17674 gimple_omp_teams_set_grid_phony (teams, true);
17675 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17676 tgt_bind, wi);
17677 gcc_checking_assert (stmt);
17678 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17679 gcc_assert (dist);
17680 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17681 if (prebody)
17682 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17683 gimple_omp_for_set_grid_phony (dist, true);
17684 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17685 tgt_bind, wi);
17686 gcc_checking_assert (stmt);
17688 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17689 gimple_omp_parallel_set_grid_phony (parallel, true);
17690 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17691 tgt_bind, wi);
17692 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17693 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17694 prebody = gimple_omp_for_pre_body (inner_loop);
17695 if (prebody)
17696 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17698 return inner_loop;
17701 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17702 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17703 is the bind into which temporaries inserted before TARGET should be
17704 added. */
17706 static void
17707 grid_attempt_target_gridification (gomp_target *target,
17708 gimple_stmt_iterator *gsi,
17709 gbind *tgt_bind)
17711 tree group_size;
17712 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17713 return;
17715 location_t loc = gimple_location (target);
17716 if (dump_enabled_p ())
17717 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17718 "Target construct will be turned into a gridified GPGPU "
17719 "kernel\n");
17721 /* Copy target body to a GPUKERNEL construct: */
17722 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17723 (gimple_omp_body (target));
17725 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17726 struct walk_stmt_info wi;
17727 memset (&wi, 0, sizeof (struct walk_stmt_info));
17728 wi.info = declmap;
17730 /* Copy assignments in between OMP statements before target, mark OMP
17731 statements within copy appropriatly. */
17732 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17733 tgt_bind, &wi);
17735 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17736 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17737 tree new_block = gimple_bind_block (new_bind);
17738 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17739 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17740 BLOCK_SUBBLOCKS (enc_block) = new_block;
17741 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17742 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17743 gimple_seq_add_stmt
17744 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17745 gpukernel);
17747 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17748 push_gimplify_context ();
17749 size_t collapse = gimple_omp_for_collapse (inner_loop);
17750 for (size_t i = 0; i < collapse; i++)
17752 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17753 if (POINTER_TYPE_P (type))
17754 itype = signed_type_for (type);
17755 else
17756 itype = type;
17758 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17759 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17760 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17761 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17762 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17763 adjust_for_condition (loc, &cond_code, &n2);
17764 tree step;
17765 step = get_omp_for_step_from_incr (loc,
17766 gimple_omp_for_incr (inner_loop, i));
17767 gimple_seq tmpseq = NULL;
17768 n1 = fold_convert (itype, n1);
17769 n2 = fold_convert (itype, n2);
17770 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17771 t = fold_build2 (PLUS_EXPR, itype, step, t);
17772 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17773 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17774 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17775 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17776 fold_build1 (NEGATE_EXPR, itype, t),
17777 fold_build1 (NEGATE_EXPR, itype, step));
17778 else
17779 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17780 tree gs = fold_convert (uint32_type_node, t);
17781 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17782 if (!gimple_seq_empty_p (tmpseq))
17783 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17785 tree ws;
17786 if (i == 0 && group_size)
17788 ws = fold_convert (uint32_type_node, group_size);
17789 tmpseq = NULL;
17790 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17791 if (!gimple_seq_empty_p (tmpseq))
17792 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17794 else
17795 ws = build_zero_cst (uint32_type_node);
17797 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17798 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17799 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17800 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17801 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17802 gimple_omp_target_set_clauses (target, c);
17804 pop_gimplify_context (tgt_bind);
17805 delete declmap;
17806 return;
17809 /* Walker function doing all the work for create_target_kernels. */
17811 static tree
17812 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17813 bool *handled_ops_p,
17814 struct walk_stmt_info *incoming)
17816 *handled_ops_p = false;
17818 gimple *stmt = gsi_stmt (*gsi);
17819 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17820 if (target)
17822 gbind *tgt_bind = (gbind *) incoming->info;
17823 gcc_checking_assert (tgt_bind);
17824 grid_attempt_target_gridification (target, gsi, tgt_bind);
17825 return NULL_TREE;
17827 gbind *bind = dyn_cast <gbind *> (stmt);
17828 if (bind)
17830 *handled_ops_p = true;
17831 struct walk_stmt_info wi;
17832 memset (&wi, 0, sizeof (wi));
17833 wi.info = bind;
17834 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17835 grid_gridify_all_targets_stmt, NULL, &wi);
17837 return NULL_TREE;
17840 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17841 have their bodies duplicated, with the new copy being put into a
17842 gimple_omp_grid_body statement. All kernel-related construct within the
17843 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17844 re-structuring is often needed, such as copying pre-bodies before the target
17845 construct so that kernel grid sizes can be computed. */
17847 static void
17848 grid_gridify_all_targets (gimple_seq *body_p)
17850 struct walk_stmt_info wi;
17851 memset (&wi, 0, sizeof (wi));
17852 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17856 /* Main entry point. */
17858 static unsigned int
17859 execute_lower_omp (void)
17861 gimple_seq body;
17862 int i;
17863 omp_context *ctx;
17865 /* This pass always runs, to provide PROP_gimple_lomp.
17866 But often, there is nothing to do. */
17867 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17868 && flag_openmp_simd == 0)
17869 return 0;
17871 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17872 delete_omp_context);
17874 body = gimple_body (current_function_decl);
17876 if (hsa_gen_requested_p ())
17877 grid_gridify_all_targets (&body);
17879 scan_omp (&body, NULL);
17880 gcc_assert (taskreg_nesting_level == 0);
17881 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17882 finish_taskreg_scan (ctx);
17883 taskreg_contexts.release ();
17885 if (all_contexts->root)
17887 if (task_shared_vars)
17888 push_gimplify_context ();
17889 lower_omp (&body, NULL);
17890 if (task_shared_vars)
17891 pop_gimplify_context (NULL);
17894 if (all_contexts)
17896 splay_tree_delete (all_contexts);
17897 all_contexts = NULL;
17899 BITMAP_FREE (task_shared_vars);
17900 return 0;
17903 namespace {
17905 const pass_data pass_data_lower_omp =
17907 GIMPLE_PASS, /* type */
17908 "omplower", /* name */
17909 OPTGROUP_NONE, /* optinfo_flags */
17910 TV_NONE, /* tv_id */
17911 PROP_gimple_any, /* properties_required */
17912 PROP_gimple_lomp, /* properties_provided */
17913 0, /* properties_destroyed */
17914 0, /* todo_flags_start */
17915 0, /* todo_flags_finish */
17918 class pass_lower_omp : public gimple_opt_pass
17920 public:
17921 pass_lower_omp (gcc::context *ctxt)
17922 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17925 /* opt_pass methods: */
17926 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17928 }; // class pass_lower_omp
17930 } // anon namespace
17932 gimple_opt_pass *
17933 make_pass_lower_omp (gcc::context *ctxt)
17935 return new pass_lower_omp (ctxt);
17938 /* The following is a utility to diagnose structured block violations.
17939 It is not part of the "omplower" pass, as that's invoked too late. It
17940 should be invoked by the respective front ends after gimplification. */
17942 static splay_tree all_labels;
17944 /* Check for mismatched contexts and generate an error if needed. Return
17945 true if an error is detected. */
17947 static bool
17948 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17949 gimple *branch_ctx, gimple *label_ctx)
17951 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17952 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17954 if (label_ctx == branch_ctx)
17955 return false;
17957 const char* kind = NULL;
17959 if (flag_cilkplus)
17961 if ((branch_ctx
17962 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17963 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17964 || (label_ctx
17965 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17966 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17967 kind = "Cilk Plus";
17969 if (flag_openacc)
17971 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17972 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17974 gcc_checking_assert (kind == NULL);
17975 kind = "OpenACC";
17978 if (kind == NULL)
17980 gcc_checking_assert (flag_openmp);
17981 kind = "OpenMP";
17985 Previously we kept track of the label's entire context in diagnose_sb_[12]
17986 so we could traverse it and issue a correct "exit" or "enter" error
17987 message upon a structured block violation.
17989 We built the context by building a list with tree_cons'ing, but there is
17990 no easy counterpart in gimple tuples. It seems like far too much work
17991 for issuing exit/enter error messages. If someone really misses the
17992 distinct error message... patches welcome.
17995 #if 0
17996 /* Try to avoid confusing the user by producing and error message
17997 with correct "exit" or "enter" verbiage. We prefer "exit"
17998 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17999 if (branch_ctx == NULL)
18000 exit_p = false;
18001 else
18003 while (label_ctx)
18005 if (TREE_VALUE (label_ctx) == branch_ctx)
18007 exit_p = false;
18008 break;
18010 label_ctx = TREE_CHAIN (label_ctx);
18014 if (exit_p)
18015 error ("invalid exit from %s structured block", kind);
18016 else
18017 error ("invalid entry to %s structured block", kind);
18018 #endif
18020 /* If it's obvious we have an invalid entry, be specific about the error. */
18021 if (branch_ctx == NULL)
18022 error ("invalid entry to %s structured block", kind);
18023 else
18025 /* Otherwise, be vague and lazy, but efficient. */
18026 error ("invalid branch to/from %s structured block", kind);
18029 gsi_replace (gsi_p, gimple_build_nop (), false);
18030 return true;
18033 /* Pass 1: Create a minimal tree of structured blocks, and record
18034 where each label is found. */
18036 static tree
18037 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18038 struct walk_stmt_info *wi)
18040 gimple *context = (gimple *) wi->info;
18041 gimple *inner_context;
18042 gimple *stmt = gsi_stmt (*gsi_p);
18044 *handled_ops_p = true;
18046 switch (gimple_code (stmt))
18048 WALK_SUBSTMTS;
18050 case GIMPLE_OMP_PARALLEL:
18051 case GIMPLE_OMP_TASK:
18052 case GIMPLE_OMP_SECTIONS:
18053 case GIMPLE_OMP_SINGLE:
18054 case GIMPLE_OMP_SECTION:
18055 case GIMPLE_OMP_MASTER:
18056 case GIMPLE_OMP_ORDERED:
18057 case GIMPLE_OMP_CRITICAL:
18058 case GIMPLE_OMP_TARGET:
18059 case GIMPLE_OMP_TEAMS:
18060 case GIMPLE_OMP_TASKGROUP:
18061 /* The minimal context here is just the current OMP construct. */
18062 inner_context = stmt;
18063 wi->info = inner_context;
18064 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18065 wi->info = context;
18066 break;
18068 case GIMPLE_OMP_FOR:
18069 inner_context = stmt;
18070 wi->info = inner_context;
18071 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18072 walk them. */
18073 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18074 diagnose_sb_1, NULL, wi);
18075 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18076 wi->info = context;
18077 break;
18079 case GIMPLE_LABEL:
18080 splay_tree_insert (all_labels,
18081 (splay_tree_key) gimple_label_label (
18082 as_a <glabel *> (stmt)),
18083 (splay_tree_value) context);
18084 break;
18086 default:
18087 break;
18090 return NULL_TREE;
18093 /* Pass 2: Check each branch and see if its context differs from that of
18094 the destination label's context. */
18096 static tree
18097 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18098 struct walk_stmt_info *wi)
18100 gimple *context = (gimple *) wi->info;
18101 splay_tree_node n;
18102 gimple *stmt = gsi_stmt (*gsi_p);
18104 *handled_ops_p = true;
18106 switch (gimple_code (stmt))
18108 WALK_SUBSTMTS;
18110 case GIMPLE_OMP_PARALLEL:
18111 case GIMPLE_OMP_TASK:
18112 case GIMPLE_OMP_SECTIONS:
18113 case GIMPLE_OMP_SINGLE:
18114 case GIMPLE_OMP_SECTION:
18115 case GIMPLE_OMP_MASTER:
18116 case GIMPLE_OMP_ORDERED:
18117 case GIMPLE_OMP_CRITICAL:
18118 case GIMPLE_OMP_TARGET:
18119 case GIMPLE_OMP_TEAMS:
18120 case GIMPLE_OMP_TASKGROUP:
18121 wi->info = stmt;
18122 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18123 wi->info = context;
18124 break;
18126 case GIMPLE_OMP_FOR:
18127 wi->info = stmt;
18128 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18129 walk them. */
18130 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18131 diagnose_sb_2, NULL, wi);
18132 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18133 wi->info = context;
18134 break;
18136 case GIMPLE_COND:
18138 gcond *cond_stmt = as_a <gcond *> (stmt);
18139 tree lab = gimple_cond_true_label (cond_stmt);
18140 if (lab)
18142 n = splay_tree_lookup (all_labels,
18143 (splay_tree_key) lab);
18144 diagnose_sb_0 (gsi_p, context,
18145 n ? (gimple *) n->value : NULL);
18147 lab = gimple_cond_false_label (cond_stmt);
18148 if (lab)
18150 n = splay_tree_lookup (all_labels,
18151 (splay_tree_key) lab);
18152 diagnose_sb_0 (gsi_p, context,
18153 n ? (gimple *) n->value : NULL);
18156 break;
18158 case GIMPLE_GOTO:
18160 tree lab = gimple_goto_dest (stmt);
18161 if (TREE_CODE (lab) != LABEL_DECL)
18162 break;
18164 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18165 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18167 break;
18169 case GIMPLE_SWITCH:
18171 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18172 unsigned int i;
18173 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18175 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18176 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18177 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18178 break;
18181 break;
18183 case GIMPLE_RETURN:
18184 diagnose_sb_0 (gsi_p, context, NULL);
18185 break;
18187 default:
18188 break;
18191 return NULL_TREE;
18194 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18195 GIMPLE_* codes. */
18196 bool
18197 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18198 int *region_idx)
18200 gimple *last = last_stmt (bb);
18201 enum gimple_code code = gimple_code (last);
18202 struct omp_region *cur_region = *region;
18203 bool fallthru = false;
18205 switch (code)
18207 case GIMPLE_OMP_PARALLEL:
18208 case GIMPLE_OMP_TASK:
18209 case GIMPLE_OMP_FOR:
18210 case GIMPLE_OMP_SINGLE:
18211 case GIMPLE_OMP_TEAMS:
18212 case GIMPLE_OMP_MASTER:
18213 case GIMPLE_OMP_TASKGROUP:
18214 case GIMPLE_OMP_CRITICAL:
18215 case GIMPLE_OMP_SECTION:
18216 case GIMPLE_OMP_GRID_BODY:
18217 cur_region = new_omp_region (bb, code, cur_region);
18218 fallthru = true;
18219 break;
18221 case GIMPLE_OMP_ORDERED:
18222 cur_region = new_omp_region (bb, code, cur_region);
18223 fallthru = true;
18224 if (find_omp_clause (gimple_omp_ordered_clauses
18225 (as_a <gomp_ordered *> (last)),
18226 OMP_CLAUSE_DEPEND))
18227 cur_region = cur_region->outer;
18228 break;
18230 case GIMPLE_OMP_TARGET:
18231 cur_region = new_omp_region (bb, code, cur_region);
18232 fallthru = true;
18233 switch (gimple_omp_target_kind (last))
18235 case GF_OMP_TARGET_KIND_REGION:
18236 case GF_OMP_TARGET_KIND_DATA:
18237 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18238 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18239 case GF_OMP_TARGET_KIND_OACC_DATA:
18240 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18241 break;
18242 case GF_OMP_TARGET_KIND_UPDATE:
18243 case GF_OMP_TARGET_KIND_ENTER_DATA:
18244 case GF_OMP_TARGET_KIND_EXIT_DATA:
18245 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18246 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18247 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18248 cur_region = cur_region->outer;
18249 break;
18250 default:
18251 gcc_unreachable ();
18253 break;
18255 case GIMPLE_OMP_SECTIONS:
18256 cur_region = new_omp_region (bb, code, cur_region);
18257 fallthru = true;
18258 break;
18260 case GIMPLE_OMP_SECTIONS_SWITCH:
18261 fallthru = false;
18262 break;
18264 case GIMPLE_OMP_ATOMIC_LOAD:
18265 case GIMPLE_OMP_ATOMIC_STORE:
18266 fallthru = true;
18267 break;
18269 case GIMPLE_OMP_RETURN:
18270 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18271 somewhere other than the next block. This will be
18272 created later. */
18273 cur_region->exit = bb;
18274 if (cur_region->type == GIMPLE_OMP_TASK)
18275 /* Add an edge corresponding to not scheduling the task
18276 immediately. */
18277 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18278 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18279 cur_region = cur_region->outer;
18280 break;
18282 case GIMPLE_OMP_CONTINUE:
18283 cur_region->cont = bb;
18284 switch (cur_region->type)
18286 case GIMPLE_OMP_FOR:
18287 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18288 succs edges as abnormal to prevent splitting
18289 them. */
18290 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18291 /* Make the loopback edge. */
18292 make_edge (bb, single_succ (cur_region->entry),
18293 EDGE_ABNORMAL);
18295 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18296 corresponds to the case that the body of the loop
18297 is not executed at all. */
18298 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18299 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18300 fallthru = false;
18301 break;
18303 case GIMPLE_OMP_SECTIONS:
18304 /* Wire up the edges into and out of the nested sections. */
18306 basic_block switch_bb = single_succ (cur_region->entry);
18308 struct omp_region *i;
18309 for (i = cur_region->inner; i ; i = i->next)
18311 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18312 make_edge (switch_bb, i->entry, 0);
18313 make_edge (i->exit, bb, EDGE_FALLTHRU);
18316 /* Make the loopback edge to the block with
18317 GIMPLE_OMP_SECTIONS_SWITCH. */
18318 make_edge (bb, switch_bb, 0);
18320 /* Make the edge from the switch to exit. */
18321 make_edge (switch_bb, bb->next_bb, 0);
18322 fallthru = false;
18324 break;
18326 case GIMPLE_OMP_TASK:
18327 fallthru = true;
18328 break;
18330 default:
18331 gcc_unreachable ();
18333 break;
18335 default:
18336 gcc_unreachable ();
18339 if (*region != cur_region)
18341 *region = cur_region;
18342 if (cur_region)
18343 *region_idx = cur_region->entry->index;
18344 else
18345 *region_idx = 0;
18348 return fallthru;
18351 static unsigned int
18352 diagnose_omp_structured_block_errors (void)
18354 struct walk_stmt_info wi;
18355 gimple_seq body = gimple_body (current_function_decl);
18357 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18359 memset (&wi, 0, sizeof (wi));
18360 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18362 memset (&wi, 0, sizeof (wi));
18363 wi.want_locations = true;
18364 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18366 gimple_set_body (current_function_decl, body);
18368 splay_tree_delete (all_labels);
18369 all_labels = NULL;
18371 return 0;
18374 namespace {
18376 const pass_data pass_data_diagnose_omp_blocks =
18378 GIMPLE_PASS, /* type */
18379 "*diagnose_omp_blocks", /* name */
18380 OPTGROUP_NONE, /* optinfo_flags */
18381 TV_NONE, /* tv_id */
18382 PROP_gimple_any, /* properties_required */
18383 0, /* properties_provided */
18384 0, /* properties_destroyed */
18385 0, /* todo_flags_start */
18386 0, /* todo_flags_finish */
18389 class pass_diagnose_omp_blocks : public gimple_opt_pass
18391 public:
18392 pass_diagnose_omp_blocks (gcc::context *ctxt)
18393 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18396 /* opt_pass methods: */
18397 virtual bool gate (function *)
18399 return flag_cilkplus || flag_openacc || flag_openmp;
18401 virtual unsigned int execute (function *)
18403 return diagnose_omp_structured_block_errors ();
18406 }; // class pass_diagnose_omp_blocks
18408 } // anon namespace
18410 gimple_opt_pass *
18411 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18413 return new pass_diagnose_omp_blocks (ctxt);
18416 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18417 adds their addresses and sizes to constructor-vector V_CTOR. */
18418 static void
18419 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18420 vec<constructor_elt, va_gc> *v_ctor)
18422 unsigned len = vec_safe_length (v_decls);
18423 for (unsigned i = 0; i < len; i++)
18425 tree it = (*v_decls)[i];
18426 bool is_var = TREE_CODE (it) == VAR_DECL;
18427 bool is_link_var
18428 = is_var
18429 #ifdef ACCEL_COMPILER
18430 && DECL_HAS_VALUE_EXPR_P (it)
18431 #endif
18432 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18434 tree size = NULL_TREE;
18435 if (is_var)
18436 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18438 tree addr;
18439 if (!is_link_var)
18440 addr = build_fold_addr_expr (it);
18441 else
18443 #ifdef ACCEL_COMPILER
18444 /* For "omp declare target link" vars add address of the pointer to
18445 the target table, instead of address of the var. */
18446 tree value_expr = DECL_VALUE_EXPR (it);
18447 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18448 varpool_node::finalize_decl (link_ptr_decl);
18449 addr = build_fold_addr_expr (link_ptr_decl);
18450 #else
18451 addr = build_fold_addr_expr (it);
18452 #endif
18454 /* Most significant bit of the size marks "omp declare target link"
18455 vars in host and target tables. */
18456 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18457 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18458 * BITS_PER_UNIT - 1);
18459 size = wide_int_to_tree (const_ptr_type_node, isize);
18462 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18463 if (is_var)
18464 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18468 /* Create new symbols containing (address, size) pairs for global variables,
18469 marked with "omp declare target" attribute, as well as addresses for the
18470 functions, which are outlined offloading regions. */
18471 void
18472 omp_finish_file (void)
18474 unsigned num_funcs = vec_safe_length (offload_funcs);
18475 unsigned num_vars = vec_safe_length (offload_vars);
18477 if (num_funcs == 0 && num_vars == 0)
18478 return;
18480 if (targetm_common.have_named_sections)
18482 vec<constructor_elt, va_gc> *v_f, *v_v;
18483 vec_alloc (v_f, num_funcs);
18484 vec_alloc (v_v, num_vars * 2);
18486 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18487 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18489 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18490 num_vars * 2);
18491 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18492 num_funcs);
18493 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18494 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18495 tree ctor_v = build_constructor (vars_decl_type, v_v);
18496 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18497 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18498 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18499 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18500 get_identifier (".offload_func_table"),
18501 funcs_decl_type);
18502 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18503 get_identifier (".offload_var_table"),
18504 vars_decl_type);
18505 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18506 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18507 otherwise a joint table in a binary will contain padding between
18508 tables from multiple object files. */
18509 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18510 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18511 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18512 DECL_INITIAL (funcs_decl) = ctor_f;
18513 DECL_INITIAL (vars_decl) = ctor_v;
18514 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18515 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18517 varpool_node::finalize_decl (vars_decl);
18518 varpool_node::finalize_decl (funcs_decl);
18520 else
18522 for (unsigned i = 0; i < num_funcs; i++)
18524 tree it = (*offload_funcs)[i];
18525 targetm.record_offload_symbol (it);
18527 for (unsigned i = 0; i < num_vars; i++)
18529 tree it = (*offload_vars)[i];
18530 targetm.record_offload_symbol (it);
18535 /* Find the number of threads (POS = false), or thread number (POS =
18536 true) for an OpenACC region partitioned as MASK. Setup code
18537 required for the calculation is added to SEQ. */
18539 static tree
18540 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18542 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18543 unsigned ix;
18545 /* Start at gang level, and examine relevant dimension indices. */
18546 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18547 if (GOMP_DIM_MASK (ix) & mask)
18549 tree arg = build_int_cst (unsigned_type_node, ix);
18551 if (res)
18553 /* We had an outer index, so scale that by the size of
18554 this dimension. */
18555 tree n = create_tmp_var (integer_type_node);
18556 gimple *call
18557 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18559 gimple_call_set_lhs (call, n);
18560 gimple_seq_add_stmt (seq, call);
18561 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18563 if (pos)
18565 /* Determine index in this dimension. */
18566 tree id = create_tmp_var (integer_type_node);
18567 gimple *call = gimple_build_call_internal
18568 (IFN_GOACC_DIM_POS, 1, arg);
18570 gimple_call_set_lhs (call, id);
18571 gimple_seq_add_stmt (seq, call);
18572 if (res)
18573 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18574 else
18575 res = id;
18579 if (res == NULL_TREE)
18580 res = integer_zero_node;
18582 return res;
18585 /* Transform IFN_GOACC_LOOP calls to actual code. See
18586 expand_oacc_for for where these are generated. At the vector
18587 level, we stride loops, such that each member of a warp will
18588 operate on adjacent iterations. At the worker and gang level,
18589 each gang/warp executes a set of contiguous iterations. Chunking
18590 can override this such that each iteration engine executes a
18591 contiguous chunk, and then moves on to stride to the next chunk. */
18593 static void
18594 oacc_xform_loop (gcall *call)
18596 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18597 enum ifn_goacc_loop_kind code
18598 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18599 tree dir = gimple_call_arg (call, 1);
18600 tree range = gimple_call_arg (call, 2);
18601 tree step = gimple_call_arg (call, 3);
18602 tree chunk_size = NULL_TREE;
18603 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18604 tree lhs = gimple_call_lhs (call);
18605 tree type = TREE_TYPE (lhs);
18606 tree diff_type = TREE_TYPE (range);
18607 tree r = NULL_TREE;
18608 gimple_seq seq = NULL;
18609 bool chunking = false, striding = true;
18610 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18611 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18613 #ifdef ACCEL_COMPILER
18614 chunk_size = gimple_call_arg (call, 4);
18615 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18616 || integer_zerop (chunk_size)) /* Default (also static). */
18618 /* If we're at the gang level, we want each to execute a
18619 contiguous run of iterations. Otherwise we want each element
18620 to stride. */
18621 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18622 chunking = false;
18624 else
18626 /* Chunk of size 1 is striding. */
18627 striding = integer_onep (chunk_size);
18628 chunking = !striding;
18630 #endif
18632 /* striding=true, chunking=true
18633 -> invalid.
18634 striding=true, chunking=false
18635 -> chunks=1
18636 striding=false,chunking=true
18637 -> chunks=ceil (range/(chunksize*threads*step))
18638 striding=false,chunking=false
18639 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18640 push_gimplify_context (true);
18642 switch (code)
18644 default: gcc_unreachable ();
18646 case IFN_GOACC_LOOP_CHUNKS:
18647 if (!chunking)
18648 r = build_int_cst (type, 1);
18649 else
18651 /* chunk_max
18652 = (range - dir) / (chunks * step * num_threads) + dir */
18653 tree per = oacc_thread_numbers (false, mask, &seq);
18654 per = fold_convert (type, per);
18655 chunk_size = fold_convert (type, chunk_size);
18656 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18657 per = fold_build2 (MULT_EXPR, type, per, step);
18658 r = build2 (MINUS_EXPR, type, range, dir);
18659 r = build2 (PLUS_EXPR, type, r, per);
18660 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18662 break;
18664 case IFN_GOACC_LOOP_STEP:
18666 /* If striding, step by the entire compute volume, otherwise
18667 step by the inner volume. */
18668 unsigned volume = striding ? mask : inner_mask;
18670 r = oacc_thread_numbers (false, volume, &seq);
18671 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18673 break;
18675 case IFN_GOACC_LOOP_OFFSET:
18676 if (striding)
18678 r = oacc_thread_numbers (true, mask, &seq);
18679 r = fold_convert (diff_type, r);
18681 else
18683 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18684 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18685 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18686 inner_size, outer_size);
18688 volume = fold_convert (diff_type, volume);
18689 if (chunking)
18690 chunk_size = fold_convert (diff_type, chunk_size);
18691 else
18693 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18695 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18696 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18697 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18700 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18701 fold_convert (diff_type, inner_size));
18702 r = oacc_thread_numbers (true, outer_mask, &seq);
18703 r = fold_convert (diff_type, r);
18704 r = build2 (MULT_EXPR, diff_type, r, span);
18706 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18707 inner = fold_convert (diff_type, inner);
18708 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18710 if (chunking)
18712 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18713 tree per
18714 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18715 per = build2 (MULT_EXPR, diff_type, per, chunk);
18717 r = build2 (PLUS_EXPR, diff_type, r, per);
18720 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18721 if (type != diff_type)
18722 r = fold_convert (type, r);
18723 break;
18725 case IFN_GOACC_LOOP_BOUND:
18726 if (striding)
18727 r = range;
18728 else
18730 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18731 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18732 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18733 inner_size, outer_size);
18735 volume = fold_convert (diff_type, volume);
18736 if (chunking)
18737 chunk_size = fold_convert (diff_type, chunk_size);
18738 else
18740 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18742 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18743 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18744 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18747 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18748 fold_convert (diff_type, inner_size));
18750 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18752 tree offset = gimple_call_arg (call, 6);
18753 r = build2 (PLUS_EXPR, diff_type, r,
18754 fold_convert (diff_type, offset));
18755 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18756 diff_type, r, range);
18758 if (diff_type != type)
18759 r = fold_convert (type, r);
18760 break;
18763 gimplify_assign (lhs, r, &seq);
18765 pop_gimplify_context (NULL);
18767 gsi_replace_with_seq (&gsi, seq, true);
18770 /* Default partitioned and minimum partitioned dimensions. */
18772 static int oacc_default_dims[GOMP_DIM_MAX];
18773 static int oacc_min_dims[GOMP_DIM_MAX];
18775 /* Parse the default dimension parameter. This is a set of
18776 :-separated optional compute dimensions. Each specified dimension
18777 is a positive integer. When device type support is added, it is
18778 planned to be a comma separated list of such compute dimensions,
18779 with all but the first prefixed by the colon-terminated device
18780 type. */
18782 static void
18783 oacc_parse_default_dims (const char *dims)
18785 int ix;
18787 for (ix = GOMP_DIM_MAX; ix--;)
18789 oacc_default_dims[ix] = -1;
18790 oacc_min_dims[ix] = 1;
18793 #ifndef ACCEL_COMPILER
18794 /* Cannot be overridden on the host. */
18795 dims = NULL;
18796 #endif
18797 if (dims)
18799 const char *pos = dims;
18801 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18803 if (ix)
18805 if (*pos != ':')
18806 goto malformed;
18807 pos++;
18810 if (*pos != ':')
18812 long val;
18813 const char *eptr;
18815 errno = 0;
18816 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18817 if (errno || val <= 0 || (int) val != val)
18818 goto malformed;
18819 pos = eptr;
18820 oacc_default_dims[ix] = (int) val;
18823 if (*pos)
18825 malformed:
18826 error_at (UNKNOWN_LOCATION,
18827 "-fopenacc-dim operand is malformed at '%s'", pos);
18831 /* Allow the backend to validate the dimensions. */
18832 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18833 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18836 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18837 raw attribute. DIMS is an array of dimensions, which is filled in.
18838 LEVEL is the partitioning level of a routine, or -1 for an offload
18839 region itself. USED is the mask of partitioned execution in the
18840 function. */
18842 static void
18843 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18845 tree purpose[GOMP_DIM_MAX];
18846 unsigned ix;
18847 tree pos = TREE_VALUE (attrs);
18848 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18850 /* Make sure the attribute creator attached the dimension
18851 information. */
18852 gcc_assert (pos);
18854 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18856 purpose[ix] = TREE_PURPOSE (pos);
18857 tree val = TREE_VALUE (pos);
18858 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18859 pos = TREE_CHAIN (pos);
18862 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18864 /* Default anything left to 1 or a partitioned default. */
18865 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18866 if (dims[ix] < 0)
18868 /* The OpenACC spec says 'If the [num_gangs] clause is not
18869 specified, an implementation-defined default will be used;
18870 the default may depend on the code within the construct.'
18871 (2.5.6). Thus an implementation is free to choose
18872 non-unity default for a parallel region that doesn't have
18873 any gang-partitioned loops. However, it appears that there
18874 is a sufficient body of user code that expects non-gang
18875 partitioned regions to not execute in gang-redundant mode.
18876 So we (a) don't warn about the non-portability and (b) pick
18877 the minimum permissible dimension size when there is no
18878 partitioned execution. Otherwise we pick the global
18879 default for the dimension, which the user can control. The
18880 same wording and logic applies to num_workers and
18881 vector_length, however the worker- or vector- single
18882 execution doesn't have the same impact as gang-redundant
18883 execution. (If the minimum gang-level partioning is not 1,
18884 the target is probably too confusing.) */
18885 dims[ix] = (used & GOMP_DIM_MASK (ix)
18886 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18887 changed = true;
18890 if (changed)
18892 /* Replace the attribute with new values. */
18893 pos = NULL_TREE;
18894 for (ix = GOMP_DIM_MAX; ix--;)
18896 pos = tree_cons (purpose[ix],
18897 build_int_cst (integer_type_node, dims[ix]),
18898 pos);
18899 if (is_kernel)
18900 TREE_PUBLIC (pos) = 1;
18902 replace_oacc_fn_attrib (fn, pos);
18906 /* Create an empty OpenACC loop structure at LOC. */
18908 static oacc_loop *
18909 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18911 oacc_loop *loop = XCNEW (oacc_loop);
18913 loop->parent = parent;
18914 loop->child = loop->sibling = NULL;
18916 if (parent)
18918 loop->sibling = parent->child;
18919 parent->child = loop;
18922 loop->loc = loc;
18923 loop->marker = NULL;
18924 memset (loop->heads, 0, sizeof (loop->heads));
18925 memset (loop->tails, 0, sizeof (loop->tails));
18926 loop->routine = NULL_TREE;
18928 loop->mask = loop->flags = loop->inner = 0;
18929 loop->ifns = 0;
18930 loop->chunk_size = 0;
18931 loop->head_end = NULL;
18933 return loop;
18936 /* Create an outermost, dummy OpenACC loop for offloaded function
18937 DECL. */
18939 static oacc_loop *
18940 new_oacc_loop_outer (tree decl)
18942 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18945 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18946 Link into PARENT loop. Return the new loop. */
18948 static oacc_loop *
18949 new_oacc_loop (oacc_loop *parent, gcall *marker)
18951 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18953 loop->marker = marker;
18955 /* TODO: This is where device_type flattening would occur for the loop
18956 flags. */
18958 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18960 tree chunk_size = integer_zero_node;
18961 if (loop->flags & OLF_GANG_STATIC)
18962 chunk_size = gimple_call_arg (marker, 4);
18963 loop->chunk_size = chunk_size;
18965 return loop;
18968 /* Create a dummy loop encompassing a call to a openACC routine.
18969 Extract the routine's partitioning requirements. */
18971 static void
18972 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18974 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18975 int level = oacc_fn_attrib_level (attrs);
18977 gcc_assert (level >= 0);
18979 loop->marker = call;
18980 loop->routine = decl;
18981 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18982 ^ (GOMP_DIM_MASK (level) - 1));
18985 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18986 Return the parent loop. */
18988 static oacc_loop *
18989 finish_oacc_loop (oacc_loop *loop)
18991 /* If the loop has been collapsed, don't partition it. */
18992 if (!loop->ifns)
18993 loop->mask = loop->flags = 0;
18994 return loop->parent;
18997 /* Free all OpenACC loop structures within LOOP (inclusive). */
18999 static void
19000 free_oacc_loop (oacc_loop *loop)
19002 if (loop->sibling)
19003 free_oacc_loop (loop->sibling);
19004 if (loop->child)
19005 free_oacc_loop (loop->child);
19007 free (loop);
19010 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19012 static void
19013 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19014 const char *title, int level)
19016 enum ifn_unique_kind kind
19017 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19019 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19020 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19022 gimple *stmt = gsi_stmt (gsi);
19024 if (is_gimple_call (stmt)
19025 && gimple_call_internal_p (stmt)
19026 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19028 enum ifn_unique_kind k
19029 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19030 (gimple_call_arg (stmt, 0)));
19032 if (k == kind && stmt != from)
19033 break;
19035 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19037 gsi_next (&gsi);
19038 while (gsi_end_p (gsi))
19039 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19043 /* Dump OpenACC loops LOOP, its siblings and its children. */
19045 static void
19046 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19048 int ix;
19050 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19051 loop->flags, loop->mask,
19052 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19054 if (loop->marker)
19055 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19057 if (loop->routine)
19058 fprintf (file, "%*sRoutine %s:%u:%s\n",
19059 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19060 DECL_SOURCE_LINE (loop->routine),
19061 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19063 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19064 if (loop->heads[ix])
19065 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19066 for (ix = GOMP_DIM_MAX; ix--;)
19067 if (loop->tails[ix])
19068 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19070 if (loop->child)
19071 dump_oacc_loop (file, loop->child, depth + 1);
19072 if (loop->sibling)
19073 dump_oacc_loop (file, loop->sibling, depth);
19076 void debug_oacc_loop (oacc_loop *);
19078 /* Dump loops to stderr. */
19080 DEBUG_FUNCTION void
19081 debug_oacc_loop (oacc_loop *loop)
19083 dump_oacc_loop (stderr, loop, 0);
19086 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19087 structures as we go. By construction these loops are properly
19088 nested. */
19090 static void
19091 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19093 int marker = 0;
19094 int remaining = 0;
19096 if (bb->flags & BB_VISITED)
19097 return;
19099 follow:
19100 bb->flags |= BB_VISITED;
19102 /* Scan for loop markers. */
19103 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19104 gsi_next (&gsi))
19106 gimple *stmt = gsi_stmt (gsi);
19108 if (!is_gimple_call (stmt))
19109 continue;
19111 gcall *call = as_a <gcall *> (stmt);
19113 /* If this is a routine, make a dummy loop for it. */
19114 if (tree decl = gimple_call_fndecl (call))
19115 if (tree attrs = get_oacc_fn_attrib (decl))
19117 gcc_assert (!marker);
19118 new_oacc_loop_routine (loop, call, decl, attrs);
19121 if (!gimple_call_internal_p (call))
19122 continue;
19124 switch (gimple_call_internal_fn (call))
19126 default:
19127 break;
19129 case IFN_GOACC_LOOP:
19130 /* Count the goacc loop abstraction fns, to determine if the
19131 loop was collapsed already. */
19132 loop->ifns++;
19133 break;
19135 case IFN_UNIQUE:
19136 enum ifn_unique_kind kind
19137 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19138 (gimple_call_arg (call, 0)));
19139 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19140 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19142 if (gimple_call_num_args (call) == 2)
19144 gcc_assert (marker && !remaining);
19145 marker = 0;
19146 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19147 loop = finish_oacc_loop (loop);
19148 else
19149 loop->head_end = call;
19151 else
19153 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19155 if (!marker)
19157 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19158 loop = new_oacc_loop (loop, call);
19159 remaining = count;
19161 gcc_assert (count == remaining);
19162 if (remaining)
19164 remaining--;
19165 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19166 loop->heads[marker] = call;
19167 else
19168 loop->tails[remaining] = call;
19170 marker++;
19175 if (remaining || marker)
19177 bb = single_succ (bb);
19178 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19179 goto follow;
19182 /* Walk successor blocks. */
19183 edge e;
19184 edge_iterator ei;
19186 FOR_EACH_EDGE (e, ei, bb->succs)
19187 oacc_loop_discover_walk (loop, e->dest);
19190 /* LOOP is the first sibling. Reverse the order in place and return
19191 the new first sibling. Recurse to child loops. */
19193 static oacc_loop *
19194 oacc_loop_sibling_nreverse (oacc_loop *loop)
19196 oacc_loop *last = NULL;
19199 if (loop->child)
19200 loop->child = oacc_loop_sibling_nreverse (loop->child);
19202 oacc_loop *next = loop->sibling;
19203 loop->sibling = last;
19204 last = loop;
19205 loop = next;
19207 while (loop);
19209 return last;
19212 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19213 the current function. */
19215 static oacc_loop *
19216 oacc_loop_discovery ()
19218 basic_block bb;
19220 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19221 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19223 /* The siblings were constructed in reverse order, reverse them so
19224 that diagnostics come out in an unsurprising order. */
19225 top = oacc_loop_sibling_nreverse (top);
19227 /* Reset the visited flags. */
19228 FOR_ALL_BB_FN (bb, cfun)
19229 bb->flags &= ~BB_VISITED;
19231 return top;
19234 /* Transform the abstract internal function markers starting at FROM
19235 to be for partitioning level LEVEL. Stop when we meet another HEAD
19236 or TAIL marker. */
19238 static void
19239 oacc_loop_xform_head_tail (gcall *from, int level)
19241 enum ifn_unique_kind kind
19242 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19243 tree replacement = build_int_cst (unsigned_type_node, level);
19245 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19247 gimple *stmt = gsi_stmt (gsi);
19249 if (is_gimple_call (stmt)
19250 && gimple_call_internal_p (stmt)
19251 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19253 enum ifn_unique_kind k
19254 = ((enum ifn_unique_kind)
19255 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19257 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19258 *gimple_call_arg_ptr (stmt, 2) = replacement;
19259 else if (k == kind && stmt != from)
19260 break;
19262 else if (is_gimple_call (stmt)
19263 && gimple_call_internal_p (stmt)
19264 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19265 *gimple_call_arg_ptr (stmt, 3) = replacement;
19267 gsi_next (&gsi);
19268 while (gsi_end_p (gsi))
19269 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19273 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19274 determined partitioning mask and chunking argument. END_MARKER
19275 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19276 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19277 the replacement partitioning mask and CHUNK_ARG is the replacement
19278 chunking arg. */
19280 static void
19281 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19282 tree mask_arg, tree chunk_arg)
19284 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19286 gcc_checking_assert (ifns);
19287 for (;;)
19289 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19291 gimple *stmt = gsi_stmt (gsi);
19293 if (!is_gimple_call (stmt))
19294 continue;
19296 gcall *call = as_a <gcall *> (stmt);
19298 if (!gimple_call_internal_p (call))
19299 continue;
19301 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19302 continue;
19304 *gimple_call_arg_ptr (call, 5) = mask_arg;
19305 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19306 ifns--;
19307 if (!ifns)
19308 return;
19311 /* The LOOP_BOUND ifn could be in the single successor
19312 block. */
19313 basic_block bb = single_succ (gsi_bb (gsi));
19314 gsi = gsi_start_bb (bb);
19318 /* Process the discovered OpenACC loops, setting the correct
19319 partitioning level etc. */
19321 static void
19322 oacc_loop_process (oacc_loop *loop)
19324 if (loop->child)
19325 oacc_loop_process (loop->child);
19327 if (loop->mask && !loop->routine)
19329 int ix;
19330 unsigned mask = loop->mask;
19331 unsigned dim = GOMP_DIM_GANG;
19332 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19333 tree chunk_arg = loop->chunk_size;
19335 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19337 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19339 while (!(GOMP_DIM_MASK (dim) & mask))
19340 dim++;
19342 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19343 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19345 mask ^= GOMP_DIM_MASK (dim);
19349 if (loop->sibling)
19350 oacc_loop_process (loop->sibling);
19353 /* Walk the OpenACC loop heirarchy checking and assigning the
19354 programmer-specified partitionings. OUTER_MASK is the partitioning
19355 this loop is contained within. Return mask of partitioning
19356 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19357 bit. */
19359 static unsigned
19360 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19362 unsigned this_mask = loop->mask;
19363 unsigned mask_all = 0;
19364 bool noisy = true;
19366 #ifdef ACCEL_COMPILER
19367 /* When device_type is supported, we want the device compiler to be
19368 noisy, if the loop parameters are device_type-specific. */
19369 noisy = false;
19370 #endif
19372 if (!loop->routine)
19374 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19375 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19377 this_mask = ((loop->flags >> OLF_DIM_BASE)
19378 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19380 if ((this_mask != 0) + auto_par + seq_par > 1)
19382 if (noisy)
19383 error_at (loop->loc,
19384 seq_par
19385 ? "%<seq%> overrides other OpenACC loop specifiers"
19386 : "%<auto%> conflicts with other OpenACC loop specifiers");
19387 auto_par = false;
19388 loop->flags &= ~OLF_AUTO;
19389 if (seq_par)
19391 loop->flags &=
19392 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19393 this_mask = 0;
19396 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19397 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19400 if (this_mask & outer_mask)
19402 const oacc_loop *outer;
19403 for (outer = loop->parent; outer; outer = outer->parent)
19404 if (outer->mask & this_mask)
19405 break;
19407 if (noisy)
19409 if (outer)
19411 error_at (loop->loc,
19412 "%s uses same OpenACC parallelism as containing loop",
19413 loop->routine ? "routine call" : "inner loop");
19414 inform (outer->loc, "containing loop here");
19416 else
19417 error_at (loop->loc,
19418 "%s uses OpenACC parallelism disallowed by containing routine",
19419 loop->routine ? "routine call" : "loop");
19421 if (loop->routine)
19422 inform (DECL_SOURCE_LOCATION (loop->routine),
19423 "routine %qD declared here", loop->routine);
19425 this_mask &= ~outer_mask;
19427 else
19429 unsigned outermost = this_mask & -this_mask;
19431 if (outermost && outermost <= outer_mask)
19433 if (noisy)
19435 error_at (loop->loc,
19436 "incorrectly nested OpenACC loop parallelism");
19438 const oacc_loop *outer;
19439 for (outer = loop->parent;
19440 outer->flags && outer->flags < outermost;
19441 outer = outer->parent)
19442 continue;
19443 inform (outer->loc, "containing loop here");
19446 this_mask &= ~outermost;
19450 loop->mask = this_mask;
19451 mask_all |= this_mask;
19453 if (loop->child)
19455 loop->inner = oacc_loop_fixed_partitions (loop->child,
19456 outer_mask | this_mask);
19457 mask_all |= loop->inner;
19460 if (loop->sibling)
19461 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19463 return mask_all;
19466 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19467 OUTER_MASK is the partitioning this loop is contained within.
19468 Return the cumulative partitioning used by this loop, siblings and
19469 children. */
19471 static unsigned
19472 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19474 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19475 bool noisy = true;
19477 #ifdef ACCEL_COMPILER
19478 /* When device_type is supported, we want the device compiler to be
19479 noisy, if the loop parameters are device_type-specific. */
19480 noisy = false;
19481 #endif
19483 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19485 /* Allocate the outermost loop at the outermost available
19486 level. */
19487 unsigned this_mask = outer_mask + 1;
19489 if (!(this_mask & loop->inner))
19490 loop->mask = this_mask;
19493 if (loop->child)
19495 unsigned child_mask = outer_mask | loop->mask;
19497 if (loop->mask || assign)
19498 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19500 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19503 if (assign && !loop->mask)
19505 /* Allocate the loop at the innermost available level. */
19506 unsigned this_mask = 0;
19508 /* Determine the outermost partitioning used within this loop. */
19509 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19510 this_mask = (this_mask & -this_mask);
19512 /* Pick the partitioning just inside that one. */
19513 this_mask >>= 1;
19515 /* And avoid picking one use by an outer loop. */
19516 this_mask &= ~outer_mask;
19518 if (!this_mask && noisy)
19519 warning_at (loop->loc, 0,
19520 "insufficient partitioning available to parallelize loop");
19522 loop->mask = this_mask;
19525 if (assign && dump_file)
19526 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19527 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19528 loop->mask);
19530 unsigned inner_mask = 0;
19532 if (loop->sibling)
19533 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19535 inner_mask |= loop->inner | loop->mask;
19537 return inner_mask;
19540 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19541 axes. Return mask of partitioning. */
19543 static unsigned
19544 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19546 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19548 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19550 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19551 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19553 return mask_all;
19556 /* Default fork/join early expander. Delete the function calls if
19557 there is no RTL expander. */
19559 bool
19560 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19561 const int *ARG_UNUSED (dims), bool is_fork)
19563 if (is_fork)
19564 return targetm.have_oacc_fork ();
19565 else
19566 return targetm.have_oacc_join ();
19569 /* Default goacc.reduction early expander.
19571 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19572 If RES_PTR is not integer-zerop:
19573 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19574 TEARDOWN - emit '*RES_PTR = VAR'
19575 If LHS is not NULL
19576 emit 'LHS = VAR' */
19578 void
19579 default_goacc_reduction (gcall *call)
19581 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19582 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19583 tree lhs = gimple_call_lhs (call);
19584 tree var = gimple_call_arg (call, 2);
19585 gimple_seq seq = NULL;
19587 if (code == IFN_GOACC_REDUCTION_SETUP
19588 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19590 /* Setup and Teardown need to copy from/to the receiver object,
19591 if there is one. */
19592 tree ref_to_res = gimple_call_arg (call, 1);
19594 if (!integer_zerop (ref_to_res))
19596 tree dst = build_simple_mem_ref (ref_to_res);
19597 tree src = var;
19599 if (code == IFN_GOACC_REDUCTION_SETUP)
19601 src = dst;
19602 dst = lhs;
19603 lhs = NULL;
19605 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19609 /* Copy VAR to LHS, if there is an LHS. */
19610 if (lhs)
19611 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19613 gsi_replace_with_seq (&gsi, seq, true);
19616 /* Main entry point for oacc transformations which run on the device
19617 compiler after LTO, so we know what the target device is at this
19618 point (including the host fallback). */
19620 static unsigned int
19621 execute_oacc_device_lower ()
19623 tree attrs = get_oacc_fn_attrib (current_function_decl);
19625 if (!attrs)
19626 /* Not an offloaded function. */
19627 return 0;
19629 /* Parse the default dim argument exactly once. */
19630 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19632 oacc_parse_default_dims (flag_openacc_dims);
19633 flag_openacc_dims = (char *)&flag_openacc_dims;
19636 /* Discover, partition and process the loops. */
19637 oacc_loop *loops = oacc_loop_discovery ();
19638 int fn_level = oacc_fn_attrib_level (attrs);
19640 if (dump_file)
19641 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19642 ? "Function is kernels offload\n"
19643 : fn_level < 0 ? "Function is parallel offload\n"
19644 : "Function is routine level %d\n", fn_level);
19646 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19647 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19648 int dims[GOMP_DIM_MAX];
19650 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19652 if (dump_file)
19654 const char *comma = "Compute dimensions [";
19655 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19656 fprintf (dump_file, "%s%d", comma, dims[ix]);
19657 fprintf (dump_file, "]\n");
19660 oacc_loop_process (loops);
19661 if (dump_file)
19663 fprintf (dump_file, "OpenACC loops\n");
19664 dump_oacc_loop (dump_file, loops, 0);
19665 fprintf (dump_file, "\n");
19668 /* Offloaded targets may introduce new basic blocks, which require
19669 dominance information to update SSA. */
19670 calculate_dominance_info (CDI_DOMINATORS);
19672 /* Now lower internal loop functions to target-specific code
19673 sequences. */
19674 basic_block bb;
19675 FOR_ALL_BB_FN (bb, cfun)
19676 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19678 gimple *stmt = gsi_stmt (gsi);
19679 if (!is_gimple_call (stmt))
19681 gsi_next (&gsi);
19682 continue;
19685 gcall *call = as_a <gcall *> (stmt);
19686 if (!gimple_call_internal_p (call))
19688 gsi_next (&gsi);
19689 continue;
19692 /* Rewind to allow rescan. */
19693 gsi_prev (&gsi);
19694 bool rescan = false, remove = false;
19695 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19697 switch (ifn_code)
19699 default: break;
19701 case IFN_GOACC_LOOP:
19702 oacc_xform_loop (call);
19703 rescan = true;
19704 break;
19706 case IFN_GOACC_REDUCTION:
19707 /* Mark the function for SSA renaming. */
19708 mark_virtual_operands_for_renaming (cfun);
19710 /* If the level is -1, this ended up being an unused
19711 axis. Handle as a default. */
19712 if (integer_minus_onep (gimple_call_arg (call, 3)))
19713 default_goacc_reduction (call);
19714 else
19715 targetm.goacc.reduction (call);
19716 rescan = true;
19717 break;
19719 case IFN_UNIQUE:
19721 enum ifn_unique_kind kind
19722 = ((enum ifn_unique_kind)
19723 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19725 switch (kind)
19727 default:
19728 gcc_unreachable ();
19730 case IFN_UNIQUE_OACC_FORK:
19731 case IFN_UNIQUE_OACC_JOIN:
19732 if (integer_minus_onep (gimple_call_arg (call, 2)))
19733 remove = true;
19734 else if (!targetm.goacc.fork_join
19735 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19736 remove = true;
19737 break;
19739 case IFN_UNIQUE_OACC_HEAD_MARK:
19740 case IFN_UNIQUE_OACC_TAIL_MARK:
19741 remove = true;
19742 break;
19744 break;
19748 if (gsi_end_p (gsi))
19749 /* We rewound past the beginning of the BB. */
19750 gsi = gsi_start_bb (bb);
19751 else
19752 /* Undo the rewind. */
19753 gsi_next (&gsi);
19755 if (remove)
19757 if (gimple_vdef (call))
19758 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19759 if (gimple_call_lhs (call))
19761 /* Propagate the data dependency var. */
19762 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19763 gimple_call_arg (call, 1));
19764 gsi_replace (&gsi, ass, false);
19766 else
19767 gsi_remove (&gsi, true);
19769 else if (!rescan)
19770 /* If not rescanning, advance over the call. */
19771 gsi_next (&gsi);
19774 free_oacc_loop (loops);
19776 return 0;
19779 /* Default launch dimension validator. Force everything to 1. A
19780 backend that wants to provide larger dimensions must override this
19781 hook. */
19783 bool
19784 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19785 int ARG_UNUSED (fn_level))
19787 bool changed = false;
19789 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19791 if (dims[ix] != 1)
19793 dims[ix] = 1;
19794 changed = true;
19798 return changed;
19801 /* Default dimension bound is unknown on accelerator and 1 on host. */
19804 default_goacc_dim_limit (int ARG_UNUSED (axis))
19806 #ifdef ACCEL_COMPILER
19807 return 0;
19808 #else
19809 return 1;
19810 #endif
19813 namespace {
19815 const pass_data pass_data_oacc_device_lower =
19817 GIMPLE_PASS, /* type */
19818 "oaccdevlow", /* name */
19819 OPTGROUP_NONE, /* optinfo_flags */
19820 TV_NONE, /* tv_id */
19821 PROP_cfg, /* properties_required */
19822 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19823 0, /* properties_destroyed */
19824 0, /* todo_flags_start */
19825 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19828 class pass_oacc_device_lower : public gimple_opt_pass
19830 public:
19831 pass_oacc_device_lower (gcc::context *ctxt)
19832 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19835 /* opt_pass methods: */
19836 virtual unsigned int execute (function *)
19838 bool gate = flag_openacc != 0;
19840 if (!gate)
19841 return 0;
19843 return execute_oacc_device_lower ();
19846 }; // class pass_oacc_device_lower
19848 } // anon namespace
19850 gimple_opt_pass *
19851 make_pass_oacc_device_lower (gcc::context *ctxt)
19853 return new pass_oacc_device_lower (ctxt);
19856 /* "omp declare target link" handling pass. */
19858 namespace {
19860 const pass_data pass_data_omp_target_link =
19862 GIMPLE_PASS, /* type */
19863 "omptargetlink", /* name */
19864 OPTGROUP_NONE, /* optinfo_flags */
19865 TV_NONE, /* tv_id */
19866 PROP_ssa, /* properties_required */
19867 0, /* properties_provided */
19868 0, /* properties_destroyed */
19869 0, /* todo_flags_start */
19870 TODO_update_ssa, /* todo_flags_finish */
19873 class pass_omp_target_link : public gimple_opt_pass
19875 public:
19876 pass_omp_target_link (gcc::context *ctxt)
19877 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19880 /* opt_pass methods: */
19881 virtual bool gate (function *fun)
19883 #ifdef ACCEL_COMPILER
19884 tree attrs = DECL_ATTRIBUTES (fun->decl);
19885 return lookup_attribute ("omp declare target", attrs)
19886 || lookup_attribute ("omp target entrypoint", attrs);
19887 #else
19888 (void) fun;
19889 return false;
19890 #endif
19893 virtual unsigned execute (function *);
19896 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19898 static tree
19899 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19901 tree t = *tp;
19903 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19904 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19906 *walk_subtrees = 0;
19907 return t;
19910 return NULL_TREE;
19913 unsigned
19914 pass_omp_target_link::execute (function *fun)
19916 basic_block bb;
19917 FOR_EACH_BB_FN (bb, fun)
19919 gimple_stmt_iterator gsi;
19920 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19921 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19922 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19925 return 0;
19928 } // anon namespace
19930 gimple_opt_pass *
19931 make_pass_omp_target_link (gcc::context *ctxt)
19933 return new pass_omp_target_link (ctxt);
19936 #include "gt-omp-low.h"