2016-05-14 Fritz Reese <fritzoreese@gmail.com>
[official-gcc.git] / gcc / omp-low.c
blobc9600fb6d33424f46e78fe221fc041745c4efb09
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_TILE:
2191 case OMP_CLAUSE_INDEPENDENT:
2192 case OMP_CLAUSE_AUTO:
2193 case OMP_CLAUSE_SEQ:
2194 break;
2196 case OMP_CLAUSE_ALIGNED:
2197 decl = OMP_CLAUSE_DECL (c);
2198 if (is_global_var (decl)
2199 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2200 install_var_local (decl, ctx);
2201 break;
2203 case OMP_CLAUSE_DEVICE_RESIDENT:
2204 case OMP_CLAUSE__CACHE_:
2205 sorry ("Clause not supported yet");
2206 break;
2208 default:
2209 gcc_unreachable ();
2213 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2215 switch (OMP_CLAUSE_CODE (c))
2217 case OMP_CLAUSE_LASTPRIVATE:
2218 /* Let the corresponding firstprivate clause create
2219 the variable. */
2220 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2221 scan_array_reductions = true;
2222 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2223 break;
2224 /* FALLTHRU */
2226 case OMP_CLAUSE_FIRSTPRIVATE:
2227 case OMP_CLAUSE_PRIVATE:
2228 case OMP_CLAUSE_LINEAR:
2229 case OMP_CLAUSE_IS_DEVICE_PTR:
2230 decl = OMP_CLAUSE_DECL (c);
2231 if (is_variable_sized (decl))
2233 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2234 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2235 && is_gimple_omp_offloaded (ctx->stmt))
2237 tree decl2 = DECL_VALUE_EXPR (decl);
2238 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2239 decl2 = TREE_OPERAND (decl2, 0);
2240 gcc_assert (DECL_P (decl2));
2241 install_var_local (decl2, ctx);
2242 fixup_remapped_decl (decl2, ctx, false);
2244 install_var_local (decl, ctx);
2246 fixup_remapped_decl (decl, ctx,
2247 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2248 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2249 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2250 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2251 scan_array_reductions = true;
2252 break;
2254 case OMP_CLAUSE_REDUCTION:
2255 decl = OMP_CLAUSE_DECL (c);
2256 if (TREE_CODE (decl) != MEM_REF)
2258 if (is_variable_sized (decl))
2259 install_var_local (decl, ctx);
2260 fixup_remapped_decl (decl, ctx, false);
2262 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2263 scan_array_reductions = true;
2264 break;
2266 case OMP_CLAUSE_SHARED:
2267 /* Ignore shared directives in teams construct. */
2268 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2269 break;
2270 decl = OMP_CLAUSE_DECL (c);
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2272 break;
2273 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2275 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2276 ctx->outer)))
2277 break;
2278 bool by_ref = use_pointer_for_field (decl, ctx);
2279 install_var_field (decl, by_ref, 11, ctx);
2280 break;
2282 fixup_remapped_decl (decl, ctx, false);
2283 break;
2285 case OMP_CLAUSE_MAP:
2286 if (!is_gimple_omp_offloaded (ctx->stmt))
2287 break;
2288 decl = OMP_CLAUSE_DECL (c);
2289 if (DECL_P (decl)
2290 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2291 && (OMP_CLAUSE_MAP_KIND (c)
2292 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2293 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2294 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2295 && varpool_node::get_create (decl)->offloadable)
2296 break;
2297 if (DECL_P (decl))
2299 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2300 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2301 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2302 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2304 tree new_decl = lookup_decl (decl, ctx);
2305 TREE_TYPE (new_decl)
2306 = remap_type (TREE_TYPE (decl), &ctx->cb);
2308 else if (DECL_SIZE (decl)
2309 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2311 tree decl2 = DECL_VALUE_EXPR (decl);
2312 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2313 decl2 = TREE_OPERAND (decl2, 0);
2314 gcc_assert (DECL_P (decl2));
2315 fixup_remapped_decl (decl2, ctx, false);
2316 fixup_remapped_decl (decl, ctx, true);
2318 else
2319 fixup_remapped_decl (decl, ctx, false);
2321 break;
2323 case OMP_CLAUSE_COPYPRIVATE:
2324 case OMP_CLAUSE_COPYIN:
2325 case OMP_CLAUSE_DEFAULT:
2326 case OMP_CLAUSE_IF:
2327 case OMP_CLAUSE_NUM_THREADS:
2328 case OMP_CLAUSE_NUM_TEAMS:
2329 case OMP_CLAUSE_THREAD_LIMIT:
2330 case OMP_CLAUSE_DEVICE:
2331 case OMP_CLAUSE_SCHEDULE:
2332 case OMP_CLAUSE_DIST_SCHEDULE:
2333 case OMP_CLAUSE_NOWAIT:
2334 case OMP_CLAUSE_ORDERED:
2335 case OMP_CLAUSE_COLLAPSE:
2336 case OMP_CLAUSE_UNTIED:
2337 case OMP_CLAUSE_FINAL:
2338 case OMP_CLAUSE_MERGEABLE:
2339 case OMP_CLAUSE_PROC_BIND:
2340 case OMP_CLAUSE_SAFELEN:
2341 case OMP_CLAUSE_SIMDLEN:
2342 case OMP_CLAUSE_ALIGNED:
2343 case OMP_CLAUSE_DEPEND:
2344 case OMP_CLAUSE__LOOPTEMP_:
2345 case OMP_CLAUSE_TO:
2346 case OMP_CLAUSE_FROM:
2347 case OMP_CLAUSE_PRIORITY:
2348 case OMP_CLAUSE_GRAINSIZE:
2349 case OMP_CLAUSE_NUM_TASKS:
2350 case OMP_CLAUSE_THREADS:
2351 case OMP_CLAUSE_SIMD:
2352 case OMP_CLAUSE_NOGROUP:
2353 case OMP_CLAUSE_DEFAULTMAP:
2354 case OMP_CLAUSE_USE_DEVICE_PTR:
2355 case OMP_CLAUSE__CILK_FOR_COUNT_:
2356 case OMP_CLAUSE_ASYNC:
2357 case OMP_CLAUSE_WAIT:
2358 case OMP_CLAUSE_NUM_GANGS:
2359 case OMP_CLAUSE_NUM_WORKERS:
2360 case OMP_CLAUSE_VECTOR_LENGTH:
2361 case OMP_CLAUSE_GANG:
2362 case OMP_CLAUSE_WORKER:
2363 case OMP_CLAUSE_VECTOR:
2364 case OMP_CLAUSE_TILE:
2365 case OMP_CLAUSE_INDEPENDENT:
2366 case OMP_CLAUSE_AUTO:
2367 case OMP_CLAUSE_SEQ:
2368 case OMP_CLAUSE__GRIDDIM_:
2369 break;
2371 case OMP_CLAUSE_DEVICE_RESIDENT:
2372 case OMP_CLAUSE__CACHE_:
2373 sorry ("Clause not supported yet");
2374 break;
2376 default:
2377 gcc_unreachable ();
2381 gcc_checking_assert (!scan_array_reductions
2382 || !is_gimple_omp_oacc (ctx->stmt));
2383 if (scan_array_reductions)
2385 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2386 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2387 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2389 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2390 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2392 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2393 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2394 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2395 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2396 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2397 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2401 /* Create a new name for omp child function. Returns an identifier. If
2402 IS_CILK_FOR is true then the suffix for the child function is
2403 "_cilk_for_fn." */
2405 static tree
2406 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2408 if (is_cilk_for)
2409 return clone_function_name (current_function_decl, "_cilk_for_fn");
2410 return clone_function_name (current_function_decl,
2411 task_copy ? "_omp_cpyfn" : "_omp_fn");
2414 /* Returns the type of the induction variable for the child function for
2415 _Cilk_for and the types for _high and _low variables based on TYPE. */
2417 static tree
2418 cilk_for_check_loop_diff_type (tree type)
2420 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2422 if (TYPE_UNSIGNED (type))
2423 return uint32_type_node;
2424 else
2425 return integer_type_node;
2427 else
2429 if (TYPE_UNSIGNED (type))
2430 return uint64_type_node;
2431 else
2432 return long_long_integer_type_node;
2436 /* Build a decl for the omp child function. It'll not contain a body
2437 yet, just the bare decl. */
2439 static void
2440 create_omp_child_function (omp_context *ctx, bool task_copy)
2442 tree decl, type, name, t;
2444 tree cilk_for_count
2445 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2446 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2447 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2448 tree cilk_var_type = NULL_TREE;
2450 name = create_omp_child_function_name (task_copy,
2451 cilk_for_count != NULL_TREE);
2452 if (task_copy)
2453 type = build_function_type_list (void_type_node, ptr_type_node,
2454 ptr_type_node, NULL_TREE);
2455 else if (cilk_for_count)
2457 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2458 cilk_var_type = cilk_for_check_loop_diff_type (type);
2459 type = build_function_type_list (void_type_node, ptr_type_node,
2460 cilk_var_type, cilk_var_type, NULL_TREE);
2462 else
2463 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2465 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2467 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2468 || !task_copy);
2469 if (!task_copy)
2470 ctx->cb.dst_fn = decl;
2471 else
2472 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2474 TREE_STATIC (decl) = 1;
2475 TREE_USED (decl) = 1;
2476 DECL_ARTIFICIAL (decl) = 1;
2477 DECL_IGNORED_P (decl) = 0;
2478 TREE_PUBLIC (decl) = 0;
2479 DECL_UNINLINABLE (decl) = 1;
2480 DECL_EXTERNAL (decl) = 0;
2481 DECL_CONTEXT (decl) = NULL_TREE;
2482 DECL_INITIAL (decl) = make_node (BLOCK);
2483 if (cgraph_node::get (current_function_decl)->offloadable)
2484 cgraph_node::get_create (decl)->offloadable = 1;
2485 else
2487 omp_context *octx;
2488 for (octx = ctx; octx; octx = octx->outer)
2489 if (is_gimple_omp_offloaded (octx->stmt))
2491 cgraph_node::get_create (decl)->offloadable = 1;
2492 if (ENABLE_OFFLOADING)
2493 g->have_offload = true;
2495 break;
2499 if (cgraph_node::get_create (decl)->offloadable
2500 && !lookup_attribute ("omp declare target",
2501 DECL_ATTRIBUTES (current_function_decl)))
2502 DECL_ATTRIBUTES (decl)
2503 = tree_cons (get_identifier ("omp target entrypoint"),
2504 NULL_TREE, DECL_ATTRIBUTES (decl));
2506 t = build_decl (DECL_SOURCE_LOCATION (decl),
2507 RESULT_DECL, NULL_TREE, void_type_node);
2508 DECL_ARTIFICIAL (t) = 1;
2509 DECL_IGNORED_P (t) = 1;
2510 DECL_CONTEXT (t) = decl;
2511 DECL_RESULT (decl) = t;
2513 /* _Cilk_for's child function requires two extra parameters called
2514 __low and __high that are set the by Cilk runtime when it calls this
2515 function. */
2516 if (cilk_for_count)
2518 t = build_decl (DECL_SOURCE_LOCATION (decl),
2519 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2520 DECL_ARTIFICIAL (t) = 1;
2521 DECL_NAMELESS (t) = 1;
2522 DECL_ARG_TYPE (t) = ptr_type_node;
2523 DECL_CONTEXT (t) = current_function_decl;
2524 TREE_USED (t) = 1;
2525 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2526 DECL_ARGUMENTS (decl) = t;
2528 t = build_decl (DECL_SOURCE_LOCATION (decl),
2529 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2530 DECL_ARTIFICIAL (t) = 1;
2531 DECL_NAMELESS (t) = 1;
2532 DECL_ARG_TYPE (t) = ptr_type_node;
2533 DECL_CONTEXT (t) = current_function_decl;
2534 TREE_USED (t) = 1;
2535 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2536 DECL_ARGUMENTS (decl) = t;
2539 tree data_name = get_identifier (".omp_data_i");
2540 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2541 ptr_type_node);
2542 DECL_ARTIFICIAL (t) = 1;
2543 DECL_NAMELESS (t) = 1;
2544 DECL_ARG_TYPE (t) = ptr_type_node;
2545 DECL_CONTEXT (t) = current_function_decl;
2546 TREE_USED (t) = 1;
2547 TREE_READONLY (t) = 1;
2548 if (cilk_for_count)
2549 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2550 DECL_ARGUMENTS (decl) = t;
2551 if (!task_copy)
2552 ctx->receiver_decl = t;
2553 else
2555 t = build_decl (DECL_SOURCE_LOCATION (decl),
2556 PARM_DECL, get_identifier (".omp_data_o"),
2557 ptr_type_node);
2558 DECL_ARTIFICIAL (t) = 1;
2559 DECL_NAMELESS (t) = 1;
2560 DECL_ARG_TYPE (t) = ptr_type_node;
2561 DECL_CONTEXT (t) = current_function_decl;
2562 TREE_USED (t) = 1;
2563 TREE_ADDRESSABLE (t) = 1;
2564 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2565 DECL_ARGUMENTS (decl) = t;
2568 /* Allocate memory for the function structure. The call to
2569 allocate_struct_function clobbers CFUN, so we need to restore
2570 it afterward. */
2571 push_struct_function (decl);
2572 cfun->function_end_locus = gimple_location (ctx->stmt);
2573 init_tree_ssa (cfun);
2574 pop_cfun ();
2577 /* Callback for walk_gimple_seq. Check if combined parallel
2578 contains gimple_omp_for_combined_into_p OMP_FOR. */
2580 static tree
2581 find_combined_for (gimple_stmt_iterator *gsi_p,
2582 bool *handled_ops_p,
2583 struct walk_stmt_info *wi)
2585 gimple *stmt = gsi_stmt (*gsi_p);
2587 *handled_ops_p = true;
2588 switch (gimple_code (stmt))
2590 WALK_SUBSTMTS;
2592 case GIMPLE_OMP_FOR:
2593 if (gimple_omp_for_combined_into_p (stmt)
2594 && gimple_omp_for_kind (stmt)
2595 == *(const enum gf_mask *) (wi->info))
2597 wi->info = stmt;
2598 return integer_zero_node;
2600 break;
2601 default:
2602 break;
2604 return NULL;
2607 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2609 static void
2610 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2611 omp_context *outer_ctx)
2613 struct walk_stmt_info wi;
2615 memset (&wi, 0, sizeof (wi));
2616 wi.val_only = true;
2617 wi.info = (void *) &msk;
2618 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2619 if (wi.info != (void *) &msk)
2621 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2622 struct omp_for_data fd;
2623 extract_omp_for_data (for_stmt, &fd, NULL);
2624 /* We need two temporaries with fd.loop.v type (istart/iend)
2625 and then (fd.collapse - 1) temporaries with the same
2626 type for count2 ... countN-1 vars if not constant. */
2627 size_t count = 2, i;
2628 tree type = fd.iter_type;
2629 if (fd.collapse > 1
2630 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2632 count += fd.collapse - 1;
2633 /* If there are lastprivate clauses on the inner
2634 GIMPLE_OMP_FOR, add one more temporaries for the total number
2635 of iterations (product of count1 ... countN-1). */
2636 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2637 OMP_CLAUSE_LASTPRIVATE))
2638 count++;
2639 else if (msk == GF_OMP_FOR_KIND_FOR
2640 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2641 OMP_CLAUSE_LASTPRIVATE))
2642 count++;
2644 for (i = 0; i < count; i++)
2646 tree temp = create_tmp_var (type);
2647 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2648 insert_decl_map (&outer_ctx->cb, temp, temp);
2649 OMP_CLAUSE_DECL (c) = temp;
2650 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2651 gimple_omp_taskreg_set_clauses (stmt, c);
2656 /* Scan an OpenMP parallel directive. */
2658 static void
2659 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2661 omp_context *ctx;
2662 tree name;
2663 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2665 /* Ignore parallel directives with empty bodies, unless there
2666 are copyin clauses. */
2667 if (optimize > 0
2668 && empty_body_p (gimple_omp_body (stmt))
2669 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2670 OMP_CLAUSE_COPYIN) == NULL)
2672 gsi_replace (gsi, gimple_build_nop (), false);
2673 return;
2676 if (gimple_omp_parallel_combined_p (stmt))
2677 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2679 ctx = new_omp_context (stmt, outer_ctx);
2680 taskreg_contexts.safe_push (ctx);
2681 if (taskreg_nesting_level > 1)
2682 ctx->is_nested = true;
2683 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2684 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2685 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2686 name = create_tmp_var_name (".omp_data_s");
2687 name = build_decl (gimple_location (stmt),
2688 TYPE_DECL, name, ctx->record_type);
2689 DECL_ARTIFICIAL (name) = 1;
2690 DECL_NAMELESS (name) = 1;
2691 TYPE_NAME (ctx->record_type) = name;
2692 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2693 if (!gimple_omp_parallel_grid_phony (stmt))
2695 create_omp_child_function (ctx, false);
2696 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2699 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2700 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2702 if (TYPE_FIELDS (ctx->record_type) == NULL)
2703 ctx->record_type = ctx->receiver_decl = NULL;
2706 /* Scan an OpenMP task directive. */
2708 static void
2709 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2711 omp_context *ctx;
2712 tree name, t;
2713 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2715 /* Ignore task directives with empty bodies. */
2716 if (optimize > 0
2717 && empty_body_p (gimple_omp_body (stmt)))
2719 gsi_replace (gsi, gimple_build_nop (), false);
2720 return;
2723 if (gimple_omp_task_taskloop_p (stmt))
2724 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2726 ctx = new_omp_context (stmt, outer_ctx);
2727 taskreg_contexts.safe_push (ctx);
2728 if (taskreg_nesting_level > 1)
2729 ctx->is_nested = true;
2730 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2731 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2732 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2733 name = create_tmp_var_name (".omp_data_s");
2734 name = build_decl (gimple_location (stmt),
2735 TYPE_DECL, name, ctx->record_type);
2736 DECL_ARTIFICIAL (name) = 1;
2737 DECL_NAMELESS (name) = 1;
2738 TYPE_NAME (ctx->record_type) = name;
2739 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2740 create_omp_child_function (ctx, false);
2741 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2743 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2745 if (ctx->srecord_type)
2747 name = create_tmp_var_name (".omp_data_a");
2748 name = build_decl (gimple_location (stmt),
2749 TYPE_DECL, name, ctx->srecord_type);
2750 DECL_ARTIFICIAL (name) = 1;
2751 DECL_NAMELESS (name) = 1;
2752 TYPE_NAME (ctx->srecord_type) = name;
2753 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2754 create_omp_child_function (ctx, true);
2757 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2759 if (TYPE_FIELDS (ctx->record_type) == NULL)
2761 ctx->record_type = ctx->receiver_decl = NULL;
2762 t = build_int_cst (long_integer_type_node, 0);
2763 gimple_omp_task_set_arg_size (stmt, t);
2764 t = build_int_cst (long_integer_type_node, 1);
2765 gimple_omp_task_set_arg_align (stmt, t);
2770 /* If any decls have been made addressable during scan_omp,
2771 adjust their fields if needed, and layout record types
2772 of parallel/task constructs. */
2774 static void
2775 finish_taskreg_scan (omp_context *ctx)
2777 if (ctx->record_type == NULL_TREE)
2778 return;
2780 /* If any task_shared_vars were needed, verify all
2781 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2782 statements if use_pointer_for_field hasn't changed
2783 because of that. If it did, update field types now. */
2784 if (task_shared_vars)
2786 tree c;
2788 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2789 c; c = OMP_CLAUSE_CHAIN (c))
2790 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2791 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2793 tree decl = OMP_CLAUSE_DECL (c);
2795 /* Global variables don't need to be copied,
2796 the receiver side will use them directly. */
2797 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2798 continue;
2799 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2800 || !use_pointer_for_field (decl, ctx))
2801 continue;
2802 tree field = lookup_field (decl, ctx);
2803 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2804 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2805 continue;
2806 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2807 TREE_THIS_VOLATILE (field) = 0;
2808 DECL_USER_ALIGN (field) = 0;
2809 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2810 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2811 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2812 if (ctx->srecord_type)
2814 tree sfield = lookup_sfield (decl, ctx);
2815 TREE_TYPE (sfield) = TREE_TYPE (field);
2816 TREE_THIS_VOLATILE (sfield) = 0;
2817 DECL_USER_ALIGN (sfield) = 0;
2818 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2819 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2820 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2825 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2827 layout_type (ctx->record_type);
2828 fixup_child_record_type (ctx);
2830 else
2832 location_t loc = gimple_location (ctx->stmt);
2833 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2834 /* Move VLA fields to the end. */
2835 p = &TYPE_FIELDS (ctx->record_type);
2836 while (*p)
2837 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2838 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2840 *q = *p;
2841 *p = TREE_CHAIN (*p);
2842 TREE_CHAIN (*q) = NULL_TREE;
2843 q = &TREE_CHAIN (*q);
2845 else
2846 p = &DECL_CHAIN (*p);
2847 *p = vla_fields;
2848 if (gimple_omp_task_taskloop_p (ctx->stmt))
2850 /* Move fields corresponding to first and second _looptemp_
2851 clause first. There are filled by GOMP_taskloop
2852 and thus need to be in specific positions. */
2853 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2854 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2855 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2856 OMP_CLAUSE__LOOPTEMP_);
2857 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2858 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2859 p = &TYPE_FIELDS (ctx->record_type);
2860 while (*p)
2861 if (*p == f1 || *p == f2)
2862 *p = DECL_CHAIN (*p);
2863 else
2864 p = &DECL_CHAIN (*p);
2865 DECL_CHAIN (f1) = f2;
2866 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2867 TYPE_FIELDS (ctx->record_type) = f1;
2868 if (ctx->srecord_type)
2870 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2871 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2872 p = &TYPE_FIELDS (ctx->srecord_type);
2873 while (*p)
2874 if (*p == f1 || *p == f2)
2875 *p = DECL_CHAIN (*p);
2876 else
2877 p = &DECL_CHAIN (*p);
2878 DECL_CHAIN (f1) = f2;
2879 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2880 TYPE_FIELDS (ctx->srecord_type) = f1;
2883 layout_type (ctx->record_type);
2884 fixup_child_record_type (ctx);
2885 if (ctx->srecord_type)
2886 layout_type (ctx->srecord_type);
2887 tree t = fold_convert_loc (loc, long_integer_type_node,
2888 TYPE_SIZE_UNIT (ctx->record_type));
2889 gimple_omp_task_set_arg_size (ctx->stmt, t);
2890 t = build_int_cst (long_integer_type_node,
2891 TYPE_ALIGN_UNIT (ctx->record_type));
2892 gimple_omp_task_set_arg_align (ctx->stmt, t);
2896 /* Find the enclosing offload context. */
2898 static omp_context *
2899 enclosing_target_ctx (omp_context *ctx)
2901 for (; ctx; ctx = ctx->outer)
2902 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2903 break;
2905 return ctx;
2908 /* Return true if ctx is part of an oacc kernels region. */
2910 static bool
2911 ctx_in_oacc_kernels_region (omp_context *ctx)
2913 for (;ctx != NULL; ctx = ctx->outer)
2915 gimple *stmt = ctx->stmt;
2916 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2917 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2918 return true;
2921 return false;
2924 /* Check the parallelism clauses inside a kernels regions.
2925 Until kernels handling moves to use the same loop indirection
2926 scheme as parallel, we need to do this checking early. */
2928 static unsigned
2929 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2931 bool checking = true;
2932 unsigned outer_mask = 0;
2933 unsigned this_mask = 0;
2934 bool has_seq = false, has_auto = false;
2936 if (ctx->outer)
2937 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2938 if (!stmt)
2940 checking = false;
2941 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2942 return outer_mask;
2943 stmt = as_a <gomp_for *> (ctx->stmt);
2946 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2948 switch (OMP_CLAUSE_CODE (c))
2950 case OMP_CLAUSE_GANG:
2951 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2952 break;
2953 case OMP_CLAUSE_WORKER:
2954 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2955 break;
2956 case OMP_CLAUSE_VECTOR:
2957 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2958 break;
2959 case OMP_CLAUSE_SEQ:
2960 has_seq = true;
2961 break;
2962 case OMP_CLAUSE_AUTO:
2963 has_auto = true;
2964 break;
2965 default:
2966 break;
2970 if (checking)
2972 if (has_seq && (this_mask || has_auto))
2973 error_at (gimple_location (stmt), "%<seq%> overrides other"
2974 " OpenACC loop specifiers");
2975 else if (has_auto && this_mask)
2976 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2977 " OpenACC loop specifiers");
2979 if (this_mask & outer_mask)
2980 error_at (gimple_location (stmt), "inner loop uses same"
2981 " OpenACC parallelism as containing loop");
2984 return outer_mask | this_mask;
2987 /* Scan a GIMPLE_OMP_FOR. */
2989 static void
2990 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2992 omp_context *ctx;
2993 size_t i;
2994 tree clauses = gimple_omp_for_clauses (stmt);
2996 ctx = new_omp_context (stmt, outer_ctx);
2998 if (is_gimple_omp_oacc (stmt))
3000 omp_context *tgt = enclosing_target_ctx (outer_ctx);
3002 if (!tgt || is_oacc_parallel (tgt))
3003 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3005 char const *check = NULL;
3007 switch (OMP_CLAUSE_CODE (c))
3009 case OMP_CLAUSE_GANG:
3010 check = "gang";
3011 break;
3013 case OMP_CLAUSE_WORKER:
3014 check = "worker";
3015 break;
3017 case OMP_CLAUSE_VECTOR:
3018 check = "vector";
3019 break;
3021 default:
3022 break;
3025 if (check && OMP_CLAUSE_OPERAND (c, 0))
3026 error_at (gimple_location (stmt),
3027 "argument not permitted on %qs clause in"
3028 " OpenACC %<parallel%>", check);
3031 if (tgt && is_oacc_kernels (tgt))
3033 /* Strip out reductions, as they are not handled yet. */
3034 tree *prev_ptr = &clauses;
3036 while (tree probe = *prev_ptr)
3038 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3040 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3041 *prev_ptr = *next_ptr;
3042 else
3043 prev_ptr = next_ptr;
3046 gimple_omp_for_set_clauses (stmt, clauses);
3047 check_oacc_kernel_gwv (stmt, ctx);
3051 scan_sharing_clauses (clauses, ctx);
3053 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3054 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3056 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3057 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3058 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3059 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3061 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3064 /* Scan an OpenMP sections directive. */
3066 static void
3067 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3069 omp_context *ctx;
3071 ctx = new_omp_context (stmt, outer_ctx);
3072 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3073 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3076 /* Scan an OpenMP single directive. */
3078 static void
3079 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3081 omp_context *ctx;
3082 tree name;
3084 ctx = new_omp_context (stmt, outer_ctx);
3085 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3086 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3087 name = create_tmp_var_name (".omp_copy_s");
3088 name = build_decl (gimple_location (stmt),
3089 TYPE_DECL, name, ctx->record_type);
3090 TYPE_NAME (ctx->record_type) = name;
3092 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3093 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3095 if (TYPE_FIELDS (ctx->record_type) == NULL)
3096 ctx->record_type = NULL;
3097 else
3098 layout_type (ctx->record_type);
3101 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3102 used in the corresponding offloaded function are restrict. */
3104 static bool
3105 omp_target_base_pointers_restrict_p (tree clauses)
3107 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3108 used by OpenACC. */
3109 if (flag_openacc == 0)
3110 return false;
3112 /* I. Basic example:
3114 void foo (void)
3116 unsigned int a[2], b[2];
3118 #pragma acc kernels \
3119 copyout (a) \
3120 copyout (b)
3122 a[0] = 0;
3123 b[0] = 1;
3127 After gimplification, we have:
3129 #pragma omp target oacc_kernels \
3130 map(force_from:a [len: 8]) \
3131 map(force_from:b [len: 8])
3133 a[0] = 0;
3134 b[0] = 1;
3137 Because both mappings have the force prefix, we know that they will be
3138 allocated when calling the corresponding offloaded function, which means we
3139 can mark the base pointers for a and b in the offloaded function as
3140 restrict. */
3142 tree c;
3143 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3145 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3146 return false;
3148 switch (OMP_CLAUSE_MAP_KIND (c))
3150 case GOMP_MAP_FORCE_ALLOC:
3151 case GOMP_MAP_FORCE_TO:
3152 case GOMP_MAP_FORCE_FROM:
3153 case GOMP_MAP_FORCE_TOFROM:
3154 break;
3155 default:
3156 return false;
3160 return true;
3163 /* Scan a GIMPLE_OMP_TARGET. */
3165 static void
3166 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3168 omp_context *ctx;
3169 tree name;
3170 bool offloaded = is_gimple_omp_offloaded (stmt);
3171 tree clauses = gimple_omp_target_clauses (stmt);
3173 ctx = new_omp_context (stmt, outer_ctx);
3174 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3175 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3176 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3177 name = create_tmp_var_name (".omp_data_t");
3178 name = build_decl (gimple_location (stmt),
3179 TYPE_DECL, name, ctx->record_type);
3180 DECL_ARTIFICIAL (name) = 1;
3181 DECL_NAMELESS (name) = 1;
3182 TYPE_NAME (ctx->record_type) = name;
3183 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3185 bool base_pointers_restrict = false;
3186 if (offloaded)
3188 create_omp_child_function (ctx, false);
3189 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3191 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3192 if (base_pointers_restrict
3193 && dump_file && (dump_flags & TDF_DETAILS))
3194 fprintf (dump_file,
3195 "Base pointers in offloaded function are restrict\n");
3198 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3199 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3201 if (TYPE_FIELDS (ctx->record_type) == NULL)
3202 ctx->record_type = ctx->receiver_decl = NULL;
3203 else
3205 TYPE_FIELDS (ctx->record_type)
3206 = nreverse (TYPE_FIELDS (ctx->record_type));
3207 if (flag_checking)
3209 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3210 for (tree field = TYPE_FIELDS (ctx->record_type);
3211 field;
3212 field = DECL_CHAIN (field))
3213 gcc_assert (DECL_ALIGN (field) == align);
3215 layout_type (ctx->record_type);
3216 if (offloaded)
3217 fixup_child_record_type (ctx);
3221 /* Scan an OpenMP teams directive. */
3223 static void
3224 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3226 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3227 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3228 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3231 /* Check nesting restrictions. */
3232 static bool
3233 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3235 tree c;
3237 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3238 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3239 the original copy of its contents. */
3240 return true;
3242 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3243 inside an OpenACC CTX. */
3244 if (!(is_gimple_omp (stmt)
3245 && is_gimple_omp_oacc (stmt))
3246 /* Except for atomic codes that we share with OpenMP. */
3247 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3248 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3250 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3252 error_at (gimple_location (stmt),
3253 "non-OpenACC construct inside of OpenACC routine");
3254 return false;
3256 else
3257 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3258 if (is_gimple_omp (octx->stmt)
3259 && is_gimple_omp_oacc (octx->stmt))
3261 error_at (gimple_location (stmt),
3262 "non-OpenACC construct inside of OpenACC region");
3263 return false;
3267 if (ctx != NULL)
3269 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3270 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3272 c = NULL_TREE;
3273 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3275 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3276 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3278 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3279 && (ctx->outer == NULL
3280 || !gimple_omp_for_combined_into_p (ctx->stmt)
3281 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3282 || (gimple_omp_for_kind (ctx->outer->stmt)
3283 != GF_OMP_FOR_KIND_FOR)
3284 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3286 error_at (gimple_location (stmt),
3287 "%<ordered simd threads%> must be closely "
3288 "nested inside of %<for simd%> region");
3289 return false;
3291 return true;
3294 error_at (gimple_location (stmt),
3295 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3296 " may not be nested inside %<simd%> region");
3297 return false;
3299 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3301 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3302 || (gimple_omp_for_kind (stmt)
3303 != GF_OMP_FOR_KIND_DISTRIBUTE))
3304 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3306 error_at (gimple_location (stmt),
3307 "only %<distribute%> or %<parallel%> regions are "
3308 "allowed to be strictly nested inside %<teams%> "
3309 "region");
3310 return false;
3314 switch (gimple_code (stmt))
3316 case GIMPLE_OMP_FOR:
3317 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3318 return true;
3319 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3321 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3323 error_at (gimple_location (stmt),
3324 "%<distribute%> region must be strictly nested "
3325 "inside %<teams%> construct");
3326 return false;
3328 return true;
3330 /* We split taskloop into task and nested taskloop in it. */
3331 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3332 return true;
3333 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3335 bool ok = false;
3337 if (ctx)
3338 switch (gimple_code (ctx->stmt))
3340 case GIMPLE_OMP_FOR:
3341 ok = (gimple_omp_for_kind (ctx->stmt)
3342 == GF_OMP_FOR_KIND_OACC_LOOP);
3343 break;
3345 case GIMPLE_OMP_TARGET:
3346 switch (gimple_omp_target_kind (ctx->stmt))
3348 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3349 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3350 ok = true;
3351 break;
3353 default:
3354 break;
3357 default:
3358 break;
3360 else if (get_oacc_fn_attrib (current_function_decl))
3361 ok = true;
3362 if (!ok)
3364 error_at (gimple_location (stmt),
3365 "OpenACC loop directive must be associated with"
3366 " an OpenACC compute region");
3367 return false;
3370 /* FALLTHRU */
3371 case GIMPLE_CALL:
3372 if (is_gimple_call (stmt)
3373 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL
3375 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376 == BUILT_IN_GOMP_CANCELLATION_POINT))
3378 const char *bad = NULL;
3379 const char *kind = NULL;
3380 const char *construct
3381 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3382 == BUILT_IN_GOMP_CANCEL)
3383 ? "#pragma omp cancel"
3384 : "#pragma omp cancellation point";
3385 if (ctx == NULL)
3387 error_at (gimple_location (stmt), "orphaned %qs construct",
3388 construct);
3389 return false;
3391 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3392 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3393 : 0)
3395 case 1:
3396 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3397 bad = "#pragma omp parallel";
3398 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3399 == BUILT_IN_GOMP_CANCEL
3400 && !integer_zerop (gimple_call_arg (stmt, 1)))
3401 ctx->cancellable = true;
3402 kind = "parallel";
3403 break;
3404 case 2:
3405 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3406 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3407 bad = "#pragma omp for";
3408 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3409 == BUILT_IN_GOMP_CANCEL
3410 && !integer_zerop (gimple_call_arg (stmt, 1)))
3412 ctx->cancellable = true;
3413 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3414 OMP_CLAUSE_NOWAIT))
3415 warning_at (gimple_location (stmt), 0,
3416 "%<#pragma omp cancel for%> inside "
3417 "%<nowait%> for construct");
3418 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3419 OMP_CLAUSE_ORDERED))
3420 warning_at (gimple_location (stmt), 0,
3421 "%<#pragma omp cancel for%> inside "
3422 "%<ordered%> for construct");
3424 kind = "for";
3425 break;
3426 case 4:
3427 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3428 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3429 bad = "#pragma omp sections";
3430 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3431 == BUILT_IN_GOMP_CANCEL
3432 && !integer_zerop (gimple_call_arg (stmt, 1)))
3434 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3436 ctx->cancellable = true;
3437 if (find_omp_clause (gimple_omp_sections_clauses
3438 (ctx->stmt),
3439 OMP_CLAUSE_NOWAIT))
3440 warning_at (gimple_location (stmt), 0,
3441 "%<#pragma omp cancel sections%> inside "
3442 "%<nowait%> sections construct");
3444 else
3446 gcc_assert (ctx->outer
3447 && gimple_code (ctx->outer->stmt)
3448 == GIMPLE_OMP_SECTIONS);
3449 ctx->outer->cancellable = true;
3450 if (find_omp_clause (gimple_omp_sections_clauses
3451 (ctx->outer->stmt),
3452 OMP_CLAUSE_NOWAIT))
3453 warning_at (gimple_location (stmt), 0,
3454 "%<#pragma omp cancel sections%> inside "
3455 "%<nowait%> sections construct");
3458 kind = "sections";
3459 break;
3460 case 8:
3461 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3462 bad = "#pragma omp task";
3463 else
3465 for (omp_context *octx = ctx->outer;
3466 octx; octx = octx->outer)
3468 switch (gimple_code (octx->stmt))
3470 case GIMPLE_OMP_TASKGROUP:
3471 break;
3472 case GIMPLE_OMP_TARGET:
3473 if (gimple_omp_target_kind (octx->stmt)
3474 != GF_OMP_TARGET_KIND_REGION)
3475 continue;
3476 /* FALLTHRU */
3477 case GIMPLE_OMP_PARALLEL:
3478 case GIMPLE_OMP_TEAMS:
3479 error_at (gimple_location (stmt),
3480 "%<%s taskgroup%> construct not closely "
3481 "nested inside of %<taskgroup%> region",
3482 construct);
3483 return false;
3484 default:
3485 continue;
3487 break;
3489 ctx->cancellable = true;
3491 kind = "taskgroup";
3492 break;
3493 default:
3494 error_at (gimple_location (stmt), "invalid arguments");
3495 return false;
3497 if (bad)
3499 error_at (gimple_location (stmt),
3500 "%<%s %s%> construct not closely nested inside of %qs",
3501 construct, kind, bad);
3502 return false;
3505 /* FALLTHRU */
3506 case GIMPLE_OMP_SECTIONS:
3507 case GIMPLE_OMP_SINGLE:
3508 for (; ctx != NULL; ctx = ctx->outer)
3509 switch (gimple_code (ctx->stmt))
3511 case GIMPLE_OMP_FOR:
3512 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3513 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3514 break;
3515 /* FALLTHRU */
3516 case GIMPLE_OMP_SECTIONS:
3517 case GIMPLE_OMP_SINGLE:
3518 case GIMPLE_OMP_ORDERED:
3519 case GIMPLE_OMP_MASTER:
3520 case GIMPLE_OMP_TASK:
3521 case GIMPLE_OMP_CRITICAL:
3522 if (is_gimple_call (stmt))
3524 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3525 != BUILT_IN_GOMP_BARRIER)
3526 return true;
3527 error_at (gimple_location (stmt),
3528 "barrier region may not be closely nested inside "
3529 "of work-sharing, %<critical%>, %<ordered%>, "
3530 "%<master%>, explicit %<task%> or %<taskloop%> "
3531 "region");
3532 return false;
3534 error_at (gimple_location (stmt),
3535 "work-sharing region may not be closely nested inside "
3536 "of work-sharing, %<critical%>, %<ordered%>, "
3537 "%<master%>, explicit %<task%> or %<taskloop%> region");
3538 return false;
3539 case GIMPLE_OMP_PARALLEL:
3540 case GIMPLE_OMP_TEAMS:
3541 return true;
3542 case GIMPLE_OMP_TARGET:
3543 if (gimple_omp_target_kind (ctx->stmt)
3544 == GF_OMP_TARGET_KIND_REGION)
3545 return true;
3546 break;
3547 default:
3548 break;
3550 break;
3551 case GIMPLE_OMP_MASTER:
3552 for (; ctx != NULL; ctx = ctx->outer)
3553 switch (gimple_code (ctx->stmt))
3555 case GIMPLE_OMP_FOR:
3556 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3557 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3558 break;
3559 /* FALLTHRU */
3560 case GIMPLE_OMP_SECTIONS:
3561 case GIMPLE_OMP_SINGLE:
3562 case GIMPLE_OMP_TASK:
3563 error_at (gimple_location (stmt),
3564 "%<master%> region may not be closely nested inside "
3565 "of work-sharing, explicit %<task%> or %<taskloop%> "
3566 "region");
3567 return false;
3568 case GIMPLE_OMP_PARALLEL:
3569 case GIMPLE_OMP_TEAMS:
3570 return true;
3571 case GIMPLE_OMP_TARGET:
3572 if (gimple_omp_target_kind (ctx->stmt)
3573 == GF_OMP_TARGET_KIND_REGION)
3574 return true;
3575 break;
3576 default:
3577 break;
3579 break;
3580 case GIMPLE_OMP_TASK:
3581 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3582 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3583 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3584 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3586 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3587 error_at (OMP_CLAUSE_LOCATION (c),
3588 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3589 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3590 return false;
3592 break;
3593 case GIMPLE_OMP_ORDERED:
3594 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3595 c; c = OMP_CLAUSE_CHAIN (c))
3597 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3599 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3600 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3601 continue;
3603 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3604 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3605 || kind == OMP_CLAUSE_DEPEND_SINK)
3607 tree oclause;
3608 /* Look for containing ordered(N) loop. */
3609 if (ctx == NULL
3610 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3611 || (oclause
3612 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3613 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3615 error_at (OMP_CLAUSE_LOCATION (c),
3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside an %<ordered%> "
3618 "loop");
3619 return false;
3621 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3623 error_at (OMP_CLAUSE_LOCATION (c),
3624 "%<ordered%> construct with %<depend%> clause "
3625 "must be closely nested inside a loop with "
3626 "%<ordered%> clause with a parameter");
3627 return false;
3630 else
3632 error_at (OMP_CLAUSE_LOCATION (c),
3633 "invalid depend kind in omp %<ordered%> %<depend%>");
3634 return false;
3637 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3638 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3640 /* ordered simd must be closely nested inside of simd region,
3641 and simd region must not encounter constructs other than
3642 ordered simd, therefore ordered simd may be either orphaned,
3643 or ctx->stmt must be simd. The latter case is handled already
3644 earlier. */
3645 if (ctx != NULL)
3647 error_at (gimple_location (stmt),
3648 "%<ordered%> %<simd%> must be closely nested inside "
3649 "%<simd%> region");
3650 return false;
3653 for (; ctx != NULL; ctx = ctx->outer)
3654 switch (gimple_code (ctx->stmt))
3656 case GIMPLE_OMP_CRITICAL:
3657 case GIMPLE_OMP_TASK:
3658 case GIMPLE_OMP_ORDERED:
3659 ordered_in_taskloop:
3660 error_at (gimple_location (stmt),
3661 "%<ordered%> region may not be closely nested inside "
3662 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3663 "%<taskloop%> region");
3664 return false;
3665 case GIMPLE_OMP_FOR:
3666 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3667 goto ordered_in_taskloop;
3668 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3669 OMP_CLAUSE_ORDERED) == NULL)
3671 error_at (gimple_location (stmt),
3672 "%<ordered%> region must be closely nested inside "
3673 "a loop region with an %<ordered%> clause");
3674 return false;
3676 return true;
3677 case GIMPLE_OMP_TARGET:
3678 if (gimple_omp_target_kind (ctx->stmt)
3679 != GF_OMP_TARGET_KIND_REGION)
3680 break;
3681 /* FALLTHRU */
3682 case GIMPLE_OMP_PARALLEL:
3683 case GIMPLE_OMP_TEAMS:
3684 error_at (gimple_location (stmt),
3685 "%<ordered%> region must be closely nested inside "
3686 "a loop region with an %<ordered%> clause");
3687 return false;
3688 default:
3689 break;
3691 break;
3692 case GIMPLE_OMP_CRITICAL:
3694 tree this_stmt_name
3695 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3696 for (; ctx != NULL; ctx = ctx->outer)
3697 if (gomp_critical *other_crit
3698 = dyn_cast <gomp_critical *> (ctx->stmt))
3699 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3701 error_at (gimple_location (stmt),
3702 "%<critical%> region may not be nested inside "
3703 "a %<critical%> region with the same name");
3704 return false;
3707 break;
3708 case GIMPLE_OMP_TEAMS:
3709 if (ctx == NULL
3710 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3711 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3713 error_at (gimple_location (stmt),
3714 "%<teams%> construct not closely nested inside of "
3715 "%<target%> construct");
3716 return false;
3718 break;
3719 case GIMPLE_OMP_TARGET:
3720 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3721 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3722 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3723 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3725 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3726 error_at (OMP_CLAUSE_LOCATION (c),
3727 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3728 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3729 return false;
3731 if (is_gimple_omp_offloaded (stmt)
3732 && get_oacc_fn_attrib (cfun->decl) != NULL)
3734 error_at (gimple_location (stmt),
3735 "OpenACC region inside of OpenACC routine, nested "
3736 "parallelism not supported yet");
3737 return false;
3739 for (; ctx != NULL; ctx = ctx->outer)
3741 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3743 if (is_gimple_omp (stmt)
3744 && is_gimple_omp_oacc (stmt)
3745 && is_gimple_omp (ctx->stmt))
3747 error_at (gimple_location (stmt),
3748 "OpenACC construct inside of non-OpenACC region");
3749 return false;
3751 continue;
3754 const char *stmt_name, *ctx_stmt_name;
3755 switch (gimple_omp_target_kind (stmt))
3757 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3758 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3759 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3760 case GF_OMP_TARGET_KIND_ENTER_DATA:
3761 stmt_name = "target enter data"; break;
3762 case GF_OMP_TARGET_KIND_EXIT_DATA:
3763 stmt_name = "target exit data"; break;
3764 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3765 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3766 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3767 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3768 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3769 stmt_name = "enter/exit data"; break;
3770 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3771 break;
3772 default: gcc_unreachable ();
3774 switch (gimple_omp_target_kind (ctx->stmt))
3776 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3777 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3778 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3779 ctx_stmt_name = "parallel"; break;
3780 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3781 ctx_stmt_name = "kernels"; break;
3782 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3783 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3784 ctx_stmt_name = "host_data"; break;
3785 default: gcc_unreachable ();
3788 /* OpenACC/OpenMP mismatch? */
3789 if (is_gimple_omp_oacc (stmt)
3790 != is_gimple_omp_oacc (ctx->stmt))
3792 error_at (gimple_location (stmt),
3793 "%s %qs construct inside of %s %qs region",
3794 (is_gimple_omp_oacc (stmt)
3795 ? "OpenACC" : "OpenMP"), stmt_name,
3796 (is_gimple_omp_oacc (ctx->stmt)
3797 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3798 return false;
3800 if (is_gimple_omp_offloaded (ctx->stmt))
3802 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3803 if (is_gimple_omp_oacc (ctx->stmt))
3805 error_at (gimple_location (stmt),
3806 "%qs construct inside of %qs region",
3807 stmt_name, ctx_stmt_name);
3808 return false;
3810 else
3812 warning_at (gimple_location (stmt), 0,
3813 "%qs construct inside of %qs region",
3814 stmt_name, ctx_stmt_name);
3818 break;
3819 default:
3820 break;
3822 return true;
3826 /* Helper function scan_omp.
3828 Callback for walk_tree or operators in walk_gimple_stmt used to
3829 scan for OMP directives in TP. */
3831 static tree
3832 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3834 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3835 omp_context *ctx = (omp_context *) wi->info;
3836 tree t = *tp;
3838 switch (TREE_CODE (t))
3840 case VAR_DECL:
3841 case PARM_DECL:
3842 case LABEL_DECL:
3843 case RESULT_DECL:
3844 if (ctx)
3846 tree repl = remap_decl (t, &ctx->cb);
3847 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3848 *tp = repl;
3850 break;
3852 default:
3853 if (ctx && TYPE_P (t))
3854 *tp = remap_type (t, &ctx->cb);
3855 else if (!DECL_P (t))
3857 *walk_subtrees = 1;
3858 if (ctx)
3860 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3861 if (tem != TREE_TYPE (t))
3863 if (TREE_CODE (t) == INTEGER_CST)
3864 *tp = wide_int_to_tree (tem, t);
3865 else
3866 TREE_TYPE (t) = tem;
3870 break;
3873 return NULL_TREE;
3876 /* Return true if FNDECL is a setjmp or a longjmp. */
3878 static bool
3879 setjmp_or_longjmp_p (const_tree fndecl)
3881 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3882 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3883 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3884 return true;
3886 tree declname = DECL_NAME (fndecl);
3887 if (!declname)
3888 return false;
3889 const char *name = IDENTIFIER_POINTER (declname);
3890 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3894 /* Helper function for scan_omp.
3896 Callback for walk_gimple_stmt used to scan for OMP directives in
3897 the current statement in GSI. */
3899 static tree
3900 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3901 struct walk_stmt_info *wi)
3903 gimple *stmt = gsi_stmt (*gsi);
3904 omp_context *ctx = (omp_context *) wi->info;
3906 if (gimple_has_location (stmt))
3907 input_location = gimple_location (stmt);
3909 /* Check the nesting restrictions. */
3910 bool remove = false;
3911 if (is_gimple_omp (stmt))
3912 remove = !check_omp_nesting_restrictions (stmt, ctx);
3913 else if (is_gimple_call (stmt))
3915 tree fndecl = gimple_call_fndecl (stmt);
3916 if (fndecl)
3918 if (setjmp_or_longjmp_p (fndecl)
3919 && ctx
3920 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3921 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3923 remove = true;
3924 error_at (gimple_location (stmt),
3925 "setjmp/longjmp inside simd construct");
3927 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3928 switch (DECL_FUNCTION_CODE (fndecl))
3930 case BUILT_IN_GOMP_BARRIER:
3931 case BUILT_IN_GOMP_CANCEL:
3932 case BUILT_IN_GOMP_CANCELLATION_POINT:
3933 case BUILT_IN_GOMP_TASKYIELD:
3934 case BUILT_IN_GOMP_TASKWAIT:
3935 case BUILT_IN_GOMP_TASKGROUP_START:
3936 case BUILT_IN_GOMP_TASKGROUP_END:
3937 remove = !check_omp_nesting_restrictions (stmt, ctx);
3938 break;
3939 default:
3940 break;
3944 if (remove)
3946 stmt = gimple_build_nop ();
3947 gsi_replace (gsi, stmt, false);
3950 *handled_ops_p = true;
3952 switch (gimple_code (stmt))
3954 case GIMPLE_OMP_PARALLEL:
3955 taskreg_nesting_level++;
3956 scan_omp_parallel (gsi, ctx);
3957 taskreg_nesting_level--;
3958 break;
3960 case GIMPLE_OMP_TASK:
3961 taskreg_nesting_level++;
3962 scan_omp_task (gsi, ctx);
3963 taskreg_nesting_level--;
3964 break;
3966 case GIMPLE_OMP_FOR:
3967 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3968 break;
3970 case GIMPLE_OMP_SECTIONS:
3971 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3972 break;
3974 case GIMPLE_OMP_SINGLE:
3975 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3976 break;
3978 case GIMPLE_OMP_SECTION:
3979 case GIMPLE_OMP_MASTER:
3980 case GIMPLE_OMP_TASKGROUP:
3981 case GIMPLE_OMP_ORDERED:
3982 case GIMPLE_OMP_CRITICAL:
3983 case GIMPLE_OMP_GRID_BODY:
3984 ctx = new_omp_context (stmt, ctx);
3985 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3986 break;
3988 case GIMPLE_OMP_TARGET:
3989 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3990 break;
3992 case GIMPLE_OMP_TEAMS:
3993 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3994 break;
3996 case GIMPLE_BIND:
3998 tree var;
4000 *handled_ops_p = false;
4001 if (ctx)
4002 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
4003 var ;
4004 var = DECL_CHAIN (var))
4005 insert_decl_map (&ctx->cb, var, var);
4007 break;
4008 default:
4009 *handled_ops_p = false;
4010 break;
4013 return NULL_TREE;
4017 /* Scan all the statements starting at the current statement. CTX
4018 contains context information about the OMP directives and
4019 clauses found during the scan. */
4021 static void
4022 scan_omp (gimple_seq *body_p, omp_context *ctx)
4024 location_t saved_location;
4025 struct walk_stmt_info wi;
4027 memset (&wi, 0, sizeof (wi));
4028 wi.info = ctx;
4029 wi.want_locations = true;
4031 saved_location = input_location;
4032 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4033 input_location = saved_location;
4036 /* Re-gimplification and code generation routines. */
4038 /* Build a call to GOMP_barrier. */
4040 static gimple *
4041 build_omp_barrier (tree lhs)
4043 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4044 : BUILT_IN_GOMP_BARRIER);
4045 gcall *g = gimple_build_call (fndecl, 0);
4046 if (lhs)
4047 gimple_call_set_lhs (g, lhs);
4048 return g;
4051 /* If a context was created for STMT when it was scanned, return it. */
4053 static omp_context *
4054 maybe_lookup_ctx (gimple *stmt)
4056 splay_tree_node n;
4057 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4058 return n ? (omp_context *) n->value : NULL;
4062 /* Find the mapping for DECL in CTX or the immediately enclosing
4063 context that has a mapping for DECL.
4065 If CTX is a nested parallel directive, we may have to use the decl
4066 mappings created in CTX's parent context. Suppose that we have the
4067 following parallel nesting (variable UIDs showed for clarity):
4069 iD.1562 = 0;
4070 #omp parallel shared(iD.1562) -> outer parallel
4071 iD.1562 = iD.1562 + 1;
4073 #omp parallel shared (iD.1562) -> inner parallel
4074 iD.1562 = iD.1562 - 1;
4076 Each parallel structure will create a distinct .omp_data_s structure
4077 for copying iD.1562 in/out of the directive:
4079 outer parallel .omp_data_s.1.i -> iD.1562
4080 inner parallel .omp_data_s.2.i -> iD.1562
4082 A shared variable mapping will produce a copy-out operation before
4083 the parallel directive and a copy-in operation after it. So, in
4084 this case we would have:
4086 iD.1562 = 0;
4087 .omp_data_o.1.i = iD.1562;
4088 #omp parallel shared(iD.1562) -> outer parallel
4089 .omp_data_i.1 = &.omp_data_o.1
4090 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4092 .omp_data_o.2.i = iD.1562; -> **
4093 #omp parallel shared(iD.1562) -> inner parallel
4094 .omp_data_i.2 = &.omp_data_o.2
4095 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4098 ** This is a problem. The symbol iD.1562 cannot be referenced
4099 inside the body of the outer parallel region. But since we are
4100 emitting this copy operation while expanding the inner parallel
4101 directive, we need to access the CTX structure of the outer
4102 parallel directive to get the correct mapping:
4104 .omp_data_o.2.i = .omp_data_i.1->i
4106 Since there may be other workshare or parallel directives enclosing
4107 the parallel directive, it may be necessary to walk up the context
4108 parent chain. This is not a problem in general because nested
4109 parallelism happens only rarely. */
4111 static tree
4112 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4114 tree t;
4115 omp_context *up;
4117 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4118 t = maybe_lookup_decl (decl, up);
4120 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4122 return t ? t : decl;
4126 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4127 in outer contexts. */
4129 static tree
4130 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4132 tree t = NULL;
4133 omp_context *up;
4135 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4136 t = maybe_lookup_decl (decl, up);
4138 return t ? t : decl;
4142 /* Construct the initialization value for reduction operation OP. */
4144 tree
4145 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4147 switch (op)
4149 case PLUS_EXPR:
4150 case MINUS_EXPR:
4151 case BIT_IOR_EXPR:
4152 case BIT_XOR_EXPR:
4153 case TRUTH_OR_EXPR:
4154 case TRUTH_ORIF_EXPR:
4155 case TRUTH_XOR_EXPR:
4156 case NE_EXPR:
4157 return build_zero_cst (type);
4159 case MULT_EXPR:
4160 case TRUTH_AND_EXPR:
4161 case TRUTH_ANDIF_EXPR:
4162 case EQ_EXPR:
4163 return fold_convert_loc (loc, type, integer_one_node);
4165 case BIT_AND_EXPR:
4166 return fold_convert_loc (loc, type, integer_minus_one_node);
4168 case MAX_EXPR:
4169 if (SCALAR_FLOAT_TYPE_P (type))
4171 REAL_VALUE_TYPE max, min;
4172 if (HONOR_INFINITIES (type))
4174 real_inf (&max);
4175 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4177 else
4178 real_maxval (&min, 1, TYPE_MODE (type));
4179 return build_real (type, min);
4181 else if (POINTER_TYPE_P (type))
4183 wide_int min
4184 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4185 return wide_int_to_tree (type, min);
4187 else
4189 gcc_assert (INTEGRAL_TYPE_P (type));
4190 return TYPE_MIN_VALUE (type);
4193 case MIN_EXPR:
4194 if (SCALAR_FLOAT_TYPE_P (type))
4196 REAL_VALUE_TYPE max;
4197 if (HONOR_INFINITIES (type))
4198 real_inf (&max);
4199 else
4200 real_maxval (&max, 0, TYPE_MODE (type));
4201 return build_real (type, max);
4203 else if (POINTER_TYPE_P (type))
4205 wide_int max
4206 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4207 return wide_int_to_tree (type, max);
4209 else
4211 gcc_assert (INTEGRAL_TYPE_P (type));
4212 return TYPE_MAX_VALUE (type);
4215 default:
4216 gcc_unreachable ();
4220 /* Construct the initialization value for reduction CLAUSE. */
4222 tree
4223 omp_reduction_init (tree clause, tree type)
4225 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4226 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4229 /* Return alignment to be assumed for var in CLAUSE, which should be
4230 OMP_CLAUSE_ALIGNED. */
4232 static tree
4233 omp_clause_aligned_alignment (tree clause)
4235 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4236 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4238 /* Otherwise return implementation defined alignment. */
4239 unsigned int al = 1;
4240 machine_mode mode, vmode;
4241 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4242 if (vs)
4243 vs = 1 << floor_log2 (vs);
4244 static enum mode_class classes[]
4245 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4246 for (int i = 0; i < 4; i += 2)
4247 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4248 mode != VOIDmode;
4249 mode = GET_MODE_WIDER_MODE (mode))
4251 vmode = targetm.vectorize.preferred_simd_mode (mode);
4252 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4253 continue;
4254 while (vs
4255 && GET_MODE_SIZE (vmode) < vs
4256 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4257 vmode = GET_MODE_2XWIDER_MODE (vmode);
4259 tree type = lang_hooks.types.type_for_mode (mode, 1);
4260 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4261 continue;
4262 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4263 / GET_MODE_SIZE (mode));
4264 if (TYPE_MODE (type) != vmode)
4265 continue;
4266 if (TYPE_ALIGN_UNIT (type) > al)
4267 al = TYPE_ALIGN_UNIT (type);
4269 return build_int_cst (integer_type_node, al);
4272 /* Return maximum possible vectorization factor for the target. */
4274 static int
4275 omp_max_vf (void)
4277 if (!optimize
4278 || optimize_debug
4279 || !flag_tree_loop_optimize
4280 || (!flag_tree_loop_vectorize
4281 && (global_options_set.x_flag_tree_loop_vectorize
4282 || global_options_set.x_flag_tree_vectorize)))
4283 return 1;
4285 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4286 if (vs)
4288 vs = 1 << floor_log2 (vs);
4289 return vs;
4291 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4292 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4293 return GET_MODE_NUNITS (vqimode);
4294 return 1;
4297 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4298 privatization. */
4300 static bool
4301 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4302 tree &idx, tree &lane, tree &ivar, tree &lvar)
4304 if (max_vf == 0)
4306 max_vf = omp_max_vf ();
4307 if (max_vf > 1)
4309 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4310 OMP_CLAUSE_SAFELEN);
4311 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4312 max_vf = 1;
4313 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4314 max_vf) == -1)
4315 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4317 if (max_vf > 1)
4319 idx = create_tmp_var (unsigned_type_node);
4320 lane = create_tmp_var (unsigned_type_node);
4323 if (max_vf == 1)
4324 return false;
4326 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4327 tree avar = create_tmp_var_raw (atype);
4328 if (TREE_ADDRESSABLE (new_var))
4329 TREE_ADDRESSABLE (avar) = 1;
4330 DECL_ATTRIBUTES (avar)
4331 = tree_cons (get_identifier ("omp simd array"), NULL,
4332 DECL_ATTRIBUTES (avar));
4333 gimple_add_tmp_var (avar);
4334 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4335 NULL_TREE, NULL_TREE);
4336 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4337 NULL_TREE, NULL_TREE);
4338 if (DECL_P (new_var))
4340 SET_DECL_VALUE_EXPR (new_var, lvar);
4341 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4343 return true;
4346 /* Helper function of lower_rec_input_clauses. For a reference
4347 in simd reduction, add an underlying variable it will reference. */
4349 static void
4350 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4352 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4353 if (TREE_CONSTANT (z))
4355 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4356 get_name (new_vard));
4357 gimple_add_tmp_var (z);
4358 TREE_ADDRESSABLE (z) = 1;
4359 z = build_fold_addr_expr_loc (loc, z);
4360 gimplify_assign (new_vard, z, ilist);
4364 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4365 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4366 private variables. Initialization statements go in ILIST, while calls
4367 to destructors go in DLIST. */
4369 static void
4370 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4371 omp_context *ctx, struct omp_for_data *fd)
4373 tree c, dtor, copyin_seq, x, ptr;
4374 bool copyin_by_ref = false;
4375 bool lastprivate_firstprivate = false;
4376 bool reduction_omp_orig_ref = false;
4377 int pass;
4378 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4379 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4380 int max_vf = 0;
4381 tree lane = NULL_TREE, idx = NULL_TREE;
4382 tree ivar = NULL_TREE, lvar = NULL_TREE;
4383 gimple_seq llist[2] = { NULL, NULL };
4385 copyin_seq = NULL;
4387 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4388 with data sharing clauses referencing variable sized vars. That
4389 is unnecessarily hard to support and very unlikely to result in
4390 vectorized code anyway. */
4391 if (is_simd)
4392 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4393 switch (OMP_CLAUSE_CODE (c))
4395 case OMP_CLAUSE_LINEAR:
4396 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4397 max_vf = 1;
4398 /* FALLTHRU */
4399 case OMP_CLAUSE_PRIVATE:
4400 case OMP_CLAUSE_FIRSTPRIVATE:
4401 case OMP_CLAUSE_LASTPRIVATE:
4402 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4403 max_vf = 1;
4404 break;
4405 case OMP_CLAUSE_REDUCTION:
4406 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4407 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4408 max_vf = 1;
4409 break;
4410 default:
4411 continue;
4414 /* Do all the fixed sized types in the first pass, and the variable sized
4415 types in the second pass. This makes sure that the scalar arguments to
4416 the variable sized types are processed before we use them in the
4417 variable sized operations. */
4418 for (pass = 0; pass < 2; ++pass)
4420 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4422 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4423 tree var, new_var;
4424 bool by_ref;
4425 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4427 switch (c_kind)
4429 case OMP_CLAUSE_PRIVATE:
4430 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4431 continue;
4432 break;
4433 case OMP_CLAUSE_SHARED:
4434 /* Ignore shared directives in teams construct. */
4435 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4436 continue;
4437 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4439 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4440 || is_global_var (OMP_CLAUSE_DECL (c)));
4441 continue;
4443 case OMP_CLAUSE_FIRSTPRIVATE:
4444 case OMP_CLAUSE_COPYIN:
4445 break;
4446 case OMP_CLAUSE_LINEAR:
4447 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4448 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4449 lastprivate_firstprivate = true;
4450 break;
4451 case OMP_CLAUSE_REDUCTION:
4452 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4453 reduction_omp_orig_ref = true;
4454 break;
4455 case OMP_CLAUSE__LOOPTEMP_:
4456 /* Handle _looptemp_ clauses only on parallel/task. */
4457 if (fd)
4458 continue;
4459 break;
4460 case OMP_CLAUSE_LASTPRIVATE:
4461 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4463 lastprivate_firstprivate = true;
4464 if (pass != 0 || is_taskloop_ctx (ctx))
4465 continue;
4467 /* Even without corresponding firstprivate, if
4468 decl is Fortran allocatable, it needs outer var
4469 reference. */
4470 else if (pass == 0
4471 && lang_hooks.decls.omp_private_outer_ref
4472 (OMP_CLAUSE_DECL (c)))
4473 lastprivate_firstprivate = true;
4474 break;
4475 case OMP_CLAUSE_ALIGNED:
4476 if (pass == 0)
4477 continue;
4478 var = OMP_CLAUSE_DECL (c);
4479 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4480 && !is_global_var (var))
4482 new_var = maybe_lookup_decl (var, ctx);
4483 if (new_var == NULL_TREE)
4484 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4485 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4486 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4487 omp_clause_aligned_alignment (c));
4488 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4489 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4490 gimplify_and_add (x, ilist);
4492 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4493 && is_global_var (var))
4495 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4496 new_var = lookup_decl (var, ctx);
4497 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4498 t = build_fold_addr_expr_loc (clause_loc, t);
4499 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4500 t = build_call_expr_loc (clause_loc, t2, 2, t,
4501 omp_clause_aligned_alignment (c));
4502 t = fold_convert_loc (clause_loc, ptype, t);
4503 x = create_tmp_var (ptype);
4504 t = build2 (MODIFY_EXPR, ptype, x, t);
4505 gimplify_and_add (t, ilist);
4506 t = build_simple_mem_ref_loc (clause_loc, x);
4507 SET_DECL_VALUE_EXPR (new_var, t);
4508 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4510 continue;
4511 default:
4512 continue;
4515 new_var = var = OMP_CLAUSE_DECL (c);
4516 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4518 var = TREE_OPERAND (var, 0);
4519 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4520 var = TREE_OPERAND (var, 0);
4521 if (TREE_CODE (var) == INDIRECT_REF
4522 || TREE_CODE (var) == ADDR_EXPR)
4523 var = TREE_OPERAND (var, 0);
4524 if (is_variable_sized (var))
4526 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4527 var = DECL_VALUE_EXPR (var);
4528 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4529 var = TREE_OPERAND (var, 0);
4530 gcc_assert (DECL_P (var));
4532 new_var = var;
4534 if (c_kind != OMP_CLAUSE_COPYIN)
4535 new_var = lookup_decl (var, ctx);
4537 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4539 if (pass != 0)
4540 continue;
4542 /* C/C++ array section reductions. */
4543 else if (c_kind == OMP_CLAUSE_REDUCTION
4544 && var != OMP_CLAUSE_DECL (c))
4546 if (pass == 0)
4547 continue;
4549 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4550 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4551 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4553 tree b = TREE_OPERAND (orig_var, 1);
4554 b = maybe_lookup_decl (b, ctx);
4555 if (b == NULL)
4557 b = TREE_OPERAND (orig_var, 1);
4558 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4560 if (integer_zerop (bias))
4561 bias = b;
4562 else
4564 bias = fold_convert_loc (clause_loc,
4565 TREE_TYPE (b), bias);
4566 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4567 TREE_TYPE (b), b, bias);
4569 orig_var = TREE_OPERAND (orig_var, 0);
4571 if (TREE_CODE (orig_var) == INDIRECT_REF
4572 || TREE_CODE (orig_var) == ADDR_EXPR)
4573 orig_var = TREE_OPERAND (orig_var, 0);
4574 tree d = OMP_CLAUSE_DECL (c);
4575 tree type = TREE_TYPE (d);
4576 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4577 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4578 const char *name = get_name (orig_var);
4579 if (TREE_CONSTANT (v))
4581 x = create_tmp_var_raw (type, name);
4582 gimple_add_tmp_var (x);
4583 TREE_ADDRESSABLE (x) = 1;
4584 x = build_fold_addr_expr_loc (clause_loc, x);
4586 else
4588 tree atmp
4589 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4590 tree t = maybe_lookup_decl (v, ctx);
4591 if (t)
4592 v = t;
4593 else
4594 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4595 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4596 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4597 TREE_TYPE (v), v,
4598 build_int_cst (TREE_TYPE (v), 1));
4599 t = fold_build2_loc (clause_loc, MULT_EXPR,
4600 TREE_TYPE (v), t,
4601 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4602 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4603 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4606 tree ptype = build_pointer_type (TREE_TYPE (type));
4607 x = fold_convert_loc (clause_loc, ptype, x);
4608 tree y = create_tmp_var (ptype, name);
4609 gimplify_assign (y, x, ilist);
4610 x = y;
4611 tree yb = y;
4613 if (!integer_zerop (bias))
4615 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4616 bias);
4617 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4619 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4620 pointer_sized_int_node, yb, bias);
4621 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4622 yb = create_tmp_var (ptype, name);
4623 gimplify_assign (yb, x, ilist);
4624 x = yb;
4627 d = TREE_OPERAND (d, 0);
4628 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4629 d = TREE_OPERAND (d, 0);
4630 if (TREE_CODE (d) == ADDR_EXPR)
4632 if (orig_var != var)
4634 gcc_assert (is_variable_sized (orig_var));
4635 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4637 gimplify_assign (new_var, x, ilist);
4638 tree new_orig_var = lookup_decl (orig_var, ctx);
4639 tree t = build_fold_indirect_ref (new_var);
4640 DECL_IGNORED_P (new_var) = 0;
4641 TREE_THIS_NOTRAP (t);
4642 SET_DECL_VALUE_EXPR (new_orig_var, t);
4643 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4645 else
4647 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4648 build_int_cst (ptype, 0));
4649 SET_DECL_VALUE_EXPR (new_var, x);
4650 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4653 else
4655 gcc_assert (orig_var == var);
4656 if (TREE_CODE (d) == INDIRECT_REF)
4658 x = create_tmp_var (ptype, name);
4659 TREE_ADDRESSABLE (x) = 1;
4660 gimplify_assign (x, yb, ilist);
4661 x = build_fold_addr_expr_loc (clause_loc, x);
4663 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4664 gimplify_assign (new_var, x, ilist);
4666 tree y1 = create_tmp_var (ptype, NULL);
4667 gimplify_assign (y1, y, ilist);
4668 tree i2 = NULL_TREE, y2 = NULL_TREE;
4669 tree body2 = NULL_TREE, end2 = NULL_TREE;
4670 tree y3 = NULL_TREE, y4 = NULL_TREE;
4671 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4673 y2 = create_tmp_var (ptype, NULL);
4674 gimplify_assign (y2, y, ilist);
4675 tree ref = build_outer_var_ref (var, ctx);
4676 /* For ref build_outer_var_ref already performs this. */
4677 if (TREE_CODE (d) == INDIRECT_REF)
4678 gcc_assert (is_reference (var));
4679 else if (TREE_CODE (d) == ADDR_EXPR)
4680 ref = build_fold_addr_expr (ref);
4681 else if (is_reference (var))
4682 ref = build_fold_addr_expr (ref);
4683 ref = fold_convert_loc (clause_loc, ptype, ref);
4684 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4685 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4687 y3 = create_tmp_var (ptype, NULL);
4688 gimplify_assign (y3, unshare_expr (ref), ilist);
4690 if (is_simd)
4692 y4 = create_tmp_var (ptype, NULL);
4693 gimplify_assign (y4, ref, dlist);
4696 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4697 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4698 tree body = create_artificial_label (UNKNOWN_LOCATION);
4699 tree end = create_artificial_label (UNKNOWN_LOCATION);
4700 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4701 if (y2)
4703 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4704 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4705 body2 = create_artificial_label (UNKNOWN_LOCATION);
4706 end2 = create_artificial_label (UNKNOWN_LOCATION);
4707 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4709 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4711 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4712 tree decl_placeholder
4713 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4714 SET_DECL_VALUE_EXPR (decl_placeholder,
4715 build_simple_mem_ref (y1));
4716 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4717 SET_DECL_VALUE_EXPR (placeholder,
4718 y3 ? build_simple_mem_ref (y3)
4719 : error_mark_node);
4720 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4721 x = lang_hooks.decls.omp_clause_default_ctor
4722 (c, build_simple_mem_ref (y1),
4723 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4724 if (x)
4725 gimplify_and_add (x, ilist);
4726 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4728 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4729 lower_omp (&tseq, ctx);
4730 gimple_seq_add_seq (ilist, tseq);
4732 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4733 if (is_simd)
4735 SET_DECL_VALUE_EXPR (decl_placeholder,
4736 build_simple_mem_ref (y2));
4737 SET_DECL_VALUE_EXPR (placeholder,
4738 build_simple_mem_ref (y4));
4739 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4740 lower_omp (&tseq, ctx);
4741 gimple_seq_add_seq (dlist, tseq);
4742 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4744 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4745 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4746 x = lang_hooks.decls.omp_clause_dtor
4747 (c, build_simple_mem_ref (y2));
4748 if (x)
4750 gimple_seq tseq = NULL;
4751 dtor = x;
4752 gimplify_stmt (&dtor, &tseq);
4753 gimple_seq_add_seq (dlist, tseq);
4756 else
4758 x = omp_reduction_init (c, TREE_TYPE (type));
4759 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4761 /* reduction(-:var) sums up the partial results, so it
4762 acts identically to reduction(+:var). */
4763 if (code == MINUS_EXPR)
4764 code = PLUS_EXPR;
4766 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4767 if (is_simd)
4769 x = build2 (code, TREE_TYPE (type),
4770 build_simple_mem_ref (y4),
4771 build_simple_mem_ref (y2));
4772 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4775 gimple *g
4776 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4777 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4778 gimple_seq_add_stmt (ilist, g);
4779 if (y3)
4781 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4782 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4783 gimple_seq_add_stmt (ilist, g);
4785 g = gimple_build_assign (i, PLUS_EXPR, i,
4786 build_int_cst (TREE_TYPE (i), 1));
4787 gimple_seq_add_stmt (ilist, g);
4788 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4789 gimple_seq_add_stmt (ilist, g);
4790 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4791 if (y2)
4793 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4794 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4795 gimple_seq_add_stmt (dlist, g);
4796 if (y4)
4798 g = gimple_build_assign
4799 (y4, POINTER_PLUS_EXPR, y4,
4800 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4801 gimple_seq_add_stmt (dlist, g);
4803 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4804 build_int_cst (TREE_TYPE (i2), 1));
4805 gimple_seq_add_stmt (dlist, g);
4806 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4807 gimple_seq_add_stmt (dlist, g);
4808 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4810 continue;
4812 else if (is_variable_sized (var))
4814 /* For variable sized types, we need to allocate the
4815 actual storage here. Call alloca and store the
4816 result in the pointer decl that we created elsewhere. */
4817 if (pass == 0)
4818 continue;
4820 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4822 gcall *stmt;
4823 tree tmp, atmp;
4825 ptr = DECL_VALUE_EXPR (new_var);
4826 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4827 ptr = TREE_OPERAND (ptr, 0);
4828 gcc_assert (DECL_P (ptr));
4829 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4831 /* void *tmp = __builtin_alloca */
4832 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4833 stmt = gimple_build_call (atmp, 2, x,
4834 size_int (DECL_ALIGN (var)));
4835 tmp = create_tmp_var_raw (ptr_type_node);
4836 gimple_add_tmp_var (tmp);
4837 gimple_call_set_lhs (stmt, tmp);
4839 gimple_seq_add_stmt (ilist, stmt);
4841 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4842 gimplify_assign (ptr, x, ilist);
4845 else if (is_reference (var))
4847 /* For references that are being privatized for Fortran,
4848 allocate new backing storage for the new pointer
4849 variable. This allows us to avoid changing all the
4850 code that expects a pointer to something that expects
4851 a direct variable. */
4852 if (pass == 0)
4853 continue;
4855 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4856 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4858 x = build_receiver_ref (var, false, ctx);
4859 x = build_fold_addr_expr_loc (clause_loc, x);
4861 else if (TREE_CONSTANT (x))
4863 /* For reduction in SIMD loop, defer adding the
4864 initialization of the reference, because if we decide
4865 to use SIMD array for it, the initilization could cause
4866 expansion ICE. */
4867 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4868 x = NULL_TREE;
4869 else
4871 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4872 get_name (var));
4873 gimple_add_tmp_var (x);
4874 TREE_ADDRESSABLE (x) = 1;
4875 x = build_fold_addr_expr_loc (clause_loc, x);
4878 else
4880 tree atmp
4881 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4882 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4883 tree al = size_int (TYPE_ALIGN (rtype));
4884 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4887 if (x)
4889 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4890 gimplify_assign (new_var, x, ilist);
4893 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4895 else if (c_kind == OMP_CLAUSE_REDUCTION
4896 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4898 if (pass == 0)
4899 continue;
4901 else if (pass != 0)
4902 continue;
4904 switch (OMP_CLAUSE_CODE (c))
4906 case OMP_CLAUSE_SHARED:
4907 /* Ignore shared directives in teams construct. */
4908 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4909 continue;
4910 /* Shared global vars are just accessed directly. */
4911 if (is_global_var (new_var))
4912 break;
4913 /* For taskloop firstprivate/lastprivate, represented
4914 as firstprivate and shared clause on the task, new_var
4915 is the firstprivate var. */
4916 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4917 break;
4918 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4919 needs to be delayed until after fixup_child_record_type so
4920 that we get the correct type during the dereference. */
4921 by_ref = use_pointer_for_field (var, ctx);
4922 x = build_receiver_ref (var, by_ref, ctx);
4923 SET_DECL_VALUE_EXPR (new_var, x);
4924 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4926 /* ??? If VAR is not passed by reference, and the variable
4927 hasn't been initialized yet, then we'll get a warning for
4928 the store into the omp_data_s structure. Ideally, we'd be
4929 able to notice this and not store anything at all, but
4930 we're generating code too early. Suppress the warning. */
4931 if (!by_ref)
4932 TREE_NO_WARNING (var) = 1;
4933 break;
4935 case OMP_CLAUSE_LASTPRIVATE:
4936 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4937 break;
4938 /* FALLTHRU */
4940 case OMP_CLAUSE_PRIVATE:
4941 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4942 x = build_outer_var_ref (var, ctx);
4943 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4945 if (is_task_ctx (ctx))
4946 x = build_receiver_ref (var, false, ctx);
4947 else
4948 x = build_outer_var_ref (var, ctx);
4950 else
4951 x = NULL;
4952 do_private:
4953 tree nx;
4954 nx = lang_hooks.decls.omp_clause_default_ctor
4955 (c, unshare_expr (new_var), x);
4956 if (is_simd)
4958 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4959 if ((TREE_ADDRESSABLE (new_var) || nx || y
4960 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4961 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4962 idx, lane, ivar, lvar))
4964 if (nx)
4965 x = lang_hooks.decls.omp_clause_default_ctor
4966 (c, unshare_expr (ivar), x);
4967 if (nx && x)
4968 gimplify_and_add (x, &llist[0]);
4969 if (y)
4971 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4972 if (y)
4974 gimple_seq tseq = NULL;
4976 dtor = y;
4977 gimplify_stmt (&dtor, &tseq);
4978 gimple_seq_add_seq (&llist[1], tseq);
4981 break;
4984 if (nx)
4985 gimplify_and_add (nx, ilist);
4986 /* FALLTHRU */
4988 do_dtor:
4989 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4990 if (x)
4992 gimple_seq tseq = NULL;
4994 dtor = x;
4995 gimplify_stmt (&dtor, &tseq);
4996 gimple_seq_add_seq (dlist, tseq);
4998 break;
5000 case OMP_CLAUSE_LINEAR:
5001 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5002 goto do_firstprivate;
5003 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5004 x = NULL;
5005 else
5006 x = build_outer_var_ref (var, ctx);
5007 goto do_private;
5009 case OMP_CLAUSE_FIRSTPRIVATE:
5010 if (is_task_ctx (ctx))
5012 if (is_reference (var) || is_variable_sized (var))
5013 goto do_dtor;
5014 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5015 ctx))
5016 || use_pointer_for_field (var, NULL))
5018 x = build_receiver_ref (var, false, ctx);
5019 SET_DECL_VALUE_EXPR (new_var, x);
5020 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5021 goto do_dtor;
5024 do_firstprivate:
5025 x = build_outer_var_ref (var, ctx);
5026 if (is_simd)
5028 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5029 && gimple_omp_for_combined_into_p (ctx->stmt))
5031 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5032 tree stept = TREE_TYPE (t);
5033 tree ct = find_omp_clause (clauses,
5034 OMP_CLAUSE__LOOPTEMP_);
5035 gcc_assert (ct);
5036 tree l = OMP_CLAUSE_DECL (ct);
5037 tree n1 = fd->loop.n1;
5038 tree step = fd->loop.step;
5039 tree itype = TREE_TYPE (l);
5040 if (POINTER_TYPE_P (itype))
5041 itype = signed_type_for (itype);
5042 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5043 if (TYPE_UNSIGNED (itype)
5044 && fd->loop.cond_code == GT_EXPR)
5045 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5046 fold_build1 (NEGATE_EXPR, itype, l),
5047 fold_build1 (NEGATE_EXPR,
5048 itype, step));
5049 else
5050 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5051 t = fold_build2 (MULT_EXPR, stept,
5052 fold_convert (stept, l), t);
5054 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5056 x = lang_hooks.decls.omp_clause_linear_ctor
5057 (c, new_var, x, t);
5058 gimplify_and_add (x, ilist);
5059 goto do_dtor;
5062 if (POINTER_TYPE_P (TREE_TYPE (x)))
5063 x = fold_build2 (POINTER_PLUS_EXPR,
5064 TREE_TYPE (x), x, t);
5065 else
5066 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5069 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5070 || TREE_ADDRESSABLE (new_var))
5071 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5072 idx, lane, ivar, lvar))
5074 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5076 tree iv = create_tmp_var (TREE_TYPE (new_var));
5077 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5078 gimplify_and_add (x, ilist);
5079 gimple_stmt_iterator gsi
5080 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5081 gassign *g
5082 = gimple_build_assign (unshare_expr (lvar), iv);
5083 gsi_insert_before_without_update (&gsi, g,
5084 GSI_SAME_STMT);
5085 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5086 enum tree_code code = PLUS_EXPR;
5087 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5088 code = POINTER_PLUS_EXPR;
5089 g = gimple_build_assign (iv, code, iv, t);
5090 gsi_insert_before_without_update (&gsi, g,
5091 GSI_SAME_STMT);
5092 break;
5094 x = lang_hooks.decls.omp_clause_copy_ctor
5095 (c, unshare_expr (ivar), x);
5096 gimplify_and_add (x, &llist[0]);
5097 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5098 if (x)
5100 gimple_seq tseq = NULL;
5102 dtor = x;
5103 gimplify_stmt (&dtor, &tseq);
5104 gimple_seq_add_seq (&llist[1], tseq);
5106 break;
5109 x = lang_hooks.decls.omp_clause_copy_ctor
5110 (c, unshare_expr (new_var), x);
5111 gimplify_and_add (x, ilist);
5112 goto do_dtor;
5114 case OMP_CLAUSE__LOOPTEMP_:
5115 gcc_assert (is_taskreg_ctx (ctx));
5116 x = build_outer_var_ref (var, ctx);
5117 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5118 gimplify_and_add (x, ilist);
5119 break;
5121 case OMP_CLAUSE_COPYIN:
5122 by_ref = use_pointer_for_field (var, NULL);
5123 x = build_receiver_ref (var, by_ref, ctx);
5124 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5125 append_to_statement_list (x, &copyin_seq);
5126 copyin_by_ref |= by_ref;
5127 break;
5129 case OMP_CLAUSE_REDUCTION:
5130 /* OpenACC reductions are initialized using the
5131 GOACC_REDUCTION internal function. */
5132 if (is_gimple_omp_oacc (ctx->stmt))
5133 break;
5134 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5136 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5137 gimple *tseq;
5138 x = build_outer_var_ref (var, ctx);
5140 if (is_reference (var)
5141 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5142 TREE_TYPE (x)))
5143 x = build_fold_addr_expr_loc (clause_loc, x);
5144 SET_DECL_VALUE_EXPR (placeholder, x);
5145 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5146 tree new_vard = new_var;
5147 if (is_reference (var))
5149 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5150 new_vard = TREE_OPERAND (new_var, 0);
5151 gcc_assert (DECL_P (new_vard));
5153 if (is_simd
5154 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5155 idx, lane, ivar, lvar))
5157 if (new_vard == new_var)
5159 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5160 SET_DECL_VALUE_EXPR (new_var, ivar);
5162 else
5164 SET_DECL_VALUE_EXPR (new_vard,
5165 build_fold_addr_expr (ivar));
5166 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5168 x = lang_hooks.decls.omp_clause_default_ctor
5169 (c, unshare_expr (ivar),
5170 build_outer_var_ref (var, ctx));
5171 if (x)
5172 gimplify_and_add (x, &llist[0]);
5173 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5175 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5176 lower_omp (&tseq, ctx);
5177 gimple_seq_add_seq (&llist[0], tseq);
5179 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5180 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5181 lower_omp (&tseq, ctx);
5182 gimple_seq_add_seq (&llist[1], tseq);
5183 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5184 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5185 if (new_vard == new_var)
5186 SET_DECL_VALUE_EXPR (new_var, lvar);
5187 else
5188 SET_DECL_VALUE_EXPR (new_vard,
5189 build_fold_addr_expr (lvar));
5190 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5191 if (x)
5193 tseq = NULL;
5194 dtor = x;
5195 gimplify_stmt (&dtor, &tseq);
5196 gimple_seq_add_seq (&llist[1], tseq);
5198 break;
5200 /* If this is a reference to constant size reduction var
5201 with placeholder, we haven't emitted the initializer
5202 for it because it is undesirable if SIMD arrays are used.
5203 But if they aren't used, we need to emit the deferred
5204 initialization now. */
5205 else if (is_reference (var) && is_simd)
5206 handle_simd_reference (clause_loc, new_vard, ilist);
5207 x = lang_hooks.decls.omp_clause_default_ctor
5208 (c, unshare_expr (new_var),
5209 build_outer_var_ref (var, ctx));
5210 if (x)
5211 gimplify_and_add (x, ilist);
5212 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5214 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5215 lower_omp (&tseq, ctx);
5216 gimple_seq_add_seq (ilist, tseq);
5218 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5219 if (is_simd)
5221 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5222 lower_omp (&tseq, ctx);
5223 gimple_seq_add_seq (dlist, tseq);
5224 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5226 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5227 goto do_dtor;
5229 else
5231 x = omp_reduction_init (c, TREE_TYPE (new_var));
5232 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5233 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5235 /* reduction(-:var) sums up the partial results, so it
5236 acts identically to reduction(+:var). */
5237 if (code == MINUS_EXPR)
5238 code = PLUS_EXPR;
5240 tree new_vard = new_var;
5241 if (is_simd && is_reference (var))
5243 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5244 new_vard = TREE_OPERAND (new_var, 0);
5245 gcc_assert (DECL_P (new_vard));
5247 if (is_simd
5248 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5249 idx, lane, ivar, lvar))
5251 tree ref = build_outer_var_ref (var, ctx);
5253 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5255 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5256 ref = build_outer_var_ref (var, ctx);
5257 gimplify_assign (ref, x, &llist[1]);
5259 if (new_vard != new_var)
5261 SET_DECL_VALUE_EXPR (new_vard,
5262 build_fold_addr_expr (lvar));
5263 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5266 else
5268 if (is_reference (var) && is_simd)
5269 handle_simd_reference (clause_loc, new_vard, ilist);
5270 gimplify_assign (new_var, x, ilist);
5271 if (is_simd)
5273 tree ref = build_outer_var_ref (var, ctx);
5275 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5276 ref = build_outer_var_ref (var, ctx);
5277 gimplify_assign (ref, x, dlist);
5281 break;
5283 default:
5284 gcc_unreachable ();
5289 if (lane)
5291 tree uid = create_tmp_var (ptr_type_node, "simduid");
5292 /* Don't want uninit warnings on simduid, it is always uninitialized,
5293 but we use it not for the value, but for the DECL_UID only. */
5294 TREE_NO_WARNING (uid) = 1;
5295 gimple *g
5296 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5297 gimple_call_set_lhs (g, lane);
5298 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5299 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5300 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5301 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5302 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5303 gimple_omp_for_set_clauses (ctx->stmt, c);
5304 g = gimple_build_assign (lane, INTEGER_CST,
5305 build_int_cst (unsigned_type_node, 0));
5306 gimple_seq_add_stmt (ilist, g);
5307 for (int i = 0; i < 2; i++)
5308 if (llist[i])
5310 tree vf = create_tmp_var (unsigned_type_node);
5311 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5312 gimple_call_set_lhs (g, vf);
5313 gimple_seq *seq = i == 0 ? ilist : dlist;
5314 gimple_seq_add_stmt (seq, g);
5315 tree t = build_int_cst (unsigned_type_node, 0);
5316 g = gimple_build_assign (idx, INTEGER_CST, t);
5317 gimple_seq_add_stmt (seq, g);
5318 tree body = create_artificial_label (UNKNOWN_LOCATION);
5319 tree header = create_artificial_label (UNKNOWN_LOCATION);
5320 tree end = create_artificial_label (UNKNOWN_LOCATION);
5321 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5322 gimple_seq_add_stmt (seq, gimple_build_label (body));
5323 gimple_seq_add_seq (seq, llist[i]);
5324 t = build_int_cst (unsigned_type_node, 1);
5325 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5326 gimple_seq_add_stmt (seq, g);
5327 gimple_seq_add_stmt (seq, gimple_build_label (header));
5328 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5329 gimple_seq_add_stmt (seq, g);
5330 gimple_seq_add_stmt (seq, gimple_build_label (end));
5334 /* The copyin sequence is not to be executed by the main thread, since
5335 that would result in self-copies. Perhaps not visible to scalars,
5336 but it certainly is to C++ operator=. */
5337 if (copyin_seq)
5339 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5341 x = build2 (NE_EXPR, boolean_type_node, x,
5342 build_int_cst (TREE_TYPE (x), 0));
5343 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5344 gimplify_and_add (x, ilist);
5347 /* If any copyin variable is passed by reference, we must ensure the
5348 master thread doesn't modify it before it is copied over in all
5349 threads. Similarly for variables in both firstprivate and
5350 lastprivate clauses we need to ensure the lastprivate copying
5351 happens after firstprivate copying in all threads. And similarly
5352 for UDRs if initializer expression refers to omp_orig. */
5353 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5355 /* Don't add any barrier for #pragma omp simd or
5356 #pragma omp distribute. */
5357 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5358 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5359 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5362 /* If max_vf is non-zero, then we can use only a vectorization factor
5363 up to the max_vf we chose. So stick it into the safelen clause. */
5364 if (max_vf)
5366 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5367 OMP_CLAUSE_SAFELEN);
5368 if (c == NULL_TREE
5369 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5370 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5371 max_vf) == 1))
5373 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5374 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5375 max_vf);
5376 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5377 gimple_omp_for_set_clauses (ctx->stmt, c);
5383 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5384 both parallel and workshare constructs. PREDICATE may be NULL if it's
5385 always true. */
5387 static void
5388 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5389 omp_context *ctx)
5391 tree x, c, label = NULL, orig_clauses = clauses;
5392 bool par_clauses = false;
5393 tree simduid = NULL, lastlane = NULL;
5395 /* Early exit if there are no lastprivate or linear clauses. */
5396 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5397 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5398 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5399 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5400 break;
5401 if (clauses == NULL)
5403 /* If this was a workshare clause, see if it had been combined
5404 with its parallel. In that case, look for the clauses on the
5405 parallel statement itself. */
5406 if (is_parallel_ctx (ctx))
5407 return;
5409 ctx = ctx->outer;
5410 if (ctx == NULL || !is_parallel_ctx (ctx))
5411 return;
5413 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5414 OMP_CLAUSE_LASTPRIVATE);
5415 if (clauses == NULL)
5416 return;
5417 par_clauses = true;
5420 if (predicate)
5422 gcond *stmt;
5423 tree label_true, arm1, arm2;
5425 label = create_artificial_label (UNKNOWN_LOCATION);
5426 label_true = create_artificial_label (UNKNOWN_LOCATION);
5427 arm1 = TREE_OPERAND (predicate, 0);
5428 arm2 = TREE_OPERAND (predicate, 1);
5429 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5430 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5431 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5432 label_true, label);
5433 gimple_seq_add_stmt (stmt_list, stmt);
5434 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5437 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5438 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5440 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5441 if (simduid)
5442 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5445 for (c = clauses; c ;)
5447 tree var, new_var;
5448 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5450 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5451 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5452 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5454 var = OMP_CLAUSE_DECL (c);
5455 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5456 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5457 && is_taskloop_ctx (ctx))
5459 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5460 new_var = lookup_decl (var, ctx->outer);
5462 else
5463 new_var = lookup_decl (var, ctx);
5465 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5467 tree val = DECL_VALUE_EXPR (new_var);
5468 if (TREE_CODE (val) == ARRAY_REF
5469 && VAR_P (TREE_OPERAND (val, 0))
5470 && lookup_attribute ("omp simd array",
5471 DECL_ATTRIBUTES (TREE_OPERAND (val,
5472 0))))
5474 if (lastlane == NULL)
5476 lastlane = create_tmp_var (unsigned_type_node);
5477 gcall *g
5478 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5479 2, simduid,
5480 TREE_OPERAND (val, 1));
5481 gimple_call_set_lhs (g, lastlane);
5482 gimple_seq_add_stmt (stmt_list, g);
5484 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5485 TREE_OPERAND (val, 0), lastlane,
5486 NULL_TREE, NULL_TREE);
5490 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5491 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5493 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5494 gimple_seq_add_seq (stmt_list,
5495 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5496 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5498 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5499 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5501 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5502 gimple_seq_add_seq (stmt_list,
5503 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5504 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5507 x = NULL_TREE;
5508 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5509 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5511 gcc_checking_assert (is_taskloop_ctx (ctx));
5512 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5513 ctx->outer->outer);
5514 if (is_global_var (ovar))
5515 x = ovar;
5517 if (!x)
5518 x = build_outer_var_ref (var, ctx, true);
5519 if (is_reference (var))
5520 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5521 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5522 gimplify_and_add (x, stmt_list);
5524 c = OMP_CLAUSE_CHAIN (c);
5525 if (c == NULL && !par_clauses)
5527 /* If this was a workshare clause, see if it had been combined
5528 with its parallel. In that case, continue looking for the
5529 clauses also on the parallel statement itself. */
5530 if (is_parallel_ctx (ctx))
5531 break;
5533 ctx = ctx->outer;
5534 if (ctx == NULL || !is_parallel_ctx (ctx))
5535 break;
5537 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5538 OMP_CLAUSE_LASTPRIVATE);
5539 par_clauses = true;
5543 if (label)
5544 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5547 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5548 (which might be a placeholder). INNER is true if this is an inner
5549 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5550 join markers. Generate the before-loop forking sequence in
5551 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5552 general form of these sequences is
5554 GOACC_REDUCTION_SETUP
5555 GOACC_FORK
5556 GOACC_REDUCTION_INIT
5558 GOACC_REDUCTION_FINI
5559 GOACC_JOIN
5560 GOACC_REDUCTION_TEARDOWN. */
5562 static void
5563 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5564 gcall *fork, gcall *join, gimple_seq *fork_seq,
5565 gimple_seq *join_seq, omp_context *ctx)
5567 gimple_seq before_fork = NULL;
5568 gimple_seq after_fork = NULL;
5569 gimple_seq before_join = NULL;
5570 gimple_seq after_join = NULL;
5571 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5572 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5573 unsigned offset = 0;
5575 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5576 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5578 tree orig = OMP_CLAUSE_DECL (c);
5579 tree var = maybe_lookup_decl (orig, ctx);
5580 tree ref_to_res = NULL_TREE;
5581 tree incoming, outgoing, v1, v2, v3;
5582 bool is_private = false;
5584 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5585 if (rcode == MINUS_EXPR)
5586 rcode = PLUS_EXPR;
5587 else if (rcode == TRUTH_ANDIF_EXPR)
5588 rcode = BIT_AND_EXPR;
5589 else if (rcode == TRUTH_ORIF_EXPR)
5590 rcode = BIT_IOR_EXPR;
5591 tree op = build_int_cst (unsigned_type_node, rcode);
5593 if (!var)
5594 var = orig;
5596 incoming = outgoing = var;
5598 if (!inner)
5600 /* See if an outer construct also reduces this variable. */
5601 omp_context *outer = ctx;
5603 while (omp_context *probe = outer->outer)
5605 enum gimple_code type = gimple_code (probe->stmt);
5606 tree cls;
5608 switch (type)
5610 case GIMPLE_OMP_FOR:
5611 cls = gimple_omp_for_clauses (probe->stmt);
5612 break;
5614 case GIMPLE_OMP_TARGET:
5615 if (gimple_omp_target_kind (probe->stmt)
5616 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5617 goto do_lookup;
5619 cls = gimple_omp_target_clauses (probe->stmt);
5620 break;
5622 default:
5623 goto do_lookup;
5626 outer = probe;
5627 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5628 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5629 && orig == OMP_CLAUSE_DECL (cls))
5631 incoming = outgoing = lookup_decl (orig, probe);
5632 goto has_outer_reduction;
5634 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5635 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5636 && orig == OMP_CLAUSE_DECL (cls))
5638 is_private = true;
5639 goto do_lookup;
5643 do_lookup:
5644 /* This is the outermost construct with this reduction,
5645 see if there's a mapping for it. */
5646 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5647 && maybe_lookup_field (orig, outer) && !is_private)
5649 ref_to_res = build_receiver_ref (orig, false, outer);
5650 if (is_reference (orig))
5651 ref_to_res = build_simple_mem_ref (ref_to_res);
5653 tree type = TREE_TYPE (var);
5654 if (POINTER_TYPE_P (type))
5655 type = TREE_TYPE (type);
5657 outgoing = var;
5658 incoming = omp_reduction_init_op (loc, rcode, type);
5660 else if (ctx->outer)
5661 incoming = outgoing = lookup_decl (orig, ctx->outer);
5662 else
5663 incoming = outgoing = orig;
5665 has_outer_reduction:;
5668 if (!ref_to_res)
5669 ref_to_res = integer_zero_node;
5671 if (is_reference (orig))
5673 tree type = TREE_TYPE (var);
5674 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5676 if (!inner)
5678 tree x = create_tmp_var (TREE_TYPE (type), id);
5679 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5682 v1 = create_tmp_var (type, id);
5683 v2 = create_tmp_var (type, id);
5684 v3 = create_tmp_var (type, id);
5686 gimplify_assign (v1, var, fork_seq);
5687 gimplify_assign (v2, var, fork_seq);
5688 gimplify_assign (v3, var, fork_seq);
5690 var = build_simple_mem_ref (var);
5691 v1 = build_simple_mem_ref (v1);
5692 v2 = build_simple_mem_ref (v2);
5693 v3 = build_simple_mem_ref (v3);
5694 outgoing = build_simple_mem_ref (outgoing);
5696 if (!TREE_CONSTANT (incoming))
5697 incoming = build_simple_mem_ref (incoming);
5699 else
5700 v1 = v2 = v3 = var;
5702 /* Determine position in reduction buffer, which may be used
5703 by target. */
5704 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5705 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5706 offset = (offset + align - 1) & ~(align - 1);
5707 tree off = build_int_cst (sizetype, offset);
5708 offset += GET_MODE_SIZE (mode);
5710 if (!init_code)
5712 init_code = build_int_cst (integer_type_node,
5713 IFN_GOACC_REDUCTION_INIT);
5714 fini_code = build_int_cst (integer_type_node,
5715 IFN_GOACC_REDUCTION_FINI);
5716 setup_code = build_int_cst (integer_type_node,
5717 IFN_GOACC_REDUCTION_SETUP);
5718 teardown_code = build_int_cst (integer_type_node,
5719 IFN_GOACC_REDUCTION_TEARDOWN);
5722 tree setup_call
5723 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5724 TREE_TYPE (var), 6, setup_code,
5725 unshare_expr (ref_to_res),
5726 incoming, level, op, off);
5727 tree init_call
5728 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5729 TREE_TYPE (var), 6, init_code,
5730 unshare_expr (ref_to_res),
5731 v1, level, op, off);
5732 tree fini_call
5733 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5734 TREE_TYPE (var), 6, fini_code,
5735 unshare_expr (ref_to_res),
5736 v2, level, op, off);
5737 tree teardown_call
5738 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5739 TREE_TYPE (var), 6, teardown_code,
5740 ref_to_res, v3, level, op, off);
5742 gimplify_assign (v1, setup_call, &before_fork);
5743 gimplify_assign (v2, init_call, &after_fork);
5744 gimplify_assign (v3, fini_call, &before_join);
5745 gimplify_assign (outgoing, teardown_call, &after_join);
5748 /* Now stitch things together. */
5749 gimple_seq_add_seq (fork_seq, before_fork);
5750 if (fork)
5751 gimple_seq_add_stmt (fork_seq, fork);
5752 gimple_seq_add_seq (fork_seq, after_fork);
5754 gimple_seq_add_seq (join_seq, before_join);
5755 if (join)
5756 gimple_seq_add_stmt (join_seq, join);
5757 gimple_seq_add_seq (join_seq, after_join);
5760 /* Generate code to implement the REDUCTION clauses. */
5762 static void
5763 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5765 gimple_seq sub_seq = NULL;
5766 gimple *stmt;
5767 tree x, c;
5768 int count = 0;
5770 /* OpenACC loop reductions are handled elsewhere. */
5771 if (is_gimple_omp_oacc (ctx->stmt))
5772 return;
5774 /* SIMD reductions are handled in lower_rec_input_clauses. */
5775 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5776 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5777 return;
5779 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5780 update in that case, otherwise use a lock. */
5781 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5784 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5785 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5787 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5788 count = -1;
5789 break;
5791 count++;
5794 if (count == 0)
5795 return;
5797 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5799 tree var, ref, new_var, orig_var;
5800 enum tree_code code;
5801 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5803 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5804 continue;
5806 orig_var = var = OMP_CLAUSE_DECL (c);
5807 if (TREE_CODE (var) == MEM_REF)
5809 var = TREE_OPERAND (var, 0);
5810 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5811 var = TREE_OPERAND (var, 0);
5812 if (TREE_CODE (var) == INDIRECT_REF
5813 || TREE_CODE (var) == ADDR_EXPR)
5814 var = TREE_OPERAND (var, 0);
5815 orig_var = var;
5816 if (is_variable_sized (var))
5818 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5819 var = DECL_VALUE_EXPR (var);
5820 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5821 var = TREE_OPERAND (var, 0);
5822 gcc_assert (DECL_P (var));
5825 new_var = lookup_decl (var, ctx);
5826 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5828 ref = build_outer_var_ref (var, ctx);
5829 code = OMP_CLAUSE_REDUCTION_CODE (c);
5831 /* reduction(-:var) sums up the partial results, so it acts
5832 identically to reduction(+:var). */
5833 if (code == MINUS_EXPR)
5834 code = PLUS_EXPR;
5836 if (count == 1)
5838 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5840 addr = save_expr (addr);
5841 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5842 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5843 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5844 gimplify_and_add (x, stmt_seqp);
5845 return;
5847 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5849 tree d = OMP_CLAUSE_DECL (c);
5850 tree type = TREE_TYPE (d);
5851 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5852 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5853 tree ptype = build_pointer_type (TREE_TYPE (type));
5854 tree bias = TREE_OPERAND (d, 1);
5855 d = TREE_OPERAND (d, 0);
5856 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5858 tree b = TREE_OPERAND (d, 1);
5859 b = maybe_lookup_decl (b, ctx);
5860 if (b == NULL)
5862 b = TREE_OPERAND (d, 1);
5863 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5865 if (integer_zerop (bias))
5866 bias = b;
5867 else
5869 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5870 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5871 TREE_TYPE (b), b, bias);
5873 d = TREE_OPERAND (d, 0);
5875 /* For ref build_outer_var_ref already performs this, so
5876 only new_var needs a dereference. */
5877 if (TREE_CODE (d) == INDIRECT_REF)
5879 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5880 gcc_assert (is_reference (var) && var == orig_var);
5882 else if (TREE_CODE (d) == ADDR_EXPR)
5884 if (orig_var == var)
5886 new_var = build_fold_addr_expr (new_var);
5887 ref = build_fold_addr_expr (ref);
5890 else
5892 gcc_assert (orig_var == var);
5893 if (is_reference (var))
5894 ref = build_fold_addr_expr (ref);
5896 if (DECL_P (v))
5898 tree t = maybe_lookup_decl (v, ctx);
5899 if (t)
5900 v = t;
5901 else
5902 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5903 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5905 if (!integer_zerop (bias))
5907 bias = fold_convert_loc (clause_loc, sizetype, bias);
5908 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5909 TREE_TYPE (new_var), new_var,
5910 unshare_expr (bias));
5911 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5912 TREE_TYPE (ref), ref, bias);
5914 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5915 ref = fold_convert_loc (clause_loc, ptype, ref);
5916 tree m = create_tmp_var (ptype, NULL);
5917 gimplify_assign (m, new_var, stmt_seqp);
5918 new_var = m;
5919 m = create_tmp_var (ptype, NULL);
5920 gimplify_assign (m, ref, stmt_seqp);
5921 ref = m;
5922 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5923 tree body = create_artificial_label (UNKNOWN_LOCATION);
5924 tree end = create_artificial_label (UNKNOWN_LOCATION);
5925 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5926 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5927 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5928 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5930 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5931 tree decl_placeholder
5932 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5933 SET_DECL_VALUE_EXPR (placeholder, out);
5934 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5935 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5936 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5937 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5938 gimple_seq_add_seq (&sub_seq,
5939 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5940 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5941 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5942 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5944 else
5946 x = build2 (code, TREE_TYPE (out), out, priv);
5947 out = unshare_expr (out);
5948 gimplify_assign (out, x, &sub_seq);
5950 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5951 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5952 gimple_seq_add_stmt (&sub_seq, g);
5953 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5954 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5955 gimple_seq_add_stmt (&sub_seq, g);
5956 g = gimple_build_assign (i, PLUS_EXPR, i,
5957 build_int_cst (TREE_TYPE (i), 1));
5958 gimple_seq_add_stmt (&sub_seq, g);
5959 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5960 gimple_seq_add_stmt (&sub_seq, g);
5961 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5963 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5965 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5967 if (is_reference (var)
5968 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5969 TREE_TYPE (ref)))
5970 ref = build_fold_addr_expr_loc (clause_loc, ref);
5971 SET_DECL_VALUE_EXPR (placeholder, ref);
5972 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5973 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5974 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5975 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5976 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5978 else
5980 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5981 ref = build_outer_var_ref (var, ctx);
5982 gimplify_assign (ref, x, &sub_seq);
5986 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5988 gimple_seq_add_stmt (stmt_seqp, stmt);
5990 gimple_seq_add_seq (stmt_seqp, sub_seq);
5992 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5994 gimple_seq_add_stmt (stmt_seqp, stmt);
5998 /* Generate code to implement the COPYPRIVATE clauses. */
6000 static void
6001 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6002 omp_context *ctx)
6004 tree c;
6006 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6008 tree var, new_var, ref, x;
6009 bool by_ref;
6010 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6012 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6013 continue;
6015 var = OMP_CLAUSE_DECL (c);
6016 by_ref = use_pointer_for_field (var, NULL);
6018 ref = build_sender_ref (var, ctx);
6019 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6020 if (by_ref)
6022 x = build_fold_addr_expr_loc (clause_loc, new_var);
6023 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6025 gimplify_assign (ref, x, slist);
6027 ref = build_receiver_ref (var, false, ctx);
6028 if (by_ref)
6030 ref = fold_convert_loc (clause_loc,
6031 build_pointer_type (TREE_TYPE (new_var)),
6032 ref);
6033 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6035 if (is_reference (var))
6037 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6038 ref = build_simple_mem_ref_loc (clause_loc, ref);
6039 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6041 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6042 gimplify_and_add (x, rlist);
6047 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6048 and REDUCTION from the sender (aka parent) side. */
6050 static void
6051 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6052 omp_context *ctx)
6054 tree c, t;
6055 int ignored_looptemp = 0;
6056 bool is_taskloop = false;
6058 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6059 by GOMP_taskloop. */
6060 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6062 ignored_looptemp = 2;
6063 is_taskloop = true;
6066 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6068 tree val, ref, x, var;
6069 bool by_ref, do_in = false, do_out = false;
6070 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6072 switch (OMP_CLAUSE_CODE (c))
6074 case OMP_CLAUSE_PRIVATE:
6075 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6076 break;
6077 continue;
6078 case OMP_CLAUSE_FIRSTPRIVATE:
6079 case OMP_CLAUSE_COPYIN:
6080 case OMP_CLAUSE_LASTPRIVATE:
6081 case OMP_CLAUSE_REDUCTION:
6082 break;
6083 case OMP_CLAUSE_SHARED:
6084 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6085 break;
6086 continue;
6087 case OMP_CLAUSE__LOOPTEMP_:
6088 if (ignored_looptemp)
6090 ignored_looptemp--;
6091 continue;
6093 break;
6094 default:
6095 continue;
6098 val = OMP_CLAUSE_DECL (c);
6099 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6100 && TREE_CODE (val) == MEM_REF)
6102 val = TREE_OPERAND (val, 0);
6103 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6104 val = TREE_OPERAND (val, 0);
6105 if (TREE_CODE (val) == INDIRECT_REF
6106 || TREE_CODE (val) == ADDR_EXPR)
6107 val = TREE_OPERAND (val, 0);
6108 if (is_variable_sized (val))
6109 continue;
6112 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6113 outer taskloop region. */
6114 omp_context *ctx_for_o = ctx;
6115 if (is_taskloop
6116 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6117 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6118 ctx_for_o = ctx->outer;
6120 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6122 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6123 && is_global_var (var))
6124 continue;
6126 t = omp_member_access_dummy_var (var);
6127 if (t)
6129 var = DECL_VALUE_EXPR (var);
6130 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6131 if (o != t)
6132 var = unshare_and_remap (var, t, o);
6133 else
6134 var = unshare_expr (var);
6137 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6139 /* Handle taskloop firstprivate/lastprivate, where the
6140 lastprivate on GIMPLE_OMP_TASK is represented as
6141 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6142 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6143 x = omp_build_component_ref (ctx->sender_decl, f);
6144 if (use_pointer_for_field (val, ctx))
6145 var = build_fold_addr_expr (var);
6146 gimplify_assign (x, var, ilist);
6147 DECL_ABSTRACT_ORIGIN (f) = NULL;
6148 continue;
6151 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6152 || val == OMP_CLAUSE_DECL (c))
6153 && is_variable_sized (val))
6154 continue;
6155 by_ref = use_pointer_for_field (val, NULL);
6157 switch (OMP_CLAUSE_CODE (c))
6159 case OMP_CLAUSE_FIRSTPRIVATE:
6160 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6161 && !by_ref
6162 && is_task_ctx (ctx))
6163 TREE_NO_WARNING (var) = 1;
6164 do_in = true;
6165 break;
6167 case OMP_CLAUSE_PRIVATE:
6168 case OMP_CLAUSE_COPYIN:
6169 case OMP_CLAUSE__LOOPTEMP_:
6170 do_in = true;
6171 break;
6173 case OMP_CLAUSE_LASTPRIVATE:
6174 if (by_ref || is_reference (val))
6176 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6177 continue;
6178 do_in = true;
6180 else
6182 do_out = true;
6183 if (lang_hooks.decls.omp_private_outer_ref (val))
6184 do_in = true;
6186 break;
6188 case OMP_CLAUSE_REDUCTION:
6189 do_in = true;
6190 if (val == OMP_CLAUSE_DECL (c))
6191 do_out = !(by_ref || is_reference (val));
6192 else
6193 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6194 break;
6196 default:
6197 gcc_unreachable ();
6200 if (do_in)
6202 ref = build_sender_ref (val, ctx);
6203 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6204 gimplify_assign (ref, x, ilist);
6205 if (is_task_ctx (ctx))
6206 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6209 if (do_out)
6211 ref = build_sender_ref (val, ctx);
6212 gimplify_assign (var, ref, olist);
6217 /* Generate code to implement SHARED from the sender (aka parent)
6218 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6219 list things that got automatically shared. */
6221 static void
6222 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6224 tree var, ovar, nvar, t, f, x, record_type;
6226 if (ctx->record_type == NULL)
6227 return;
6229 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6230 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6232 ovar = DECL_ABSTRACT_ORIGIN (f);
6233 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6234 continue;
6236 nvar = maybe_lookup_decl (ovar, ctx);
6237 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6238 continue;
6240 /* If CTX is a nested parallel directive. Find the immediately
6241 enclosing parallel or workshare construct that contains a
6242 mapping for OVAR. */
6243 var = lookup_decl_in_outer_ctx (ovar, ctx);
6245 t = omp_member_access_dummy_var (var);
6246 if (t)
6248 var = DECL_VALUE_EXPR (var);
6249 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6250 if (o != t)
6251 var = unshare_and_remap (var, t, o);
6252 else
6253 var = unshare_expr (var);
6256 if (use_pointer_for_field (ovar, ctx))
6258 x = build_sender_ref (ovar, ctx);
6259 var = build_fold_addr_expr (var);
6260 gimplify_assign (x, var, ilist);
6262 else
6264 x = build_sender_ref (ovar, ctx);
6265 gimplify_assign (x, var, ilist);
6267 if (!TREE_READONLY (var)
6268 /* We don't need to receive a new reference to a result
6269 or parm decl. In fact we may not store to it as we will
6270 invalidate any pending RSO and generate wrong gimple
6271 during inlining. */
6272 && !((TREE_CODE (var) == RESULT_DECL
6273 || TREE_CODE (var) == PARM_DECL)
6274 && DECL_BY_REFERENCE (var)))
6276 x = build_sender_ref (ovar, ctx);
6277 gimplify_assign (var, x, olist);
6283 /* Emit an OpenACC head marker call, encapulating the partitioning and
6284 other information that must be processed by the target compiler.
6285 Return the maximum number of dimensions the associated loop might
6286 be partitioned over. */
6288 static unsigned
6289 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6290 gimple_seq *seq, omp_context *ctx)
6292 unsigned levels = 0;
6293 unsigned tag = 0;
6294 tree gang_static = NULL_TREE;
6295 auto_vec<tree, 5> args;
6297 args.quick_push (build_int_cst
6298 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6299 args.quick_push (ddvar);
6300 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6302 switch (OMP_CLAUSE_CODE (c))
6304 case OMP_CLAUSE_GANG:
6305 tag |= OLF_DIM_GANG;
6306 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6307 /* static:* is represented by -1, and we can ignore it, as
6308 scheduling is always static. */
6309 if (gang_static && integer_minus_onep (gang_static))
6310 gang_static = NULL_TREE;
6311 levels++;
6312 break;
6314 case OMP_CLAUSE_WORKER:
6315 tag |= OLF_DIM_WORKER;
6316 levels++;
6317 break;
6319 case OMP_CLAUSE_VECTOR:
6320 tag |= OLF_DIM_VECTOR;
6321 levels++;
6322 break;
6324 case OMP_CLAUSE_SEQ:
6325 tag |= OLF_SEQ;
6326 break;
6328 case OMP_CLAUSE_AUTO:
6329 tag |= OLF_AUTO;
6330 break;
6332 case OMP_CLAUSE_INDEPENDENT:
6333 tag |= OLF_INDEPENDENT;
6334 break;
6336 default:
6337 continue;
6341 if (gang_static)
6343 if (DECL_P (gang_static))
6344 gang_static = build_outer_var_ref (gang_static, ctx);
6345 tag |= OLF_GANG_STATIC;
6348 /* In a parallel region, loops are implicitly INDEPENDENT. */
6349 omp_context *tgt = enclosing_target_ctx (ctx);
6350 if (!tgt || is_oacc_parallel (tgt))
6351 tag |= OLF_INDEPENDENT;
6353 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6354 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6355 | OLF_SEQ)))
6356 tag |= OLF_AUTO;
6358 /* Ensure at least one level. */
6359 if (!levels)
6360 levels++;
6362 args.quick_push (build_int_cst (integer_type_node, levels));
6363 args.quick_push (build_int_cst (integer_type_node, tag));
6364 if (gang_static)
6365 args.quick_push (gang_static);
6367 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6368 gimple_set_location (call, loc);
6369 gimple_set_lhs (call, ddvar);
6370 gimple_seq_add_stmt (seq, call);
6372 return levels;
6375 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6376 partitioning level of the enclosed region. */
6378 static void
6379 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6380 tree tofollow, gimple_seq *seq)
6382 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6383 : IFN_UNIQUE_OACC_TAIL_MARK);
6384 tree marker = build_int_cst (integer_type_node, marker_kind);
6385 int nargs = 2 + (tofollow != NULL_TREE);
6386 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6387 marker, ddvar, tofollow);
6388 gimple_set_location (call, loc);
6389 gimple_set_lhs (call, ddvar);
6390 gimple_seq_add_stmt (seq, call);
6393 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6394 the loop clauses, from which we extract reductions. Initialize
6395 HEAD and TAIL. */
6397 static void
6398 lower_oacc_head_tail (location_t loc, tree clauses,
6399 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6401 bool inner = false;
6402 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6403 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6405 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6406 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6407 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6409 gcc_assert (count);
6410 for (unsigned done = 1; count; count--, done++)
6412 gimple_seq fork_seq = NULL;
6413 gimple_seq join_seq = NULL;
6415 tree place = build_int_cst (integer_type_node, -1);
6416 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6417 fork_kind, ddvar, place);
6418 gimple_set_location (fork, loc);
6419 gimple_set_lhs (fork, ddvar);
6421 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6422 join_kind, ddvar, place);
6423 gimple_set_location (join, loc);
6424 gimple_set_lhs (join, ddvar);
6426 /* Mark the beginning of this level sequence. */
6427 if (inner)
6428 lower_oacc_loop_marker (loc, ddvar, true,
6429 build_int_cst (integer_type_node, count),
6430 &fork_seq);
6431 lower_oacc_loop_marker (loc, ddvar, false,
6432 build_int_cst (integer_type_node, done),
6433 &join_seq);
6435 lower_oacc_reductions (loc, clauses, place, inner,
6436 fork, join, &fork_seq, &join_seq, ctx);
6438 /* Append this level to head. */
6439 gimple_seq_add_seq (head, fork_seq);
6440 /* Prepend it to tail. */
6441 gimple_seq_add_seq (&join_seq, *tail);
6442 *tail = join_seq;
6444 inner = true;
6447 /* Mark the end of the sequence. */
6448 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6449 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6452 /* A convenience function to build an empty GIMPLE_COND with just the
6453 condition. */
6455 static gcond *
6456 gimple_build_cond_empty (tree cond)
6458 enum tree_code pred_code;
6459 tree lhs, rhs;
6461 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6462 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6465 /* Return true if a parallel REGION is within a declare target function or
6466 within a target region and is not a part of a gridified target. */
6468 static bool
6469 parallel_needs_hsa_kernel_p (struct omp_region *region)
6471 bool indirect = false;
6472 for (region = region->outer; region; region = region->outer)
6474 if (region->type == GIMPLE_OMP_PARALLEL)
6475 indirect = true;
6476 else if (region->type == GIMPLE_OMP_TARGET)
6478 gomp_target *tgt_stmt
6479 = as_a <gomp_target *> (last_stmt (region->entry));
6481 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6482 OMP_CLAUSE__GRIDDIM_))
6483 return indirect;
6484 else
6485 return true;
6489 if (lookup_attribute ("omp declare target",
6490 DECL_ATTRIBUTES (current_function_decl)))
6491 return true;
6493 return false;
6496 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6497 bool = false);
6499 /* Build the function calls to GOMP_parallel_start etc to actually
6500 generate the parallel operation. REGION is the parallel region
6501 being expanded. BB is the block where to insert the code. WS_ARGS
6502 will be set if this is a call to a combined parallel+workshare
6503 construct, it contains the list of additional arguments needed by
6504 the workshare construct. */
6506 static void
6507 expand_parallel_call (struct omp_region *region, basic_block bb,
6508 gomp_parallel *entry_stmt,
6509 vec<tree, va_gc> *ws_args)
6511 tree t, t1, t2, val, cond, c, clauses, flags;
6512 gimple_stmt_iterator gsi;
6513 gimple *stmt;
6514 enum built_in_function start_ix;
6515 int start_ix2;
6516 location_t clause_loc;
6517 vec<tree, va_gc> *args;
6519 clauses = gimple_omp_parallel_clauses (entry_stmt);
6521 /* Determine what flavor of GOMP_parallel we will be
6522 emitting. */
6523 start_ix = BUILT_IN_GOMP_PARALLEL;
6524 if (is_combined_parallel (region))
6526 switch (region->inner->type)
6528 case GIMPLE_OMP_FOR:
6529 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6530 switch (region->inner->sched_kind)
6532 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6533 start_ix2 = 3;
6534 break;
6535 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6536 case OMP_CLAUSE_SCHEDULE_GUIDED:
6537 if (region->inner->sched_modifiers
6538 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6540 start_ix2 = 3 + region->inner->sched_kind;
6541 break;
6543 /* FALLTHRU */
6544 default:
6545 start_ix2 = region->inner->sched_kind;
6546 break;
6548 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6549 start_ix = (enum built_in_function) start_ix2;
6550 break;
6551 case GIMPLE_OMP_SECTIONS:
6552 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6553 break;
6554 default:
6555 gcc_unreachable ();
6559 /* By default, the value of NUM_THREADS is zero (selected at run time)
6560 and there is no conditional. */
6561 cond = NULL_TREE;
6562 val = build_int_cst (unsigned_type_node, 0);
6563 flags = build_int_cst (unsigned_type_node, 0);
6565 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6566 if (c)
6567 cond = OMP_CLAUSE_IF_EXPR (c);
6569 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6570 if (c)
6572 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6573 clause_loc = OMP_CLAUSE_LOCATION (c);
6575 else
6576 clause_loc = gimple_location (entry_stmt);
6578 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6579 if (c)
6580 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6582 /* Ensure 'val' is of the correct type. */
6583 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6585 /* If we found the clause 'if (cond)', build either
6586 (cond != 0) or (cond ? val : 1u). */
6587 if (cond)
6589 cond = gimple_boolify (cond);
6591 if (integer_zerop (val))
6592 val = fold_build2_loc (clause_loc,
6593 EQ_EXPR, unsigned_type_node, cond,
6594 build_int_cst (TREE_TYPE (cond), 0));
6595 else
6597 basic_block cond_bb, then_bb, else_bb;
6598 edge e, e_then, e_else;
6599 tree tmp_then, tmp_else, tmp_join, tmp_var;
6601 tmp_var = create_tmp_var (TREE_TYPE (val));
6602 if (gimple_in_ssa_p (cfun))
6604 tmp_then = make_ssa_name (tmp_var);
6605 tmp_else = make_ssa_name (tmp_var);
6606 tmp_join = make_ssa_name (tmp_var);
6608 else
6610 tmp_then = tmp_var;
6611 tmp_else = tmp_var;
6612 tmp_join = tmp_var;
6615 e = split_block_after_labels (bb);
6616 cond_bb = e->src;
6617 bb = e->dest;
6618 remove_edge (e);
6620 then_bb = create_empty_bb (cond_bb);
6621 else_bb = create_empty_bb (then_bb);
6622 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6623 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6625 stmt = gimple_build_cond_empty (cond);
6626 gsi = gsi_start_bb (cond_bb);
6627 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6629 gsi = gsi_start_bb (then_bb);
6630 expand_omp_build_assign (&gsi, tmp_then, val, true);
6632 gsi = gsi_start_bb (else_bb);
6633 expand_omp_build_assign (&gsi, tmp_else,
6634 build_int_cst (unsigned_type_node, 1),
6635 true);
6637 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6638 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6639 add_bb_to_loop (then_bb, cond_bb->loop_father);
6640 add_bb_to_loop (else_bb, cond_bb->loop_father);
6641 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6642 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6644 if (gimple_in_ssa_p (cfun))
6646 gphi *phi = create_phi_node (tmp_join, bb);
6647 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6648 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6651 val = tmp_join;
6654 gsi = gsi_start_bb (bb);
6655 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6656 false, GSI_CONTINUE_LINKING);
6659 gsi = gsi_last_bb (bb);
6660 t = gimple_omp_parallel_data_arg (entry_stmt);
6661 if (t == NULL)
6662 t1 = null_pointer_node;
6663 else
6664 t1 = build_fold_addr_expr (t);
6665 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6666 t2 = build_fold_addr_expr (child_fndecl);
6668 vec_alloc (args, 4 + vec_safe_length (ws_args));
6669 args->quick_push (t2);
6670 args->quick_push (t1);
6671 args->quick_push (val);
6672 if (ws_args)
6673 args->splice (*ws_args);
6674 args->quick_push (flags);
6676 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6677 builtin_decl_explicit (start_ix), args);
6679 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6680 false, GSI_CONTINUE_LINKING);
6682 if (hsa_gen_requested_p ()
6683 && parallel_needs_hsa_kernel_p (region))
6685 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6686 hsa_register_kernel (child_cnode);
6690 /* Insert a function call whose name is FUNC_NAME with the information from
6691 ENTRY_STMT into the basic_block BB. */
6693 static void
6694 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6695 vec <tree, va_gc> *ws_args)
6697 tree t, t1, t2;
6698 gimple_stmt_iterator gsi;
6699 vec <tree, va_gc> *args;
6701 gcc_assert (vec_safe_length (ws_args) == 2);
6702 tree func_name = (*ws_args)[0];
6703 tree grain = (*ws_args)[1];
6705 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6706 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6707 gcc_assert (count != NULL_TREE);
6708 count = OMP_CLAUSE_OPERAND (count, 0);
6710 gsi = gsi_last_bb (bb);
6711 t = gimple_omp_parallel_data_arg (entry_stmt);
6712 if (t == NULL)
6713 t1 = null_pointer_node;
6714 else
6715 t1 = build_fold_addr_expr (t);
6716 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6718 vec_alloc (args, 4);
6719 args->quick_push (t2);
6720 args->quick_push (t1);
6721 args->quick_push (count);
6722 args->quick_push (grain);
6723 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6725 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6726 GSI_CONTINUE_LINKING);
6729 /* Build the function call to GOMP_task to actually
6730 generate the task operation. BB is the block where to insert the code. */
6732 static void
6733 expand_task_call (struct omp_region *region, basic_block bb,
6734 gomp_task *entry_stmt)
6736 tree t1, t2, t3;
6737 gimple_stmt_iterator gsi;
6738 location_t loc = gimple_location (entry_stmt);
6740 tree clauses = gimple_omp_task_clauses (entry_stmt);
6742 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6743 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6744 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6745 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6746 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6747 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6749 unsigned int iflags
6750 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6751 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6752 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6754 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6755 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6756 tree num_tasks = NULL_TREE;
6757 bool ull = false;
6758 if (taskloop_p)
6760 gimple *g = last_stmt (region->outer->entry);
6761 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6762 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6763 struct omp_for_data fd;
6764 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6765 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6766 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6767 OMP_CLAUSE__LOOPTEMP_);
6768 startvar = OMP_CLAUSE_DECL (startvar);
6769 endvar = OMP_CLAUSE_DECL (endvar);
6770 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6771 if (fd.loop.cond_code == LT_EXPR)
6772 iflags |= GOMP_TASK_FLAG_UP;
6773 tree tclauses = gimple_omp_for_clauses (g);
6774 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6775 if (num_tasks)
6776 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6777 else
6779 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6780 if (num_tasks)
6782 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6783 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6785 else
6786 num_tasks = integer_zero_node;
6788 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6789 if (ifc == NULL_TREE)
6790 iflags |= GOMP_TASK_FLAG_IF;
6791 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6792 iflags |= GOMP_TASK_FLAG_NOGROUP;
6793 ull = fd.iter_type == long_long_unsigned_type_node;
6795 else if (priority)
6796 iflags |= GOMP_TASK_FLAG_PRIORITY;
6798 tree flags = build_int_cst (unsigned_type_node, iflags);
6800 tree cond = boolean_true_node;
6801 if (ifc)
6803 if (taskloop_p)
6805 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6806 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6807 build_int_cst (unsigned_type_node,
6808 GOMP_TASK_FLAG_IF),
6809 build_int_cst (unsigned_type_node, 0));
6810 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6811 flags, t);
6813 else
6814 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6817 if (finalc)
6819 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6820 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6821 build_int_cst (unsigned_type_node,
6822 GOMP_TASK_FLAG_FINAL),
6823 build_int_cst (unsigned_type_node, 0));
6824 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6826 if (depend)
6827 depend = OMP_CLAUSE_DECL (depend);
6828 else
6829 depend = build_int_cst (ptr_type_node, 0);
6830 if (priority)
6831 priority = fold_convert (integer_type_node,
6832 OMP_CLAUSE_PRIORITY_EXPR (priority));
6833 else
6834 priority = integer_zero_node;
6836 gsi = gsi_last_bb (bb);
6837 tree t = gimple_omp_task_data_arg (entry_stmt);
6838 if (t == NULL)
6839 t2 = null_pointer_node;
6840 else
6841 t2 = build_fold_addr_expr_loc (loc, t);
6842 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6843 t = gimple_omp_task_copy_fn (entry_stmt);
6844 if (t == NULL)
6845 t3 = null_pointer_node;
6846 else
6847 t3 = build_fold_addr_expr_loc (loc, t);
6849 if (taskloop_p)
6850 t = build_call_expr (ull
6851 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6852 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6853 11, t1, t2, t3,
6854 gimple_omp_task_arg_size (entry_stmt),
6855 gimple_omp_task_arg_align (entry_stmt), flags,
6856 num_tasks, priority, startvar, endvar, step);
6857 else
6858 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6859 9, t1, t2, t3,
6860 gimple_omp_task_arg_size (entry_stmt),
6861 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6862 depend, priority);
6864 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6865 false, GSI_CONTINUE_LINKING);
6869 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6870 catch handler and return it. This prevents programs from violating the
6871 structured block semantics with throws. */
6873 static gimple_seq
6874 maybe_catch_exception (gimple_seq body)
6876 gimple *g;
6877 tree decl;
6879 if (!flag_exceptions)
6880 return body;
6882 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6883 decl = lang_hooks.eh_protect_cleanup_actions ();
6884 else
6885 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6887 g = gimple_build_eh_must_not_throw (decl);
6888 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6889 GIMPLE_TRY_CATCH);
6891 return gimple_seq_alloc_with_stmt (g);
6894 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6896 static tree
6897 vec2chain (vec<tree, va_gc> *v)
6899 tree chain = NULL_TREE, t;
6900 unsigned ix;
6902 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6904 DECL_CHAIN (t) = chain;
6905 chain = t;
6908 return chain;
6912 /* Remove barriers in REGION->EXIT's block. Note that this is only
6913 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6914 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6915 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6916 removed. */
6918 static void
6919 remove_exit_barrier (struct omp_region *region)
6921 gimple_stmt_iterator gsi;
6922 basic_block exit_bb;
6923 edge_iterator ei;
6924 edge e;
6925 gimple *stmt;
6926 int any_addressable_vars = -1;
6928 exit_bb = region->exit;
6930 /* If the parallel region doesn't return, we don't have REGION->EXIT
6931 block at all. */
6932 if (! exit_bb)
6933 return;
6935 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6936 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6937 statements that can appear in between are extremely limited -- no
6938 memory operations at all. Here, we allow nothing at all, so the
6939 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6940 gsi = gsi_last_bb (exit_bb);
6941 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6942 gsi_prev (&gsi);
6943 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6944 return;
6946 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6948 gsi = gsi_last_bb (e->src);
6949 if (gsi_end_p (gsi))
6950 continue;
6951 stmt = gsi_stmt (gsi);
6952 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6953 && !gimple_omp_return_nowait_p (stmt))
6955 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6956 in many cases. If there could be tasks queued, the barrier
6957 might be needed to let the tasks run before some local
6958 variable of the parallel that the task uses as shared
6959 runs out of scope. The task can be spawned either
6960 from within current function (this would be easy to check)
6961 or from some function it calls and gets passed an address
6962 of such a variable. */
6963 if (any_addressable_vars < 0)
6965 gomp_parallel *parallel_stmt
6966 = as_a <gomp_parallel *> (last_stmt (region->entry));
6967 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6968 tree local_decls, block, decl;
6969 unsigned ix;
6971 any_addressable_vars = 0;
6972 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6973 if (TREE_ADDRESSABLE (decl))
6975 any_addressable_vars = 1;
6976 break;
6978 for (block = gimple_block (stmt);
6979 !any_addressable_vars
6980 && block
6981 && TREE_CODE (block) == BLOCK;
6982 block = BLOCK_SUPERCONTEXT (block))
6984 for (local_decls = BLOCK_VARS (block);
6985 local_decls;
6986 local_decls = DECL_CHAIN (local_decls))
6987 if (TREE_ADDRESSABLE (local_decls))
6989 any_addressable_vars = 1;
6990 break;
6992 if (block == gimple_block (parallel_stmt))
6993 break;
6996 if (!any_addressable_vars)
6997 gimple_omp_return_set_nowait (stmt);
7002 static void
7003 remove_exit_barriers (struct omp_region *region)
7005 if (region->type == GIMPLE_OMP_PARALLEL)
7006 remove_exit_barrier (region);
7008 if (region->inner)
7010 region = region->inner;
7011 remove_exit_barriers (region);
7012 while (region->next)
7014 region = region->next;
7015 remove_exit_barriers (region);
7020 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7021 calls. These can't be declared as const functions, but
7022 within one parallel body they are constant, so they can be
7023 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7024 which are declared const. Similarly for task body, except
7025 that in untied task omp_get_thread_num () can change at any task
7026 scheduling point. */
7028 static void
7029 optimize_omp_library_calls (gimple *entry_stmt)
7031 basic_block bb;
7032 gimple_stmt_iterator gsi;
7033 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7034 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7035 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7036 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7037 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7038 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7039 OMP_CLAUSE_UNTIED) != NULL);
7041 FOR_EACH_BB_FN (bb, cfun)
7042 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7044 gimple *call = gsi_stmt (gsi);
7045 tree decl;
7047 if (is_gimple_call (call)
7048 && (decl = gimple_call_fndecl (call))
7049 && DECL_EXTERNAL (decl)
7050 && TREE_PUBLIC (decl)
7051 && DECL_INITIAL (decl) == NULL)
7053 tree built_in;
7055 if (DECL_NAME (decl) == thr_num_id)
7057 /* In #pragma omp task untied omp_get_thread_num () can change
7058 during the execution of the task region. */
7059 if (untied_task)
7060 continue;
7061 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7063 else if (DECL_NAME (decl) == num_thr_id)
7064 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7065 else
7066 continue;
7068 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7069 || gimple_call_num_args (call) != 0)
7070 continue;
7072 if (flag_exceptions && !TREE_NOTHROW (decl))
7073 continue;
7075 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7076 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7077 TREE_TYPE (TREE_TYPE (built_in))))
7078 continue;
7080 gimple_call_set_fndecl (call, built_in);
7085 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7086 regimplified. */
7088 static tree
7089 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7091 tree t = *tp;
7093 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7094 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7095 return t;
7097 if (TREE_CODE (t) == ADDR_EXPR)
7098 recompute_tree_invariant_for_addr_expr (t);
7100 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7101 return NULL_TREE;
7104 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7106 static void
7107 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7108 bool after)
7110 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7111 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7112 !after, after ? GSI_CONTINUE_LINKING
7113 : GSI_SAME_STMT);
7114 gimple *stmt = gimple_build_assign (to, from);
7115 if (after)
7116 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7117 else
7118 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7119 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7120 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7122 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7123 gimple_regimplify_operands (stmt, &gsi);
7127 /* Expand the OpenMP parallel or task directive starting at REGION. */
7129 static void
7130 expand_omp_taskreg (struct omp_region *region)
7132 basic_block entry_bb, exit_bb, new_bb;
7133 struct function *child_cfun;
7134 tree child_fn, block, t;
7135 gimple_stmt_iterator gsi;
7136 gimple *entry_stmt, *stmt;
7137 edge e;
7138 vec<tree, va_gc> *ws_args;
7140 entry_stmt = last_stmt (region->entry);
7141 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7142 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7144 entry_bb = region->entry;
7145 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7146 exit_bb = region->cont;
7147 else
7148 exit_bb = region->exit;
7150 bool is_cilk_for
7151 = (flag_cilkplus
7152 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7153 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7154 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7156 if (is_cilk_for)
7157 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7158 and the inner statement contains the name of the built-in function
7159 and grain. */
7160 ws_args = region->inner->ws_args;
7161 else if (is_combined_parallel (region))
7162 ws_args = region->ws_args;
7163 else
7164 ws_args = NULL;
7166 if (child_cfun->cfg)
7168 /* Due to inlining, it may happen that we have already outlined
7169 the region, in which case all we need to do is make the
7170 sub-graph unreachable and emit the parallel call. */
7171 edge entry_succ_e, exit_succ_e;
7173 entry_succ_e = single_succ_edge (entry_bb);
7175 gsi = gsi_last_bb (entry_bb);
7176 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7177 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7178 gsi_remove (&gsi, true);
7180 new_bb = entry_bb;
7181 if (exit_bb)
7183 exit_succ_e = single_succ_edge (exit_bb);
7184 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7186 remove_edge_and_dominated_blocks (entry_succ_e);
7188 else
7190 unsigned srcidx, dstidx, num;
7192 /* If the parallel region needs data sent from the parent
7193 function, then the very first statement (except possible
7194 tree profile counter updates) of the parallel body
7195 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7196 &.OMP_DATA_O is passed as an argument to the child function,
7197 we need to replace it with the argument as seen by the child
7198 function.
7200 In most cases, this will end up being the identity assignment
7201 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7202 a function call that has been inlined, the original PARM_DECL
7203 .OMP_DATA_I may have been converted into a different local
7204 variable. In which case, we need to keep the assignment. */
7205 if (gimple_omp_taskreg_data_arg (entry_stmt))
7207 basic_block entry_succ_bb
7208 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7209 : FALLTHRU_EDGE (entry_bb)->dest;
7210 tree arg;
7211 gimple *parcopy_stmt = NULL;
7213 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7215 gimple *stmt;
7217 gcc_assert (!gsi_end_p (gsi));
7218 stmt = gsi_stmt (gsi);
7219 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7220 continue;
7222 if (gimple_num_ops (stmt) == 2)
7224 tree arg = gimple_assign_rhs1 (stmt);
7226 /* We're ignore the subcode because we're
7227 effectively doing a STRIP_NOPS. */
7229 if (TREE_CODE (arg) == ADDR_EXPR
7230 && TREE_OPERAND (arg, 0)
7231 == gimple_omp_taskreg_data_arg (entry_stmt))
7233 parcopy_stmt = stmt;
7234 break;
7239 gcc_assert (parcopy_stmt != NULL);
7240 arg = DECL_ARGUMENTS (child_fn);
7242 if (!gimple_in_ssa_p (cfun))
7244 if (gimple_assign_lhs (parcopy_stmt) == arg)
7245 gsi_remove (&gsi, true);
7246 else
7248 /* ?? Is setting the subcode really necessary ?? */
7249 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7250 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7253 else
7255 tree lhs = gimple_assign_lhs (parcopy_stmt);
7256 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7257 /* We'd like to set the rhs to the default def in the child_fn,
7258 but it's too early to create ssa names in the child_fn.
7259 Instead, we set the rhs to the parm. In
7260 move_sese_region_to_fn, we introduce a default def for the
7261 parm, map the parm to it's default def, and once we encounter
7262 this stmt, replace the parm with the default def. */
7263 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7264 update_stmt (parcopy_stmt);
7268 /* Declare local variables needed in CHILD_CFUN. */
7269 block = DECL_INITIAL (child_fn);
7270 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7271 /* The gimplifier could record temporaries in parallel/task block
7272 rather than in containing function's local_decls chain,
7273 which would mean cgraph missed finalizing them. Do it now. */
7274 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7275 if (TREE_CODE (t) == VAR_DECL
7276 && TREE_STATIC (t)
7277 && !DECL_EXTERNAL (t))
7278 varpool_node::finalize_decl (t);
7279 DECL_SAVED_TREE (child_fn) = NULL;
7280 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7281 gimple_set_body (child_fn, NULL);
7282 TREE_USED (block) = 1;
7284 /* Reset DECL_CONTEXT on function arguments. */
7285 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7286 DECL_CONTEXT (t) = child_fn;
7288 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7289 so that it can be moved to the child function. */
7290 gsi = gsi_last_bb (entry_bb);
7291 stmt = gsi_stmt (gsi);
7292 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7293 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7294 e = split_block (entry_bb, stmt);
7295 gsi_remove (&gsi, true);
7296 entry_bb = e->dest;
7297 edge e2 = NULL;
7298 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7299 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7300 else
7302 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7303 gcc_assert (e2->dest == region->exit);
7304 remove_edge (BRANCH_EDGE (entry_bb));
7305 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7306 gsi = gsi_last_bb (region->exit);
7307 gcc_assert (!gsi_end_p (gsi)
7308 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7309 gsi_remove (&gsi, true);
7312 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7313 if (exit_bb)
7315 gsi = gsi_last_bb (exit_bb);
7316 gcc_assert (!gsi_end_p (gsi)
7317 && (gimple_code (gsi_stmt (gsi))
7318 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7319 stmt = gimple_build_return (NULL);
7320 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7321 gsi_remove (&gsi, true);
7324 /* Move the parallel region into CHILD_CFUN. */
7326 if (gimple_in_ssa_p (cfun))
7328 init_tree_ssa (child_cfun);
7329 init_ssa_operands (child_cfun);
7330 child_cfun->gimple_df->in_ssa_p = true;
7331 block = NULL_TREE;
7333 else
7334 block = gimple_block (entry_stmt);
7336 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7337 if (exit_bb)
7338 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7339 if (e2)
7341 basic_block dest_bb = e2->dest;
7342 if (!exit_bb)
7343 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7344 remove_edge (e2);
7345 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7347 /* When the OMP expansion process cannot guarantee an up-to-date
7348 loop tree arrange for the child function to fixup loops. */
7349 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7350 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7352 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7353 num = vec_safe_length (child_cfun->local_decls);
7354 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7356 t = (*child_cfun->local_decls)[srcidx];
7357 if (DECL_CONTEXT (t) == cfun->decl)
7358 continue;
7359 if (srcidx != dstidx)
7360 (*child_cfun->local_decls)[dstidx] = t;
7361 dstidx++;
7363 if (dstidx != num)
7364 vec_safe_truncate (child_cfun->local_decls, dstidx);
7366 /* Inform the callgraph about the new function. */
7367 child_cfun->curr_properties = cfun->curr_properties;
7368 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7369 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7370 cgraph_node *node = cgraph_node::get_create (child_fn);
7371 node->parallelized_function = 1;
7372 cgraph_node::add_new_function (child_fn, true);
7374 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7375 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7377 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7378 fixed in a following pass. */
7379 push_cfun (child_cfun);
7380 if (need_asm)
7381 assign_assembler_name_if_neeeded (child_fn);
7383 if (optimize)
7384 optimize_omp_library_calls (entry_stmt);
7385 cgraph_edge::rebuild_edges ();
7387 /* Some EH regions might become dead, see PR34608. If
7388 pass_cleanup_cfg isn't the first pass to happen with the
7389 new child, these dead EH edges might cause problems.
7390 Clean them up now. */
7391 if (flag_exceptions)
7393 basic_block bb;
7394 bool changed = false;
7396 FOR_EACH_BB_FN (bb, cfun)
7397 changed |= gimple_purge_dead_eh_edges (bb);
7398 if (changed)
7399 cleanup_tree_cfg ();
7401 if (gimple_in_ssa_p (cfun))
7402 update_ssa (TODO_update_ssa);
7403 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7404 verify_loop_structure ();
7405 pop_cfun ();
7407 if (dump_file && !gimple_in_ssa_p (cfun))
7409 omp_any_child_fn_dumped = true;
7410 dump_function_header (dump_file, child_fn, dump_flags);
7411 dump_function_to_file (child_fn, dump_file, dump_flags);
7415 /* Emit a library call to launch the children threads. */
7416 if (is_cilk_for)
7417 expand_cilk_for_call (new_bb,
7418 as_a <gomp_parallel *> (entry_stmt), ws_args);
7419 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7420 expand_parallel_call (region, new_bb,
7421 as_a <gomp_parallel *> (entry_stmt), ws_args);
7422 else
7423 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7424 if (gimple_in_ssa_p (cfun))
7425 update_ssa (TODO_update_ssa_only_virtuals);
7428 /* Information about members of an OpenACC collapsed loop nest. */
7430 struct oacc_collapse
7432 tree base; /* Base value. */
7433 tree iters; /* Number of steps. */
7434 tree step; /* step size. */
7437 /* Helper for expand_oacc_for. Determine collapsed loop information.
7438 Fill in COUNTS array. Emit any initialization code before GSI.
7439 Return the calculated outer loop bound of BOUND_TYPE. */
7441 static tree
7442 expand_oacc_collapse_init (const struct omp_for_data *fd,
7443 gimple_stmt_iterator *gsi,
7444 oacc_collapse *counts, tree bound_type)
7446 tree total = build_int_cst (bound_type, 1);
7447 int ix;
7449 gcc_assert (integer_onep (fd->loop.step));
7450 gcc_assert (integer_zerop (fd->loop.n1));
7452 for (ix = 0; ix != fd->collapse; ix++)
7454 const omp_for_data_loop *loop = &fd->loops[ix];
7456 tree iter_type = TREE_TYPE (loop->v);
7457 tree diff_type = iter_type;
7458 tree plus_type = iter_type;
7460 gcc_assert (loop->cond_code == fd->loop.cond_code);
7462 if (POINTER_TYPE_P (iter_type))
7463 plus_type = sizetype;
7464 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7465 diff_type = signed_type_for (diff_type);
7467 tree b = loop->n1;
7468 tree e = loop->n2;
7469 tree s = loop->step;
7470 bool up = loop->cond_code == LT_EXPR;
7471 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7472 bool negating;
7473 tree expr;
7475 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7476 true, GSI_SAME_STMT);
7477 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7478 true, GSI_SAME_STMT);
7480 /* Convert the step, avoiding possible unsigned->signed overflow. */
7481 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7482 if (negating)
7483 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7484 s = fold_convert (diff_type, s);
7485 if (negating)
7486 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7487 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7488 true, GSI_SAME_STMT);
7490 /* Determine the range, avoiding possible unsigned->signed overflow. */
7491 negating = !up && TYPE_UNSIGNED (iter_type);
7492 expr = fold_build2 (MINUS_EXPR, plus_type,
7493 fold_convert (plus_type, negating ? b : e),
7494 fold_convert (plus_type, negating ? e : b));
7495 expr = fold_convert (diff_type, expr);
7496 if (negating)
7497 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7498 tree range = force_gimple_operand_gsi
7499 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7501 /* Determine number of iterations. */
7502 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7503 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7504 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7506 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7507 true, GSI_SAME_STMT);
7509 counts[ix].base = b;
7510 counts[ix].iters = iters;
7511 counts[ix].step = s;
7513 total = fold_build2 (MULT_EXPR, bound_type, total,
7514 fold_convert (bound_type, iters));
7517 return total;
7520 /* Emit initializers for collapsed loop members. IVAR is the outer
7521 loop iteration variable, from which collapsed loop iteration values
7522 are calculated. COUNTS array has been initialized by
7523 expand_oacc_collapse_inits. */
7525 static void
7526 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7527 gimple_stmt_iterator *gsi,
7528 const oacc_collapse *counts, tree ivar)
7530 tree ivar_type = TREE_TYPE (ivar);
7532 /* The most rapidly changing iteration variable is the innermost
7533 one. */
7534 for (int ix = fd->collapse; ix--;)
7536 const omp_for_data_loop *loop = &fd->loops[ix];
7537 const oacc_collapse *collapse = &counts[ix];
7538 tree iter_type = TREE_TYPE (loop->v);
7539 tree diff_type = TREE_TYPE (collapse->step);
7540 tree plus_type = iter_type;
7541 enum tree_code plus_code = PLUS_EXPR;
7542 tree expr;
7544 if (POINTER_TYPE_P (iter_type))
7546 plus_code = POINTER_PLUS_EXPR;
7547 plus_type = sizetype;
7550 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7551 fold_convert (ivar_type, collapse->iters));
7552 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7553 collapse->step);
7554 expr = fold_build2 (plus_code, iter_type, collapse->base,
7555 fold_convert (plus_type, expr));
7556 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7557 true, GSI_SAME_STMT);
7558 gassign *ass = gimple_build_assign (loop->v, expr);
7559 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7561 if (ix)
7563 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7564 fold_convert (ivar_type, collapse->iters));
7565 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7566 true, GSI_SAME_STMT);
7572 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7573 of the combined collapse > 1 loop constructs, generate code like:
7574 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7575 if (cond3 is <)
7576 adj = STEP3 - 1;
7577 else
7578 adj = STEP3 + 1;
7579 count3 = (adj + N32 - N31) / STEP3;
7580 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7581 if (cond2 is <)
7582 adj = STEP2 - 1;
7583 else
7584 adj = STEP2 + 1;
7585 count2 = (adj + N22 - N21) / STEP2;
7586 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7587 if (cond1 is <)
7588 adj = STEP1 - 1;
7589 else
7590 adj = STEP1 + 1;
7591 count1 = (adj + N12 - N11) / STEP1;
7592 count = count1 * count2 * count3;
7593 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7594 count = 0;
7595 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7596 of the combined loop constructs, just initialize COUNTS array
7597 from the _looptemp_ clauses. */
7599 /* NOTE: It *could* be better to moosh all of the BBs together,
7600 creating one larger BB with all the computation and the unexpected
7601 jump at the end. I.e.
7603 bool zero3, zero2, zero1, zero;
7605 zero3 = N32 c3 N31;
7606 count3 = (N32 - N31) /[cl] STEP3;
7607 zero2 = N22 c2 N21;
7608 count2 = (N22 - N21) /[cl] STEP2;
7609 zero1 = N12 c1 N11;
7610 count1 = (N12 - N11) /[cl] STEP1;
7611 zero = zero3 || zero2 || zero1;
7612 count = count1 * count2 * count3;
7613 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7615 After all, we expect the zero=false, and thus we expect to have to
7616 evaluate all of the comparison expressions, so short-circuiting
7617 oughtn't be a win. Since the condition isn't protecting a
7618 denominator, we're not concerned about divide-by-zero, so we can
7619 fully evaluate count even if a numerator turned out to be wrong.
7621 It seems like putting this all together would create much better
7622 scheduling opportunities, and less pressure on the chip's branch
7623 predictor. */
7625 static void
7626 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7627 basic_block &entry_bb, tree *counts,
7628 basic_block &zero_iter1_bb, int &first_zero_iter1,
7629 basic_block &zero_iter2_bb, int &first_zero_iter2,
7630 basic_block &l2_dom_bb)
7632 tree t, type = TREE_TYPE (fd->loop.v);
7633 edge e, ne;
7634 int i;
7636 /* Collapsed loops need work for expansion into SSA form. */
7637 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7640 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7642 gcc_assert (fd->ordered == 0);
7643 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7644 isn't supposed to be handled, as the inner loop doesn't
7645 use it. */
7646 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7647 OMP_CLAUSE__LOOPTEMP_);
7648 gcc_assert (innerc);
7649 for (i = 0; i < fd->collapse; i++)
7651 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7652 OMP_CLAUSE__LOOPTEMP_);
7653 gcc_assert (innerc);
7654 if (i)
7655 counts[i] = OMP_CLAUSE_DECL (innerc);
7656 else
7657 counts[0] = NULL_TREE;
7659 return;
7662 for (i = fd->collapse; i < fd->ordered; i++)
7664 tree itype = TREE_TYPE (fd->loops[i].v);
7665 counts[i] = NULL_TREE;
7666 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7667 fold_convert (itype, fd->loops[i].n1),
7668 fold_convert (itype, fd->loops[i].n2));
7669 if (t && integer_zerop (t))
7671 for (i = fd->collapse; i < fd->ordered; i++)
7672 counts[i] = build_int_cst (type, 0);
7673 break;
7676 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7678 tree itype = TREE_TYPE (fd->loops[i].v);
7680 if (i >= fd->collapse && counts[i])
7681 continue;
7682 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7683 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7684 fold_convert (itype, fd->loops[i].n1),
7685 fold_convert (itype, fd->loops[i].n2)))
7686 == NULL_TREE || !integer_onep (t)))
7688 gcond *cond_stmt;
7689 tree n1, n2;
7690 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7691 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7692 true, GSI_SAME_STMT);
7693 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7694 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7695 true, GSI_SAME_STMT);
7696 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7697 NULL_TREE, NULL_TREE);
7698 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7699 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7700 expand_omp_regimplify_p, NULL, NULL)
7701 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7702 expand_omp_regimplify_p, NULL, NULL))
7704 *gsi = gsi_for_stmt (cond_stmt);
7705 gimple_regimplify_operands (cond_stmt, gsi);
7707 e = split_block (entry_bb, cond_stmt);
7708 basic_block &zero_iter_bb
7709 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7710 int &first_zero_iter
7711 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7712 if (zero_iter_bb == NULL)
7714 gassign *assign_stmt;
7715 first_zero_iter = i;
7716 zero_iter_bb = create_empty_bb (entry_bb);
7717 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7718 *gsi = gsi_after_labels (zero_iter_bb);
7719 if (i < fd->collapse)
7720 assign_stmt = gimple_build_assign (fd->loop.n2,
7721 build_zero_cst (type));
7722 else
7724 counts[i] = create_tmp_reg (type, ".count");
7725 assign_stmt
7726 = gimple_build_assign (counts[i], build_zero_cst (type));
7728 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7729 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7730 entry_bb);
7732 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7733 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7734 e->flags = EDGE_TRUE_VALUE;
7735 e->probability = REG_BR_PROB_BASE - ne->probability;
7736 if (l2_dom_bb == NULL)
7737 l2_dom_bb = entry_bb;
7738 entry_bb = e->dest;
7739 *gsi = gsi_last_bb (entry_bb);
7742 if (POINTER_TYPE_P (itype))
7743 itype = signed_type_for (itype);
7744 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7745 ? -1 : 1));
7746 t = fold_build2 (PLUS_EXPR, itype,
7747 fold_convert (itype, fd->loops[i].step), t);
7748 t = fold_build2 (PLUS_EXPR, itype, t,
7749 fold_convert (itype, fd->loops[i].n2));
7750 t = fold_build2 (MINUS_EXPR, itype, t,
7751 fold_convert (itype, fd->loops[i].n1));
7752 /* ?? We could probably use CEIL_DIV_EXPR instead of
7753 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7754 generate the same code in the end because generically we
7755 don't know that the values involved must be negative for
7756 GT?? */
7757 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7758 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7759 fold_build1 (NEGATE_EXPR, itype, t),
7760 fold_build1 (NEGATE_EXPR, itype,
7761 fold_convert (itype,
7762 fd->loops[i].step)));
7763 else
7764 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7765 fold_convert (itype, fd->loops[i].step));
7766 t = fold_convert (type, t);
7767 if (TREE_CODE (t) == INTEGER_CST)
7768 counts[i] = t;
7769 else
7771 if (i < fd->collapse || i != first_zero_iter2)
7772 counts[i] = create_tmp_reg (type, ".count");
7773 expand_omp_build_assign (gsi, counts[i], t);
7775 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7777 if (i == 0)
7778 t = counts[0];
7779 else
7780 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7781 expand_omp_build_assign (gsi, fd->loop.n2, t);
7787 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7788 T = V;
7789 V3 = N31 + (T % count3) * STEP3;
7790 T = T / count3;
7791 V2 = N21 + (T % count2) * STEP2;
7792 T = T / count2;
7793 V1 = N11 + T * STEP1;
7794 if this loop doesn't have an inner loop construct combined with it.
7795 If it does have an inner loop construct combined with it and the
7796 iteration count isn't known constant, store values from counts array
7797 into its _looptemp_ temporaries instead. */
7799 static void
7800 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7801 tree *counts, gimple *inner_stmt, tree startvar)
7803 int i;
7804 if (gimple_omp_for_combined_p (fd->for_stmt))
7806 /* If fd->loop.n2 is constant, then no propagation of the counts
7807 is needed, they are constant. */
7808 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7809 return;
7811 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7812 ? gimple_omp_taskreg_clauses (inner_stmt)
7813 : gimple_omp_for_clauses (inner_stmt);
7814 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7815 isn't supposed to be handled, as the inner loop doesn't
7816 use it. */
7817 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7818 gcc_assert (innerc);
7819 for (i = 0; i < fd->collapse; i++)
7821 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7822 OMP_CLAUSE__LOOPTEMP_);
7823 gcc_assert (innerc);
7824 if (i)
7826 tree tem = OMP_CLAUSE_DECL (innerc);
7827 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7828 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7829 false, GSI_CONTINUE_LINKING);
7830 gassign *stmt = gimple_build_assign (tem, t);
7831 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7834 return;
7837 tree type = TREE_TYPE (fd->loop.v);
7838 tree tem = create_tmp_reg (type, ".tem");
7839 gassign *stmt = gimple_build_assign (tem, startvar);
7840 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7842 for (i = fd->collapse - 1; i >= 0; i--)
7844 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7845 itype = vtype;
7846 if (POINTER_TYPE_P (vtype))
7847 itype = signed_type_for (vtype);
7848 if (i != 0)
7849 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7850 else
7851 t = tem;
7852 t = fold_convert (itype, t);
7853 t = fold_build2 (MULT_EXPR, itype, t,
7854 fold_convert (itype, fd->loops[i].step));
7855 if (POINTER_TYPE_P (vtype))
7856 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7857 else
7858 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7859 t = force_gimple_operand_gsi (gsi, t,
7860 DECL_P (fd->loops[i].v)
7861 && TREE_ADDRESSABLE (fd->loops[i].v),
7862 NULL_TREE, false,
7863 GSI_CONTINUE_LINKING);
7864 stmt = gimple_build_assign (fd->loops[i].v, t);
7865 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7866 if (i != 0)
7868 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7869 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7870 false, GSI_CONTINUE_LINKING);
7871 stmt = gimple_build_assign (tem, t);
7872 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7878 /* Helper function for expand_omp_for_*. Generate code like:
7879 L10:
7880 V3 += STEP3;
7881 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7882 L11:
7883 V3 = N31;
7884 V2 += STEP2;
7885 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7886 L12:
7887 V2 = N21;
7888 V1 += STEP1;
7889 goto BODY_BB; */
7891 static basic_block
7892 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7893 basic_block body_bb)
7895 basic_block last_bb, bb, collapse_bb = NULL;
7896 int i;
7897 gimple_stmt_iterator gsi;
7898 edge e;
7899 tree t;
7900 gimple *stmt;
7902 last_bb = cont_bb;
7903 for (i = fd->collapse - 1; i >= 0; i--)
7905 tree vtype = TREE_TYPE (fd->loops[i].v);
7907 bb = create_empty_bb (last_bb);
7908 add_bb_to_loop (bb, last_bb->loop_father);
7909 gsi = gsi_start_bb (bb);
7911 if (i < fd->collapse - 1)
7913 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7914 e->probability = REG_BR_PROB_BASE / 8;
7916 t = fd->loops[i + 1].n1;
7917 t = force_gimple_operand_gsi (&gsi, t,
7918 DECL_P (fd->loops[i + 1].v)
7919 && TREE_ADDRESSABLE (fd->loops[i
7920 + 1].v),
7921 NULL_TREE, false,
7922 GSI_CONTINUE_LINKING);
7923 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7924 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7926 else
7927 collapse_bb = bb;
7929 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7931 if (POINTER_TYPE_P (vtype))
7932 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7933 else
7934 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7935 t = force_gimple_operand_gsi (&gsi, t,
7936 DECL_P (fd->loops[i].v)
7937 && TREE_ADDRESSABLE (fd->loops[i].v),
7938 NULL_TREE, false, GSI_CONTINUE_LINKING);
7939 stmt = gimple_build_assign (fd->loops[i].v, t);
7940 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7942 if (i > 0)
7944 t = fd->loops[i].n2;
7945 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7946 false, GSI_CONTINUE_LINKING);
7947 tree v = fd->loops[i].v;
7948 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7949 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7950 false, GSI_CONTINUE_LINKING);
7951 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7952 stmt = gimple_build_cond_empty (t);
7953 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7954 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7955 e->probability = REG_BR_PROB_BASE * 7 / 8;
7957 else
7958 make_edge (bb, body_bb, EDGE_FALLTHRU);
7959 last_bb = bb;
7962 return collapse_bb;
7966 /* Expand #pragma omp ordered depend(source). */
7968 static void
7969 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7970 tree *counts, location_t loc)
7972 enum built_in_function source_ix
7973 = fd->iter_type == long_integer_type_node
7974 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7975 gimple *g
7976 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7977 build_fold_addr_expr (counts[fd->ordered]));
7978 gimple_set_location (g, loc);
7979 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7982 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7984 static void
7985 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7986 tree *counts, tree c, location_t loc)
7988 auto_vec<tree, 10> args;
7989 enum built_in_function sink_ix
7990 = fd->iter_type == long_integer_type_node
7991 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7992 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7993 int i;
7994 gimple_stmt_iterator gsi2 = *gsi;
7995 bool warned_step = false;
7997 for (i = 0; i < fd->ordered; i++)
7999 off = TREE_PURPOSE (deps);
8000 if (!integer_zerop (off))
8002 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8003 || fd->loops[i].cond_code == GT_EXPR);
8004 bool forward = fd->loops[i].cond_code == LT_EXPR;
8005 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8006 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8007 "lexically later iteration");
8008 break;
8010 deps = TREE_CHAIN (deps);
8012 /* If all offsets corresponding to the collapsed loops are zero,
8013 this depend clause can be ignored. FIXME: but there is still a
8014 flush needed. We need to emit one __sync_synchronize () for it
8015 though (perhaps conditionally)? Solve this together with the
8016 conservative dependence folding optimization.
8017 if (i >= fd->collapse)
8018 return; */
8020 deps = OMP_CLAUSE_DECL (c);
8021 gsi_prev (&gsi2);
8022 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8023 edge e2 = split_block_after_labels (e1->dest);
8025 *gsi = gsi_after_labels (e1->dest);
8026 for (i = 0; i < fd->ordered; i++)
8028 tree itype = TREE_TYPE (fd->loops[i].v);
8029 if (POINTER_TYPE_P (itype))
8030 itype = sizetype;
8031 if (i)
8032 deps = TREE_CHAIN (deps);
8033 off = TREE_PURPOSE (deps);
8034 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8036 if (integer_zerop (off))
8037 t = boolean_true_node;
8038 else
8040 tree a;
8041 tree co = fold_convert_loc (loc, itype, off);
8042 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8044 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8045 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8046 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8047 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8048 co);
8050 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8051 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8052 fd->loops[i].v, co);
8053 else
8054 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8055 fd->loops[i].v, co);
8056 if (fd->loops[i].cond_code == LT_EXPR)
8058 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8059 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8060 fd->loops[i].n1);
8061 else
8062 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8063 fd->loops[i].n2);
8065 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8066 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8067 fd->loops[i].n2);
8068 else
8069 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8070 fd->loops[i].n1);
8072 if (cond)
8073 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8074 else
8075 cond = t;
8077 off = fold_convert_loc (loc, itype, off);
8079 if (fd->loops[i].cond_code == LT_EXPR
8080 ? !integer_onep (fd->loops[i].step)
8081 : !integer_minus_onep (fd->loops[i].step))
8083 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8084 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8085 fold_build1_loc (loc, NEGATE_EXPR, itype,
8086 s));
8087 else
8088 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8089 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8090 build_int_cst (itype, 0));
8091 if (integer_zerop (t) && !warned_step)
8093 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8094 "in the iteration space");
8095 warned_step = true;
8097 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8098 cond, t);
8101 if (i <= fd->collapse - 1 && fd->collapse > 1)
8102 t = fd->loop.v;
8103 else if (counts[i])
8104 t = counts[i];
8105 else
8107 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8108 fd->loops[i].v, fd->loops[i].n1);
8109 t = fold_convert_loc (loc, fd->iter_type, t);
8111 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8112 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8113 fold_build1_loc (loc, NEGATE_EXPR, itype,
8114 s));
8115 else
8116 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8117 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8118 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8119 off = fold_convert_loc (loc, fd->iter_type, off);
8120 if (i <= fd->collapse - 1 && fd->collapse > 1)
8122 if (i)
8123 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8124 off);
8125 if (i < fd->collapse - 1)
8127 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8128 counts[i]);
8129 continue;
8132 off = unshare_expr (off);
8133 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8134 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8135 true, GSI_SAME_STMT);
8136 args.safe_push (t);
8138 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8139 gimple_set_location (g, loc);
8140 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8142 *gsi = gsi_last_bb (e1->src);
8143 cond = unshare_expr (cond);
8144 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8145 GSI_CONTINUE_LINKING);
8146 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8147 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8148 e3->probability = REG_BR_PROB_BASE / 8;
8149 e1->probability = REG_BR_PROB_BASE - e3->probability;
8150 e1->flags = EDGE_TRUE_VALUE;
8151 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8153 *gsi = gsi_after_labels (e2->dest);
8156 /* Expand all #pragma omp ordered depend(source) and
8157 #pragma omp ordered depend(sink:...) constructs in the current
8158 #pragma omp for ordered(n) region. */
8160 static void
8161 expand_omp_ordered_source_sink (struct omp_region *region,
8162 struct omp_for_data *fd, tree *counts,
8163 basic_block cont_bb)
8165 struct omp_region *inner;
8166 int i;
8167 for (i = fd->collapse - 1; i < fd->ordered; i++)
8168 if (i == fd->collapse - 1 && fd->collapse > 1)
8169 counts[i] = NULL_TREE;
8170 else if (i >= fd->collapse && !cont_bb)
8171 counts[i] = build_zero_cst (fd->iter_type);
8172 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8173 && integer_onep (fd->loops[i].step))
8174 counts[i] = NULL_TREE;
8175 else
8176 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8177 tree atype
8178 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8179 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8180 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8182 for (inner = region->inner; inner; inner = inner->next)
8183 if (inner->type == GIMPLE_OMP_ORDERED)
8185 gomp_ordered *ord_stmt = inner->ord_stmt;
8186 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8187 location_t loc = gimple_location (ord_stmt);
8188 tree c;
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_SOURCE)
8192 break;
8193 if (c)
8194 expand_omp_ordered_source (&gsi, fd, counts, loc);
8195 for (c = gimple_omp_ordered_clauses (ord_stmt);
8196 c; c = OMP_CLAUSE_CHAIN (c))
8197 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8198 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8199 gsi_remove (&gsi, true);
8203 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8204 collapsed. */
8206 static basic_block
8207 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8208 basic_block cont_bb, basic_block body_bb,
8209 bool ordered_lastprivate)
8211 if (fd->ordered == fd->collapse)
8212 return cont_bb;
8214 if (!cont_bb)
8216 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8217 for (int i = fd->collapse; i < fd->ordered; i++)
8219 tree type = TREE_TYPE (fd->loops[i].v);
8220 tree n1 = fold_convert (type, fd->loops[i].n1);
8221 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8222 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8223 size_int (i - fd->collapse + 1),
8224 NULL_TREE, NULL_TREE);
8225 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8227 return NULL;
8230 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8232 tree t, type = TREE_TYPE (fd->loops[i].v);
8233 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8234 expand_omp_build_assign (&gsi, fd->loops[i].v,
8235 fold_convert (type, fd->loops[i].n1));
8236 if (counts[i])
8237 expand_omp_build_assign (&gsi, counts[i],
8238 build_zero_cst (fd->iter_type));
8239 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8240 size_int (i - fd->collapse + 1),
8241 NULL_TREE, NULL_TREE);
8242 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8243 if (!gsi_end_p (gsi))
8244 gsi_prev (&gsi);
8245 else
8246 gsi = gsi_last_bb (body_bb);
8247 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8248 basic_block new_body = e1->dest;
8249 if (body_bb == cont_bb)
8250 cont_bb = new_body;
8251 edge e2 = NULL;
8252 basic_block new_header;
8253 if (EDGE_COUNT (cont_bb->preds) > 0)
8255 gsi = gsi_last_bb (cont_bb);
8256 if (POINTER_TYPE_P (type))
8257 t = fold_build_pointer_plus (fd->loops[i].v,
8258 fold_convert (sizetype,
8259 fd->loops[i].step));
8260 else
8261 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8262 fold_convert (type, fd->loops[i].step));
8263 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8264 if (counts[i])
8266 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8267 build_int_cst (fd->iter_type, 1));
8268 expand_omp_build_assign (&gsi, counts[i], t);
8269 t = counts[i];
8271 else
8273 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8274 fd->loops[i].v, fd->loops[i].n1);
8275 t = fold_convert (fd->iter_type, t);
8276 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8277 true, GSI_SAME_STMT);
8279 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8280 size_int (i - fd->collapse + 1),
8281 NULL_TREE, NULL_TREE);
8282 expand_omp_build_assign (&gsi, aref, t);
8283 gsi_prev (&gsi);
8284 e2 = split_block (cont_bb, gsi_stmt (gsi));
8285 new_header = e2->dest;
8287 else
8288 new_header = cont_bb;
8289 gsi = gsi_after_labels (new_header);
8290 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8291 true, GSI_SAME_STMT);
8292 tree n2
8293 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8294 true, NULL_TREE, true, GSI_SAME_STMT);
8295 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8296 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8297 edge e3 = split_block (new_header, gsi_stmt (gsi));
8298 cont_bb = e3->dest;
8299 remove_edge (e1);
8300 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8301 e3->flags = EDGE_FALSE_VALUE;
8302 e3->probability = REG_BR_PROB_BASE / 8;
8303 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8304 e1->probability = REG_BR_PROB_BASE - e3->probability;
8306 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8307 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8309 if (e2)
8311 struct loop *loop = alloc_loop ();
8312 loop->header = new_header;
8313 loop->latch = e2->src;
8314 add_loop (loop, body_bb->loop_father);
8318 /* If there are any lastprivate clauses and it is possible some loops
8319 might have zero iterations, ensure all the decls are initialized,
8320 otherwise we could crash evaluating C++ class iterators with lastprivate
8321 clauses. */
8322 bool need_inits = false;
8323 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8324 if (need_inits)
8326 tree type = TREE_TYPE (fd->loops[i].v);
8327 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8328 expand_omp_build_assign (&gsi, fd->loops[i].v,
8329 fold_convert (type, fd->loops[i].n1));
8331 else
8333 tree type = TREE_TYPE (fd->loops[i].v);
8334 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8335 boolean_type_node,
8336 fold_convert (type, fd->loops[i].n1),
8337 fold_convert (type, fd->loops[i].n2));
8338 if (!integer_onep (this_cond))
8339 need_inits = true;
8342 return cont_bb;
8346 /* A subroutine of expand_omp_for. Generate code for a parallel
8347 loop with any schedule. Given parameters:
8349 for (V = N1; V cond N2; V += STEP) BODY;
8351 where COND is "<" or ">", we generate pseudocode
8353 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8354 if (more) goto L0; else goto L3;
8356 V = istart0;
8357 iend = iend0;
8359 BODY;
8360 V += STEP;
8361 if (V cond iend) goto L1; else goto L2;
8363 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8366 If this is a combined omp parallel loop, instead of the call to
8367 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8368 If this is gimple_omp_for_combined_p loop, then instead of assigning
8369 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8370 inner GIMPLE_OMP_FOR and V += STEP; and
8371 if (V cond iend) goto L1; else goto L2; are removed.
8373 For collapsed loops, given parameters:
8374 collapse(3)
8375 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8376 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8377 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8378 BODY;
8380 we generate pseudocode
8382 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8383 if (cond3 is <)
8384 adj = STEP3 - 1;
8385 else
8386 adj = STEP3 + 1;
8387 count3 = (adj + N32 - N31) / STEP3;
8388 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8389 if (cond2 is <)
8390 adj = STEP2 - 1;
8391 else
8392 adj = STEP2 + 1;
8393 count2 = (adj + N22 - N21) / STEP2;
8394 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8395 if (cond1 is <)
8396 adj = STEP1 - 1;
8397 else
8398 adj = STEP1 + 1;
8399 count1 = (adj + N12 - N11) / STEP1;
8400 count = count1 * count2 * count3;
8401 goto Z1;
8403 count = 0;
8405 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8406 if (more) goto L0; else goto L3;
8408 V = istart0;
8409 T = V;
8410 V3 = N31 + (T % count3) * STEP3;
8411 T = T / count3;
8412 V2 = N21 + (T % count2) * STEP2;
8413 T = T / count2;
8414 V1 = N11 + T * STEP1;
8415 iend = iend0;
8417 BODY;
8418 V += 1;
8419 if (V < iend) goto L10; else goto L2;
8420 L10:
8421 V3 += STEP3;
8422 if (V3 cond3 N32) goto L1; else goto L11;
8423 L11:
8424 V3 = N31;
8425 V2 += STEP2;
8426 if (V2 cond2 N22) goto L1; else goto L12;
8427 L12:
8428 V2 = N21;
8429 V1 += STEP1;
8430 goto L1;
8432 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8437 static void
8438 expand_omp_for_generic (struct omp_region *region,
8439 struct omp_for_data *fd,
8440 enum built_in_function start_fn,
8441 enum built_in_function next_fn,
8442 gimple *inner_stmt)
8444 tree type, istart0, iend0, iend;
8445 tree t, vmain, vback, bias = NULL_TREE;
8446 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8447 basic_block l2_bb = NULL, l3_bb = NULL;
8448 gimple_stmt_iterator gsi;
8449 gassign *assign_stmt;
8450 bool in_combined_parallel = is_combined_parallel (region);
8451 bool broken_loop = region->cont == NULL;
8452 edge e, ne;
8453 tree *counts = NULL;
8454 int i;
8455 bool ordered_lastprivate = false;
8457 gcc_assert (!broken_loop || !in_combined_parallel);
8458 gcc_assert (fd->iter_type == long_integer_type_node
8459 || !in_combined_parallel);
8461 entry_bb = region->entry;
8462 cont_bb = region->cont;
8463 collapse_bb = NULL;
8464 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8465 gcc_assert (broken_loop
8466 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8467 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8468 l1_bb = single_succ (l0_bb);
8469 if (!broken_loop)
8471 l2_bb = create_empty_bb (cont_bb);
8472 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8473 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8474 == l1_bb));
8475 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8477 else
8478 l2_bb = NULL;
8479 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8480 exit_bb = region->exit;
8482 gsi = gsi_last_bb (entry_bb);
8484 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8485 if (fd->ordered
8486 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8487 OMP_CLAUSE_LASTPRIVATE))
8488 ordered_lastprivate = false;
8489 if (fd->collapse > 1 || fd->ordered)
8491 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8492 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8494 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8495 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8496 zero_iter1_bb, first_zero_iter1,
8497 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8499 if (zero_iter1_bb)
8501 /* Some counts[i] vars might be uninitialized if
8502 some loop has zero iterations. But the body shouldn't
8503 be executed in that case, so just avoid uninit warnings. */
8504 for (i = first_zero_iter1;
8505 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8506 if (SSA_VAR_P (counts[i]))
8507 TREE_NO_WARNING (counts[i]) = 1;
8508 gsi_prev (&gsi);
8509 e = split_block (entry_bb, gsi_stmt (gsi));
8510 entry_bb = e->dest;
8511 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8512 gsi = gsi_last_bb (entry_bb);
8513 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8514 get_immediate_dominator (CDI_DOMINATORS,
8515 zero_iter1_bb));
8517 if (zero_iter2_bb)
8519 /* Some counts[i] vars might be uninitialized if
8520 some loop has zero iterations. But the body shouldn't
8521 be executed in that case, so just avoid uninit warnings. */
8522 for (i = first_zero_iter2; i < fd->ordered; i++)
8523 if (SSA_VAR_P (counts[i]))
8524 TREE_NO_WARNING (counts[i]) = 1;
8525 if (zero_iter1_bb)
8526 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8527 else
8529 gsi_prev (&gsi);
8530 e = split_block (entry_bb, gsi_stmt (gsi));
8531 entry_bb = e->dest;
8532 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8533 gsi = gsi_last_bb (entry_bb);
8534 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8535 get_immediate_dominator
8536 (CDI_DOMINATORS, zero_iter2_bb));
8539 if (fd->collapse == 1)
8541 counts[0] = fd->loop.n2;
8542 fd->loop = fd->loops[0];
8546 type = TREE_TYPE (fd->loop.v);
8547 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8548 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8549 TREE_ADDRESSABLE (istart0) = 1;
8550 TREE_ADDRESSABLE (iend0) = 1;
8552 /* See if we need to bias by LLONG_MIN. */
8553 if (fd->iter_type == long_long_unsigned_type_node
8554 && TREE_CODE (type) == INTEGER_TYPE
8555 && !TYPE_UNSIGNED (type)
8556 && fd->ordered == 0)
8558 tree n1, n2;
8560 if (fd->loop.cond_code == LT_EXPR)
8562 n1 = fd->loop.n1;
8563 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8565 else
8567 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8568 n2 = fd->loop.n1;
8570 if (TREE_CODE (n1) != INTEGER_CST
8571 || TREE_CODE (n2) != INTEGER_CST
8572 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8573 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8576 gimple_stmt_iterator gsif = gsi;
8577 gsi_prev (&gsif);
8579 tree arr = NULL_TREE;
8580 if (in_combined_parallel)
8582 gcc_assert (fd->ordered == 0);
8583 /* In a combined parallel loop, emit a call to
8584 GOMP_loop_foo_next. */
8585 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8586 build_fold_addr_expr (istart0),
8587 build_fold_addr_expr (iend0));
8589 else
8591 tree t0, t1, t2, t3, t4;
8592 /* If this is not a combined parallel loop, emit a call to
8593 GOMP_loop_foo_start in ENTRY_BB. */
8594 t4 = build_fold_addr_expr (iend0);
8595 t3 = build_fold_addr_expr (istart0);
8596 if (fd->ordered)
8598 t0 = build_int_cst (unsigned_type_node,
8599 fd->ordered - fd->collapse + 1);
8600 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8601 fd->ordered
8602 - fd->collapse + 1),
8603 ".omp_counts");
8604 DECL_NAMELESS (arr) = 1;
8605 TREE_ADDRESSABLE (arr) = 1;
8606 TREE_STATIC (arr) = 1;
8607 vec<constructor_elt, va_gc> *v;
8608 vec_alloc (v, fd->ordered - fd->collapse + 1);
8609 int idx;
8611 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8613 tree c;
8614 if (idx == 0 && fd->collapse > 1)
8615 c = fd->loop.n2;
8616 else
8617 c = counts[idx + fd->collapse - 1];
8618 tree purpose = size_int (idx);
8619 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8620 if (TREE_CODE (c) != INTEGER_CST)
8621 TREE_STATIC (arr) = 0;
8624 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8625 if (!TREE_STATIC (arr))
8626 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8627 void_type_node, arr),
8628 true, NULL_TREE, true, GSI_SAME_STMT);
8629 t1 = build_fold_addr_expr (arr);
8630 t2 = NULL_TREE;
8632 else
8634 t2 = fold_convert (fd->iter_type, fd->loop.step);
8635 t1 = fd->loop.n2;
8636 t0 = fd->loop.n1;
8637 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8639 tree innerc
8640 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8641 OMP_CLAUSE__LOOPTEMP_);
8642 gcc_assert (innerc);
8643 t0 = OMP_CLAUSE_DECL (innerc);
8644 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8645 OMP_CLAUSE__LOOPTEMP_);
8646 gcc_assert (innerc);
8647 t1 = OMP_CLAUSE_DECL (innerc);
8649 if (POINTER_TYPE_P (TREE_TYPE (t0))
8650 && TYPE_PRECISION (TREE_TYPE (t0))
8651 != TYPE_PRECISION (fd->iter_type))
8653 /* Avoid casting pointers to integer of a different size. */
8654 tree itype = signed_type_for (type);
8655 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8656 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8658 else
8660 t1 = fold_convert (fd->iter_type, t1);
8661 t0 = fold_convert (fd->iter_type, t0);
8663 if (bias)
8665 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8666 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8669 if (fd->iter_type == long_integer_type_node || fd->ordered)
8671 if (fd->chunk_size)
8673 t = fold_convert (fd->iter_type, fd->chunk_size);
8674 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8675 if (fd->ordered)
8676 t = build_call_expr (builtin_decl_explicit (start_fn),
8677 5, t0, t1, t, t3, t4);
8678 else
8679 t = build_call_expr (builtin_decl_explicit (start_fn),
8680 6, t0, t1, t2, t, t3, t4);
8682 else if (fd->ordered)
8683 t = build_call_expr (builtin_decl_explicit (start_fn),
8684 4, t0, t1, t3, t4);
8685 else
8686 t = build_call_expr (builtin_decl_explicit (start_fn),
8687 5, t0, t1, t2, t3, t4);
8689 else
8691 tree t5;
8692 tree c_bool_type;
8693 tree bfn_decl;
8695 /* The GOMP_loop_ull_*start functions have additional boolean
8696 argument, true for < loops and false for > loops.
8697 In Fortran, the C bool type can be different from
8698 boolean_type_node. */
8699 bfn_decl = builtin_decl_explicit (start_fn);
8700 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8701 t5 = build_int_cst (c_bool_type,
8702 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8703 if (fd->chunk_size)
8705 tree bfn_decl = builtin_decl_explicit (start_fn);
8706 t = fold_convert (fd->iter_type, fd->chunk_size);
8707 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8708 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8710 else
8711 t = build_call_expr (builtin_decl_explicit (start_fn),
8712 6, t5, t0, t1, t2, t3, t4);
8715 if (TREE_TYPE (t) != boolean_type_node)
8716 t = fold_build2 (NE_EXPR, boolean_type_node,
8717 t, build_int_cst (TREE_TYPE (t), 0));
8718 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8719 true, GSI_SAME_STMT);
8720 if (arr && !TREE_STATIC (arr))
8722 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8723 TREE_THIS_VOLATILE (clobber) = 1;
8724 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8725 GSI_SAME_STMT);
8727 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8729 /* Remove the GIMPLE_OMP_FOR statement. */
8730 gsi_remove (&gsi, true);
8732 if (gsi_end_p (gsif))
8733 gsif = gsi_after_labels (gsi_bb (gsif));
8734 gsi_next (&gsif);
8736 /* Iteration setup for sequential loop goes in L0_BB. */
8737 tree startvar = fd->loop.v;
8738 tree endvar = NULL_TREE;
8740 if (gimple_omp_for_combined_p (fd->for_stmt))
8742 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8743 && gimple_omp_for_kind (inner_stmt)
8744 == GF_OMP_FOR_KIND_SIMD);
8745 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8746 OMP_CLAUSE__LOOPTEMP_);
8747 gcc_assert (innerc);
8748 startvar = OMP_CLAUSE_DECL (innerc);
8749 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8750 OMP_CLAUSE__LOOPTEMP_);
8751 gcc_assert (innerc);
8752 endvar = OMP_CLAUSE_DECL (innerc);
8755 gsi = gsi_start_bb (l0_bb);
8756 t = istart0;
8757 if (fd->ordered && fd->collapse == 1)
8758 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8759 fold_convert (fd->iter_type, fd->loop.step));
8760 else if (bias)
8761 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8762 if (fd->ordered && fd->collapse == 1)
8764 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8765 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8766 fd->loop.n1, fold_convert (sizetype, t));
8767 else
8769 t = fold_convert (TREE_TYPE (startvar), t);
8770 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8771 fd->loop.n1, t);
8774 else
8776 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8777 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8778 t = fold_convert (TREE_TYPE (startvar), t);
8780 t = force_gimple_operand_gsi (&gsi, t,
8781 DECL_P (startvar)
8782 && TREE_ADDRESSABLE (startvar),
8783 NULL_TREE, false, GSI_CONTINUE_LINKING);
8784 assign_stmt = gimple_build_assign (startvar, t);
8785 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8787 t = iend0;
8788 if (fd->ordered && fd->collapse == 1)
8789 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8790 fold_convert (fd->iter_type, fd->loop.step));
8791 else if (bias)
8792 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8793 if (fd->ordered && fd->collapse == 1)
8795 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8796 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8797 fd->loop.n1, fold_convert (sizetype, t));
8798 else
8800 t = fold_convert (TREE_TYPE (startvar), t);
8801 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8802 fd->loop.n1, t);
8805 else
8807 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8808 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8809 t = fold_convert (TREE_TYPE (startvar), t);
8811 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8812 false, GSI_CONTINUE_LINKING);
8813 if (endvar)
8815 assign_stmt = gimple_build_assign (endvar, iend);
8816 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8817 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8818 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8819 else
8820 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8821 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8823 /* Handle linear clause adjustments. */
8824 tree itercnt = NULL_TREE;
8825 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8826 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8827 c; c = OMP_CLAUSE_CHAIN (c))
8828 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8829 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8831 tree d = OMP_CLAUSE_DECL (c);
8832 bool is_ref = is_reference (d);
8833 tree t = d, a, dest;
8834 if (is_ref)
8835 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8836 tree type = TREE_TYPE (t);
8837 if (POINTER_TYPE_P (type))
8838 type = sizetype;
8839 dest = unshare_expr (t);
8840 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8841 expand_omp_build_assign (&gsif, v, t);
8842 if (itercnt == NULL_TREE)
8844 itercnt = startvar;
8845 tree n1 = fd->loop.n1;
8846 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8848 itercnt
8849 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8850 itercnt);
8851 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8853 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8854 itercnt, n1);
8855 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8856 itercnt, fd->loop.step);
8857 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8858 NULL_TREE, false,
8859 GSI_CONTINUE_LINKING);
8861 a = fold_build2 (MULT_EXPR, type,
8862 fold_convert (type, itercnt),
8863 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8864 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8865 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8866 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8867 false, GSI_CONTINUE_LINKING);
8868 assign_stmt = gimple_build_assign (dest, t);
8869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8871 if (fd->collapse > 1)
8872 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8874 if (fd->ordered)
8876 /* Until now, counts array contained number of iterations or
8877 variable containing it for ith loop. From now on, we need
8878 those counts only for collapsed loops, and only for the 2nd
8879 till the last collapsed one. Move those one element earlier,
8880 we'll use counts[fd->collapse - 1] for the first source/sink
8881 iteration counter and so on and counts[fd->ordered]
8882 as the array holding the current counter values for
8883 depend(source). */
8884 if (fd->collapse > 1)
8885 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8886 if (broken_loop)
8888 int i;
8889 for (i = fd->collapse; i < fd->ordered; i++)
8891 tree type = TREE_TYPE (fd->loops[i].v);
8892 tree this_cond
8893 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8894 fold_convert (type, fd->loops[i].n1),
8895 fold_convert (type, fd->loops[i].n2));
8896 if (!integer_onep (this_cond))
8897 break;
8899 if (i < fd->ordered)
8901 cont_bb
8902 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8903 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8904 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8905 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8906 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8907 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8908 make_edge (cont_bb, l1_bb, 0);
8909 l2_bb = create_empty_bb (cont_bb);
8910 broken_loop = false;
8913 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8914 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8915 ordered_lastprivate);
8916 if (counts[fd->collapse - 1])
8918 gcc_assert (fd->collapse == 1);
8919 gsi = gsi_last_bb (l0_bb);
8920 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8921 istart0, true);
8922 gsi = gsi_last_bb (cont_bb);
8923 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8924 build_int_cst (fd->iter_type, 1));
8925 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8926 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8927 size_zero_node, NULL_TREE, NULL_TREE);
8928 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8929 t = counts[fd->collapse - 1];
8931 else if (fd->collapse > 1)
8932 t = fd->loop.v;
8933 else
8935 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8936 fd->loops[0].v, fd->loops[0].n1);
8937 t = fold_convert (fd->iter_type, t);
8939 gsi = gsi_last_bb (l0_bb);
8940 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8941 size_zero_node, NULL_TREE, NULL_TREE);
8942 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8943 false, GSI_CONTINUE_LINKING);
8944 expand_omp_build_assign (&gsi, aref, t, true);
8947 if (!broken_loop)
8949 /* Code to control the increment and predicate for the sequential
8950 loop goes in the CONT_BB. */
8951 gsi = gsi_last_bb (cont_bb);
8952 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8953 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8954 vmain = gimple_omp_continue_control_use (cont_stmt);
8955 vback = gimple_omp_continue_control_def (cont_stmt);
8957 if (!gimple_omp_for_combined_p (fd->for_stmt))
8959 if (POINTER_TYPE_P (type))
8960 t = fold_build_pointer_plus (vmain, fd->loop.step);
8961 else
8962 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8963 t = force_gimple_operand_gsi (&gsi, t,
8964 DECL_P (vback)
8965 && TREE_ADDRESSABLE (vback),
8966 NULL_TREE, true, GSI_SAME_STMT);
8967 assign_stmt = gimple_build_assign (vback, t);
8968 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8970 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8972 if (fd->collapse > 1)
8973 t = fd->loop.v;
8974 else
8976 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8977 fd->loops[0].v, fd->loops[0].n1);
8978 t = fold_convert (fd->iter_type, t);
8980 tree aref = build4 (ARRAY_REF, fd->iter_type,
8981 counts[fd->ordered], size_zero_node,
8982 NULL_TREE, NULL_TREE);
8983 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8984 true, GSI_SAME_STMT);
8985 expand_omp_build_assign (&gsi, aref, t);
8988 t = build2 (fd->loop.cond_code, boolean_type_node,
8989 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8990 iend);
8991 gcond *cond_stmt = gimple_build_cond_empty (t);
8992 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8995 /* Remove GIMPLE_OMP_CONTINUE. */
8996 gsi_remove (&gsi, true);
8998 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8999 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9001 /* Emit code to get the next parallel iteration in L2_BB. */
9002 gsi = gsi_start_bb (l2_bb);
9004 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9005 build_fold_addr_expr (istart0),
9006 build_fold_addr_expr (iend0));
9007 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9008 false, GSI_CONTINUE_LINKING);
9009 if (TREE_TYPE (t) != boolean_type_node)
9010 t = fold_build2 (NE_EXPR, boolean_type_node,
9011 t, build_int_cst (TREE_TYPE (t), 0));
9012 gcond *cond_stmt = gimple_build_cond_empty (t);
9013 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9016 /* Add the loop cleanup function. */
9017 gsi = gsi_last_bb (exit_bb);
9018 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9019 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9020 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9021 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9022 else
9023 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9024 gcall *call_stmt = gimple_build_call (t, 0);
9025 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9026 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9027 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9028 if (fd->ordered)
9030 tree arr = counts[fd->ordered];
9031 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9032 TREE_THIS_VOLATILE (clobber) = 1;
9033 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9034 GSI_SAME_STMT);
9036 gsi_remove (&gsi, true);
9038 /* Connect the new blocks. */
9039 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9040 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9042 if (!broken_loop)
9044 gimple_seq phis;
9046 e = find_edge (cont_bb, l3_bb);
9047 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9049 phis = phi_nodes (l3_bb);
9050 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9052 gimple *phi = gsi_stmt (gsi);
9053 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9054 PHI_ARG_DEF_FROM_EDGE (phi, e));
9056 remove_edge (e);
9058 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9059 e = find_edge (cont_bb, l1_bb);
9060 if (e == NULL)
9062 e = BRANCH_EDGE (cont_bb);
9063 gcc_assert (single_succ (e->dest) == l1_bb);
9065 if (gimple_omp_for_combined_p (fd->for_stmt))
9067 remove_edge (e);
9068 e = NULL;
9070 else if (fd->collapse > 1)
9072 remove_edge (e);
9073 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9075 else
9076 e->flags = EDGE_TRUE_VALUE;
9077 if (e)
9079 e->probability = REG_BR_PROB_BASE * 7 / 8;
9080 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9082 else
9084 e = find_edge (cont_bb, l2_bb);
9085 e->flags = EDGE_FALLTHRU;
9087 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9089 if (gimple_in_ssa_p (cfun))
9091 /* Add phis to the outer loop that connect to the phis in the inner,
9092 original loop, and move the loop entry value of the inner phi to
9093 the loop entry value of the outer phi. */
9094 gphi_iterator psi;
9095 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9097 source_location locus;
9098 gphi *nphi;
9099 gphi *exit_phi = psi.phi ();
9101 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9102 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9104 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9105 edge latch_to_l1 = find_edge (latch, l1_bb);
9106 gphi *inner_phi
9107 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9109 tree t = gimple_phi_result (exit_phi);
9110 tree new_res = copy_ssa_name (t, NULL);
9111 nphi = create_phi_node (new_res, l0_bb);
9113 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9114 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9115 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9116 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9117 add_phi_arg (nphi, t, entry_to_l0, locus);
9119 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9120 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9122 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9126 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9127 recompute_dominator (CDI_DOMINATORS, l2_bb));
9128 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9129 recompute_dominator (CDI_DOMINATORS, l3_bb));
9130 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9131 recompute_dominator (CDI_DOMINATORS, l0_bb));
9132 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9133 recompute_dominator (CDI_DOMINATORS, l1_bb));
9135 /* We enter expand_omp_for_generic with a loop. This original loop may
9136 have its own loop struct, or it may be part of an outer loop struct
9137 (which may be the fake loop). */
9138 struct loop *outer_loop = entry_bb->loop_father;
9139 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9141 add_bb_to_loop (l2_bb, outer_loop);
9143 /* We've added a new loop around the original loop. Allocate the
9144 corresponding loop struct. */
9145 struct loop *new_loop = alloc_loop ();
9146 new_loop->header = l0_bb;
9147 new_loop->latch = l2_bb;
9148 add_loop (new_loop, outer_loop);
9150 /* Allocate a loop structure for the original loop unless we already
9151 had one. */
9152 if (!orig_loop_has_loop_struct
9153 && !gimple_omp_for_combined_p (fd->for_stmt))
9155 struct loop *orig_loop = alloc_loop ();
9156 orig_loop->header = l1_bb;
9157 /* The loop may have multiple latches. */
9158 add_loop (orig_loop, new_loop);
9164 /* A subroutine of expand_omp_for. Generate code for a parallel
9165 loop with static schedule and no specified chunk size. Given
9166 parameters:
9168 for (V = N1; V cond N2; V += STEP) BODY;
9170 where COND is "<" or ">", we generate pseudocode
9172 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9173 if (cond is <)
9174 adj = STEP - 1;
9175 else
9176 adj = STEP + 1;
9177 if ((__typeof (V)) -1 > 0 && cond is >)
9178 n = -(adj + N2 - N1) / -STEP;
9179 else
9180 n = (adj + N2 - N1) / STEP;
9181 q = n / nthreads;
9182 tt = n % nthreads;
9183 if (threadid < tt) goto L3; else goto L4;
9185 tt = 0;
9186 q = q + 1;
9188 s0 = q * threadid + tt;
9189 e0 = s0 + q;
9190 V = s0 * STEP + N1;
9191 if (s0 >= e0) goto L2; else goto L0;
9193 e = e0 * STEP + N1;
9195 BODY;
9196 V += STEP;
9197 if (V cond e) goto L1;
9201 static void
9202 expand_omp_for_static_nochunk (struct omp_region *region,
9203 struct omp_for_data *fd,
9204 gimple *inner_stmt)
9206 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9207 tree type, itype, vmain, vback;
9208 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9209 basic_block body_bb, cont_bb, collapse_bb = NULL;
9210 basic_block fin_bb;
9211 gimple_stmt_iterator gsi;
9212 edge ep;
9213 bool broken_loop = region->cont == NULL;
9214 tree *counts = NULL;
9215 tree n1, n2, step;
9217 itype = type = TREE_TYPE (fd->loop.v);
9218 if (POINTER_TYPE_P (type))
9219 itype = signed_type_for (type);
9221 entry_bb = region->entry;
9222 cont_bb = region->cont;
9223 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9224 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9225 gcc_assert (broken_loop
9226 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9227 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9228 body_bb = single_succ (seq_start_bb);
9229 if (!broken_loop)
9231 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9232 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9233 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9235 exit_bb = region->exit;
9237 /* Iteration space partitioning goes in ENTRY_BB. */
9238 gsi = gsi_last_bb (entry_bb);
9239 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9241 if (fd->collapse > 1)
9243 int first_zero_iter = -1, dummy = -1;
9244 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9246 counts = XALLOCAVEC (tree, fd->collapse);
9247 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9248 fin_bb, first_zero_iter,
9249 dummy_bb, dummy, l2_dom_bb);
9250 t = NULL_TREE;
9252 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9253 t = integer_one_node;
9254 else
9255 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9256 fold_convert (type, fd->loop.n1),
9257 fold_convert (type, fd->loop.n2));
9258 if (fd->collapse == 1
9259 && TYPE_UNSIGNED (type)
9260 && (t == NULL_TREE || !integer_onep (t)))
9262 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9263 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9264 true, GSI_SAME_STMT);
9265 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9266 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9267 true, GSI_SAME_STMT);
9268 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9269 NULL_TREE, NULL_TREE);
9270 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9271 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9272 expand_omp_regimplify_p, NULL, NULL)
9273 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9274 expand_omp_regimplify_p, NULL, NULL))
9276 gsi = gsi_for_stmt (cond_stmt);
9277 gimple_regimplify_operands (cond_stmt, &gsi);
9279 ep = split_block (entry_bb, cond_stmt);
9280 ep->flags = EDGE_TRUE_VALUE;
9281 entry_bb = ep->dest;
9282 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9283 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9284 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9285 if (gimple_in_ssa_p (cfun))
9287 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9288 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9289 !gsi_end_p (gpi); gsi_next (&gpi))
9291 gphi *phi = gpi.phi ();
9292 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9293 ep, UNKNOWN_LOCATION);
9296 gsi = gsi_last_bb (entry_bb);
9299 switch (gimple_omp_for_kind (fd->for_stmt))
9301 case GF_OMP_FOR_KIND_FOR:
9302 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9303 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9304 break;
9305 case GF_OMP_FOR_KIND_DISTRIBUTE:
9306 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9307 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9308 break;
9309 default:
9310 gcc_unreachable ();
9312 nthreads = build_call_expr (nthreads, 0);
9313 nthreads = fold_convert (itype, nthreads);
9314 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9315 true, GSI_SAME_STMT);
9316 threadid = build_call_expr (threadid, 0);
9317 threadid = fold_convert (itype, threadid);
9318 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9319 true, GSI_SAME_STMT);
9321 n1 = fd->loop.n1;
9322 n2 = fd->loop.n2;
9323 step = fd->loop.step;
9324 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9326 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9327 OMP_CLAUSE__LOOPTEMP_);
9328 gcc_assert (innerc);
9329 n1 = OMP_CLAUSE_DECL (innerc);
9330 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9331 OMP_CLAUSE__LOOPTEMP_);
9332 gcc_assert (innerc);
9333 n2 = OMP_CLAUSE_DECL (innerc);
9335 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9336 true, NULL_TREE, true, GSI_SAME_STMT);
9337 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9338 true, NULL_TREE, true, GSI_SAME_STMT);
9339 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9340 true, NULL_TREE, true, GSI_SAME_STMT);
9342 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9343 t = fold_build2 (PLUS_EXPR, itype, step, t);
9344 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9345 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9346 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9347 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9348 fold_build1 (NEGATE_EXPR, itype, t),
9349 fold_build1 (NEGATE_EXPR, itype, step));
9350 else
9351 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9352 t = fold_convert (itype, t);
9353 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9355 q = create_tmp_reg (itype, "q");
9356 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9357 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9358 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9360 tt = create_tmp_reg (itype, "tt");
9361 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9362 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9363 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9365 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9366 gcond *cond_stmt = gimple_build_cond_empty (t);
9367 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9369 second_bb = split_block (entry_bb, cond_stmt)->dest;
9370 gsi = gsi_last_bb (second_bb);
9371 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9373 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9374 GSI_SAME_STMT);
9375 gassign *assign_stmt
9376 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9377 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9379 third_bb = split_block (second_bb, assign_stmt)->dest;
9380 gsi = gsi_last_bb (third_bb);
9381 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9383 t = build2 (MULT_EXPR, itype, q, threadid);
9384 t = build2 (PLUS_EXPR, itype, t, tt);
9385 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9387 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9388 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9390 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9391 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9393 /* Remove the GIMPLE_OMP_FOR statement. */
9394 gsi_remove (&gsi, true);
9396 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9397 gsi = gsi_start_bb (seq_start_bb);
9399 tree startvar = fd->loop.v;
9400 tree endvar = NULL_TREE;
9402 if (gimple_omp_for_combined_p (fd->for_stmt))
9404 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9405 ? gimple_omp_parallel_clauses (inner_stmt)
9406 : gimple_omp_for_clauses (inner_stmt);
9407 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9408 gcc_assert (innerc);
9409 startvar = OMP_CLAUSE_DECL (innerc);
9410 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9411 OMP_CLAUSE__LOOPTEMP_);
9412 gcc_assert (innerc);
9413 endvar = OMP_CLAUSE_DECL (innerc);
9414 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9415 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9417 int i;
9418 for (i = 1; i < fd->collapse; i++)
9420 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9421 OMP_CLAUSE__LOOPTEMP_);
9422 gcc_assert (innerc);
9424 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9425 OMP_CLAUSE__LOOPTEMP_);
9426 if (innerc)
9428 /* If needed (distribute parallel for with lastprivate),
9429 propagate down the total number of iterations. */
9430 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9431 fd->loop.n2);
9432 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9433 GSI_CONTINUE_LINKING);
9434 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9435 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9439 t = fold_convert (itype, s0);
9440 t = fold_build2 (MULT_EXPR, itype, t, step);
9441 if (POINTER_TYPE_P (type))
9442 t = fold_build_pointer_plus (n1, t);
9443 else
9444 t = fold_build2 (PLUS_EXPR, type, t, n1);
9445 t = fold_convert (TREE_TYPE (startvar), t);
9446 t = force_gimple_operand_gsi (&gsi, t,
9447 DECL_P (startvar)
9448 && TREE_ADDRESSABLE (startvar),
9449 NULL_TREE, false, GSI_CONTINUE_LINKING);
9450 assign_stmt = gimple_build_assign (startvar, t);
9451 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9453 t = fold_convert (itype, e0);
9454 t = fold_build2 (MULT_EXPR, itype, t, step);
9455 if (POINTER_TYPE_P (type))
9456 t = fold_build_pointer_plus (n1, t);
9457 else
9458 t = fold_build2 (PLUS_EXPR, type, t, n1);
9459 t = fold_convert (TREE_TYPE (startvar), t);
9460 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9461 false, GSI_CONTINUE_LINKING);
9462 if (endvar)
9464 assign_stmt = gimple_build_assign (endvar, e);
9465 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9466 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9467 assign_stmt = gimple_build_assign (fd->loop.v, e);
9468 else
9469 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9470 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9472 /* Handle linear clause adjustments. */
9473 tree itercnt = NULL_TREE;
9474 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9475 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9476 c; c = OMP_CLAUSE_CHAIN (c))
9477 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9478 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9480 tree d = OMP_CLAUSE_DECL (c);
9481 bool is_ref = is_reference (d);
9482 tree t = d, a, dest;
9483 if (is_ref)
9484 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9485 if (itercnt == NULL_TREE)
9487 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9489 itercnt = fold_build2 (MINUS_EXPR, itype,
9490 fold_convert (itype, n1),
9491 fold_convert (itype, fd->loop.n1));
9492 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9493 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9494 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9495 NULL_TREE, false,
9496 GSI_CONTINUE_LINKING);
9498 else
9499 itercnt = s0;
9501 tree type = TREE_TYPE (t);
9502 if (POINTER_TYPE_P (type))
9503 type = sizetype;
9504 a = fold_build2 (MULT_EXPR, type,
9505 fold_convert (type, itercnt),
9506 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9507 dest = unshare_expr (t);
9508 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9509 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9510 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9511 false, GSI_CONTINUE_LINKING);
9512 assign_stmt = gimple_build_assign (dest, t);
9513 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9515 if (fd->collapse > 1)
9516 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9518 if (!broken_loop)
9520 /* The code controlling the sequential loop replaces the
9521 GIMPLE_OMP_CONTINUE. */
9522 gsi = gsi_last_bb (cont_bb);
9523 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9524 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9525 vmain = gimple_omp_continue_control_use (cont_stmt);
9526 vback = gimple_omp_continue_control_def (cont_stmt);
9528 if (!gimple_omp_for_combined_p (fd->for_stmt))
9530 if (POINTER_TYPE_P (type))
9531 t = fold_build_pointer_plus (vmain, step);
9532 else
9533 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9534 t = force_gimple_operand_gsi (&gsi, t,
9535 DECL_P (vback)
9536 && TREE_ADDRESSABLE (vback),
9537 NULL_TREE, true, GSI_SAME_STMT);
9538 assign_stmt = gimple_build_assign (vback, t);
9539 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9541 t = build2 (fd->loop.cond_code, boolean_type_node,
9542 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9543 ? t : vback, e);
9544 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9547 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9548 gsi_remove (&gsi, true);
9550 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9551 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9554 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9555 gsi = gsi_last_bb (exit_bb);
9556 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9558 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9559 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9561 gsi_remove (&gsi, true);
9563 /* Connect all the blocks. */
9564 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9565 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9566 ep = find_edge (entry_bb, second_bb);
9567 ep->flags = EDGE_TRUE_VALUE;
9568 ep->probability = REG_BR_PROB_BASE / 4;
9569 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9570 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9572 if (!broken_loop)
9574 ep = find_edge (cont_bb, body_bb);
9575 if (ep == NULL)
9577 ep = BRANCH_EDGE (cont_bb);
9578 gcc_assert (single_succ (ep->dest) == body_bb);
9580 if (gimple_omp_for_combined_p (fd->for_stmt))
9582 remove_edge (ep);
9583 ep = NULL;
9585 else if (fd->collapse > 1)
9587 remove_edge (ep);
9588 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9590 else
9591 ep->flags = EDGE_TRUE_VALUE;
9592 find_edge (cont_bb, fin_bb)->flags
9593 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9596 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9597 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9598 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9600 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9601 recompute_dominator (CDI_DOMINATORS, body_bb));
9602 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9603 recompute_dominator (CDI_DOMINATORS, fin_bb));
9605 struct loop *loop = body_bb->loop_father;
9606 if (loop != entry_bb->loop_father)
9608 gcc_assert (loop->header == body_bb);
9609 gcc_assert (broken_loop
9610 || loop->latch == region->cont
9611 || single_pred (loop->latch) == region->cont);
9612 return;
9615 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9617 loop = alloc_loop ();
9618 loop->header = body_bb;
9619 if (collapse_bb == NULL)
9620 loop->latch = cont_bb;
9621 add_loop (loop, body_bb->loop_father);
9625 /* Return phi in E->DEST with ARG on edge E. */
9627 static gphi *
9628 find_phi_with_arg_on_edge (tree arg, edge e)
9630 basic_block bb = e->dest;
9632 for (gphi_iterator gpi = gsi_start_phis (bb);
9633 !gsi_end_p (gpi);
9634 gsi_next (&gpi))
9636 gphi *phi = gpi.phi ();
9637 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9638 return phi;
9641 return NULL;
9644 /* A subroutine of expand_omp_for. Generate code for a parallel
9645 loop with static schedule and a specified chunk size. Given
9646 parameters:
9648 for (V = N1; V cond N2; V += STEP) BODY;
9650 where COND is "<" or ">", we generate pseudocode
9652 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9653 if (cond is <)
9654 adj = STEP - 1;
9655 else
9656 adj = STEP + 1;
9657 if ((__typeof (V)) -1 > 0 && cond is >)
9658 n = -(adj + N2 - N1) / -STEP;
9659 else
9660 n = (adj + N2 - N1) / STEP;
9661 trip = 0;
9662 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9663 here so that V is defined
9664 if the loop is not entered
9666 s0 = (trip * nthreads + threadid) * CHUNK;
9667 e0 = min(s0 + CHUNK, n);
9668 if (s0 < n) goto L1; else goto L4;
9670 V = s0 * STEP + N1;
9671 e = e0 * STEP + N1;
9673 BODY;
9674 V += STEP;
9675 if (V cond e) goto L2; else goto L3;
9677 trip += 1;
9678 goto L0;
9682 static void
9683 expand_omp_for_static_chunk (struct omp_region *region,
9684 struct omp_for_data *fd, gimple *inner_stmt)
9686 tree n, s0, e0, e, t;
9687 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9688 tree type, itype, vmain, vback, vextra;
9689 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9690 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9691 gimple_stmt_iterator gsi;
9692 edge se;
9693 bool broken_loop = region->cont == NULL;
9694 tree *counts = NULL;
9695 tree n1, n2, step;
9697 itype = type = TREE_TYPE (fd->loop.v);
9698 if (POINTER_TYPE_P (type))
9699 itype = signed_type_for (type);
9701 entry_bb = region->entry;
9702 se = split_block (entry_bb, last_stmt (entry_bb));
9703 entry_bb = se->src;
9704 iter_part_bb = se->dest;
9705 cont_bb = region->cont;
9706 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9707 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9708 gcc_assert (broken_loop
9709 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9710 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9711 body_bb = single_succ (seq_start_bb);
9712 if (!broken_loop)
9714 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9715 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9716 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9717 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9719 exit_bb = region->exit;
9721 /* Trip and adjustment setup goes in ENTRY_BB. */
9722 gsi = gsi_last_bb (entry_bb);
9723 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9725 if (fd->collapse > 1)
9727 int first_zero_iter = -1, dummy = -1;
9728 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9730 counts = XALLOCAVEC (tree, fd->collapse);
9731 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9732 fin_bb, first_zero_iter,
9733 dummy_bb, dummy, l2_dom_bb);
9734 t = NULL_TREE;
9736 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9737 t = integer_one_node;
9738 else
9739 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9740 fold_convert (type, fd->loop.n1),
9741 fold_convert (type, fd->loop.n2));
9742 if (fd->collapse == 1
9743 && TYPE_UNSIGNED (type)
9744 && (t == NULL_TREE || !integer_onep (t)))
9746 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9747 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9748 true, GSI_SAME_STMT);
9749 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9750 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9751 true, GSI_SAME_STMT);
9752 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9753 NULL_TREE, NULL_TREE);
9754 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9755 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9756 expand_omp_regimplify_p, NULL, NULL)
9757 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9758 expand_omp_regimplify_p, NULL, NULL))
9760 gsi = gsi_for_stmt (cond_stmt);
9761 gimple_regimplify_operands (cond_stmt, &gsi);
9763 se = split_block (entry_bb, cond_stmt);
9764 se->flags = EDGE_TRUE_VALUE;
9765 entry_bb = se->dest;
9766 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9767 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9768 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9769 if (gimple_in_ssa_p (cfun))
9771 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9772 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9773 !gsi_end_p (gpi); gsi_next (&gpi))
9775 gphi *phi = gpi.phi ();
9776 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9777 se, UNKNOWN_LOCATION);
9780 gsi = gsi_last_bb (entry_bb);
9783 switch (gimple_omp_for_kind (fd->for_stmt))
9785 case GF_OMP_FOR_KIND_FOR:
9786 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9787 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9788 break;
9789 case GF_OMP_FOR_KIND_DISTRIBUTE:
9790 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9791 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9792 break;
9793 default:
9794 gcc_unreachable ();
9796 nthreads = build_call_expr (nthreads, 0);
9797 nthreads = fold_convert (itype, nthreads);
9798 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9799 true, GSI_SAME_STMT);
9800 threadid = build_call_expr (threadid, 0);
9801 threadid = fold_convert (itype, threadid);
9802 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9803 true, GSI_SAME_STMT);
9805 n1 = fd->loop.n1;
9806 n2 = fd->loop.n2;
9807 step = fd->loop.step;
9808 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9810 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9811 OMP_CLAUSE__LOOPTEMP_);
9812 gcc_assert (innerc);
9813 n1 = OMP_CLAUSE_DECL (innerc);
9814 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9815 OMP_CLAUSE__LOOPTEMP_);
9816 gcc_assert (innerc);
9817 n2 = OMP_CLAUSE_DECL (innerc);
9819 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9820 true, NULL_TREE, true, GSI_SAME_STMT);
9821 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9822 true, NULL_TREE, true, GSI_SAME_STMT);
9823 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9824 true, NULL_TREE, true, GSI_SAME_STMT);
9825 tree chunk_size = fold_convert (itype, fd->chunk_size);
9826 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9827 chunk_size
9828 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9829 GSI_SAME_STMT);
9831 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9832 t = fold_build2 (PLUS_EXPR, itype, step, t);
9833 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9834 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9835 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9836 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9837 fold_build1 (NEGATE_EXPR, itype, t),
9838 fold_build1 (NEGATE_EXPR, itype, step));
9839 else
9840 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9841 t = fold_convert (itype, t);
9842 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9843 true, GSI_SAME_STMT);
9845 trip_var = create_tmp_reg (itype, ".trip");
9846 if (gimple_in_ssa_p (cfun))
9848 trip_init = make_ssa_name (trip_var);
9849 trip_main = make_ssa_name (trip_var);
9850 trip_back = make_ssa_name (trip_var);
9852 else
9854 trip_init = trip_var;
9855 trip_main = trip_var;
9856 trip_back = trip_var;
9859 gassign *assign_stmt
9860 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9861 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9863 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9864 t = fold_build2 (MULT_EXPR, itype, t, step);
9865 if (POINTER_TYPE_P (type))
9866 t = fold_build_pointer_plus (n1, t);
9867 else
9868 t = fold_build2 (PLUS_EXPR, type, t, n1);
9869 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9870 true, GSI_SAME_STMT);
9872 /* Remove the GIMPLE_OMP_FOR. */
9873 gsi_remove (&gsi, true);
9875 gimple_stmt_iterator gsif = gsi;
9877 /* Iteration space partitioning goes in ITER_PART_BB. */
9878 gsi = gsi_last_bb (iter_part_bb);
9880 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9881 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9882 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9883 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9884 false, GSI_CONTINUE_LINKING);
9886 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9887 t = fold_build2 (MIN_EXPR, itype, t, n);
9888 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9889 false, GSI_CONTINUE_LINKING);
9891 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9892 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9894 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9895 gsi = gsi_start_bb (seq_start_bb);
9897 tree startvar = fd->loop.v;
9898 tree endvar = NULL_TREE;
9900 if (gimple_omp_for_combined_p (fd->for_stmt))
9902 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9903 ? gimple_omp_parallel_clauses (inner_stmt)
9904 : gimple_omp_for_clauses (inner_stmt);
9905 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9906 gcc_assert (innerc);
9907 startvar = OMP_CLAUSE_DECL (innerc);
9908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9909 OMP_CLAUSE__LOOPTEMP_);
9910 gcc_assert (innerc);
9911 endvar = OMP_CLAUSE_DECL (innerc);
9912 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9913 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9915 int i;
9916 for (i = 1; i < fd->collapse; i++)
9918 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9919 OMP_CLAUSE__LOOPTEMP_);
9920 gcc_assert (innerc);
9922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9923 OMP_CLAUSE__LOOPTEMP_);
9924 if (innerc)
9926 /* If needed (distribute parallel for with lastprivate),
9927 propagate down the total number of iterations. */
9928 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9929 fd->loop.n2);
9930 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9931 GSI_CONTINUE_LINKING);
9932 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9933 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9938 t = fold_convert (itype, s0);
9939 t = fold_build2 (MULT_EXPR, itype, t, step);
9940 if (POINTER_TYPE_P (type))
9941 t = fold_build_pointer_plus (n1, t);
9942 else
9943 t = fold_build2 (PLUS_EXPR, type, t, n1);
9944 t = fold_convert (TREE_TYPE (startvar), t);
9945 t = force_gimple_operand_gsi (&gsi, t,
9946 DECL_P (startvar)
9947 && TREE_ADDRESSABLE (startvar),
9948 NULL_TREE, false, GSI_CONTINUE_LINKING);
9949 assign_stmt = gimple_build_assign (startvar, t);
9950 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9952 t = fold_convert (itype, e0);
9953 t = fold_build2 (MULT_EXPR, itype, t, step);
9954 if (POINTER_TYPE_P (type))
9955 t = fold_build_pointer_plus (n1, t);
9956 else
9957 t = fold_build2 (PLUS_EXPR, type, t, n1);
9958 t = fold_convert (TREE_TYPE (startvar), t);
9959 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9960 false, GSI_CONTINUE_LINKING);
9961 if (endvar)
9963 assign_stmt = gimple_build_assign (endvar, e);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9966 assign_stmt = gimple_build_assign (fd->loop.v, e);
9967 else
9968 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9969 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9971 /* Handle linear clause adjustments. */
9972 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9973 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9974 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9975 c; c = OMP_CLAUSE_CHAIN (c))
9976 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9977 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9979 tree d = OMP_CLAUSE_DECL (c);
9980 bool is_ref = is_reference (d);
9981 tree t = d, a, dest;
9982 if (is_ref)
9983 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9984 tree type = TREE_TYPE (t);
9985 if (POINTER_TYPE_P (type))
9986 type = sizetype;
9987 dest = unshare_expr (t);
9988 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9989 expand_omp_build_assign (&gsif, v, t);
9990 if (itercnt == NULL_TREE)
9992 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9994 itercntbias
9995 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9996 fold_convert (itype, fd->loop.n1));
9997 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9998 itercntbias, step);
9999 itercntbias
10000 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10001 NULL_TREE, true,
10002 GSI_SAME_STMT);
10003 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10004 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10005 NULL_TREE, false,
10006 GSI_CONTINUE_LINKING);
10008 else
10009 itercnt = s0;
10011 a = fold_build2 (MULT_EXPR, type,
10012 fold_convert (type, itercnt),
10013 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10014 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10015 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10016 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10017 false, GSI_CONTINUE_LINKING);
10018 assign_stmt = gimple_build_assign (dest, t);
10019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10021 if (fd->collapse > 1)
10022 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10024 if (!broken_loop)
10026 /* The code controlling the sequential loop goes in CONT_BB,
10027 replacing the GIMPLE_OMP_CONTINUE. */
10028 gsi = gsi_last_bb (cont_bb);
10029 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10030 vmain = gimple_omp_continue_control_use (cont_stmt);
10031 vback = gimple_omp_continue_control_def (cont_stmt);
10033 if (!gimple_omp_for_combined_p (fd->for_stmt))
10035 if (POINTER_TYPE_P (type))
10036 t = fold_build_pointer_plus (vmain, step);
10037 else
10038 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10039 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10040 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10041 true, GSI_SAME_STMT);
10042 assign_stmt = gimple_build_assign (vback, t);
10043 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10045 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10046 t = build2 (EQ_EXPR, boolean_type_node,
10047 build_int_cst (itype, 0),
10048 build_int_cst (itype, 1));
10049 else
10050 t = build2 (fd->loop.cond_code, boolean_type_node,
10051 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10052 ? t : vback, e);
10053 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10056 /* Remove GIMPLE_OMP_CONTINUE. */
10057 gsi_remove (&gsi, true);
10059 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10060 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10062 /* Trip update code goes into TRIP_UPDATE_BB. */
10063 gsi = gsi_start_bb (trip_update_bb);
10065 t = build_int_cst (itype, 1);
10066 t = build2 (PLUS_EXPR, itype, trip_main, t);
10067 assign_stmt = gimple_build_assign (trip_back, t);
10068 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10071 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10072 gsi = gsi_last_bb (exit_bb);
10073 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10075 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10076 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10078 gsi_remove (&gsi, true);
10080 /* Connect the new blocks. */
10081 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10082 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10084 if (!broken_loop)
10086 se = find_edge (cont_bb, body_bb);
10087 if (se == NULL)
10089 se = BRANCH_EDGE (cont_bb);
10090 gcc_assert (single_succ (se->dest) == body_bb);
10092 if (gimple_omp_for_combined_p (fd->for_stmt))
10094 remove_edge (se);
10095 se = NULL;
10097 else if (fd->collapse > 1)
10099 remove_edge (se);
10100 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10102 else
10103 se->flags = EDGE_TRUE_VALUE;
10104 find_edge (cont_bb, trip_update_bb)->flags
10105 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10107 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10110 if (gimple_in_ssa_p (cfun))
10112 gphi_iterator psi;
10113 gphi *phi;
10114 edge re, ene;
10115 edge_var_map *vm;
10116 size_t i;
10118 gcc_assert (fd->collapse == 1 && !broken_loop);
10120 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10121 remove arguments of the phi nodes in fin_bb. We need to create
10122 appropriate phi nodes in iter_part_bb instead. */
10123 se = find_edge (iter_part_bb, fin_bb);
10124 re = single_succ_edge (trip_update_bb);
10125 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10126 ene = single_succ_edge (entry_bb);
10128 psi = gsi_start_phis (fin_bb);
10129 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10130 gsi_next (&psi), ++i)
10132 gphi *nphi;
10133 source_location locus;
10135 phi = psi.phi ();
10136 t = gimple_phi_result (phi);
10137 gcc_assert (t == redirect_edge_var_map_result (vm));
10139 if (!single_pred_p (fin_bb))
10140 t = copy_ssa_name (t, phi);
10142 nphi = create_phi_node (t, iter_part_bb);
10144 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10145 locus = gimple_phi_arg_location_from_edge (phi, se);
10147 /* A special case -- fd->loop.v is not yet computed in
10148 iter_part_bb, we need to use vextra instead. */
10149 if (t == fd->loop.v)
10150 t = vextra;
10151 add_phi_arg (nphi, t, ene, locus);
10152 locus = redirect_edge_var_map_location (vm);
10153 tree back_arg = redirect_edge_var_map_def (vm);
10154 add_phi_arg (nphi, back_arg, re, locus);
10155 edge ce = find_edge (cont_bb, body_bb);
10156 if (ce == NULL)
10158 ce = BRANCH_EDGE (cont_bb);
10159 gcc_assert (single_succ (ce->dest) == body_bb);
10160 ce = single_succ_edge (ce->dest);
10162 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10163 gcc_assert (inner_loop_phi != NULL);
10164 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10165 find_edge (seq_start_bb, body_bb), locus);
10167 if (!single_pred_p (fin_bb))
10168 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10170 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10171 redirect_edge_var_map_clear (re);
10172 if (single_pred_p (fin_bb))
10173 while (1)
10175 psi = gsi_start_phis (fin_bb);
10176 if (gsi_end_p (psi))
10177 break;
10178 remove_phi_node (&psi, false);
10181 /* Make phi node for trip. */
10182 phi = create_phi_node (trip_main, iter_part_bb);
10183 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10184 UNKNOWN_LOCATION);
10185 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10186 UNKNOWN_LOCATION);
10189 if (!broken_loop)
10190 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10191 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10192 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10193 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10194 recompute_dominator (CDI_DOMINATORS, fin_bb));
10195 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10196 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10197 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10198 recompute_dominator (CDI_DOMINATORS, body_bb));
10200 if (!broken_loop)
10202 struct loop *loop = body_bb->loop_father;
10203 struct loop *trip_loop = alloc_loop ();
10204 trip_loop->header = iter_part_bb;
10205 trip_loop->latch = trip_update_bb;
10206 add_loop (trip_loop, iter_part_bb->loop_father);
10208 if (loop != entry_bb->loop_father)
10210 gcc_assert (loop->header == body_bb);
10211 gcc_assert (loop->latch == region->cont
10212 || single_pred (loop->latch) == region->cont);
10213 trip_loop->inner = loop;
10214 return;
10217 if (!gimple_omp_for_combined_p (fd->for_stmt))
10219 loop = alloc_loop ();
10220 loop->header = body_bb;
10221 if (collapse_bb == NULL)
10222 loop->latch = cont_bb;
10223 add_loop (loop, trip_loop);
10228 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10229 Given parameters:
10230 for (V = N1; V cond N2; V += STEP) BODY;
10232 where COND is "<" or ">" or "!=", we generate pseudocode
10234 for (ind_var = low; ind_var < high; ind_var++)
10236 V = n1 + (ind_var * STEP)
10238 <BODY>
10241 In the above pseudocode, low and high are function parameters of the
10242 child function. In the function below, we are inserting a temp.
10243 variable that will be making a call to two OMP functions that will not be
10244 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10245 with _Cilk_for). These functions are replaced with low and high
10246 by the function that handles taskreg. */
10249 static void
10250 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10252 bool broken_loop = region->cont == NULL;
10253 basic_block entry_bb = region->entry;
10254 basic_block cont_bb = region->cont;
10256 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10257 gcc_assert (broken_loop
10258 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10259 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10260 basic_block l1_bb, l2_bb;
10262 if (!broken_loop)
10264 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10265 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10266 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10267 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10269 else
10271 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10272 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10273 l2_bb = single_succ (l1_bb);
10275 basic_block exit_bb = region->exit;
10276 basic_block l2_dom_bb = NULL;
10278 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10280 /* Below statements until the "tree high_val = ..." are pseudo statements
10281 used to pass information to be used by expand_omp_taskreg.
10282 low_val and high_val will be replaced by the __low and __high
10283 parameter from the child function.
10285 The call_exprs part is a place-holder, it is mainly used
10286 to distinctly identify to the top-level part that this is
10287 where we should put low and high (reasoning given in header
10288 comment). */
10290 tree child_fndecl
10291 = gimple_omp_parallel_child_fn (
10292 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10293 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10294 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10296 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10297 high_val = t;
10298 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10299 low_val = t;
10301 gcc_assert (low_val && high_val);
10303 tree type = TREE_TYPE (low_val);
10304 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10305 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10307 /* Not needed in SSA form right now. */
10308 gcc_assert (!gimple_in_ssa_p (cfun));
10309 if (l2_dom_bb == NULL)
10310 l2_dom_bb = l1_bb;
10312 tree n1 = low_val;
10313 tree n2 = high_val;
10315 gimple *stmt = gimple_build_assign (ind_var, n1);
10317 /* Replace the GIMPLE_OMP_FOR statement. */
10318 gsi_replace (&gsi, stmt, true);
10320 if (!broken_loop)
10322 /* Code to control the increment goes in the CONT_BB. */
10323 gsi = gsi_last_bb (cont_bb);
10324 stmt = gsi_stmt (gsi);
10325 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10326 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10327 build_one_cst (type));
10329 /* Replace GIMPLE_OMP_CONTINUE. */
10330 gsi_replace (&gsi, stmt, true);
10333 /* Emit the condition in L1_BB. */
10334 gsi = gsi_after_labels (l1_bb);
10335 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10336 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10337 fd->loop.step);
10338 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10339 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10340 fd->loop.n1, fold_convert (sizetype, t));
10341 else
10342 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10343 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10344 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10345 expand_omp_build_assign (&gsi, fd->loop.v, t);
10347 /* The condition is always '<' since the runtime will fill in the low
10348 and high values. */
10349 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10350 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10352 /* Remove GIMPLE_OMP_RETURN. */
10353 gsi = gsi_last_bb (exit_bb);
10354 gsi_remove (&gsi, true);
10356 /* Connect the new blocks. */
10357 remove_edge (FALLTHRU_EDGE (entry_bb));
10359 edge e, ne;
10360 if (!broken_loop)
10362 remove_edge (BRANCH_EDGE (entry_bb));
10363 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10365 e = BRANCH_EDGE (l1_bb);
10366 ne = FALLTHRU_EDGE (l1_bb);
10367 e->flags = EDGE_TRUE_VALUE;
10369 else
10371 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10373 ne = single_succ_edge (l1_bb);
10374 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10377 ne->flags = EDGE_FALSE_VALUE;
10378 e->probability = REG_BR_PROB_BASE * 7 / 8;
10379 ne->probability = REG_BR_PROB_BASE / 8;
10381 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10382 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10383 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10385 if (!broken_loop)
10387 struct loop *loop = alloc_loop ();
10388 loop->header = l1_bb;
10389 loop->latch = cont_bb;
10390 add_loop (loop, l1_bb->loop_father);
10391 loop->safelen = INT_MAX;
10394 /* Pick the correct library function based on the precision of the
10395 induction variable type. */
10396 tree lib_fun = NULL_TREE;
10397 if (TYPE_PRECISION (type) == 32)
10398 lib_fun = cilk_for_32_fndecl;
10399 else if (TYPE_PRECISION (type) == 64)
10400 lib_fun = cilk_for_64_fndecl;
10401 else
10402 gcc_unreachable ();
10404 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10406 /* WS_ARGS contains the library function flavor to call:
10407 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10408 user-defined grain value. If the user does not define one, then zero
10409 is passed in by the parser. */
10410 vec_alloc (region->ws_args, 2);
10411 region->ws_args->quick_push (lib_fun);
10412 region->ws_args->quick_push (fd->chunk_size);
10415 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10416 loop. Given parameters:
10418 for (V = N1; V cond N2; V += STEP) BODY;
10420 where COND is "<" or ">", we generate pseudocode
10422 V = N1;
10423 goto L1;
10425 BODY;
10426 V += STEP;
10428 if (V cond N2) goto L0; else goto L2;
10431 For collapsed loops, given parameters:
10432 collapse(3)
10433 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10434 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10435 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10436 BODY;
10438 we generate pseudocode
10440 if (cond3 is <)
10441 adj = STEP3 - 1;
10442 else
10443 adj = STEP3 + 1;
10444 count3 = (adj + N32 - N31) / STEP3;
10445 if (cond2 is <)
10446 adj = STEP2 - 1;
10447 else
10448 adj = STEP2 + 1;
10449 count2 = (adj + N22 - N21) / STEP2;
10450 if (cond1 is <)
10451 adj = STEP1 - 1;
10452 else
10453 adj = STEP1 + 1;
10454 count1 = (adj + N12 - N11) / STEP1;
10455 count = count1 * count2 * count3;
10456 V = 0;
10457 V1 = N11;
10458 V2 = N21;
10459 V3 = N31;
10460 goto L1;
10462 BODY;
10463 V += 1;
10464 V3 += STEP3;
10465 V2 += (V3 cond3 N32) ? 0 : STEP2;
10466 V3 = (V3 cond3 N32) ? V3 : N31;
10467 V1 += (V2 cond2 N22) ? 0 : STEP1;
10468 V2 = (V2 cond2 N22) ? V2 : N21;
10470 if (V < count) goto L0; else goto L2;
10475 static void
10476 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10478 tree type, t;
10479 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10480 gimple_stmt_iterator gsi;
10481 gimple *stmt;
10482 gcond *cond_stmt;
10483 bool broken_loop = region->cont == NULL;
10484 edge e, ne;
10485 tree *counts = NULL;
10486 int i;
10487 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10488 OMP_CLAUSE_SAFELEN);
10489 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10490 OMP_CLAUSE__SIMDUID_);
10491 tree n1, n2;
10493 type = TREE_TYPE (fd->loop.v);
10494 entry_bb = region->entry;
10495 cont_bb = region->cont;
10496 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10497 gcc_assert (broken_loop
10498 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10499 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10500 if (!broken_loop)
10502 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10503 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10504 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10505 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10507 else
10509 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10510 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10511 l2_bb = single_succ (l1_bb);
10513 exit_bb = region->exit;
10514 l2_dom_bb = NULL;
10516 gsi = gsi_last_bb (entry_bb);
10518 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10519 /* Not needed in SSA form right now. */
10520 gcc_assert (!gimple_in_ssa_p (cfun));
10521 if (fd->collapse > 1)
10523 int first_zero_iter = -1, dummy = -1;
10524 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10526 counts = XALLOCAVEC (tree, fd->collapse);
10527 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10528 zero_iter_bb, first_zero_iter,
10529 dummy_bb, dummy, l2_dom_bb);
10531 if (l2_dom_bb == NULL)
10532 l2_dom_bb = l1_bb;
10534 n1 = fd->loop.n1;
10535 n2 = fd->loop.n2;
10536 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10538 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10539 OMP_CLAUSE__LOOPTEMP_);
10540 gcc_assert (innerc);
10541 n1 = OMP_CLAUSE_DECL (innerc);
10542 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10543 OMP_CLAUSE__LOOPTEMP_);
10544 gcc_assert (innerc);
10545 n2 = OMP_CLAUSE_DECL (innerc);
10546 expand_omp_build_assign (&gsi, fd->loop.v,
10547 fold_convert (type, n1));
10548 if (fd->collapse > 1)
10550 gsi_prev (&gsi);
10551 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10552 gsi_next (&gsi);
10555 else
10557 expand_omp_build_assign (&gsi, fd->loop.v,
10558 fold_convert (type, fd->loop.n1));
10559 if (fd->collapse > 1)
10560 for (i = 0; i < fd->collapse; i++)
10562 tree itype = TREE_TYPE (fd->loops[i].v);
10563 if (POINTER_TYPE_P (itype))
10564 itype = signed_type_for (itype);
10565 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10566 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10570 /* Remove the GIMPLE_OMP_FOR statement. */
10571 gsi_remove (&gsi, true);
10573 if (!broken_loop)
10575 /* Code to control the increment goes in the CONT_BB. */
10576 gsi = gsi_last_bb (cont_bb);
10577 stmt = gsi_stmt (gsi);
10578 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10580 if (POINTER_TYPE_P (type))
10581 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10582 else
10583 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10584 expand_omp_build_assign (&gsi, fd->loop.v, t);
10586 if (fd->collapse > 1)
10588 i = fd->collapse - 1;
10589 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10591 t = fold_convert (sizetype, fd->loops[i].step);
10592 t = fold_build_pointer_plus (fd->loops[i].v, t);
10594 else
10596 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10597 fd->loops[i].step);
10598 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10599 fd->loops[i].v, t);
10601 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10603 for (i = fd->collapse - 1; i > 0; i--)
10605 tree itype = TREE_TYPE (fd->loops[i].v);
10606 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10607 if (POINTER_TYPE_P (itype2))
10608 itype2 = signed_type_for (itype2);
10609 t = build3 (COND_EXPR, itype2,
10610 build2 (fd->loops[i].cond_code, boolean_type_node,
10611 fd->loops[i].v,
10612 fold_convert (itype, fd->loops[i].n2)),
10613 build_int_cst (itype2, 0),
10614 fold_convert (itype2, fd->loops[i - 1].step));
10615 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10616 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10617 else
10618 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10619 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10621 t = build3 (COND_EXPR, itype,
10622 build2 (fd->loops[i].cond_code, boolean_type_node,
10623 fd->loops[i].v,
10624 fold_convert (itype, fd->loops[i].n2)),
10625 fd->loops[i].v,
10626 fold_convert (itype, fd->loops[i].n1));
10627 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10631 /* Remove GIMPLE_OMP_CONTINUE. */
10632 gsi_remove (&gsi, true);
10635 /* Emit the condition in L1_BB. */
10636 gsi = gsi_start_bb (l1_bb);
10638 t = fold_convert (type, n2);
10639 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10640 false, GSI_CONTINUE_LINKING);
10641 tree v = fd->loop.v;
10642 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10643 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10644 false, GSI_CONTINUE_LINKING);
10645 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10646 cond_stmt = gimple_build_cond_empty (t);
10647 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10648 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10649 NULL, NULL)
10650 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10651 NULL, NULL))
10653 gsi = gsi_for_stmt (cond_stmt);
10654 gimple_regimplify_operands (cond_stmt, &gsi);
10657 /* Remove GIMPLE_OMP_RETURN. */
10658 gsi = gsi_last_bb (exit_bb);
10659 gsi_remove (&gsi, true);
10661 /* Connect the new blocks. */
10662 remove_edge (FALLTHRU_EDGE (entry_bb));
10664 if (!broken_loop)
10666 remove_edge (BRANCH_EDGE (entry_bb));
10667 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10669 e = BRANCH_EDGE (l1_bb);
10670 ne = FALLTHRU_EDGE (l1_bb);
10671 e->flags = EDGE_TRUE_VALUE;
10673 else
10675 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10677 ne = single_succ_edge (l1_bb);
10678 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10681 ne->flags = EDGE_FALSE_VALUE;
10682 e->probability = REG_BR_PROB_BASE * 7 / 8;
10683 ne->probability = REG_BR_PROB_BASE / 8;
10685 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10686 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10687 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10689 if (!broken_loop)
10691 struct loop *loop = alloc_loop ();
10692 loop->header = l1_bb;
10693 loop->latch = cont_bb;
10694 add_loop (loop, l1_bb->loop_father);
10695 if (safelen == NULL_TREE)
10696 loop->safelen = INT_MAX;
10697 else
10699 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10700 if (TREE_CODE (safelen) != INTEGER_CST)
10701 loop->safelen = 0;
10702 else if (!tree_fits_uhwi_p (safelen)
10703 || tree_to_uhwi (safelen) > INT_MAX)
10704 loop->safelen = INT_MAX;
10705 else
10706 loop->safelen = tree_to_uhwi (safelen);
10707 if (loop->safelen == 1)
10708 loop->safelen = 0;
10710 if (simduid)
10712 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10713 cfun->has_simduid_loops = true;
10715 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10716 the loop. */
10717 if ((flag_tree_loop_vectorize
10718 || (!global_options_set.x_flag_tree_loop_vectorize
10719 && !global_options_set.x_flag_tree_vectorize))
10720 && flag_tree_loop_optimize
10721 && loop->safelen > 1)
10723 loop->force_vectorize = true;
10724 cfun->has_force_vectorize_loops = true;
10727 else if (simduid)
10728 cfun->has_simduid_loops = true;
10731 /* Taskloop construct is represented after gimplification with
10732 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10733 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10734 which should just compute all the needed loop temporaries
10735 for GIMPLE_OMP_TASK. */
10737 static void
10738 expand_omp_taskloop_for_outer (struct omp_region *region,
10739 struct omp_for_data *fd,
10740 gimple *inner_stmt)
10742 tree type, bias = NULL_TREE;
10743 basic_block entry_bb, cont_bb, exit_bb;
10744 gimple_stmt_iterator gsi;
10745 gassign *assign_stmt;
10746 tree *counts = NULL;
10747 int i;
10749 gcc_assert (inner_stmt);
10750 gcc_assert (region->cont);
10751 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10752 && gimple_omp_task_taskloop_p (inner_stmt));
10753 type = TREE_TYPE (fd->loop.v);
10755 /* See if we need to bias by LLONG_MIN. */
10756 if (fd->iter_type == long_long_unsigned_type_node
10757 && TREE_CODE (type) == INTEGER_TYPE
10758 && !TYPE_UNSIGNED (type))
10760 tree n1, n2;
10762 if (fd->loop.cond_code == LT_EXPR)
10764 n1 = fd->loop.n1;
10765 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10767 else
10769 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10770 n2 = fd->loop.n1;
10772 if (TREE_CODE (n1) != INTEGER_CST
10773 || TREE_CODE (n2) != INTEGER_CST
10774 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10775 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10778 entry_bb = region->entry;
10779 cont_bb = region->cont;
10780 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10781 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10782 exit_bb = region->exit;
10784 gsi = gsi_last_bb (entry_bb);
10785 gimple *for_stmt = gsi_stmt (gsi);
10786 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10787 if (fd->collapse > 1)
10789 int first_zero_iter = -1, dummy = -1;
10790 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10792 counts = XALLOCAVEC (tree, fd->collapse);
10793 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10794 zero_iter_bb, first_zero_iter,
10795 dummy_bb, dummy, l2_dom_bb);
10797 if (zero_iter_bb)
10799 /* Some counts[i] vars might be uninitialized if
10800 some loop has zero iterations. But the body shouldn't
10801 be executed in that case, so just avoid uninit warnings. */
10802 for (i = first_zero_iter; i < fd->collapse; i++)
10803 if (SSA_VAR_P (counts[i]))
10804 TREE_NO_WARNING (counts[i]) = 1;
10805 gsi_prev (&gsi);
10806 edge e = split_block (entry_bb, gsi_stmt (gsi));
10807 entry_bb = e->dest;
10808 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10809 gsi = gsi_last_bb (entry_bb);
10810 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10811 get_immediate_dominator (CDI_DOMINATORS,
10812 zero_iter_bb));
10816 tree t0, t1;
10817 t1 = fd->loop.n2;
10818 t0 = fd->loop.n1;
10819 if (POINTER_TYPE_P (TREE_TYPE (t0))
10820 && TYPE_PRECISION (TREE_TYPE (t0))
10821 != TYPE_PRECISION (fd->iter_type))
10823 /* Avoid casting pointers to integer of a different size. */
10824 tree itype = signed_type_for (type);
10825 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10826 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10828 else
10830 t1 = fold_convert (fd->iter_type, t1);
10831 t0 = fold_convert (fd->iter_type, t0);
10833 if (bias)
10835 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10836 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10839 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10840 OMP_CLAUSE__LOOPTEMP_);
10841 gcc_assert (innerc);
10842 tree startvar = OMP_CLAUSE_DECL (innerc);
10843 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10844 gcc_assert (innerc);
10845 tree endvar = OMP_CLAUSE_DECL (innerc);
10846 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10848 gcc_assert (innerc);
10849 for (i = 1; i < fd->collapse; i++)
10851 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10852 OMP_CLAUSE__LOOPTEMP_);
10853 gcc_assert (innerc);
10855 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10856 OMP_CLAUSE__LOOPTEMP_);
10857 if (innerc)
10859 /* If needed (inner taskloop has lastprivate clause), propagate
10860 down the total number of iterations. */
10861 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10862 NULL_TREE, false,
10863 GSI_CONTINUE_LINKING);
10864 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10865 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10869 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10870 GSI_CONTINUE_LINKING);
10871 assign_stmt = gimple_build_assign (startvar, t0);
10872 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10874 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10875 GSI_CONTINUE_LINKING);
10876 assign_stmt = gimple_build_assign (endvar, t1);
10877 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10878 if (fd->collapse > 1)
10879 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10881 /* Remove the GIMPLE_OMP_FOR statement. */
10882 gsi = gsi_for_stmt (for_stmt);
10883 gsi_remove (&gsi, true);
10885 gsi = gsi_last_bb (cont_bb);
10886 gsi_remove (&gsi, true);
10888 gsi = gsi_last_bb (exit_bb);
10889 gsi_remove (&gsi, true);
10891 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10892 remove_edge (BRANCH_EDGE (entry_bb));
10893 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10894 remove_edge (BRANCH_EDGE (cont_bb));
10895 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10896 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10897 recompute_dominator (CDI_DOMINATORS, region->entry));
10900 /* Taskloop construct is represented after gimplification with
10901 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10902 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10903 GOMP_taskloop{,_ull} function arranges for each task to be given just
10904 a single range of iterations. */
10906 static void
10907 expand_omp_taskloop_for_inner (struct omp_region *region,
10908 struct omp_for_data *fd,
10909 gimple *inner_stmt)
10911 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10912 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10913 basic_block fin_bb;
10914 gimple_stmt_iterator gsi;
10915 edge ep;
10916 bool broken_loop = region->cont == NULL;
10917 tree *counts = NULL;
10918 tree n1, n2, step;
10920 itype = type = TREE_TYPE (fd->loop.v);
10921 if (POINTER_TYPE_P (type))
10922 itype = signed_type_for (type);
10924 /* See if we need to bias by LLONG_MIN. */
10925 if (fd->iter_type == long_long_unsigned_type_node
10926 && TREE_CODE (type) == INTEGER_TYPE
10927 && !TYPE_UNSIGNED (type))
10929 tree n1, n2;
10931 if (fd->loop.cond_code == LT_EXPR)
10933 n1 = fd->loop.n1;
10934 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10936 else
10938 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10939 n2 = fd->loop.n1;
10941 if (TREE_CODE (n1) != INTEGER_CST
10942 || TREE_CODE (n2) != INTEGER_CST
10943 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10944 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10947 entry_bb = region->entry;
10948 cont_bb = region->cont;
10949 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10950 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10951 gcc_assert (broken_loop
10952 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10953 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10954 if (!broken_loop)
10956 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10957 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10959 exit_bb = region->exit;
10961 /* Iteration space partitioning goes in ENTRY_BB. */
10962 gsi = gsi_last_bb (entry_bb);
10963 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10965 if (fd->collapse > 1)
10967 int first_zero_iter = -1, dummy = -1;
10968 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10970 counts = XALLOCAVEC (tree, fd->collapse);
10971 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10972 fin_bb, first_zero_iter,
10973 dummy_bb, dummy, l2_dom_bb);
10974 t = NULL_TREE;
10976 else
10977 t = integer_one_node;
10979 step = fd->loop.step;
10980 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10981 OMP_CLAUSE__LOOPTEMP_);
10982 gcc_assert (innerc);
10983 n1 = OMP_CLAUSE_DECL (innerc);
10984 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10985 gcc_assert (innerc);
10986 n2 = OMP_CLAUSE_DECL (innerc);
10987 if (bias)
10989 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10990 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10992 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10993 true, NULL_TREE, true, GSI_SAME_STMT);
10994 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10995 true, NULL_TREE, true, GSI_SAME_STMT);
10996 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10997 true, NULL_TREE, true, GSI_SAME_STMT);
10999 tree startvar = fd->loop.v;
11000 tree endvar = NULL_TREE;
11002 if (gimple_omp_for_combined_p (fd->for_stmt))
11004 tree clauses = gimple_omp_for_clauses (inner_stmt);
11005 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11006 gcc_assert (innerc);
11007 startvar = OMP_CLAUSE_DECL (innerc);
11008 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11009 OMP_CLAUSE__LOOPTEMP_);
11010 gcc_assert (innerc);
11011 endvar = OMP_CLAUSE_DECL (innerc);
11013 t = fold_convert (TREE_TYPE (startvar), n1);
11014 t = force_gimple_operand_gsi (&gsi, t,
11015 DECL_P (startvar)
11016 && TREE_ADDRESSABLE (startvar),
11017 NULL_TREE, false, GSI_CONTINUE_LINKING);
11018 gimple *assign_stmt = gimple_build_assign (startvar, t);
11019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11021 t = fold_convert (TREE_TYPE (startvar), n2);
11022 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11023 false, GSI_CONTINUE_LINKING);
11024 if (endvar)
11026 assign_stmt = gimple_build_assign (endvar, e);
11027 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11028 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11029 assign_stmt = gimple_build_assign (fd->loop.v, e);
11030 else
11031 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11032 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11034 if (fd->collapse > 1)
11035 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11037 if (!broken_loop)
11039 /* The code controlling the sequential loop replaces the
11040 GIMPLE_OMP_CONTINUE. */
11041 gsi = gsi_last_bb (cont_bb);
11042 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11043 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11044 vmain = gimple_omp_continue_control_use (cont_stmt);
11045 vback = gimple_omp_continue_control_def (cont_stmt);
11047 if (!gimple_omp_for_combined_p (fd->for_stmt))
11049 if (POINTER_TYPE_P (type))
11050 t = fold_build_pointer_plus (vmain, step);
11051 else
11052 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11053 t = force_gimple_operand_gsi (&gsi, t,
11054 DECL_P (vback)
11055 && TREE_ADDRESSABLE (vback),
11056 NULL_TREE, true, GSI_SAME_STMT);
11057 assign_stmt = gimple_build_assign (vback, t);
11058 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11060 t = build2 (fd->loop.cond_code, boolean_type_node,
11061 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11062 ? t : vback, e);
11063 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11066 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11067 gsi_remove (&gsi, true);
11069 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11070 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11073 /* Remove the GIMPLE_OMP_FOR statement. */
11074 gsi = gsi_for_stmt (fd->for_stmt);
11075 gsi_remove (&gsi, true);
11077 /* Remove the GIMPLE_OMP_RETURN statement. */
11078 gsi = gsi_last_bb (exit_bb);
11079 gsi_remove (&gsi, true);
11081 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11082 if (!broken_loop)
11083 remove_edge (BRANCH_EDGE (entry_bb));
11084 else
11086 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11087 region->outer->cont = NULL;
11090 /* Connect all the blocks. */
11091 if (!broken_loop)
11093 ep = find_edge (cont_bb, body_bb);
11094 if (gimple_omp_for_combined_p (fd->for_stmt))
11096 remove_edge (ep);
11097 ep = NULL;
11099 else if (fd->collapse > 1)
11101 remove_edge (ep);
11102 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11104 else
11105 ep->flags = EDGE_TRUE_VALUE;
11106 find_edge (cont_bb, fin_bb)->flags
11107 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11110 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11111 recompute_dominator (CDI_DOMINATORS, body_bb));
11112 if (!broken_loop)
11113 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11114 recompute_dominator (CDI_DOMINATORS, fin_bb));
11116 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11118 struct loop *loop = alloc_loop ();
11119 loop->header = body_bb;
11120 if (collapse_bb == NULL)
11121 loop->latch = cont_bb;
11122 add_loop (loop, body_bb->loop_father);
11126 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11127 partitioned loop. The lowering here is abstracted, in that the
11128 loop parameters are passed through internal functions, which are
11129 further lowered by oacc_device_lower, once we get to the target
11130 compiler. The loop is of the form:
11132 for (V = B; V LTGT E; V += S) {BODY}
11134 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11135 (constant 0 for no chunking) and we will have a GWV partitioning
11136 mask, specifying dimensions over which the loop is to be
11137 partitioned (see note below). We generate code that looks like:
11139 <entry_bb> [incoming FALL->body, BRANCH->exit]
11140 typedef signedintify (typeof (V)) T; // underlying signed integral type
11141 T range = E - B;
11142 T chunk_no = 0;
11143 T DIR = LTGT == '<' ? +1 : -1;
11144 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11145 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11147 <head_bb> [created by splitting end of entry_bb]
11148 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11149 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11150 if (!(offset LTGT bound)) goto bottom_bb;
11152 <body_bb> [incoming]
11153 V = B + offset;
11154 {BODY}
11156 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11157 offset += step;
11158 if (offset LTGT bound) goto body_bb; [*]
11160 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11161 chunk_no++;
11162 if (chunk < chunk_max) goto head_bb;
11164 <exit_bb> [incoming]
11165 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11167 [*] Needed if V live at end of loop
11169 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11170 transition, and will be specified by a more general mechanism shortly.
11173 static void
11174 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11176 tree v = fd->loop.v;
11177 enum tree_code cond_code = fd->loop.cond_code;
11178 enum tree_code plus_code = PLUS_EXPR;
11180 tree chunk_size = integer_minus_one_node;
11181 tree gwv = integer_zero_node;
11182 tree iter_type = TREE_TYPE (v);
11183 tree diff_type = iter_type;
11184 tree plus_type = iter_type;
11185 struct oacc_collapse *counts = NULL;
11187 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11188 == GF_OMP_FOR_KIND_OACC_LOOP);
11189 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11190 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11192 if (POINTER_TYPE_P (iter_type))
11194 plus_code = POINTER_PLUS_EXPR;
11195 plus_type = sizetype;
11197 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11198 diff_type = signed_type_for (diff_type);
11200 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11201 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11202 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11203 basic_block bottom_bb = NULL;
11205 /* entry_bb has two sucessors; the branch edge is to the exit
11206 block, fallthrough edge to body. */
11207 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11208 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11210 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11211 body_bb, or to a block whose only successor is the body_bb. Its
11212 fallthrough successor is the final block (same as the branch
11213 successor of the entry_bb). */
11214 if (cont_bb)
11216 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11217 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11219 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11220 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11222 else
11223 gcc_assert (!gimple_in_ssa_p (cfun));
11225 /* The exit block only has entry_bb and cont_bb as predecessors. */
11226 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11228 tree chunk_no;
11229 tree chunk_max = NULL_TREE;
11230 tree bound, offset;
11231 tree step = create_tmp_var (diff_type, ".step");
11232 bool up = cond_code == LT_EXPR;
11233 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11234 bool chunking = !gimple_in_ssa_p (cfun);;
11235 bool negating;
11237 /* SSA instances. */
11238 tree offset_incr = NULL_TREE;
11239 tree offset_init = NULL_TREE;
11241 gimple_stmt_iterator gsi;
11242 gassign *ass;
11243 gcall *call;
11244 gimple *stmt;
11245 tree expr;
11246 location_t loc;
11247 edge split, be, fte;
11249 /* Split the end of entry_bb to create head_bb. */
11250 split = split_block (entry_bb, last_stmt (entry_bb));
11251 basic_block head_bb = split->dest;
11252 entry_bb = split->src;
11254 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11255 gsi = gsi_last_bb (entry_bb);
11256 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11257 loc = gimple_location (for_stmt);
11259 if (gimple_in_ssa_p (cfun))
11261 offset_init = gimple_omp_for_index (for_stmt, 0);
11262 gcc_assert (integer_zerop (fd->loop.n1));
11263 /* The SSA parallelizer does gang parallelism. */
11264 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11267 if (fd->collapse > 1)
11269 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11270 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11271 TREE_TYPE (fd->loop.n2));
11273 if (SSA_VAR_P (fd->loop.n2))
11275 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11276 true, GSI_SAME_STMT);
11277 ass = gimple_build_assign (fd->loop.n2, total);
11278 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11283 tree b = fd->loop.n1;
11284 tree e = fd->loop.n2;
11285 tree s = fd->loop.step;
11287 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11288 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11290 /* Convert the step, avoiding possible unsigned->signed overflow. */
11291 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11292 if (negating)
11293 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11294 s = fold_convert (diff_type, s);
11295 if (negating)
11296 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11297 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11299 if (!chunking)
11300 chunk_size = integer_zero_node;
11301 expr = fold_convert (diff_type, chunk_size);
11302 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11303 NULL_TREE, true, GSI_SAME_STMT);
11304 /* Determine the range, avoiding possible unsigned->signed overflow. */
11305 negating = !up && TYPE_UNSIGNED (iter_type);
11306 expr = fold_build2 (MINUS_EXPR, plus_type,
11307 fold_convert (plus_type, negating ? b : e),
11308 fold_convert (plus_type, negating ? e : b));
11309 expr = fold_convert (diff_type, expr);
11310 if (negating)
11311 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11312 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11313 NULL_TREE, true, GSI_SAME_STMT);
11315 chunk_no = build_int_cst (diff_type, 0);
11316 if (chunking)
11318 gcc_assert (!gimple_in_ssa_p (cfun));
11320 expr = chunk_no;
11321 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11322 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11324 ass = gimple_build_assign (chunk_no, expr);
11325 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11327 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11328 build_int_cst (integer_type_node,
11329 IFN_GOACC_LOOP_CHUNKS),
11330 dir, range, s, chunk_size, gwv);
11331 gimple_call_set_lhs (call, chunk_max);
11332 gimple_set_location (call, loc);
11333 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11335 else
11336 chunk_size = chunk_no;
11338 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11339 build_int_cst (integer_type_node,
11340 IFN_GOACC_LOOP_STEP),
11341 dir, range, s, chunk_size, gwv);
11342 gimple_call_set_lhs (call, step);
11343 gimple_set_location (call, loc);
11344 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11346 /* Remove the GIMPLE_OMP_FOR. */
11347 gsi_remove (&gsi, true);
11349 /* Fixup edges from head_bb */
11350 be = BRANCH_EDGE (head_bb);
11351 fte = FALLTHRU_EDGE (head_bb);
11352 be->flags |= EDGE_FALSE_VALUE;
11353 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11355 basic_block body_bb = fte->dest;
11357 if (gimple_in_ssa_p (cfun))
11359 gsi = gsi_last_bb (cont_bb);
11360 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11362 offset = gimple_omp_continue_control_use (cont_stmt);
11363 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11365 else
11367 offset = create_tmp_var (diff_type, ".offset");
11368 offset_init = offset_incr = offset;
11370 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11372 /* Loop offset & bound go into head_bb. */
11373 gsi = gsi_start_bb (head_bb);
11375 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11376 build_int_cst (integer_type_node,
11377 IFN_GOACC_LOOP_OFFSET),
11378 dir, range, s,
11379 chunk_size, gwv, chunk_no);
11380 gimple_call_set_lhs (call, offset_init);
11381 gimple_set_location (call, loc);
11382 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11384 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11385 build_int_cst (integer_type_node,
11386 IFN_GOACC_LOOP_BOUND),
11387 dir, range, s,
11388 chunk_size, gwv, offset_init);
11389 gimple_call_set_lhs (call, bound);
11390 gimple_set_location (call, loc);
11391 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11393 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11394 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11395 GSI_CONTINUE_LINKING);
11397 /* V assignment goes into body_bb. */
11398 if (!gimple_in_ssa_p (cfun))
11400 gsi = gsi_start_bb (body_bb);
11402 expr = build2 (plus_code, iter_type, b,
11403 fold_convert (plus_type, offset));
11404 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11405 true, GSI_SAME_STMT);
11406 ass = gimple_build_assign (v, expr);
11407 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11408 if (fd->collapse > 1)
11409 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11412 /* Loop increment goes into cont_bb. If this is not a loop, we
11413 will have spawned threads as if it was, and each one will
11414 execute one iteration. The specification is not explicit about
11415 whether such constructs are ill-formed or not, and they can
11416 occur, especially when noreturn routines are involved. */
11417 if (cont_bb)
11419 gsi = gsi_last_bb (cont_bb);
11420 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11421 loc = gimple_location (cont_stmt);
11423 /* Increment offset. */
11424 if (gimple_in_ssa_p (cfun))
11425 expr= build2 (plus_code, iter_type, offset,
11426 fold_convert (plus_type, step));
11427 else
11428 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11429 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11430 true, GSI_SAME_STMT);
11431 ass = gimple_build_assign (offset_incr, expr);
11432 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11433 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11434 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11436 /* Remove the GIMPLE_OMP_CONTINUE. */
11437 gsi_remove (&gsi, true);
11439 /* Fixup edges from cont_bb */
11440 be = BRANCH_EDGE (cont_bb);
11441 fte = FALLTHRU_EDGE (cont_bb);
11442 be->flags |= EDGE_TRUE_VALUE;
11443 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11445 if (chunking)
11447 /* Split the beginning of exit_bb to make bottom_bb. We
11448 need to insert a nop at the start, because splitting is
11449 after a stmt, not before. */
11450 gsi = gsi_start_bb (exit_bb);
11451 stmt = gimple_build_nop ();
11452 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11453 split = split_block (exit_bb, stmt);
11454 bottom_bb = split->src;
11455 exit_bb = split->dest;
11456 gsi = gsi_last_bb (bottom_bb);
11458 /* Chunk increment and test goes into bottom_bb. */
11459 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11460 build_int_cst (diff_type, 1));
11461 ass = gimple_build_assign (chunk_no, expr);
11462 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11464 /* Chunk test at end of bottom_bb. */
11465 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11466 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11467 GSI_CONTINUE_LINKING);
11469 /* Fixup edges from bottom_bb. */
11470 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11471 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11475 gsi = gsi_last_bb (exit_bb);
11476 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11477 loc = gimple_location (gsi_stmt (gsi));
11479 if (!gimple_in_ssa_p (cfun))
11481 /* Insert the final value of V, in case it is live. This is the
11482 value for the only thread that survives past the join. */
11483 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11484 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11485 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11486 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11487 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11488 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11489 true, GSI_SAME_STMT);
11490 ass = gimple_build_assign (v, expr);
11491 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11494 /* Remove the OMP_RETURN. */
11495 gsi_remove (&gsi, true);
11497 if (cont_bb)
11499 /* We now have one or two nested loops. Update the loop
11500 structures. */
11501 struct loop *parent = entry_bb->loop_father;
11502 struct loop *body = body_bb->loop_father;
11504 if (chunking)
11506 struct loop *chunk_loop = alloc_loop ();
11507 chunk_loop->header = head_bb;
11508 chunk_loop->latch = bottom_bb;
11509 add_loop (chunk_loop, parent);
11510 parent = chunk_loop;
11512 else if (parent != body)
11514 gcc_assert (body->header == body_bb);
11515 gcc_assert (body->latch == cont_bb
11516 || single_pred (body->latch) == cont_bb);
11517 parent = NULL;
11520 if (parent)
11522 struct loop *body_loop = alloc_loop ();
11523 body_loop->header = body_bb;
11524 body_loop->latch = cont_bb;
11525 add_loop (body_loop, parent);
11530 /* Expand the OMP loop defined by REGION. */
11532 static void
11533 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11535 struct omp_for_data fd;
11536 struct omp_for_data_loop *loops;
11538 loops
11539 = (struct omp_for_data_loop *)
11540 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11541 * sizeof (struct omp_for_data_loop));
11542 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11543 &fd, loops);
11544 region->sched_kind = fd.sched_kind;
11545 region->sched_modifiers = fd.sched_modifiers;
11547 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11548 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11549 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11550 if (region->cont)
11552 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11553 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11554 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11556 else
11557 /* If there isn't a continue then this is a degerate case where
11558 the introduction of abnormal edges during lowering will prevent
11559 original loops from being detected. Fix that up. */
11560 loops_state_set (LOOPS_NEED_FIXUP);
11562 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11563 expand_omp_simd (region, &fd);
11564 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11565 expand_cilk_for (region, &fd);
11566 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11568 gcc_assert (!inner_stmt);
11569 expand_oacc_for (region, &fd);
11571 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11573 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11574 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11575 else
11576 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11578 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11579 && !fd.have_ordered)
11581 if (fd.chunk_size == NULL)
11582 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11583 else
11584 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11586 else
11588 int fn_index, start_ix, next_ix;
11590 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11591 == GF_OMP_FOR_KIND_FOR);
11592 if (fd.chunk_size == NULL
11593 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11594 fd.chunk_size = integer_zero_node;
11595 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11596 switch (fd.sched_kind)
11598 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11599 fn_index = 3;
11600 break;
11601 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11602 case OMP_CLAUSE_SCHEDULE_GUIDED:
11603 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11604 && !fd.ordered
11605 && !fd.have_ordered)
11607 fn_index = 3 + fd.sched_kind;
11608 break;
11610 /* FALLTHRU */
11611 default:
11612 fn_index = fd.sched_kind;
11613 break;
11615 if (!fd.ordered)
11616 fn_index += fd.have_ordered * 6;
11617 if (fd.ordered)
11618 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11619 else
11620 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11621 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11622 if (fd.iter_type == long_long_unsigned_type_node)
11624 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11625 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11626 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11627 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11629 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11630 (enum built_in_function) next_ix, inner_stmt);
11633 if (gimple_in_ssa_p (cfun))
11634 update_ssa (TODO_update_ssa_only_virtuals);
11638 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11640 v = GOMP_sections_start (n);
11642 switch (v)
11644 case 0:
11645 goto L2;
11646 case 1:
11647 section 1;
11648 goto L1;
11649 case 2:
11651 case n:
11653 default:
11654 abort ();
11657 v = GOMP_sections_next ();
11658 goto L0;
11660 reduction;
11662 If this is a combined parallel sections, replace the call to
11663 GOMP_sections_start with call to GOMP_sections_next. */
11665 static void
11666 expand_omp_sections (struct omp_region *region)
11668 tree t, u, vin = NULL, vmain, vnext, l2;
11669 unsigned len;
11670 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11671 gimple_stmt_iterator si, switch_si;
11672 gomp_sections *sections_stmt;
11673 gimple *stmt;
11674 gomp_continue *cont;
11675 edge_iterator ei;
11676 edge e;
11677 struct omp_region *inner;
11678 unsigned i, casei;
11679 bool exit_reachable = region->cont != NULL;
11681 gcc_assert (region->exit != NULL);
11682 entry_bb = region->entry;
11683 l0_bb = single_succ (entry_bb);
11684 l1_bb = region->cont;
11685 l2_bb = region->exit;
11686 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11687 l2 = gimple_block_label (l2_bb);
11688 else
11690 /* This can happen if there are reductions. */
11691 len = EDGE_COUNT (l0_bb->succs);
11692 gcc_assert (len > 0);
11693 e = EDGE_SUCC (l0_bb, len - 1);
11694 si = gsi_last_bb (e->dest);
11695 l2 = NULL_TREE;
11696 if (gsi_end_p (si)
11697 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11698 l2 = gimple_block_label (e->dest);
11699 else
11700 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11702 si = gsi_last_bb (e->dest);
11703 if (gsi_end_p (si)
11704 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11706 l2 = gimple_block_label (e->dest);
11707 break;
11711 if (exit_reachable)
11712 default_bb = create_empty_bb (l1_bb->prev_bb);
11713 else
11714 default_bb = create_empty_bb (l0_bb);
11716 /* We will build a switch() with enough cases for all the
11717 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11718 and a default case to abort if something goes wrong. */
11719 len = EDGE_COUNT (l0_bb->succs);
11721 /* Use vec::quick_push on label_vec throughout, since we know the size
11722 in advance. */
11723 auto_vec<tree> label_vec (len);
11725 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11726 GIMPLE_OMP_SECTIONS statement. */
11727 si = gsi_last_bb (entry_bb);
11728 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11729 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11730 vin = gimple_omp_sections_control (sections_stmt);
11731 if (!is_combined_parallel (region))
11733 /* If we are not inside a combined parallel+sections region,
11734 call GOMP_sections_start. */
11735 t = build_int_cst (unsigned_type_node, len - 1);
11736 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11737 stmt = gimple_build_call (u, 1, t);
11739 else
11741 /* Otherwise, call GOMP_sections_next. */
11742 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11743 stmt = gimple_build_call (u, 0);
11745 gimple_call_set_lhs (stmt, vin);
11746 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11747 gsi_remove (&si, true);
11749 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11750 L0_BB. */
11751 switch_si = gsi_last_bb (l0_bb);
11752 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11753 if (exit_reachable)
11755 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11756 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11757 vmain = gimple_omp_continue_control_use (cont);
11758 vnext = gimple_omp_continue_control_def (cont);
11760 else
11762 vmain = vin;
11763 vnext = NULL_TREE;
11766 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11767 label_vec.quick_push (t);
11768 i = 1;
11770 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11771 for (inner = region->inner, casei = 1;
11772 inner;
11773 inner = inner->next, i++, casei++)
11775 basic_block s_entry_bb, s_exit_bb;
11777 /* Skip optional reduction region. */
11778 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11780 --i;
11781 --casei;
11782 continue;
11785 s_entry_bb = inner->entry;
11786 s_exit_bb = inner->exit;
11788 t = gimple_block_label (s_entry_bb);
11789 u = build_int_cst (unsigned_type_node, casei);
11790 u = build_case_label (u, NULL, t);
11791 label_vec.quick_push (u);
11793 si = gsi_last_bb (s_entry_bb);
11794 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11795 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11796 gsi_remove (&si, true);
11797 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11799 if (s_exit_bb == NULL)
11800 continue;
11802 si = gsi_last_bb (s_exit_bb);
11803 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11804 gsi_remove (&si, true);
11806 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11809 /* Error handling code goes in DEFAULT_BB. */
11810 t = gimple_block_label (default_bb);
11811 u = build_case_label (NULL, NULL, t);
11812 make_edge (l0_bb, default_bb, 0);
11813 add_bb_to_loop (default_bb, current_loops->tree_root);
11815 stmt = gimple_build_switch (vmain, u, label_vec);
11816 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11817 gsi_remove (&switch_si, true);
11819 si = gsi_start_bb (default_bb);
11820 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11821 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11823 if (exit_reachable)
11825 tree bfn_decl;
11827 /* Code to get the next section goes in L1_BB. */
11828 si = gsi_last_bb (l1_bb);
11829 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11831 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11832 stmt = gimple_build_call (bfn_decl, 0);
11833 gimple_call_set_lhs (stmt, vnext);
11834 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11835 gsi_remove (&si, true);
11837 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11840 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11841 si = gsi_last_bb (l2_bb);
11842 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11843 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11844 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11845 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11846 else
11847 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11848 stmt = gimple_build_call (t, 0);
11849 if (gimple_omp_return_lhs (gsi_stmt (si)))
11850 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11851 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11852 gsi_remove (&si, true);
11854 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11858 /* Expand code for an OpenMP single directive. We've already expanded
11859 much of the code, here we simply place the GOMP_barrier call. */
11861 static void
11862 expand_omp_single (struct omp_region *region)
11864 basic_block entry_bb, exit_bb;
11865 gimple_stmt_iterator si;
11867 entry_bb = region->entry;
11868 exit_bb = region->exit;
11870 si = gsi_last_bb (entry_bb);
11871 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11872 gsi_remove (&si, true);
11873 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11875 si = gsi_last_bb (exit_bb);
11876 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11878 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11879 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11881 gsi_remove (&si, true);
11882 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11886 /* Generic expansion for OpenMP synchronization directives: master,
11887 ordered and critical. All we need to do here is remove the entry
11888 and exit markers for REGION. */
11890 static void
11891 expand_omp_synch (struct omp_region *region)
11893 basic_block entry_bb, exit_bb;
11894 gimple_stmt_iterator si;
11896 entry_bb = region->entry;
11897 exit_bb = region->exit;
11899 si = gsi_last_bb (entry_bb);
11900 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11901 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11902 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11903 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11904 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11905 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11906 gsi_remove (&si, true);
11907 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11909 if (exit_bb)
11911 si = gsi_last_bb (exit_bb);
11912 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11913 gsi_remove (&si, true);
11914 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11918 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11919 operation as a normal volatile load. */
11921 static bool
11922 expand_omp_atomic_load (basic_block load_bb, tree addr,
11923 tree loaded_val, int index)
11925 enum built_in_function tmpbase;
11926 gimple_stmt_iterator gsi;
11927 basic_block store_bb;
11928 location_t loc;
11929 gimple *stmt;
11930 tree decl, call, type, itype;
11932 gsi = gsi_last_bb (load_bb);
11933 stmt = gsi_stmt (gsi);
11934 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11935 loc = gimple_location (stmt);
11937 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11938 is smaller than word size, then expand_atomic_load assumes that the load
11939 is atomic. We could avoid the builtin entirely in this case. */
11941 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11942 decl = builtin_decl_explicit (tmpbase);
11943 if (decl == NULL_TREE)
11944 return false;
11946 type = TREE_TYPE (loaded_val);
11947 itype = TREE_TYPE (TREE_TYPE (decl));
11949 call = build_call_expr_loc (loc, decl, 2, addr,
11950 build_int_cst (NULL,
11951 gimple_omp_atomic_seq_cst_p (stmt)
11952 ? MEMMODEL_SEQ_CST
11953 : MEMMODEL_RELAXED));
11954 if (!useless_type_conversion_p (type, itype))
11955 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11956 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11958 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11959 gsi_remove (&gsi, true);
11961 store_bb = single_succ (load_bb);
11962 gsi = gsi_last_bb (store_bb);
11963 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11964 gsi_remove (&gsi, true);
11966 if (gimple_in_ssa_p (cfun))
11967 update_ssa (TODO_update_ssa_no_phi);
11969 return true;
11972 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11973 operation as a normal volatile store. */
11975 static bool
11976 expand_omp_atomic_store (basic_block load_bb, tree addr,
11977 tree loaded_val, tree stored_val, int index)
11979 enum built_in_function tmpbase;
11980 gimple_stmt_iterator gsi;
11981 basic_block store_bb = single_succ (load_bb);
11982 location_t loc;
11983 gimple *stmt;
11984 tree decl, call, type, itype;
11985 machine_mode imode;
11986 bool exchange;
11988 gsi = gsi_last_bb (load_bb);
11989 stmt = gsi_stmt (gsi);
11990 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11992 /* If the load value is needed, then this isn't a store but an exchange. */
11993 exchange = gimple_omp_atomic_need_value_p (stmt);
11995 gsi = gsi_last_bb (store_bb);
11996 stmt = gsi_stmt (gsi);
11997 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11998 loc = gimple_location (stmt);
12000 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12001 is smaller than word size, then expand_atomic_store assumes that the store
12002 is atomic. We could avoid the builtin entirely in this case. */
12004 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12005 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12006 decl = builtin_decl_explicit (tmpbase);
12007 if (decl == NULL_TREE)
12008 return false;
12010 type = TREE_TYPE (stored_val);
12012 /* Dig out the type of the function's second argument. */
12013 itype = TREE_TYPE (decl);
12014 itype = TYPE_ARG_TYPES (itype);
12015 itype = TREE_CHAIN (itype);
12016 itype = TREE_VALUE (itype);
12017 imode = TYPE_MODE (itype);
12019 if (exchange && !can_atomic_exchange_p (imode, true))
12020 return false;
12022 if (!useless_type_conversion_p (itype, type))
12023 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12024 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12025 build_int_cst (NULL,
12026 gimple_omp_atomic_seq_cst_p (stmt)
12027 ? MEMMODEL_SEQ_CST
12028 : MEMMODEL_RELAXED));
12029 if (exchange)
12031 if (!useless_type_conversion_p (type, itype))
12032 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12033 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12036 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12037 gsi_remove (&gsi, true);
12039 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12040 gsi = gsi_last_bb (load_bb);
12041 gsi_remove (&gsi, true);
12043 if (gimple_in_ssa_p (cfun))
12044 update_ssa (TODO_update_ssa_no_phi);
12046 return true;
12049 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12050 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12051 size of the data type, and thus usable to find the index of the builtin
12052 decl. Returns false if the expression is not of the proper form. */
12054 static bool
12055 expand_omp_atomic_fetch_op (basic_block load_bb,
12056 tree addr, tree loaded_val,
12057 tree stored_val, int index)
12059 enum built_in_function oldbase, newbase, tmpbase;
12060 tree decl, itype, call;
12061 tree lhs, rhs;
12062 basic_block store_bb = single_succ (load_bb);
12063 gimple_stmt_iterator gsi;
12064 gimple *stmt;
12065 location_t loc;
12066 enum tree_code code;
12067 bool need_old, need_new;
12068 machine_mode imode;
12069 bool seq_cst;
12071 /* We expect to find the following sequences:
12073 load_bb:
12074 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12076 store_bb:
12077 val = tmp OP something; (or: something OP tmp)
12078 GIMPLE_OMP_STORE (val)
12080 ???FIXME: Allow a more flexible sequence.
12081 Perhaps use data flow to pick the statements.
12085 gsi = gsi_after_labels (store_bb);
12086 stmt = gsi_stmt (gsi);
12087 loc = gimple_location (stmt);
12088 if (!is_gimple_assign (stmt))
12089 return false;
12090 gsi_next (&gsi);
12091 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12092 return false;
12093 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12094 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12095 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12096 gcc_checking_assert (!need_old || !need_new);
12098 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12099 return false;
12101 /* Check for one of the supported fetch-op operations. */
12102 code = gimple_assign_rhs_code (stmt);
12103 switch (code)
12105 case PLUS_EXPR:
12106 case POINTER_PLUS_EXPR:
12107 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12108 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12109 break;
12110 case MINUS_EXPR:
12111 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12112 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12113 break;
12114 case BIT_AND_EXPR:
12115 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12116 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12117 break;
12118 case BIT_IOR_EXPR:
12119 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12120 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12121 break;
12122 case BIT_XOR_EXPR:
12123 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12124 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12125 break;
12126 default:
12127 return false;
12130 /* Make sure the expression is of the proper form. */
12131 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12132 rhs = gimple_assign_rhs2 (stmt);
12133 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12134 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12135 rhs = gimple_assign_rhs1 (stmt);
12136 else
12137 return false;
12139 tmpbase = ((enum built_in_function)
12140 ((need_new ? newbase : oldbase) + index + 1));
12141 decl = builtin_decl_explicit (tmpbase);
12142 if (decl == NULL_TREE)
12143 return false;
12144 itype = TREE_TYPE (TREE_TYPE (decl));
12145 imode = TYPE_MODE (itype);
12147 /* We could test all of the various optabs involved, but the fact of the
12148 matter is that (with the exception of i486 vs i586 and xadd) all targets
12149 that support any atomic operaton optab also implements compare-and-swap.
12150 Let optabs.c take care of expanding any compare-and-swap loop. */
12151 if (!can_compare_and_swap_p (imode, true))
12152 return false;
12154 gsi = gsi_last_bb (load_bb);
12155 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12157 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12158 It only requires that the operation happen atomically. Thus we can
12159 use the RELAXED memory model. */
12160 call = build_call_expr_loc (loc, decl, 3, addr,
12161 fold_convert_loc (loc, itype, rhs),
12162 build_int_cst (NULL,
12163 seq_cst ? MEMMODEL_SEQ_CST
12164 : MEMMODEL_RELAXED));
12166 if (need_old || need_new)
12168 lhs = need_old ? loaded_val : stored_val;
12169 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12170 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12172 else
12173 call = fold_convert_loc (loc, void_type_node, call);
12174 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12175 gsi_remove (&gsi, true);
12177 gsi = gsi_last_bb (store_bb);
12178 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12179 gsi_remove (&gsi, true);
12180 gsi = gsi_last_bb (store_bb);
12181 stmt = gsi_stmt (gsi);
12182 gsi_remove (&gsi, true);
12184 if (gimple_in_ssa_p (cfun))
12186 release_defs (stmt);
12187 update_ssa (TODO_update_ssa_no_phi);
12190 return true;
12193 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12195 oldval = *addr;
12196 repeat:
12197 newval = rhs; // with oldval replacing *addr in rhs
12198 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12199 if (oldval != newval)
12200 goto repeat;
12202 INDEX is log2 of the size of the data type, and thus usable to find the
12203 index of the builtin decl. */
12205 static bool
12206 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12207 tree addr, tree loaded_val, tree stored_val,
12208 int index)
12210 tree loadedi, storedi, initial, new_storedi, old_vali;
12211 tree type, itype, cmpxchg, iaddr;
12212 gimple_stmt_iterator si;
12213 basic_block loop_header = single_succ (load_bb);
12214 gimple *phi, *stmt;
12215 edge e;
12216 enum built_in_function fncode;
12218 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12219 order to use the RELAXED memory model effectively. */
12220 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12221 + index + 1);
12222 cmpxchg = builtin_decl_explicit (fncode);
12223 if (cmpxchg == NULL_TREE)
12224 return false;
12225 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12226 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12228 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12229 return false;
12231 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12232 si = gsi_last_bb (load_bb);
12233 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12235 /* For floating-point values, we'll need to view-convert them to integers
12236 so that we can perform the atomic compare and swap. Simplify the
12237 following code by always setting up the "i"ntegral variables. */
12238 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12240 tree iaddr_val;
12242 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12243 true));
12244 iaddr_val
12245 = force_gimple_operand_gsi (&si,
12246 fold_convert (TREE_TYPE (iaddr), addr),
12247 false, NULL_TREE, true, GSI_SAME_STMT);
12248 stmt = gimple_build_assign (iaddr, iaddr_val);
12249 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12250 loadedi = create_tmp_var (itype);
12251 if (gimple_in_ssa_p (cfun))
12252 loadedi = make_ssa_name (loadedi);
12254 else
12256 iaddr = addr;
12257 loadedi = loaded_val;
12260 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12261 tree loaddecl = builtin_decl_explicit (fncode);
12262 if (loaddecl)
12263 initial
12264 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12265 build_call_expr (loaddecl, 2, iaddr,
12266 build_int_cst (NULL_TREE,
12267 MEMMODEL_RELAXED)));
12268 else
12269 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12270 build_int_cst (TREE_TYPE (iaddr), 0));
12272 initial
12273 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12274 GSI_SAME_STMT);
12276 /* Move the value to the LOADEDI temporary. */
12277 if (gimple_in_ssa_p (cfun))
12279 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12280 phi = create_phi_node (loadedi, loop_header);
12281 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12282 initial);
12284 else
12285 gsi_insert_before (&si,
12286 gimple_build_assign (loadedi, initial),
12287 GSI_SAME_STMT);
12288 if (loadedi != loaded_val)
12290 gimple_stmt_iterator gsi2;
12291 tree x;
12293 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12294 gsi2 = gsi_start_bb (loop_header);
12295 if (gimple_in_ssa_p (cfun))
12297 gassign *stmt;
12298 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12299 true, GSI_SAME_STMT);
12300 stmt = gimple_build_assign (loaded_val, x);
12301 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12303 else
12305 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12306 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12307 true, GSI_SAME_STMT);
12310 gsi_remove (&si, true);
12312 si = gsi_last_bb (store_bb);
12313 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12315 if (iaddr == addr)
12316 storedi = stored_val;
12317 else
12318 storedi =
12319 force_gimple_operand_gsi (&si,
12320 build1 (VIEW_CONVERT_EXPR, itype,
12321 stored_val), true, NULL_TREE, true,
12322 GSI_SAME_STMT);
12324 /* Build the compare&swap statement. */
12325 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12326 new_storedi = force_gimple_operand_gsi (&si,
12327 fold_convert (TREE_TYPE (loadedi),
12328 new_storedi),
12329 true, NULL_TREE,
12330 true, GSI_SAME_STMT);
12332 if (gimple_in_ssa_p (cfun))
12333 old_vali = loadedi;
12334 else
12336 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12337 stmt = gimple_build_assign (old_vali, loadedi);
12338 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12340 stmt = gimple_build_assign (loadedi, new_storedi);
12341 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12344 /* Note that we always perform the comparison as an integer, even for
12345 floating point. This allows the atomic operation to properly
12346 succeed even with NaNs and -0.0. */
12347 stmt = gimple_build_cond_empty
12348 (build2 (NE_EXPR, boolean_type_node,
12349 new_storedi, old_vali));
12350 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12352 /* Update cfg. */
12353 e = single_succ_edge (store_bb);
12354 e->flags &= ~EDGE_FALLTHRU;
12355 e->flags |= EDGE_FALSE_VALUE;
12357 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12359 /* Copy the new value to loadedi (we already did that before the condition
12360 if we are not in SSA). */
12361 if (gimple_in_ssa_p (cfun))
12363 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12364 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12367 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12368 gsi_remove (&si, true);
12370 struct loop *loop = alloc_loop ();
12371 loop->header = loop_header;
12372 loop->latch = store_bb;
12373 add_loop (loop, loop_header->loop_father);
12375 if (gimple_in_ssa_p (cfun))
12376 update_ssa (TODO_update_ssa_no_phi);
12378 return true;
12381 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12383 GOMP_atomic_start ();
12384 *addr = rhs;
12385 GOMP_atomic_end ();
12387 The result is not globally atomic, but works so long as all parallel
12388 references are within #pragma omp atomic directives. According to
12389 responses received from omp@openmp.org, appears to be within spec.
12390 Which makes sense, since that's how several other compilers handle
12391 this situation as well.
12392 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12393 expanding. STORED_VAL is the operand of the matching
12394 GIMPLE_OMP_ATOMIC_STORE.
12396 We replace
12397 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12398 loaded_val = *addr;
12400 and replace
12401 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12402 *addr = stored_val;
12405 static bool
12406 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12407 tree addr, tree loaded_val, tree stored_val)
12409 gimple_stmt_iterator si;
12410 gassign *stmt;
12411 tree t;
12413 si = gsi_last_bb (load_bb);
12414 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12416 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12417 t = build_call_expr (t, 0);
12418 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12420 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12421 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12422 gsi_remove (&si, true);
12424 si = gsi_last_bb (store_bb);
12425 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12427 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12428 stored_val);
12429 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12431 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12432 t = build_call_expr (t, 0);
12433 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12434 gsi_remove (&si, true);
12436 if (gimple_in_ssa_p (cfun))
12437 update_ssa (TODO_update_ssa_no_phi);
12438 return true;
12441 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12442 using expand_omp_atomic_fetch_op. If it failed, we try to
12443 call expand_omp_atomic_pipeline, and if it fails too, the
12444 ultimate fallback is wrapping the operation in a mutex
12445 (expand_omp_atomic_mutex). REGION is the atomic region built
12446 by build_omp_regions_1(). */
12448 static void
12449 expand_omp_atomic (struct omp_region *region)
12451 basic_block load_bb = region->entry, store_bb = region->exit;
12452 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12453 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12454 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12455 tree addr = gimple_omp_atomic_load_rhs (load);
12456 tree stored_val = gimple_omp_atomic_store_val (store);
12457 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12458 HOST_WIDE_INT index;
12460 /* Make sure the type is one of the supported sizes. */
12461 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12462 index = exact_log2 (index);
12463 if (index >= 0 && index <= 4)
12465 unsigned int align = TYPE_ALIGN_UNIT (type);
12467 /* __sync builtins require strict data alignment. */
12468 if (exact_log2 (align) >= index)
12470 /* Atomic load. */
12471 if (loaded_val == stored_val
12472 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12473 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12474 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12475 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12476 return;
12478 /* Atomic store. */
12479 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12480 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12481 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12482 && store_bb == single_succ (load_bb)
12483 && first_stmt (store_bb) == store
12484 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12485 stored_val, index))
12486 return;
12488 /* When possible, use specialized atomic update functions. */
12489 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12490 && store_bb == single_succ (load_bb)
12491 && expand_omp_atomic_fetch_op (load_bb, addr,
12492 loaded_val, stored_val, index))
12493 return;
12495 /* If we don't have specialized __sync builtins, try and implement
12496 as a compare and swap loop. */
12497 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12498 loaded_val, stored_val, index))
12499 return;
12503 /* The ultimate fallback is wrapping the operation in a mutex. */
12504 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12508 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12509 macro on gomp-constants.h. We do not check for overflow. */
12511 static tree
12512 oacc_launch_pack (unsigned code, tree device, unsigned op)
12514 tree res;
12516 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12517 if (device)
12519 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12520 device, build_int_cst (unsigned_type_node,
12521 GOMP_LAUNCH_DEVICE_SHIFT));
12522 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12524 return res;
12527 /* Look for compute grid dimension clauses and convert to an attribute
12528 attached to FN. This permits the target-side code to (a) massage
12529 the dimensions, (b) emit that data and (c) optimize. Non-constant
12530 dimensions are pushed onto ARGS.
12532 The attribute value is a TREE_LIST. A set of dimensions is
12533 represented as a list of INTEGER_CST. Those that are runtime
12534 exprs are represented as an INTEGER_CST of zero.
12536 TOOO. Normally the attribute will just contain a single such list. If
12537 however it contains a list of lists, this will represent the use of
12538 device_type. Each member of the outer list is an assoc list of
12539 dimensions, keyed by the device type. The first entry will be the
12540 default. Well, that's the plan. */
12542 #define OACC_FN_ATTRIB "oacc function"
12544 /* Replace any existing oacc fn attribute with updated dimensions. */
12546 void
12547 replace_oacc_fn_attrib (tree fn, tree dims)
12549 tree ident = get_identifier (OACC_FN_ATTRIB);
12550 tree attribs = DECL_ATTRIBUTES (fn);
12552 /* If we happen to be present as the first attrib, drop it. */
12553 if (attribs && TREE_PURPOSE (attribs) == ident)
12554 attribs = TREE_CHAIN (attribs);
12555 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12558 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12559 function attribute. Push any that are non-constant onto the ARGS
12560 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12561 true, if these are for a kernels region offload function. */
12563 void
12564 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12566 /* Must match GOMP_DIM ordering. */
12567 static const omp_clause_code ids[]
12568 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12569 OMP_CLAUSE_VECTOR_LENGTH };
12570 unsigned ix;
12571 tree dims[GOMP_DIM_MAX];
12572 tree attr = NULL_TREE;
12573 unsigned non_const = 0;
12575 for (ix = GOMP_DIM_MAX; ix--;)
12577 tree clause = find_omp_clause (clauses, ids[ix]);
12578 tree dim = NULL_TREE;
12580 if (clause)
12581 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12582 dims[ix] = dim;
12583 if (dim && TREE_CODE (dim) != INTEGER_CST)
12585 dim = integer_zero_node;
12586 non_const |= GOMP_DIM_MASK (ix);
12588 attr = tree_cons (NULL_TREE, dim, attr);
12589 /* Note kernelness with TREE_PUBLIC. */
12590 if (is_kernel)
12591 TREE_PUBLIC (attr) = 1;
12594 replace_oacc_fn_attrib (fn, attr);
12596 if (non_const)
12598 /* Push a dynamic argument set. */
12599 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12600 NULL_TREE, non_const));
12601 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12602 if (non_const & GOMP_DIM_MASK (ix))
12603 args->safe_push (dims[ix]);
12607 /* Process the routine's dimension clauess to generate an attribute
12608 value. Issue diagnostics as appropriate. We default to SEQ
12609 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12610 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12611 can have a loop partitioned on it. non-zero indicates
12612 yes, zero indicates no. By construction once a non-zero has been
12613 reached, further inner dimensions must also be non-zero. We set
12614 TREE_VALUE to zero for the dimensions that may be partitioned and
12615 1 for the other ones -- if a loop is (erroneously) spawned at
12616 an outer level, we don't want to try and partition it. */
12618 tree
12619 build_oacc_routine_dims (tree clauses)
12621 /* Must match GOMP_DIM ordering. */
12622 static const omp_clause_code ids[] =
12623 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12624 int ix;
12625 int level = -1;
12627 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12628 for (ix = GOMP_DIM_MAX + 1; ix--;)
12629 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12631 if (level >= 0)
12632 error_at (OMP_CLAUSE_LOCATION (clauses),
12633 "multiple loop axes specified for routine");
12634 level = ix;
12635 break;
12638 /* Default to SEQ. */
12639 if (level < 0)
12640 level = GOMP_DIM_MAX;
12642 tree dims = NULL_TREE;
12644 for (ix = GOMP_DIM_MAX; ix--;)
12645 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12646 build_int_cst (integer_type_node, ix < level), dims);
12648 return dims;
12651 /* Retrieve the oacc function attrib and return it. Non-oacc
12652 functions will return NULL. */
12654 tree
12655 get_oacc_fn_attrib (tree fn)
12657 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12660 /* Return true if this oacc fn attrib is for a kernels offload
12661 region. We use the TREE_PUBLIC flag of each dimension -- only
12662 need to check the first one. */
12664 bool
12665 oacc_fn_attrib_kernels_p (tree attr)
12667 return TREE_PUBLIC (TREE_VALUE (attr));
12670 /* Return level at which oacc routine may spawn a partitioned loop, or
12671 -1 if it is not a routine (i.e. is an offload fn). */
12673 static int
12674 oacc_fn_attrib_level (tree attr)
12676 tree pos = TREE_VALUE (attr);
12678 if (!TREE_PURPOSE (pos))
12679 return -1;
12681 int ix = 0;
12682 for (ix = 0; ix != GOMP_DIM_MAX;
12683 ix++, pos = TREE_CHAIN (pos))
12684 if (!integer_zerop (TREE_PURPOSE (pos)))
12685 break;
12687 return ix;
12690 /* Extract an oacc execution dimension from FN. FN must be an
12691 offloaded function or routine that has already had its execution
12692 dimensions lowered to the target-specific values. */
12695 get_oacc_fn_dim_size (tree fn, int axis)
12697 tree attrs = get_oacc_fn_attrib (fn);
12699 gcc_assert (axis < GOMP_DIM_MAX);
12701 tree dims = TREE_VALUE (attrs);
12702 while (axis--)
12703 dims = TREE_CHAIN (dims);
12705 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12707 return size;
12710 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12711 IFN_GOACC_DIM_SIZE call. */
12714 get_oacc_ifn_dim_arg (const gimple *stmt)
12716 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12717 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12718 tree arg = gimple_call_arg (stmt, 0);
12719 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12721 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12722 return (int) axis;
12725 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12726 at REGION_EXIT. */
12728 static void
12729 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12730 basic_block region_exit)
12732 struct loop *outer = region_entry->loop_father;
12733 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12735 /* Don't parallelize the kernels region if it contains more than one outer
12736 loop. */
12737 unsigned int nr_outer_loops = 0;
12738 struct loop *single_outer = NULL;
12739 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12741 gcc_assert (loop_outer (loop) == outer);
12743 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12744 continue;
12746 if (region_exit != NULL
12747 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12748 continue;
12750 nr_outer_loops++;
12751 single_outer = loop;
12753 if (nr_outer_loops != 1)
12754 return;
12756 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12757 if (loop->next)
12758 return;
12760 /* Mark the loops in the region. */
12761 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12762 loop->in_oacc_kernels_region = true;
12765 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12767 struct GTY(()) grid_launch_attributes_trees
12769 tree kernel_dim_array_type;
12770 tree kernel_lattrs_dimnum_decl;
12771 tree kernel_lattrs_grid_decl;
12772 tree kernel_lattrs_group_decl;
12773 tree kernel_launch_attributes_type;
12776 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12778 /* Create types used to pass kernel launch attributes to target. */
12780 static void
12781 grid_create_kernel_launch_attr_types (void)
12783 if (grid_attr_trees)
12784 return;
12785 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12787 tree dim_arr_index_type
12788 = build_index_type (build_int_cst (integer_type_node, 2));
12789 grid_attr_trees->kernel_dim_array_type
12790 = build_array_type (uint32_type_node, dim_arr_index_type);
12792 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12793 grid_attr_trees->kernel_lattrs_dimnum_decl
12794 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12795 uint32_type_node);
12796 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12798 grid_attr_trees->kernel_lattrs_grid_decl
12799 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12800 grid_attr_trees->kernel_dim_array_type);
12801 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12802 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12803 grid_attr_trees->kernel_lattrs_group_decl
12804 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12805 grid_attr_trees->kernel_dim_array_type);
12806 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12807 = grid_attr_trees->kernel_lattrs_grid_decl;
12808 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12809 "__gomp_kernel_launch_attributes",
12810 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12813 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12814 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12815 of type uint32_type_node. */
12817 static void
12818 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12819 tree fld_decl, int index, tree value)
12821 tree ref = build4 (ARRAY_REF, uint32_type_node,
12822 build3 (COMPONENT_REF,
12823 grid_attr_trees->kernel_dim_array_type,
12824 range_var, fld_decl, NULL_TREE),
12825 build_int_cst (integer_type_node, index),
12826 NULL_TREE, NULL_TREE);
12827 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12830 /* Return a tree representation of a pointer to a structure with grid and
12831 work-group size information. Statements filling that information will be
12832 inserted before GSI, TGT_STMT is the target statement which has the
12833 necessary information in it. */
12835 static tree
12836 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12837 gomp_target *tgt_stmt)
12839 grid_create_kernel_launch_attr_types ();
12840 tree u32_one = build_one_cst (uint32_type_node);
12841 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12842 "__kernel_launch_attrs");
12844 unsigned max_dim = 0;
12845 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12846 clause;
12847 clause = OMP_CLAUSE_CHAIN (clause))
12849 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12850 continue;
12852 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12853 max_dim = MAX (dim, max_dim);
12855 grid_insert_store_range_dim (gsi, lattrs,
12856 grid_attr_trees->kernel_lattrs_grid_decl,
12857 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12858 grid_insert_store_range_dim (gsi, lattrs,
12859 grid_attr_trees->kernel_lattrs_group_decl,
12860 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12863 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12864 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12865 /* At this moment we cannot gridify a loop with a collapse clause. */
12866 /* TODO: Adjust when we support bigger collapse. */
12867 gcc_assert (max_dim == 0);
12868 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12869 TREE_ADDRESSABLE (lattrs) = 1;
12870 return build_fold_addr_expr (lattrs);
12873 /* Build target argument identifier from the DEVICE identifier, value
12874 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12876 static tree
12877 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12879 tree t = build_int_cst (integer_type_node, device);
12880 if (subseqent_param)
12881 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12882 build_int_cst (integer_type_node,
12883 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12884 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12885 build_int_cst (integer_type_node, id));
12886 return t;
12889 /* Like above but return it in type that can be directly stored as an element
12890 of the argument array. */
12892 static tree
12893 get_target_argument_identifier (int device, bool subseqent_param, int id)
12895 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12896 return fold_convert (ptr_type_node, t);
12899 /* Return a target argument consisting of DEVICE identifier, value identifier
12900 ID, and the actual VALUE. */
12902 static tree
12903 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12904 tree value)
12906 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12907 fold_convert (integer_type_node, value),
12908 build_int_cst (unsigned_type_node,
12909 GOMP_TARGET_ARG_VALUE_SHIFT));
12910 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12911 get_target_argument_identifier_1 (device, false, id));
12912 t = fold_convert (ptr_type_node, t);
12913 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12916 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12917 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12918 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12919 arguments. */
12921 static void
12922 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12923 int id, tree value, vec <tree> *args)
12925 if (tree_fits_shwi_p (value)
12926 && tree_to_shwi (value) > -(1 << 15)
12927 && tree_to_shwi (value) < (1 << 15))
12928 args->quick_push (get_target_argument_value (gsi, device, id, value));
12929 else
12931 args->quick_push (get_target_argument_identifier (device, true, id));
12932 value = fold_convert (ptr_type_node, value);
12933 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12934 GSI_SAME_STMT);
12935 args->quick_push (value);
12939 /* Create an array of arguments that is then passed to GOMP_target. */
12941 static tree
12942 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12944 auto_vec <tree, 6> args;
12945 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12946 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12947 if (c)
12948 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12949 else
12950 t = integer_minus_one_node;
12951 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12952 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12954 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12955 if (c)
12956 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12957 else
12958 t = integer_minus_one_node;
12959 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12960 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12961 &args);
12963 /* Add HSA-specific grid sizes, if available. */
12964 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12965 OMP_CLAUSE__GRIDDIM_))
12967 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12968 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12969 args.quick_push (t);
12970 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12973 /* Produce more, perhaps device specific, arguments here. */
12975 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12976 args.length () + 1),
12977 ".omp_target_args");
12978 for (unsigned i = 0; i < args.length (); i++)
12980 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12981 build_int_cst (integer_type_node, i),
12982 NULL_TREE, NULL_TREE);
12983 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12984 GSI_SAME_STMT);
12986 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12987 build_int_cst (integer_type_node, args.length ()),
12988 NULL_TREE, NULL_TREE);
12989 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12990 GSI_SAME_STMT);
12991 TREE_ADDRESSABLE (argarray) = 1;
12992 return build_fold_addr_expr (argarray);
12995 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12997 static void
12998 expand_omp_target (struct omp_region *region)
13000 basic_block entry_bb, exit_bb, new_bb;
13001 struct function *child_cfun;
13002 tree child_fn, block, t;
13003 gimple_stmt_iterator gsi;
13004 gomp_target *entry_stmt;
13005 gimple *stmt;
13006 edge e;
13007 bool offloaded, data_region;
13009 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13010 new_bb = region->entry;
13012 offloaded = is_gimple_omp_offloaded (entry_stmt);
13013 switch (gimple_omp_target_kind (entry_stmt))
13015 case GF_OMP_TARGET_KIND_REGION:
13016 case GF_OMP_TARGET_KIND_UPDATE:
13017 case GF_OMP_TARGET_KIND_ENTER_DATA:
13018 case GF_OMP_TARGET_KIND_EXIT_DATA:
13019 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13020 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13021 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13022 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13023 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13024 data_region = false;
13025 break;
13026 case GF_OMP_TARGET_KIND_DATA:
13027 case GF_OMP_TARGET_KIND_OACC_DATA:
13028 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13029 data_region = true;
13030 break;
13031 default:
13032 gcc_unreachable ();
13035 child_fn = NULL_TREE;
13036 child_cfun = NULL;
13037 if (offloaded)
13039 child_fn = gimple_omp_target_child_fn (entry_stmt);
13040 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13043 /* Supported by expand_omp_taskreg, but not here. */
13044 if (child_cfun != NULL)
13045 gcc_checking_assert (!child_cfun->cfg);
13046 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13048 entry_bb = region->entry;
13049 exit_bb = region->exit;
13051 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13052 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13054 if (offloaded)
13056 unsigned srcidx, dstidx, num;
13058 /* If the offloading region needs data sent from the parent
13059 function, then the very first statement (except possible
13060 tree profile counter updates) of the offloading body
13061 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13062 &.OMP_DATA_O is passed as an argument to the child function,
13063 we need to replace it with the argument as seen by the child
13064 function.
13066 In most cases, this will end up being the identity assignment
13067 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13068 a function call that has been inlined, the original PARM_DECL
13069 .OMP_DATA_I may have been converted into a different local
13070 variable. In which case, we need to keep the assignment. */
13071 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13072 if (data_arg)
13074 basic_block entry_succ_bb = single_succ (entry_bb);
13075 gimple_stmt_iterator gsi;
13076 tree arg;
13077 gimple *tgtcopy_stmt = NULL;
13078 tree sender = TREE_VEC_ELT (data_arg, 0);
13080 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13082 gcc_assert (!gsi_end_p (gsi));
13083 stmt = gsi_stmt (gsi);
13084 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13085 continue;
13087 if (gimple_num_ops (stmt) == 2)
13089 tree arg = gimple_assign_rhs1 (stmt);
13091 /* We're ignoring the subcode because we're
13092 effectively doing a STRIP_NOPS. */
13094 if (TREE_CODE (arg) == ADDR_EXPR
13095 && TREE_OPERAND (arg, 0) == sender)
13097 tgtcopy_stmt = stmt;
13098 break;
13103 gcc_assert (tgtcopy_stmt != NULL);
13104 arg = DECL_ARGUMENTS (child_fn);
13106 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13107 gsi_remove (&gsi, true);
13110 /* Declare local variables needed in CHILD_CFUN. */
13111 block = DECL_INITIAL (child_fn);
13112 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13113 /* The gimplifier could record temporaries in the offloading block
13114 rather than in containing function's local_decls chain,
13115 which would mean cgraph missed finalizing them. Do it now. */
13116 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13117 if (TREE_CODE (t) == VAR_DECL
13118 && TREE_STATIC (t)
13119 && !DECL_EXTERNAL (t))
13120 varpool_node::finalize_decl (t);
13121 DECL_SAVED_TREE (child_fn) = NULL;
13122 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13123 gimple_set_body (child_fn, NULL);
13124 TREE_USED (block) = 1;
13126 /* Reset DECL_CONTEXT on function arguments. */
13127 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13128 DECL_CONTEXT (t) = child_fn;
13130 /* Split ENTRY_BB at GIMPLE_*,
13131 so that it can be moved to the child function. */
13132 gsi = gsi_last_bb (entry_bb);
13133 stmt = gsi_stmt (gsi);
13134 gcc_assert (stmt
13135 && gimple_code (stmt) == gimple_code (entry_stmt));
13136 e = split_block (entry_bb, stmt);
13137 gsi_remove (&gsi, true);
13138 entry_bb = e->dest;
13139 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13141 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13142 if (exit_bb)
13144 gsi = gsi_last_bb (exit_bb);
13145 gcc_assert (!gsi_end_p (gsi)
13146 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13147 stmt = gimple_build_return (NULL);
13148 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13149 gsi_remove (&gsi, true);
13152 /* Move the offloading region into CHILD_CFUN. */
13154 block = gimple_block (entry_stmt);
13156 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13157 if (exit_bb)
13158 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13159 /* When the OMP expansion process cannot guarantee an up-to-date
13160 loop tree arrange for the child function to fixup loops. */
13161 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13162 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13164 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13165 num = vec_safe_length (child_cfun->local_decls);
13166 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13168 t = (*child_cfun->local_decls)[srcidx];
13169 if (DECL_CONTEXT (t) == cfun->decl)
13170 continue;
13171 if (srcidx != dstidx)
13172 (*child_cfun->local_decls)[dstidx] = t;
13173 dstidx++;
13175 if (dstidx != num)
13176 vec_safe_truncate (child_cfun->local_decls, dstidx);
13178 /* Inform the callgraph about the new function. */
13179 child_cfun->curr_properties = cfun->curr_properties;
13180 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13181 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13182 cgraph_node *node = cgraph_node::get_create (child_fn);
13183 node->parallelized_function = 1;
13184 cgraph_node::add_new_function (child_fn, true);
13186 /* Add the new function to the offload table. */
13187 if (ENABLE_OFFLOADING)
13188 vec_safe_push (offload_funcs, child_fn);
13190 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13191 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13193 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13194 fixed in a following pass. */
13195 push_cfun (child_cfun);
13196 if (need_asm)
13197 assign_assembler_name_if_neeeded (child_fn);
13198 cgraph_edge::rebuild_edges ();
13200 /* Some EH regions might become dead, see PR34608. If
13201 pass_cleanup_cfg isn't the first pass to happen with the
13202 new child, these dead EH edges might cause problems.
13203 Clean them up now. */
13204 if (flag_exceptions)
13206 basic_block bb;
13207 bool changed = false;
13209 FOR_EACH_BB_FN (bb, cfun)
13210 changed |= gimple_purge_dead_eh_edges (bb);
13211 if (changed)
13212 cleanup_tree_cfg ();
13214 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13215 verify_loop_structure ();
13216 pop_cfun ();
13218 if (dump_file && !gimple_in_ssa_p (cfun))
13220 omp_any_child_fn_dumped = true;
13221 dump_function_header (dump_file, child_fn, dump_flags);
13222 dump_function_to_file (child_fn, dump_file, dump_flags);
13226 /* Emit a library call to launch the offloading region, or do data
13227 transfers. */
13228 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13229 enum built_in_function start_ix;
13230 location_t clause_loc;
13231 unsigned int flags_i = 0;
13232 bool oacc_kernels_p = false;
13234 switch (gimple_omp_target_kind (entry_stmt))
13236 case GF_OMP_TARGET_KIND_REGION:
13237 start_ix = BUILT_IN_GOMP_TARGET;
13238 break;
13239 case GF_OMP_TARGET_KIND_DATA:
13240 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13241 break;
13242 case GF_OMP_TARGET_KIND_UPDATE:
13243 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13244 break;
13245 case GF_OMP_TARGET_KIND_ENTER_DATA:
13246 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13247 break;
13248 case GF_OMP_TARGET_KIND_EXIT_DATA:
13249 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13250 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13251 break;
13252 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13253 oacc_kernels_p = true;
13254 /* FALLTHROUGH */
13255 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13256 start_ix = BUILT_IN_GOACC_PARALLEL;
13257 break;
13258 case GF_OMP_TARGET_KIND_OACC_DATA:
13259 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13260 start_ix = BUILT_IN_GOACC_DATA_START;
13261 break;
13262 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13263 start_ix = BUILT_IN_GOACC_UPDATE;
13264 break;
13265 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13266 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13267 break;
13268 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13269 start_ix = BUILT_IN_GOACC_DECLARE;
13270 break;
13271 default:
13272 gcc_unreachable ();
13275 clauses = gimple_omp_target_clauses (entry_stmt);
13277 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13278 library choose) and there is no conditional. */
13279 cond = NULL_TREE;
13280 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13282 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13283 if (c)
13284 cond = OMP_CLAUSE_IF_EXPR (c);
13286 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13287 if (c)
13289 /* Even if we pass it to all library function calls, it is currently only
13290 defined/used for the OpenMP target ones. */
13291 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13292 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13293 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13294 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13296 device = OMP_CLAUSE_DEVICE_ID (c);
13297 clause_loc = OMP_CLAUSE_LOCATION (c);
13299 else
13300 clause_loc = gimple_location (entry_stmt);
13302 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13303 if (c)
13304 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13306 /* Ensure 'device' is of the correct type. */
13307 device = fold_convert_loc (clause_loc, integer_type_node, device);
13309 /* If we found the clause 'if (cond)', build
13310 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13311 if (cond)
13313 cond = gimple_boolify (cond);
13315 basic_block cond_bb, then_bb, else_bb;
13316 edge e;
13317 tree tmp_var;
13319 tmp_var = create_tmp_var (TREE_TYPE (device));
13320 if (offloaded)
13321 e = split_block_after_labels (new_bb);
13322 else
13324 gsi = gsi_last_bb (new_bb);
13325 gsi_prev (&gsi);
13326 e = split_block (new_bb, gsi_stmt (gsi));
13328 cond_bb = e->src;
13329 new_bb = e->dest;
13330 remove_edge (e);
13332 then_bb = create_empty_bb (cond_bb);
13333 else_bb = create_empty_bb (then_bb);
13334 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13335 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13337 stmt = gimple_build_cond_empty (cond);
13338 gsi = gsi_last_bb (cond_bb);
13339 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13341 gsi = gsi_start_bb (then_bb);
13342 stmt = gimple_build_assign (tmp_var, device);
13343 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13345 gsi = gsi_start_bb (else_bb);
13346 stmt = gimple_build_assign (tmp_var,
13347 build_int_cst (integer_type_node,
13348 GOMP_DEVICE_HOST_FALLBACK));
13349 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13351 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13352 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13353 add_bb_to_loop (then_bb, cond_bb->loop_father);
13354 add_bb_to_loop (else_bb, cond_bb->loop_father);
13355 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13356 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13358 device = tmp_var;
13361 gsi = gsi_last_bb (new_bb);
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 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13685 kern_cfun->curr_properties = cfun->curr_properties;
13687 remove_edge (BRANCH_EDGE (kfor->entry));
13688 grid_expand_omp_for_loop (kfor);
13690 /* Remove the omp for statement */
13691 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13692 gsi_remove (&gsi, true);
13693 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13694 return. */
13695 gsi = gsi_last_bb (gpukernel->exit);
13696 gcc_assert (!gsi_end_p (gsi)
13697 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13698 gimple *ret_stmt = gimple_build_return (NULL);
13699 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13700 gsi_remove (&gsi, true);
13702 /* Statements in the first BB in the target construct have been produced by
13703 target lowering and must be copied inside the GPUKERNEL, with the two
13704 exceptions of the first OMP statement and the OMP_DATA assignment
13705 statement. */
13706 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13707 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13708 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13709 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13710 !gsi_end_p (tsi); gsi_next (&tsi))
13712 gimple *stmt = gsi_stmt (tsi);
13713 if (is_gimple_omp (stmt))
13714 break;
13715 if (sender
13716 && is_gimple_assign (stmt)
13717 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13718 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13719 continue;
13720 gimple *copy = gimple_copy (stmt);
13721 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13722 gimple_set_block (copy, fniniblock);
13725 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13726 gpukernel->exit, inside_block);
13728 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13729 kcn->mark_force_output ();
13730 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13732 hsa_register_kernel (kcn, orig_child);
13734 cgraph_node::add_new_function (kern_fndecl, true);
13735 push_cfun (kern_cfun);
13736 cgraph_edge::rebuild_edges ();
13738 /* Re-map any mention of the PARM_DECL of the original function to the
13739 PARM_DECL of the new one.
13741 TODO: It would be great if lowering produced references into the GPU
13742 kernel decl straight away and we did not have to do this. */
13743 struct grid_arg_decl_map adm;
13744 adm.old_arg = old_parm_decl;
13745 adm.new_arg = new_parm_decl;
13746 basic_block bb;
13747 FOR_EACH_BB_FN (bb, kern_cfun)
13749 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13751 gimple *stmt = gsi_stmt (gsi);
13752 struct walk_stmt_info wi;
13753 memset (&wi, 0, sizeof (wi));
13754 wi.info = &adm;
13755 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13758 pop_cfun ();
13760 return;
13763 /* Expand the parallel region tree rooted at REGION. Expansion
13764 proceeds in depth-first order. Innermost regions are expanded
13765 first. This way, parallel regions that require a new function to
13766 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13767 internal dependencies in their body. */
13769 static void
13770 expand_omp (struct omp_region *region)
13772 omp_any_child_fn_dumped = false;
13773 while (region)
13775 location_t saved_location;
13776 gimple *inner_stmt = NULL;
13778 /* First, determine whether this is a combined parallel+workshare
13779 region. */
13780 if (region->type == GIMPLE_OMP_PARALLEL)
13781 determine_parallel_type (region);
13782 else if (region->type == GIMPLE_OMP_TARGET)
13783 grid_expand_target_grid_body (region);
13785 if (region->type == GIMPLE_OMP_FOR
13786 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13787 inner_stmt = last_stmt (region->inner->entry);
13789 if (region->inner)
13790 expand_omp (region->inner);
13792 saved_location = input_location;
13793 if (gimple_has_location (last_stmt (region->entry)))
13794 input_location = gimple_location (last_stmt (region->entry));
13796 switch (region->type)
13798 case GIMPLE_OMP_PARALLEL:
13799 case GIMPLE_OMP_TASK:
13800 expand_omp_taskreg (region);
13801 break;
13803 case GIMPLE_OMP_FOR:
13804 expand_omp_for (region, inner_stmt);
13805 break;
13807 case GIMPLE_OMP_SECTIONS:
13808 expand_omp_sections (region);
13809 break;
13811 case GIMPLE_OMP_SECTION:
13812 /* Individual omp sections are handled together with their
13813 parent GIMPLE_OMP_SECTIONS region. */
13814 break;
13816 case GIMPLE_OMP_SINGLE:
13817 expand_omp_single (region);
13818 break;
13820 case GIMPLE_OMP_ORDERED:
13822 gomp_ordered *ord_stmt
13823 = as_a <gomp_ordered *> (last_stmt (region->entry));
13824 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13825 OMP_CLAUSE_DEPEND))
13827 /* We'll expand these when expanding corresponding
13828 worksharing region with ordered(n) clause. */
13829 gcc_assert (region->outer
13830 && region->outer->type == GIMPLE_OMP_FOR);
13831 region->ord_stmt = ord_stmt;
13832 break;
13835 /* FALLTHRU */
13836 case GIMPLE_OMP_MASTER:
13837 case GIMPLE_OMP_TASKGROUP:
13838 case GIMPLE_OMP_CRITICAL:
13839 case GIMPLE_OMP_TEAMS:
13840 expand_omp_synch (region);
13841 break;
13843 case GIMPLE_OMP_ATOMIC_LOAD:
13844 expand_omp_atomic (region);
13845 break;
13847 case GIMPLE_OMP_TARGET:
13848 expand_omp_target (region);
13849 break;
13851 default:
13852 gcc_unreachable ();
13855 input_location = saved_location;
13856 region = region->next;
13858 if (omp_any_child_fn_dumped)
13860 if (dump_file)
13861 dump_function_header (dump_file, current_function_decl, dump_flags);
13862 omp_any_child_fn_dumped = false;
13867 /* Helper for build_omp_regions. Scan the dominator tree starting at
13868 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13869 true, the function ends once a single tree is built (otherwise, whole
13870 forest of OMP constructs may be built). */
13872 static void
13873 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13874 bool single_tree)
13876 gimple_stmt_iterator gsi;
13877 gimple *stmt;
13878 basic_block son;
13880 gsi = gsi_last_bb (bb);
13881 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13883 struct omp_region *region;
13884 enum gimple_code code;
13886 stmt = gsi_stmt (gsi);
13887 code = gimple_code (stmt);
13888 if (code == GIMPLE_OMP_RETURN)
13890 /* STMT is the return point out of region PARENT. Mark it
13891 as the exit point and make PARENT the immediately
13892 enclosing region. */
13893 gcc_assert (parent);
13894 region = parent;
13895 region->exit = bb;
13896 parent = parent->outer;
13898 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13900 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13901 GIMPLE_OMP_RETURN, but matches with
13902 GIMPLE_OMP_ATOMIC_LOAD. */
13903 gcc_assert (parent);
13904 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13905 region = parent;
13906 region->exit = bb;
13907 parent = parent->outer;
13909 else if (code == GIMPLE_OMP_CONTINUE)
13911 gcc_assert (parent);
13912 parent->cont = bb;
13914 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13916 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13917 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13919 else
13921 region = new_omp_region (bb, code, parent);
13922 /* Otherwise... */
13923 if (code == GIMPLE_OMP_TARGET)
13925 switch (gimple_omp_target_kind (stmt))
13927 case GF_OMP_TARGET_KIND_REGION:
13928 case GF_OMP_TARGET_KIND_DATA:
13929 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13930 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13931 case GF_OMP_TARGET_KIND_OACC_DATA:
13932 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13933 break;
13934 case GF_OMP_TARGET_KIND_UPDATE:
13935 case GF_OMP_TARGET_KIND_ENTER_DATA:
13936 case GF_OMP_TARGET_KIND_EXIT_DATA:
13937 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13938 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13939 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13940 /* ..., other than for those stand-alone directives... */
13941 region = NULL;
13942 break;
13943 default:
13944 gcc_unreachable ();
13947 else if (code == GIMPLE_OMP_ORDERED
13948 && find_omp_clause (gimple_omp_ordered_clauses
13949 (as_a <gomp_ordered *> (stmt)),
13950 OMP_CLAUSE_DEPEND))
13951 /* #pragma omp ordered depend is also just a stand-alone
13952 directive. */
13953 region = NULL;
13954 /* ..., this directive becomes the parent for a new region. */
13955 if (region)
13956 parent = region;
13960 if (single_tree && !parent)
13961 return;
13963 for (son = first_dom_son (CDI_DOMINATORS, bb);
13964 son;
13965 son = next_dom_son (CDI_DOMINATORS, son))
13966 build_omp_regions_1 (son, parent, single_tree);
13969 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13970 root_omp_region. */
13972 static void
13973 build_omp_regions_root (basic_block root)
13975 gcc_assert (root_omp_region == NULL);
13976 build_omp_regions_1 (root, NULL, true);
13977 gcc_assert (root_omp_region != NULL);
13980 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13982 void
13983 omp_expand_local (basic_block head)
13985 build_omp_regions_root (head);
13986 if (dump_file && (dump_flags & TDF_DETAILS))
13988 fprintf (dump_file, "\nOMP region tree\n\n");
13989 dump_omp_region (dump_file, root_omp_region, 0);
13990 fprintf (dump_file, "\n");
13993 remove_exit_barriers (root_omp_region);
13994 expand_omp (root_omp_region);
13996 free_omp_regions ();
13999 /* Scan the CFG and build a tree of OMP regions. Return the root of
14000 the OMP region tree. */
14002 static void
14003 build_omp_regions (void)
14005 gcc_assert (root_omp_region == NULL);
14006 calculate_dominance_info (CDI_DOMINATORS);
14007 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14010 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14012 static unsigned int
14013 execute_expand_omp (void)
14015 build_omp_regions ();
14017 if (!root_omp_region)
14018 return 0;
14020 if (dump_file)
14022 fprintf (dump_file, "\nOMP region tree\n\n");
14023 dump_omp_region (dump_file, root_omp_region, 0);
14024 fprintf (dump_file, "\n");
14027 remove_exit_barriers (root_omp_region);
14029 expand_omp (root_omp_region);
14031 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14032 verify_loop_structure ();
14033 cleanup_tree_cfg ();
14035 free_omp_regions ();
14037 return 0;
14040 /* OMP expansion -- the default pass, run before creation of SSA form. */
14042 namespace {
14044 const pass_data pass_data_expand_omp =
14046 GIMPLE_PASS, /* type */
14047 "ompexp", /* name */
14048 OPTGROUP_NONE, /* optinfo_flags */
14049 TV_NONE, /* tv_id */
14050 PROP_gimple_any, /* properties_required */
14051 PROP_gimple_eomp, /* properties_provided */
14052 0, /* properties_destroyed */
14053 0, /* todo_flags_start */
14054 0, /* todo_flags_finish */
14057 class pass_expand_omp : public gimple_opt_pass
14059 public:
14060 pass_expand_omp (gcc::context *ctxt)
14061 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14064 /* opt_pass methods: */
14065 virtual unsigned int execute (function *)
14067 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14068 || flag_openmp_simd != 0)
14069 && !seen_error ());
14071 /* This pass always runs, to provide PROP_gimple_eomp.
14072 But often, there is nothing to do. */
14073 if (!gate)
14074 return 0;
14076 return execute_expand_omp ();
14079 }; // class pass_expand_omp
14081 } // anon namespace
14083 gimple_opt_pass *
14084 make_pass_expand_omp (gcc::context *ctxt)
14086 return new pass_expand_omp (ctxt);
14089 namespace {
14091 const pass_data pass_data_expand_omp_ssa =
14093 GIMPLE_PASS, /* type */
14094 "ompexpssa", /* name */
14095 OPTGROUP_NONE, /* optinfo_flags */
14096 TV_NONE, /* tv_id */
14097 PROP_cfg | PROP_ssa, /* properties_required */
14098 PROP_gimple_eomp, /* properties_provided */
14099 0, /* properties_destroyed */
14100 0, /* todo_flags_start */
14101 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14104 class pass_expand_omp_ssa : public gimple_opt_pass
14106 public:
14107 pass_expand_omp_ssa (gcc::context *ctxt)
14108 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14111 /* opt_pass methods: */
14112 virtual bool gate (function *fun)
14114 return !(fun->curr_properties & PROP_gimple_eomp);
14116 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14117 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14119 }; // class pass_expand_omp_ssa
14121 } // anon namespace
14123 gimple_opt_pass *
14124 make_pass_expand_omp_ssa (gcc::context *ctxt)
14126 return new pass_expand_omp_ssa (ctxt);
14129 /* Routines to lower OMP directives into OMP-GIMPLE. */
14131 /* If ctx is a worksharing context inside of a cancellable parallel
14132 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14133 and conditional branch to parallel's cancel_label to handle
14134 cancellation in the implicit barrier. */
14136 static void
14137 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14139 gimple *omp_return = gimple_seq_last_stmt (*body);
14140 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14141 if (gimple_omp_return_nowait_p (omp_return))
14142 return;
14143 if (ctx->outer
14144 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14145 && ctx->outer->cancellable)
14147 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14148 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14149 tree lhs = create_tmp_var (c_bool_type);
14150 gimple_omp_return_set_lhs (omp_return, lhs);
14151 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14152 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14153 fold_convert (c_bool_type,
14154 boolean_false_node),
14155 ctx->outer->cancel_label, fallthru_label);
14156 gimple_seq_add_stmt (body, g);
14157 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14161 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14162 CTX is the enclosing OMP context for the current statement. */
14164 static void
14165 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14167 tree block, control;
14168 gimple_stmt_iterator tgsi;
14169 gomp_sections *stmt;
14170 gimple *t;
14171 gbind *new_stmt, *bind;
14172 gimple_seq ilist, dlist, olist, new_body;
14174 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14176 push_gimplify_context ();
14178 dlist = NULL;
14179 ilist = NULL;
14180 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14181 &ilist, &dlist, ctx, NULL);
14183 new_body = gimple_omp_body (stmt);
14184 gimple_omp_set_body (stmt, NULL);
14185 tgsi = gsi_start (new_body);
14186 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14188 omp_context *sctx;
14189 gimple *sec_start;
14191 sec_start = gsi_stmt (tgsi);
14192 sctx = maybe_lookup_ctx (sec_start);
14193 gcc_assert (sctx);
14195 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14196 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14197 GSI_CONTINUE_LINKING);
14198 gimple_omp_set_body (sec_start, NULL);
14200 if (gsi_one_before_end_p (tgsi))
14202 gimple_seq l = NULL;
14203 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14204 &l, ctx);
14205 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14206 gimple_omp_section_set_last (sec_start);
14209 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14210 GSI_CONTINUE_LINKING);
14213 block = make_node (BLOCK);
14214 bind = gimple_build_bind (NULL, new_body, block);
14216 olist = NULL;
14217 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14219 block = make_node (BLOCK);
14220 new_stmt = gimple_build_bind (NULL, NULL, block);
14221 gsi_replace (gsi_p, new_stmt, true);
14223 pop_gimplify_context (new_stmt);
14224 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14225 BLOCK_VARS (block) = gimple_bind_vars (bind);
14226 if (BLOCK_VARS (block))
14227 TREE_USED (block) = 1;
14229 new_body = NULL;
14230 gimple_seq_add_seq (&new_body, ilist);
14231 gimple_seq_add_stmt (&new_body, stmt);
14232 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14233 gimple_seq_add_stmt (&new_body, bind);
14235 control = create_tmp_var (unsigned_type_node, ".section");
14236 t = gimple_build_omp_continue (control, control);
14237 gimple_omp_sections_set_control (stmt, control);
14238 gimple_seq_add_stmt (&new_body, t);
14240 gimple_seq_add_seq (&new_body, olist);
14241 if (ctx->cancellable)
14242 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14243 gimple_seq_add_seq (&new_body, dlist);
14245 new_body = maybe_catch_exception (new_body);
14247 t = gimple_build_omp_return
14248 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14249 OMP_CLAUSE_NOWAIT));
14250 gimple_seq_add_stmt (&new_body, t);
14251 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14253 gimple_bind_set_body (new_stmt, new_body);
14257 /* A subroutine of lower_omp_single. Expand the simple form of
14258 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14260 if (GOMP_single_start ())
14261 BODY;
14262 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14264 FIXME. It may be better to delay expanding the logic of this until
14265 pass_expand_omp. The expanded logic may make the job more difficult
14266 to a synchronization analysis pass. */
14268 static void
14269 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14271 location_t loc = gimple_location (single_stmt);
14272 tree tlabel = create_artificial_label (loc);
14273 tree flabel = create_artificial_label (loc);
14274 gimple *call, *cond;
14275 tree lhs, decl;
14277 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14278 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14279 call = gimple_build_call (decl, 0);
14280 gimple_call_set_lhs (call, lhs);
14281 gimple_seq_add_stmt (pre_p, call);
14283 cond = gimple_build_cond (EQ_EXPR, lhs,
14284 fold_convert_loc (loc, TREE_TYPE (lhs),
14285 boolean_true_node),
14286 tlabel, flabel);
14287 gimple_seq_add_stmt (pre_p, cond);
14288 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14289 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14290 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14294 /* A subroutine of lower_omp_single. Expand the simple form of
14295 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14297 #pragma omp single copyprivate (a, b, c)
14299 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14302 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14304 BODY;
14305 copyout.a = a;
14306 copyout.b = b;
14307 copyout.c = c;
14308 GOMP_single_copy_end (&copyout);
14310 else
14312 a = copyout_p->a;
14313 b = copyout_p->b;
14314 c = copyout_p->c;
14316 GOMP_barrier ();
14319 FIXME. It may be better to delay expanding the logic of this until
14320 pass_expand_omp. The expanded logic may make the job more difficult
14321 to a synchronization analysis pass. */
14323 static void
14324 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14325 omp_context *ctx)
14327 tree ptr_type, t, l0, l1, l2, bfn_decl;
14328 gimple_seq copyin_seq;
14329 location_t loc = gimple_location (single_stmt);
14331 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14333 ptr_type = build_pointer_type (ctx->record_type);
14334 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14336 l0 = create_artificial_label (loc);
14337 l1 = create_artificial_label (loc);
14338 l2 = create_artificial_label (loc);
14340 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14341 t = build_call_expr_loc (loc, bfn_decl, 0);
14342 t = fold_convert_loc (loc, ptr_type, t);
14343 gimplify_assign (ctx->receiver_decl, t, pre_p);
14345 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14346 build_int_cst (ptr_type, 0));
14347 t = build3 (COND_EXPR, void_type_node, t,
14348 build_and_jump (&l0), build_and_jump (&l1));
14349 gimplify_and_add (t, pre_p);
14351 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14353 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14355 copyin_seq = NULL;
14356 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14357 &copyin_seq, ctx);
14359 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14360 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14361 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14362 gimplify_and_add (t, pre_p);
14364 t = build_and_jump (&l2);
14365 gimplify_and_add (t, pre_p);
14367 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14369 gimple_seq_add_seq (pre_p, copyin_seq);
14371 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14375 /* Expand code for an OpenMP single directive. */
14377 static void
14378 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14380 tree block;
14381 gimple *t;
14382 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14383 gbind *bind;
14384 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14386 push_gimplify_context ();
14388 block = make_node (BLOCK);
14389 bind = gimple_build_bind (NULL, NULL, block);
14390 gsi_replace (gsi_p, bind, true);
14391 bind_body = NULL;
14392 dlist = NULL;
14393 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14394 &bind_body, &dlist, ctx, NULL);
14395 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14397 gimple_seq_add_stmt (&bind_body, single_stmt);
14399 if (ctx->record_type)
14400 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14401 else
14402 lower_omp_single_simple (single_stmt, &bind_body);
14404 gimple_omp_set_body (single_stmt, NULL);
14406 gimple_seq_add_seq (&bind_body, dlist);
14408 bind_body = maybe_catch_exception (bind_body);
14410 t = gimple_build_omp_return
14411 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14412 OMP_CLAUSE_NOWAIT));
14413 gimple_seq_add_stmt (&bind_body_tail, t);
14414 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14415 if (ctx->record_type)
14417 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14418 tree clobber = build_constructor (ctx->record_type, NULL);
14419 TREE_THIS_VOLATILE (clobber) = 1;
14420 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14421 clobber), GSI_SAME_STMT);
14423 gimple_seq_add_seq (&bind_body, bind_body_tail);
14424 gimple_bind_set_body (bind, bind_body);
14426 pop_gimplify_context (bind);
14428 gimple_bind_append_vars (bind, ctx->block_vars);
14429 BLOCK_VARS (block) = ctx->block_vars;
14430 if (BLOCK_VARS (block))
14431 TREE_USED (block) = 1;
14435 /* Expand code for an OpenMP master directive. */
14437 static void
14438 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14440 tree block, lab = NULL, x, bfn_decl;
14441 gimple *stmt = gsi_stmt (*gsi_p);
14442 gbind *bind;
14443 location_t loc = gimple_location (stmt);
14444 gimple_seq tseq;
14446 push_gimplify_context ();
14448 block = make_node (BLOCK);
14449 bind = gimple_build_bind (NULL, NULL, block);
14450 gsi_replace (gsi_p, bind, true);
14451 gimple_bind_add_stmt (bind, stmt);
14453 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14454 x = build_call_expr_loc (loc, bfn_decl, 0);
14455 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14456 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14457 tseq = NULL;
14458 gimplify_and_add (x, &tseq);
14459 gimple_bind_add_seq (bind, tseq);
14461 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14462 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14463 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14464 gimple_omp_set_body (stmt, NULL);
14466 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14468 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14470 pop_gimplify_context (bind);
14472 gimple_bind_append_vars (bind, ctx->block_vars);
14473 BLOCK_VARS (block) = ctx->block_vars;
14477 /* Expand code for an OpenMP taskgroup directive. */
14479 static void
14480 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14482 gimple *stmt = gsi_stmt (*gsi_p);
14483 gcall *x;
14484 gbind *bind;
14485 tree block = make_node (BLOCK);
14487 bind = gimple_build_bind (NULL, NULL, block);
14488 gsi_replace (gsi_p, bind, true);
14489 gimple_bind_add_stmt (bind, stmt);
14491 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14493 gimple_bind_add_stmt (bind, x);
14495 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14496 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14497 gimple_omp_set_body (stmt, NULL);
14499 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14501 gimple_bind_append_vars (bind, ctx->block_vars);
14502 BLOCK_VARS (block) = ctx->block_vars;
14506 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14508 static void
14509 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14510 omp_context *ctx)
14512 struct omp_for_data fd;
14513 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14514 return;
14516 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14517 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14518 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14519 if (!fd.ordered)
14520 return;
14522 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14523 tree c = gimple_omp_ordered_clauses (ord_stmt);
14524 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14525 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14527 /* Merge depend clauses from multiple adjacent
14528 #pragma omp ordered depend(sink:...) constructs
14529 into one #pragma omp ordered depend(sink:...), so that
14530 we can optimize them together. */
14531 gimple_stmt_iterator gsi = *gsi_p;
14532 gsi_next (&gsi);
14533 while (!gsi_end_p (gsi))
14535 gimple *stmt = gsi_stmt (gsi);
14536 if (is_gimple_debug (stmt)
14537 || gimple_code (stmt) == GIMPLE_NOP)
14539 gsi_next (&gsi);
14540 continue;
14542 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14543 break;
14544 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14545 c = gimple_omp_ordered_clauses (ord_stmt2);
14546 if (c == NULL_TREE
14547 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14548 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14549 break;
14550 while (*list_p)
14551 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14552 *list_p = c;
14553 gsi_remove (&gsi, true);
14557 /* Canonicalize sink dependence clauses into one folded clause if
14558 possible.
14560 The basic algorithm is to create a sink vector whose first
14561 element is the GCD of all the first elements, and whose remaining
14562 elements are the minimum of the subsequent columns.
14564 We ignore dependence vectors whose first element is zero because
14565 such dependencies are known to be executed by the same thread.
14567 We take into account the direction of the loop, so a minimum
14568 becomes a maximum if the loop is iterating forwards. We also
14569 ignore sink clauses where the loop direction is unknown, or where
14570 the offsets are clearly invalid because they are not a multiple
14571 of the loop increment.
14573 For example:
14575 #pragma omp for ordered(2)
14576 for (i=0; i < N; ++i)
14577 for (j=0; j < M; ++j)
14579 #pragma omp ordered \
14580 depend(sink:i-8,j-2) \
14581 depend(sink:i,j-1) \ // Completely ignored because i+0.
14582 depend(sink:i-4,j-3) \
14583 depend(sink:i-6,j-4)
14584 #pragma omp ordered depend(source)
14587 Folded clause is:
14589 depend(sink:-gcd(8,4,6),-min(2,3,4))
14590 -or-
14591 depend(sink:-2,-2)
14594 /* FIXME: Computing GCD's where the first element is zero is
14595 non-trivial in the presence of collapsed loops. Do this later. */
14596 if (fd.collapse > 1)
14597 return;
14599 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14600 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14601 tree folded_dep = NULL_TREE;
14602 /* TRUE if the first dimension's offset is negative. */
14603 bool neg_offset_p = false;
14605 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14606 unsigned int i;
14607 while ((c = *list_p) != NULL)
14609 bool remove = false;
14611 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14612 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14613 goto next_ordered_clause;
14615 tree vec;
14616 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14617 vec && TREE_CODE (vec) == TREE_LIST;
14618 vec = TREE_CHAIN (vec), ++i)
14620 gcc_assert (i < len);
14622 /* extract_omp_for_data has canonicalized the condition. */
14623 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14624 || fd.loops[i].cond_code == GT_EXPR);
14625 bool forward = fd.loops[i].cond_code == LT_EXPR;
14626 bool maybe_lexically_later = true;
14628 /* While the committee makes up its mind, bail if we have any
14629 non-constant steps. */
14630 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14631 goto lower_omp_ordered_ret;
14633 tree itype = TREE_TYPE (TREE_VALUE (vec));
14634 if (POINTER_TYPE_P (itype))
14635 itype = sizetype;
14636 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14637 TYPE_PRECISION (itype),
14638 TYPE_SIGN (itype));
14640 /* Ignore invalid offsets that are not multiples of the step. */
14641 if (!wi::multiple_of_p
14642 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14643 UNSIGNED))
14645 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14646 "ignoring sink clause with offset that is not "
14647 "a multiple of the loop step");
14648 remove = true;
14649 goto next_ordered_clause;
14652 /* Calculate the first dimension. The first dimension of
14653 the folded dependency vector is the GCD of the first
14654 elements, while ignoring any first elements whose offset
14655 is 0. */
14656 if (i == 0)
14658 /* Ignore dependence vectors whose first dimension is 0. */
14659 if (offset == 0)
14661 remove = true;
14662 goto next_ordered_clause;
14664 else
14666 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14668 error_at (OMP_CLAUSE_LOCATION (c),
14669 "first offset must be in opposite direction "
14670 "of loop iterations");
14671 goto lower_omp_ordered_ret;
14673 if (forward)
14674 offset = -offset;
14675 neg_offset_p = forward;
14676 /* Initialize the first time around. */
14677 if (folded_dep == NULL_TREE)
14679 folded_dep = c;
14680 folded_deps[0] = offset;
14682 else
14683 folded_deps[0] = wi::gcd (folded_deps[0],
14684 offset, UNSIGNED);
14687 /* Calculate minimum for the remaining dimensions. */
14688 else
14690 folded_deps[len + i - 1] = offset;
14691 if (folded_dep == c)
14692 folded_deps[i] = offset;
14693 else if (maybe_lexically_later
14694 && !wi::eq_p (folded_deps[i], offset))
14696 if (forward ^ wi::gts_p (folded_deps[i], offset))
14698 unsigned int j;
14699 folded_dep = c;
14700 for (j = 1; j <= i; j++)
14701 folded_deps[j] = folded_deps[len + j - 1];
14703 else
14704 maybe_lexically_later = false;
14708 gcc_assert (i == len);
14710 remove = true;
14712 next_ordered_clause:
14713 if (remove)
14714 *list_p = OMP_CLAUSE_CHAIN (c);
14715 else
14716 list_p = &OMP_CLAUSE_CHAIN (c);
14719 if (folded_dep)
14721 if (neg_offset_p)
14722 folded_deps[0] = -folded_deps[0];
14724 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14725 if (POINTER_TYPE_P (itype))
14726 itype = sizetype;
14728 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14729 = wide_int_to_tree (itype, folded_deps[0]);
14730 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14731 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14734 lower_omp_ordered_ret:
14736 /* Ordered without clauses is #pragma omp threads, while we want
14737 a nop instead if we remove all clauses. */
14738 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14739 gsi_replace (gsi_p, gimple_build_nop (), true);
14743 /* Expand code for an OpenMP ordered directive. */
14745 static void
14746 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14748 tree block;
14749 gimple *stmt = gsi_stmt (*gsi_p);
14750 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14751 gcall *x;
14752 gbind *bind;
14753 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14754 OMP_CLAUSE_SIMD);
14755 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14756 OMP_CLAUSE_THREADS);
14758 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14759 OMP_CLAUSE_DEPEND))
14761 /* FIXME: This is needs to be moved to the expansion to verify various
14762 conditions only testable on cfg with dominators computed, and also
14763 all the depend clauses to be merged still might need to be available
14764 for the runtime checks. */
14765 if (0)
14766 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14767 return;
14770 push_gimplify_context ();
14772 block = make_node (BLOCK);
14773 bind = gimple_build_bind (NULL, NULL, block);
14774 gsi_replace (gsi_p, bind, true);
14775 gimple_bind_add_stmt (bind, stmt);
14777 if (simd)
14779 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14780 build_int_cst (NULL_TREE, threads));
14781 cfun->has_simduid_loops = true;
14783 else
14784 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14786 gimple_bind_add_stmt (bind, x);
14788 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14789 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14790 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14791 gimple_omp_set_body (stmt, NULL);
14793 if (simd)
14794 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14795 build_int_cst (NULL_TREE, threads));
14796 else
14797 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14799 gimple_bind_add_stmt (bind, x);
14801 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14803 pop_gimplify_context (bind);
14805 gimple_bind_append_vars (bind, ctx->block_vars);
14806 BLOCK_VARS (block) = gimple_bind_vars (bind);
14810 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14811 substitution of a couple of function calls. But in the NAMED case,
14812 requires that languages coordinate a symbol name. It is therefore
14813 best put here in common code. */
14815 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14817 static void
14818 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14820 tree block;
14821 tree name, lock, unlock;
14822 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14823 gbind *bind;
14824 location_t loc = gimple_location (stmt);
14825 gimple_seq tbody;
14827 name = gimple_omp_critical_name (stmt);
14828 if (name)
14830 tree decl;
14832 if (!critical_name_mutexes)
14833 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14835 tree *n = critical_name_mutexes->get (name);
14836 if (n == NULL)
14838 char *new_str;
14840 decl = create_tmp_var_raw (ptr_type_node);
14842 new_str = ACONCAT ((".gomp_critical_user_",
14843 IDENTIFIER_POINTER (name), NULL));
14844 DECL_NAME (decl) = get_identifier (new_str);
14845 TREE_PUBLIC (decl) = 1;
14846 TREE_STATIC (decl) = 1;
14847 DECL_COMMON (decl) = 1;
14848 DECL_ARTIFICIAL (decl) = 1;
14849 DECL_IGNORED_P (decl) = 1;
14851 varpool_node::finalize_decl (decl);
14853 critical_name_mutexes->put (name, decl);
14855 else
14856 decl = *n;
14858 /* If '#pragma omp critical' is inside offloaded region or
14859 inside function marked as offloadable, the symbol must be
14860 marked as offloadable too. */
14861 omp_context *octx;
14862 if (cgraph_node::get (current_function_decl)->offloadable)
14863 varpool_node::get_create (decl)->offloadable = 1;
14864 else
14865 for (octx = ctx->outer; octx; octx = octx->outer)
14866 if (is_gimple_omp_offloaded (octx->stmt))
14868 varpool_node::get_create (decl)->offloadable = 1;
14869 break;
14872 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14873 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14875 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14876 unlock = build_call_expr_loc (loc, unlock, 1,
14877 build_fold_addr_expr_loc (loc, decl));
14879 else
14881 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14882 lock = build_call_expr_loc (loc, lock, 0);
14884 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14885 unlock = build_call_expr_loc (loc, unlock, 0);
14888 push_gimplify_context ();
14890 block = make_node (BLOCK);
14891 bind = gimple_build_bind (NULL, NULL, block);
14892 gsi_replace (gsi_p, bind, true);
14893 gimple_bind_add_stmt (bind, stmt);
14895 tbody = gimple_bind_body (bind);
14896 gimplify_and_add (lock, &tbody);
14897 gimple_bind_set_body (bind, tbody);
14899 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14900 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14901 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14902 gimple_omp_set_body (stmt, NULL);
14904 tbody = gimple_bind_body (bind);
14905 gimplify_and_add (unlock, &tbody);
14906 gimple_bind_set_body (bind, tbody);
14908 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14910 pop_gimplify_context (bind);
14911 gimple_bind_append_vars (bind, ctx->block_vars);
14912 BLOCK_VARS (block) = gimple_bind_vars (bind);
14916 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14917 for a lastprivate clause. Given a loop control predicate of (V
14918 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14919 is appended to *DLIST, iterator initialization is appended to
14920 *BODY_P. */
14922 static void
14923 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14924 gimple_seq *dlist, struct omp_context *ctx)
14926 tree clauses, cond, vinit;
14927 enum tree_code cond_code;
14928 gimple_seq stmts;
14930 cond_code = fd->loop.cond_code;
14931 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14933 /* When possible, use a strict equality expression. This can let VRP
14934 type optimizations deduce the value and remove a copy. */
14935 if (tree_fits_shwi_p (fd->loop.step))
14937 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14938 if (step == 1 || step == -1)
14939 cond_code = EQ_EXPR;
14942 tree n2 = fd->loop.n2;
14943 if (fd->collapse > 1
14944 && TREE_CODE (n2) != INTEGER_CST
14945 && gimple_omp_for_combined_into_p (fd->for_stmt))
14947 struct omp_context *taskreg_ctx = NULL;
14948 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14950 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14951 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14952 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14954 if (gimple_omp_for_combined_into_p (gfor))
14956 gcc_assert (ctx->outer->outer
14957 && is_parallel_ctx (ctx->outer->outer));
14958 taskreg_ctx = ctx->outer->outer;
14960 else
14962 struct omp_for_data outer_fd;
14963 extract_omp_for_data (gfor, &outer_fd, NULL);
14964 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14967 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14968 taskreg_ctx = ctx->outer->outer;
14970 else if (is_taskreg_ctx (ctx->outer))
14971 taskreg_ctx = ctx->outer;
14972 if (taskreg_ctx)
14974 int i;
14975 tree innerc
14976 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14977 OMP_CLAUSE__LOOPTEMP_);
14978 gcc_assert (innerc);
14979 for (i = 0; i < fd->collapse; i++)
14981 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14982 OMP_CLAUSE__LOOPTEMP_);
14983 gcc_assert (innerc);
14985 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14986 OMP_CLAUSE__LOOPTEMP_);
14987 if (innerc)
14988 n2 = fold_convert (TREE_TYPE (n2),
14989 lookup_decl (OMP_CLAUSE_DECL (innerc),
14990 taskreg_ctx));
14993 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14995 clauses = gimple_omp_for_clauses (fd->for_stmt);
14996 stmts = NULL;
14997 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14998 if (!gimple_seq_empty_p (stmts))
15000 gimple_seq_add_seq (&stmts, *dlist);
15001 *dlist = stmts;
15003 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15004 vinit = fd->loop.n1;
15005 if (cond_code == EQ_EXPR
15006 && tree_fits_shwi_p (fd->loop.n2)
15007 && ! integer_zerop (fd->loop.n2))
15008 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15009 else
15010 vinit = unshare_expr (vinit);
15012 /* Initialize the iterator variable, so that threads that don't execute
15013 any iterations don't execute the lastprivate clauses by accident. */
15014 gimplify_assign (fd->loop.v, vinit, body_p);
15019 /* Lower code for an OMP loop directive. */
15021 static void
15022 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15024 tree *rhs_p, block;
15025 struct omp_for_data fd, *fdp = NULL;
15026 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15027 gbind *new_stmt;
15028 gimple_seq omp_for_body, body, dlist;
15029 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15030 size_t i;
15032 push_gimplify_context ();
15034 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15036 block = make_node (BLOCK);
15037 new_stmt = gimple_build_bind (NULL, NULL, block);
15038 /* Replace at gsi right away, so that 'stmt' is no member
15039 of a sequence anymore as we're going to add to a different
15040 one below. */
15041 gsi_replace (gsi_p, new_stmt, true);
15043 /* Move declaration of temporaries in the loop body before we make
15044 it go away. */
15045 omp_for_body = gimple_omp_body (stmt);
15046 if (!gimple_seq_empty_p (omp_for_body)
15047 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15049 gbind *inner_bind
15050 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15051 tree vars = gimple_bind_vars (inner_bind);
15052 gimple_bind_append_vars (new_stmt, vars);
15053 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15054 keep them on the inner_bind and it's block. */
15055 gimple_bind_set_vars (inner_bind, NULL_TREE);
15056 if (gimple_bind_block (inner_bind))
15057 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15060 if (gimple_omp_for_combined_into_p (stmt))
15062 extract_omp_for_data (stmt, &fd, NULL);
15063 fdp = &fd;
15065 /* We need two temporaries with fd.loop.v type (istart/iend)
15066 and then (fd.collapse - 1) temporaries with the same
15067 type for count2 ... countN-1 vars if not constant. */
15068 size_t count = 2;
15069 tree type = fd.iter_type;
15070 if (fd.collapse > 1
15071 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15072 count += fd.collapse - 1;
15073 bool taskreg_for
15074 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15075 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15076 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15077 tree clauses = *pc;
15078 if (taskreg_for)
15079 outerc
15080 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15081 OMP_CLAUSE__LOOPTEMP_);
15082 for (i = 0; i < count; i++)
15084 tree temp;
15085 if (taskreg_for)
15087 gcc_assert (outerc);
15088 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15089 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15090 OMP_CLAUSE__LOOPTEMP_);
15092 else
15094 temp = create_tmp_var (type);
15095 insert_decl_map (&ctx->outer->cb, temp, temp);
15097 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15098 OMP_CLAUSE_DECL (*pc) = temp;
15099 pc = &OMP_CLAUSE_CHAIN (*pc);
15101 *pc = clauses;
15104 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15105 dlist = NULL;
15106 body = NULL;
15107 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15108 fdp);
15109 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15111 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15113 /* Lower the header expressions. At this point, we can assume that
15114 the header is of the form:
15116 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15118 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15119 using the .omp_data_s mapping, if needed. */
15120 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15122 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15123 if (!is_gimple_min_invariant (*rhs_p))
15124 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15126 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15127 if (!is_gimple_min_invariant (*rhs_p))
15128 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15130 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15131 if (!is_gimple_min_invariant (*rhs_p))
15132 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15135 /* Once lowered, extract the bounds and clauses. */
15136 extract_omp_for_data (stmt, &fd, NULL);
15138 if (is_gimple_omp_oacc (ctx->stmt)
15139 && !ctx_in_oacc_kernels_region (ctx))
15140 lower_oacc_head_tail (gimple_location (stmt),
15141 gimple_omp_for_clauses (stmt),
15142 &oacc_head, &oacc_tail, ctx);
15144 /* Add OpenACC partitioning and reduction markers just before the loop */
15145 if (oacc_head)
15146 gimple_seq_add_seq (&body, oacc_head);
15148 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15150 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15151 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15152 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15153 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15155 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15156 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15157 OMP_CLAUSE_LINEAR_STEP (c)
15158 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15159 ctx);
15162 if (!gimple_omp_for_grid_phony (stmt))
15163 gimple_seq_add_stmt (&body, stmt);
15164 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15166 if (!gimple_omp_for_grid_phony (stmt))
15167 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15168 fd.loop.v));
15170 /* After the loop, add exit clauses. */
15171 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15173 if (ctx->cancellable)
15174 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15176 gimple_seq_add_seq (&body, dlist);
15178 body = maybe_catch_exception (body);
15180 if (!gimple_omp_for_grid_phony (stmt))
15182 /* Region exit marker goes at the end of the loop body. */
15183 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15184 maybe_add_implicit_barrier_cancel (ctx, &body);
15187 /* Add OpenACC joining and reduction markers just after the loop. */
15188 if (oacc_tail)
15189 gimple_seq_add_seq (&body, oacc_tail);
15191 pop_gimplify_context (new_stmt);
15193 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15194 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15195 if (BLOCK_VARS (block))
15196 TREE_USED (block) = 1;
15198 gimple_bind_set_body (new_stmt, body);
15199 gimple_omp_set_body (stmt, NULL);
15200 gimple_omp_for_set_pre_body (stmt, NULL);
15203 /* Callback for walk_stmts. Check if the current statement only contains
15204 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15206 static tree
15207 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15208 bool *handled_ops_p,
15209 struct walk_stmt_info *wi)
15211 int *info = (int *) wi->info;
15212 gimple *stmt = gsi_stmt (*gsi_p);
15214 *handled_ops_p = true;
15215 switch (gimple_code (stmt))
15217 WALK_SUBSTMTS;
15219 case GIMPLE_OMP_FOR:
15220 case GIMPLE_OMP_SECTIONS:
15221 *info = *info == 0 ? 1 : -1;
15222 break;
15223 default:
15224 *info = -1;
15225 break;
15227 return NULL;
15230 struct omp_taskcopy_context
15232 /* This field must be at the beginning, as we do "inheritance": Some
15233 callback functions for tree-inline.c (e.g., omp_copy_decl)
15234 receive a copy_body_data pointer that is up-casted to an
15235 omp_context pointer. */
15236 copy_body_data cb;
15237 omp_context *ctx;
15240 static tree
15241 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15243 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15245 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15246 return create_tmp_var (TREE_TYPE (var));
15248 return var;
15251 static tree
15252 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15254 tree name, new_fields = NULL, type, f;
15256 type = lang_hooks.types.make_type (RECORD_TYPE);
15257 name = DECL_NAME (TYPE_NAME (orig_type));
15258 name = build_decl (gimple_location (tcctx->ctx->stmt),
15259 TYPE_DECL, name, type);
15260 TYPE_NAME (type) = name;
15262 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15264 tree new_f = copy_node (f);
15265 DECL_CONTEXT (new_f) = type;
15266 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15267 TREE_CHAIN (new_f) = new_fields;
15268 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15269 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15270 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15271 &tcctx->cb, NULL);
15272 new_fields = new_f;
15273 tcctx->cb.decl_map->put (f, new_f);
15275 TYPE_FIELDS (type) = nreverse (new_fields);
15276 layout_type (type);
15277 return type;
15280 /* Create task copyfn. */
15282 static void
15283 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15285 struct function *child_cfun;
15286 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15287 tree record_type, srecord_type, bind, list;
15288 bool record_needs_remap = false, srecord_needs_remap = false;
15289 splay_tree_node n;
15290 struct omp_taskcopy_context tcctx;
15291 location_t loc = gimple_location (task_stmt);
15293 child_fn = gimple_omp_task_copy_fn (task_stmt);
15294 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15295 gcc_assert (child_cfun->cfg == NULL);
15296 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15298 /* Reset DECL_CONTEXT on function arguments. */
15299 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15300 DECL_CONTEXT (t) = child_fn;
15302 /* Populate the function. */
15303 push_gimplify_context ();
15304 push_cfun (child_cfun);
15306 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15307 TREE_SIDE_EFFECTS (bind) = 1;
15308 list = NULL;
15309 DECL_SAVED_TREE (child_fn) = bind;
15310 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15312 /* Remap src and dst argument types if needed. */
15313 record_type = ctx->record_type;
15314 srecord_type = ctx->srecord_type;
15315 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15316 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15318 record_needs_remap = true;
15319 break;
15321 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15322 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15324 srecord_needs_remap = true;
15325 break;
15328 if (record_needs_remap || srecord_needs_remap)
15330 memset (&tcctx, '\0', sizeof (tcctx));
15331 tcctx.cb.src_fn = ctx->cb.src_fn;
15332 tcctx.cb.dst_fn = child_fn;
15333 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15334 gcc_checking_assert (tcctx.cb.src_node);
15335 tcctx.cb.dst_node = tcctx.cb.src_node;
15336 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15337 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15338 tcctx.cb.eh_lp_nr = 0;
15339 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15340 tcctx.cb.decl_map = new hash_map<tree, tree>;
15341 tcctx.ctx = ctx;
15343 if (record_needs_remap)
15344 record_type = task_copyfn_remap_type (&tcctx, record_type);
15345 if (srecord_needs_remap)
15346 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15348 else
15349 tcctx.cb.decl_map = NULL;
15351 arg = DECL_ARGUMENTS (child_fn);
15352 TREE_TYPE (arg) = build_pointer_type (record_type);
15353 sarg = DECL_CHAIN (arg);
15354 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15356 /* First pass: initialize temporaries used in record_type and srecord_type
15357 sizes and field offsets. */
15358 if (tcctx.cb.decl_map)
15359 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15360 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15362 tree *p;
15364 decl = OMP_CLAUSE_DECL (c);
15365 p = tcctx.cb.decl_map->get (decl);
15366 if (p == NULL)
15367 continue;
15368 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15369 sf = (tree) n->value;
15370 sf = *tcctx.cb.decl_map->get (sf);
15371 src = build_simple_mem_ref_loc (loc, sarg);
15372 src = omp_build_component_ref (src, sf);
15373 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15374 append_to_statement_list (t, &list);
15377 /* Second pass: copy shared var pointers and copy construct non-VLA
15378 firstprivate vars. */
15379 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15380 switch (OMP_CLAUSE_CODE (c))
15382 splay_tree_key key;
15383 case OMP_CLAUSE_SHARED:
15384 decl = OMP_CLAUSE_DECL (c);
15385 key = (splay_tree_key) decl;
15386 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15387 key = (splay_tree_key) &DECL_UID (decl);
15388 n = splay_tree_lookup (ctx->field_map, key);
15389 if (n == NULL)
15390 break;
15391 f = (tree) n->value;
15392 if (tcctx.cb.decl_map)
15393 f = *tcctx.cb.decl_map->get (f);
15394 n = splay_tree_lookup (ctx->sfield_map, key);
15395 sf = (tree) n->value;
15396 if (tcctx.cb.decl_map)
15397 sf = *tcctx.cb.decl_map->get (sf);
15398 src = build_simple_mem_ref_loc (loc, sarg);
15399 src = omp_build_component_ref (src, sf);
15400 dst = build_simple_mem_ref_loc (loc, arg);
15401 dst = omp_build_component_ref (dst, f);
15402 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15403 append_to_statement_list (t, &list);
15404 break;
15405 case OMP_CLAUSE_FIRSTPRIVATE:
15406 decl = OMP_CLAUSE_DECL (c);
15407 if (is_variable_sized (decl))
15408 break;
15409 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15410 if (n == NULL)
15411 break;
15412 f = (tree) n->value;
15413 if (tcctx.cb.decl_map)
15414 f = *tcctx.cb.decl_map->get (f);
15415 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15416 if (n != NULL)
15418 sf = (tree) n->value;
15419 if (tcctx.cb.decl_map)
15420 sf = *tcctx.cb.decl_map->get (sf);
15421 src = build_simple_mem_ref_loc (loc, sarg);
15422 src = omp_build_component_ref (src, sf);
15423 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15424 src = build_simple_mem_ref_loc (loc, src);
15426 else
15427 src = decl;
15428 dst = build_simple_mem_ref_loc (loc, arg);
15429 dst = omp_build_component_ref (dst, f);
15430 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15431 append_to_statement_list (t, &list);
15432 break;
15433 case OMP_CLAUSE_PRIVATE:
15434 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15435 break;
15436 decl = OMP_CLAUSE_DECL (c);
15437 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15438 f = (tree) n->value;
15439 if (tcctx.cb.decl_map)
15440 f = *tcctx.cb.decl_map->get (f);
15441 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15442 if (n != NULL)
15444 sf = (tree) n->value;
15445 if (tcctx.cb.decl_map)
15446 sf = *tcctx.cb.decl_map->get (sf);
15447 src = build_simple_mem_ref_loc (loc, sarg);
15448 src = omp_build_component_ref (src, sf);
15449 if (use_pointer_for_field (decl, NULL))
15450 src = build_simple_mem_ref_loc (loc, src);
15452 else
15453 src = decl;
15454 dst = build_simple_mem_ref_loc (loc, arg);
15455 dst = omp_build_component_ref (dst, f);
15456 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15457 append_to_statement_list (t, &list);
15458 break;
15459 default:
15460 break;
15463 /* Last pass: handle VLA firstprivates. */
15464 if (tcctx.cb.decl_map)
15465 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15466 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15468 tree ind, ptr, df;
15470 decl = OMP_CLAUSE_DECL (c);
15471 if (!is_variable_sized (decl))
15472 continue;
15473 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15474 if (n == NULL)
15475 continue;
15476 f = (tree) n->value;
15477 f = *tcctx.cb.decl_map->get (f);
15478 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15479 ind = DECL_VALUE_EXPR (decl);
15480 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15481 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15482 n = splay_tree_lookup (ctx->sfield_map,
15483 (splay_tree_key) TREE_OPERAND (ind, 0));
15484 sf = (tree) n->value;
15485 sf = *tcctx.cb.decl_map->get (sf);
15486 src = build_simple_mem_ref_loc (loc, sarg);
15487 src = omp_build_component_ref (src, sf);
15488 src = build_simple_mem_ref_loc (loc, src);
15489 dst = build_simple_mem_ref_loc (loc, arg);
15490 dst = omp_build_component_ref (dst, f);
15491 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15492 append_to_statement_list (t, &list);
15493 n = splay_tree_lookup (ctx->field_map,
15494 (splay_tree_key) TREE_OPERAND (ind, 0));
15495 df = (tree) n->value;
15496 df = *tcctx.cb.decl_map->get (df);
15497 ptr = build_simple_mem_ref_loc (loc, arg);
15498 ptr = omp_build_component_ref (ptr, df);
15499 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15500 build_fold_addr_expr_loc (loc, dst));
15501 append_to_statement_list (t, &list);
15504 t = build1 (RETURN_EXPR, void_type_node, NULL);
15505 append_to_statement_list (t, &list);
15507 if (tcctx.cb.decl_map)
15508 delete tcctx.cb.decl_map;
15509 pop_gimplify_context (NULL);
15510 BIND_EXPR_BODY (bind) = list;
15511 pop_cfun ();
15514 static void
15515 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15517 tree c, clauses;
15518 gimple *g;
15519 size_t n_in = 0, n_out = 0, idx = 2, i;
15521 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15522 gcc_assert (clauses);
15523 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15524 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15525 switch (OMP_CLAUSE_DEPEND_KIND (c))
15527 case OMP_CLAUSE_DEPEND_IN:
15528 n_in++;
15529 break;
15530 case OMP_CLAUSE_DEPEND_OUT:
15531 case OMP_CLAUSE_DEPEND_INOUT:
15532 n_out++;
15533 break;
15534 case OMP_CLAUSE_DEPEND_SOURCE:
15535 case OMP_CLAUSE_DEPEND_SINK:
15536 /* FALLTHRU */
15537 default:
15538 gcc_unreachable ();
15540 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15541 tree array = create_tmp_var (type);
15542 TREE_ADDRESSABLE (array) = 1;
15543 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15544 NULL_TREE);
15545 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15546 gimple_seq_add_stmt (iseq, g);
15547 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15548 NULL_TREE);
15549 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15550 gimple_seq_add_stmt (iseq, g);
15551 for (i = 0; i < 2; i++)
15553 if ((i ? n_in : n_out) == 0)
15554 continue;
15555 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15556 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15557 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15559 tree t = OMP_CLAUSE_DECL (c);
15560 t = fold_convert (ptr_type_node, t);
15561 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15562 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15563 NULL_TREE, NULL_TREE);
15564 g = gimple_build_assign (r, t);
15565 gimple_seq_add_stmt (iseq, g);
15568 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15569 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15570 OMP_CLAUSE_CHAIN (c) = *pclauses;
15571 *pclauses = c;
15572 tree clobber = build_constructor (type, NULL);
15573 TREE_THIS_VOLATILE (clobber) = 1;
15574 g = gimple_build_assign (array, clobber);
15575 gimple_seq_add_stmt (oseq, g);
15578 /* Lower the OpenMP parallel or task directive in the current statement
15579 in GSI_P. CTX holds context information for the directive. */
15581 static void
15582 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15584 tree clauses;
15585 tree child_fn, t;
15586 gimple *stmt = gsi_stmt (*gsi_p);
15587 gbind *par_bind, *bind, *dep_bind = NULL;
15588 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15589 location_t loc = gimple_location (stmt);
15591 clauses = gimple_omp_taskreg_clauses (stmt);
15592 par_bind
15593 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15594 par_body = gimple_bind_body (par_bind);
15595 child_fn = ctx->cb.dst_fn;
15596 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15597 && !gimple_omp_parallel_combined_p (stmt))
15599 struct walk_stmt_info wi;
15600 int ws_num = 0;
15602 memset (&wi, 0, sizeof (wi));
15603 wi.info = &ws_num;
15604 wi.val_only = true;
15605 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15606 if (ws_num == 1)
15607 gimple_omp_parallel_set_combined_p (stmt, true);
15609 gimple_seq dep_ilist = NULL;
15610 gimple_seq dep_olist = NULL;
15611 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15612 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15614 push_gimplify_context ();
15615 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15616 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15617 &dep_ilist, &dep_olist);
15620 if (ctx->srecord_type)
15621 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15623 push_gimplify_context ();
15625 par_olist = NULL;
15626 par_ilist = NULL;
15627 par_rlist = NULL;
15628 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15629 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15630 if (phony_construct && ctx->record_type)
15632 gcc_checking_assert (!ctx->receiver_decl);
15633 ctx->receiver_decl = create_tmp_var
15634 (build_reference_type (ctx->record_type), ".omp_rec");
15636 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15637 lower_omp (&par_body, ctx);
15638 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15639 lower_reduction_clauses (clauses, &par_rlist, ctx);
15641 /* Declare all the variables created by mapping and the variables
15642 declared in the scope of the parallel body. */
15643 record_vars_into (ctx->block_vars, child_fn);
15644 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15646 if (ctx->record_type)
15648 ctx->sender_decl
15649 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15650 : ctx->record_type, ".omp_data_o");
15651 DECL_NAMELESS (ctx->sender_decl) = 1;
15652 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15653 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15656 olist = NULL;
15657 ilist = NULL;
15658 lower_send_clauses (clauses, &ilist, &olist, ctx);
15659 lower_send_shared_vars (&ilist, &olist, ctx);
15661 if (ctx->record_type)
15663 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15664 TREE_THIS_VOLATILE (clobber) = 1;
15665 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15666 clobber));
15669 /* Once all the expansions are done, sequence all the different
15670 fragments inside gimple_omp_body. */
15672 new_body = NULL;
15674 if (ctx->record_type)
15676 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15677 /* fixup_child_record_type might have changed receiver_decl's type. */
15678 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15679 gimple_seq_add_stmt (&new_body,
15680 gimple_build_assign (ctx->receiver_decl, t));
15683 gimple_seq_add_seq (&new_body, par_ilist);
15684 gimple_seq_add_seq (&new_body, par_body);
15685 gimple_seq_add_seq (&new_body, par_rlist);
15686 if (ctx->cancellable)
15687 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15688 gimple_seq_add_seq (&new_body, par_olist);
15689 new_body = maybe_catch_exception (new_body);
15690 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15691 gimple_seq_add_stmt (&new_body,
15692 gimple_build_omp_continue (integer_zero_node,
15693 integer_zero_node));
15694 if (!phony_construct)
15696 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15697 gimple_omp_set_body (stmt, new_body);
15700 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15701 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15702 gimple_bind_add_seq (bind, ilist);
15703 if (!phony_construct)
15704 gimple_bind_add_stmt (bind, stmt);
15705 else
15706 gimple_bind_add_seq (bind, new_body);
15707 gimple_bind_add_seq (bind, olist);
15709 pop_gimplify_context (NULL);
15711 if (dep_bind)
15713 gimple_bind_add_seq (dep_bind, dep_ilist);
15714 gimple_bind_add_stmt (dep_bind, bind);
15715 gimple_bind_add_seq (dep_bind, dep_olist);
15716 pop_gimplify_context (dep_bind);
15720 /* Lower the GIMPLE_OMP_TARGET in the current statement
15721 in GSI_P. CTX holds context information for the directive. */
15723 static void
15724 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15726 tree clauses;
15727 tree child_fn, t, c;
15728 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15729 gbind *tgt_bind, *bind, *dep_bind = NULL;
15730 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15731 location_t loc = gimple_location (stmt);
15732 bool offloaded, data_region;
15733 unsigned int map_cnt = 0;
15735 offloaded = is_gimple_omp_offloaded (stmt);
15736 switch (gimple_omp_target_kind (stmt))
15738 case GF_OMP_TARGET_KIND_REGION:
15739 case GF_OMP_TARGET_KIND_UPDATE:
15740 case GF_OMP_TARGET_KIND_ENTER_DATA:
15741 case GF_OMP_TARGET_KIND_EXIT_DATA:
15742 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15743 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15744 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15745 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15746 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15747 data_region = false;
15748 break;
15749 case GF_OMP_TARGET_KIND_DATA:
15750 case GF_OMP_TARGET_KIND_OACC_DATA:
15751 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15752 data_region = true;
15753 break;
15754 default:
15755 gcc_unreachable ();
15758 clauses = gimple_omp_target_clauses (stmt);
15760 gimple_seq dep_ilist = NULL;
15761 gimple_seq dep_olist = NULL;
15762 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15764 push_gimplify_context ();
15765 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15766 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15767 &dep_ilist, &dep_olist);
15770 tgt_bind = NULL;
15771 tgt_body = NULL;
15772 if (offloaded)
15774 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15775 tgt_body = gimple_bind_body (tgt_bind);
15777 else if (data_region)
15778 tgt_body = gimple_omp_body (stmt);
15779 child_fn = ctx->cb.dst_fn;
15781 push_gimplify_context ();
15782 fplist = NULL;
15784 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15785 switch (OMP_CLAUSE_CODE (c))
15787 tree var, x;
15789 default:
15790 break;
15791 case OMP_CLAUSE_MAP:
15792 #if CHECKING_P
15793 /* First check what we're prepared to handle in the following. */
15794 switch (OMP_CLAUSE_MAP_KIND (c))
15796 case GOMP_MAP_ALLOC:
15797 case GOMP_MAP_TO:
15798 case GOMP_MAP_FROM:
15799 case GOMP_MAP_TOFROM:
15800 case GOMP_MAP_POINTER:
15801 case GOMP_MAP_TO_PSET:
15802 case GOMP_MAP_DELETE:
15803 case GOMP_MAP_RELEASE:
15804 case GOMP_MAP_ALWAYS_TO:
15805 case GOMP_MAP_ALWAYS_FROM:
15806 case GOMP_MAP_ALWAYS_TOFROM:
15807 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15808 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15809 case GOMP_MAP_STRUCT:
15810 case GOMP_MAP_ALWAYS_POINTER:
15811 break;
15812 case GOMP_MAP_FORCE_ALLOC:
15813 case GOMP_MAP_FORCE_TO:
15814 case GOMP_MAP_FORCE_FROM:
15815 case GOMP_MAP_FORCE_TOFROM:
15816 case GOMP_MAP_FORCE_PRESENT:
15817 case GOMP_MAP_FORCE_DEVICEPTR:
15818 case GOMP_MAP_DEVICE_RESIDENT:
15819 case GOMP_MAP_LINK:
15820 gcc_assert (is_gimple_omp_oacc (stmt));
15821 break;
15822 default:
15823 gcc_unreachable ();
15825 #endif
15826 /* FALLTHRU */
15827 case OMP_CLAUSE_TO:
15828 case OMP_CLAUSE_FROM:
15829 oacc_firstprivate:
15830 var = OMP_CLAUSE_DECL (c);
15831 if (!DECL_P (var))
15833 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15834 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15835 && (OMP_CLAUSE_MAP_KIND (c)
15836 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15837 map_cnt++;
15838 continue;
15841 if (DECL_SIZE (var)
15842 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15844 tree var2 = DECL_VALUE_EXPR (var);
15845 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15846 var2 = TREE_OPERAND (var2, 0);
15847 gcc_assert (DECL_P (var2));
15848 var = var2;
15851 if (offloaded
15852 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15853 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15854 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15856 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15858 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15859 && varpool_node::get_create (var)->offloadable)
15860 continue;
15862 tree type = build_pointer_type (TREE_TYPE (var));
15863 tree new_var = lookup_decl (var, ctx);
15864 x = create_tmp_var_raw (type, get_name (new_var));
15865 gimple_add_tmp_var (x);
15866 x = build_simple_mem_ref (x);
15867 SET_DECL_VALUE_EXPR (new_var, x);
15868 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15870 continue;
15873 if (!maybe_lookup_field (var, ctx))
15874 continue;
15876 /* Don't remap oacc parallel reduction variables, because the
15877 intermediate result must be local to each gang. */
15878 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15879 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15881 x = build_receiver_ref (var, true, ctx);
15882 tree new_var = lookup_decl (var, ctx);
15884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15885 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15886 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15887 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15888 x = build_simple_mem_ref (x);
15889 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15891 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15892 if (is_reference (new_var))
15894 /* Create a local object to hold the instance
15895 value. */
15896 tree type = TREE_TYPE (TREE_TYPE (new_var));
15897 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15898 tree inst = create_tmp_var (type, id);
15899 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15900 x = build_fold_addr_expr (inst);
15902 gimplify_assign (new_var, x, &fplist);
15904 else if (DECL_P (new_var))
15906 SET_DECL_VALUE_EXPR (new_var, x);
15907 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15909 else
15910 gcc_unreachable ();
15912 map_cnt++;
15913 break;
15915 case OMP_CLAUSE_FIRSTPRIVATE:
15916 if (is_oacc_parallel (ctx))
15917 goto oacc_firstprivate;
15918 map_cnt++;
15919 var = OMP_CLAUSE_DECL (c);
15920 if (!is_reference (var)
15921 && !is_gimple_reg_type (TREE_TYPE (var)))
15923 tree new_var = lookup_decl (var, ctx);
15924 if (is_variable_sized (var))
15926 tree pvar = DECL_VALUE_EXPR (var);
15927 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15928 pvar = TREE_OPERAND (pvar, 0);
15929 gcc_assert (DECL_P (pvar));
15930 tree new_pvar = lookup_decl (pvar, ctx);
15931 x = build_fold_indirect_ref (new_pvar);
15932 TREE_THIS_NOTRAP (x) = 1;
15934 else
15935 x = build_receiver_ref (var, true, ctx);
15936 SET_DECL_VALUE_EXPR (new_var, x);
15937 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15939 break;
15941 case OMP_CLAUSE_PRIVATE:
15942 if (is_gimple_omp_oacc (ctx->stmt))
15943 break;
15944 var = OMP_CLAUSE_DECL (c);
15945 if (is_variable_sized (var))
15947 tree new_var = lookup_decl (var, ctx);
15948 tree pvar = DECL_VALUE_EXPR (var);
15949 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15950 pvar = TREE_OPERAND (pvar, 0);
15951 gcc_assert (DECL_P (pvar));
15952 tree new_pvar = lookup_decl (pvar, ctx);
15953 x = build_fold_indirect_ref (new_pvar);
15954 TREE_THIS_NOTRAP (x) = 1;
15955 SET_DECL_VALUE_EXPR (new_var, x);
15956 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15958 break;
15960 case OMP_CLAUSE_USE_DEVICE_PTR:
15961 case OMP_CLAUSE_IS_DEVICE_PTR:
15962 var = OMP_CLAUSE_DECL (c);
15963 map_cnt++;
15964 if (is_variable_sized (var))
15966 tree new_var = lookup_decl (var, ctx);
15967 tree pvar = DECL_VALUE_EXPR (var);
15968 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15969 pvar = TREE_OPERAND (pvar, 0);
15970 gcc_assert (DECL_P (pvar));
15971 tree new_pvar = lookup_decl (pvar, ctx);
15972 x = build_fold_indirect_ref (new_pvar);
15973 TREE_THIS_NOTRAP (x) = 1;
15974 SET_DECL_VALUE_EXPR (new_var, x);
15975 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15977 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15979 tree new_var = lookup_decl (var, ctx);
15980 tree type = build_pointer_type (TREE_TYPE (var));
15981 x = create_tmp_var_raw (type, get_name (new_var));
15982 gimple_add_tmp_var (x);
15983 x = build_simple_mem_ref (x);
15984 SET_DECL_VALUE_EXPR (new_var, x);
15985 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15987 else
15989 tree new_var = lookup_decl (var, ctx);
15990 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15991 gimple_add_tmp_var (x);
15992 SET_DECL_VALUE_EXPR (new_var, x);
15993 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15995 break;
15998 if (offloaded)
16000 target_nesting_level++;
16001 lower_omp (&tgt_body, ctx);
16002 target_nesting_level--;
16004 else if (data_region)
16005 lower_omp (&tgt_body, ctx);
16007 if (offloaded)
16009 /* Declare all the variables created by mapping and the variables
16010 declared in the scope of the target body. */
16011 record_vars_into (ctx->block_vars, child_fn);
16012 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16015 olist = NULL;
16016 ilist = NULL;
16017 if (ctx->record_type)
16019 ctx->sender_decl
16020 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16021 DECL_NAMELESS (ctx->sender_decl) = 1;
16022 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16023 t = make_tree_vec (3);
16024 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16025 TREE_VEC_ELT (t, 1)
16026 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16027 ".omp_data_sizes");
16028 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16029 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16030 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16031 tree tkind_type = short_unsigned_type_node;
16032 int talign_shift = 8;
16033 TREE_VEC_ELT (t, 2)
16034 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16035 ".omp_data_kinds");
16036 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16037 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16038 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16039 gimple_omp_target_set_data_arg (stmt, t);
16041 vec<constructor_elt, va_gc> *vsize;
16042 vec<constructor_elt, va_gc> *vkind;
16043 vec_alloc (vsize, map_cnt);
16044 vec_alloc (vkind, map_cnt);
16045 unsigned int map_idx = 0;
16047 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16048 switch (OMP_CLAUSE_CODE (c))
16050 tree ovar, nc, s, purpose, var, x, type;
16051 unsigned int talign;
16053 default:
16054 break;
16056 case OMP_CLAUSE_MAP:
16057 case OMP_CLAUSE_TO:
16058 case OMP_CLAUSE_FROM:
16059 oacc_firstprivate_map:
16060 nc = c;
16061 ovar = OMP_CLAUSE_DECL (c);
16062 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16063 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16064 || (OMP_CLAUSE_MAP_KIND (c)
16065 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16066 break;
16067 if (!DECL_P (ovar))
16069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16070 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16072 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16073 == get_base_address (ovar));
16074 nc = OMP_CLAUSE_CHAIN (c);
16075 ovar = OMP_CLAUSE_DECL (nc);
16077 else
16079 tree x = build_sender_ref (ovar, ctx);
16080 tree v
16081 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16082 gimplify_assign (x, v, &ilist);
16083 nc = NULL_TREE;
16086 else
16088 if (DECL_SIZE (ovar)
16089 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16091 tree ovar2 = DECL_VALUE_EXPR (ovar);
16092 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16093 ovar2 = TREE_OPERAND (ovar2, 0);
16094 gcc_assert (DECL_P (ovar2));
16095 ovar = ovar2;
16097 if (!maybe_lookup_field (ovar, ctx))
16098 continue;
16101 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16102 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16103 talign = DECL_ALIGN_UNIT (ovar);
16104 if (nc)
16106 var = lookup_decl_in_outer_ctx (ovar, ctx);
16107 x = build_sender_ref (ovar, ctx);
16109 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16110 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16111 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16112 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16114 gcc_assert (offloaded);
16115 tree avar
16116 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16117 mark_addressable (avar);
16118 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16119 talign = DECL_ALIGN_UNIT (avar);
16120 avar = build_fold_addr_expr (avar);
16121 gimplify_assign (x, avar, &ilist);
16123 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16125 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16126 if (!is_reference (var))
16128 if (is_gimple_reg (var)
16129 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16130 TREE_NO_WARNING (var) = 1;
16131 var = build_fold_addr_expr (var);
16133 else
16134 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16135 gimplify_assign (x, var, &ilist);
16137 else if (is_gimple_reg (var))
16139 gcc_assert (offloaded);
16140 tree avar = create_tmp_var (TREE_TYPE (var));
16141 mark_addressable (avar);
16142 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16143 if (GOMP_MAP_COPY_TO_P (map_kind)
16144 || map_kind == GOMP_MAP_POINTER
16145 || map_kind == GOMP_MAP_TO_PSET
16146 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16148 /* If we need to initialize a temporary
16149 with VAR because it is not addressable, and
16150 the variable hasn't been initialized yet, then
16151 we'll get a warning for the store to avar.
16152 Don't warn in that case, the mapping might
16153 be implicit. */
16154 TREE_NO_WARNING (var) = 1;
16155 gimplify_assign (avar, var, &ilist);
16157 avar = build_fold_addr_expr (avar);
16158 gimplify_assign (x, avar, &ilist);
16159 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16160 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16161 && !TYPE_READONLY (TREE_TYPE (var)))
16163 x = unshare_expr (x);
16164 x = build_simple_mem_ref (x);
16165 gimplify_assign (var, x, &olist);
16168 else
16170 var = build_fold_addr_expr (var);
16171 gimplify_assign (x, var, &ilist);
16174 s = NULL_TREE;
16175 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16177 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16178 s = TREE_TYPE (ovar);
16179 if (TREE_CODE (s) == REFERENCE_TYPE)
16180 s = TREE_TYPE (s);
16181 s = TYPE_SIZE_UNIT (s);
16183 else
16184 s = OMP_CLAUSE_SIZE (c);
16185 if (s == NULL_TREE)
16186 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16187 s = fold_convert (size_type_node, s);
16188 purpose = size_int (map_idx++);
16189 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16190 if (TREE_CODE (s) != INTEGER_CST)
16191 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16193 unsigned HOST_WIDE_INT tkind, tkind_zero;
16194 switch (OMP_CLAUSE_CODE (c))
16196 case OMP_CLAUSE_MAP:
16197 tkind = OMP_CLAUSE_MAP_KIND (c);
16198 tkind_zero = tkind;
16199 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16200 switch (tkind)
16202 case GOMP_MAP_ALLOC:
16203 case GOMP_MAP_TO:
16204 case GOMP_MAP_FROM:
16205 case GOMP_MAP_TOFROM:
16206 case GOMP_MAP_ALWAYS_TO:
16207 case GOMP_MAP_ALWAYS_FROM:
16208 case GOMP_MAP_ALWAYS_TOFROM:
16209 case GOMP_MAP_RELEASE:
16210 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16211 break;
16212 case GOMP_MAP_DELETE:
16213 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16214 default:
16215 break;
16217 if (tkind_zero != tkind)
16219 if (integer_zerop (s))
16220 tkind = tkind_zero;
16221 else if (integer_nonzerop (s))
16222 tkind_zero = tkind;
16224 break;
16225 case OMP_CLAUSE_FIRSTPRIVATE:
16226 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16227 tkind = GOMP_MAP_TO;
16228 tkind_zero = tkind;
16229 break;
16230 case OMP_CLAUSE_TO:
16231 tkind = GOMP_MAP_TO;
16232 tkind_zero = tkind;
16233 break;
16234 case OMP_CLAUSE_FROM:
16235 tkind = GOMP_MAP_FROM;
16236 tkind_zero = tkind;
16237 break;
16238 default:
16239 gcc_unreachable ();
16241 gcc_checking_assert (tkind
16242 < (HOST_WIDE_INT_C (1U) << talign_shift));
16243 gcc_checking_assert (tkind_zero
16244 < (HOST_WIDE_INT_C (1U) << talign_shift));
16245 talign = ceil_log2 (talign);
16246 tkind |= talign << talign_shift;
16247 tkind_zero |= talign << talign_shift;
16248 gcc_checking_assert (tkind
16249 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16250 gcc_checking_assert (tkind_zero
16251 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16252 if (tkind == tkind_zero)
16253 x = build_int_cstu (tkind_type, tkind);
16254 else
16256 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16257 x = build3 (COND_EXPR, tkind_type,
16258 fold_build2 (EQ_EXPR, boolean_type_node,
16259 unshare_expr (s), size_zero_node),
16260 build_int_cstu (tkind_type, tkind_zero),
16261 build_int_cstu (tkind_type, tkind));
16263 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16264 if (nc && nc != c)
16265 c = nc;
16266 break;
16268 case OMP_CLAUSE_FIRSTPRIVATE:
16269 if (is_oacc_parallel (ctx))
16270 goto oacc_firstprivate_map;
16271 ovar = OMP_CLAUSE_DECL (c);
16272 if (is_reference (ovar))
16273 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16274 else
16275 talign = DECL_ALIGN_UNIT (ovar);
16276 var = lookup_decl_in_outer_ctx (ovar, ctx);
16277 x = build_sender_ref (ovar, ctx);
16278 tkind = GOMP_MAP_FIRSTPRIVATE;
16279 type = TREE_TYPE (ovar);
16280 if (is_reference (ovar))
16281 type = TREE_TYPE (type);
16282 if ((INTEGRAL_TYPE_P (type)
16283 && TYPE_PRECISION (type) <= POINTER_SIZE)
16284 || TREE_CODE (type) == POINTER_TYPE)
16286 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16287 tree t = var;
16288 if (is_reference (var))
16289 t = build_simple_mem_ref (var);
16290 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16291 TREE_NO_WARNING (var) = 1;
16292 if (TREE_CODE (type) != POINTER_TYPE)
16293 t = fold_convert (pointer_sized_int_node, t);
16294 t = fold_convert (TREE_TYPE (x), t);
16295 gimplify_assign (x, t, &ilist);
16297 else if (is_reference (var))
16298 gimplify_assign (x, var, &ilist);
16299 else if (is_gimple_reg (var))
16301 tree avar = create_tmp_var (TREE_TYPE (var));
16302 mark_addressable (avar);
16303 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16304 TREE_NO_WARNING (var) = 1;
16305 gimplify_assign (avar, var, &ilist);
16306 avar = build_fold_addr_expr (avar);
16307 gimplify_assign (x, avar, &ilist);
16309 else
16311 var = build_fold_addr_expr (var);
16312 gimplify_assign (x, var, &ilist);
16314 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16315 s = size_int (0);
16316 else if (is_reference (var))
16317 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16318 else
16319 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16320 s = fold_convert (size_type_node, s);
16321 purpose = size_int (map_idx++);
16322 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16323 if (TREE_CODE (s) != INTEGER_CST)
16324 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16326 gcc_checking_assert (tkind
16327 < (HOST_WIDE_INT_C (1U) << talign_shift));
16328 talign = ceil_log2 (talign);
16329 tkind |= talign << talign_shift;
16330 gcc_checking_assert (tkind
16331 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16332 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16333 build_int_cstu (tkind_type, tkind));
16334 break;
16336 case OMP_CLAUSE_USE_DEVICE_PTR:
16337 case OMP_CLAUSE_IS_DEVICE_PTR:
16338 ovar = OMP_CLAUSE_DECL (c);
16339 var = lookup_decl_in_outer_ctx (ovar, ctx);
16340 x = build_sender_ref (ovar, ctx);
16341 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16342 tkind = GOMP_MAP_USE_DEVICE_PTR;
16343 else
16344 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16345 type = TREE_TYPE (ovar);
16346 if (TREE_CODE (type) == ARRAY_TYPE)
16347 var = build_fold_addr_expr (var);
16348 else
16350 if (is_reference (ovar))
16352 type = TREE_TYPE (type);
16353 if (TREE_CODE (type) != ARRAY_TYPE)
16354 var = build_simple_mem_ref (var);
16355 var = fold_convert (TREE_TYPE (x), var);
16358 gimplify_assign (x, var, &ilist);
16359 s = size_int (0);
16360 purpose = size_int (map_idx++);
16361 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16362 gcc_checking_assert (tkind
16363 < (HOST_WIDE_INT_C (1U) << talign_shift));
16364 gcc_checking_assert (tkind
16365 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16366 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16367 build_int_cstu (tkind_type, tkind));
16368 break;
16371 gcc_assert (map_idx == map_cnt);
16373 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16374 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16375 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16376 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16377 for (int i = 1; i <= 2; i++)
16378 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16380 gimple_seq initlist = NULL;
16381 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16382 TREE_VEC_ELT (t, i)),
16383 &initlist, true, NULL_TREE);
16384 gimple_seq_add_seq (&ilist, initlist);
16386 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16387 NULL);
16388 TREE_THIS_VOLATILE (clobber) = 1;
16389 gimple_seq_add_stmt (&olist,
16390 gimple_build_assign (TREE_VEC_ELT (t, i),
16391 clobber));
16394 tree clobber = build_constructor (ctx->record_type, NULL);
16395 TREE_THIS_VOLATILE (clobber) = 1;
16396 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16397 clobber));
16400 /* Once all the expansions are done, sequence all the different
16401 fragments inside gimple_omp_body. */
16403 new_body = NULL;
16405 if (offloaded
16406 && ctx->record_type)
16408 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16409 /* fixup_child_record_type might have changed receiver_decl's type. */
16410 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16411 gimple_seq_add_stmt (&new_body,
16412 gimple_build_assign (ctx->receiver_decl, t));
16414 gimple_seq_add_seq (&new_body, fplist);
16416 if (offloaded || data_region)
16418 tree prev = NULL_TREE;
16419 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16420 switch (OMP_CLAUSE_CODE (c))
16422 tree var, x;
16423 default:
16424 break;
16425 case OMP_CLAUSE_FIRSTPRIVATE:
16426 if (is_gimple_omp_oacc (ctx->stmt))
16427 break;
16428 var = OMP_CLAUSE_DECL (c);
16429 if (is_reference (var)
16430 || is_gimple_reg_type (TREE_TYPE (var)))
16432 tree new_var = lookup_decl (var, ctx);
16433 tree type;
16434 type = TREE_TYPE (var);
16435 if (is_reference (var))
16436 type = TREE_TYPE (type);
16437 if ((INTEGRAL_TYPE_P (type)
16438 && TYPE_PRECISION (type) <= POINTER_SIZE)
16439 || TREE_CODE (type) == POINTER_TYPE)
16441 x = build_receiver_ref (var, false, ctx);
16442 if (TREE_CODE (type) != POINTER_TYPE)
16443 x = fold_convert (pointer_sized_int_node, x);
16444 x = fold_convert (type, x);
16445 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16446 fb_rvalue);
16447 if (is_reference (var))
16449 tree v = create_tmp_var_raw (type, get_name (var));
16450 gimple_add_tmp_var (v);
16451 TREE_ADDRESSABLE (v) = 1;
16452 gimple_seq_add_stmt (&new_body,
16453 gimple_build_assign (v, x));
16454 x = build_fold_addr_expr (v);
16456 gimple_seq_add_stmt (&new_body,
16457 gimple_build_assign (new_var, x));
16459 else
16461 x = build_receiver_ref (var, !is_reference (var), ctx);
16462 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16463 fb_rvalue);
16464 gimple_seq_add_stmt (&new_body,
16465 gimple_build_assign (new_var, x));
16468 else if (is_variable_sized (var))
16470 tree pvar = DECL_VALUE_EXPR (var);
16471 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16472 pvar = TREE_OPERAND (pvar, 0);
16473 gcc_assert (DECL_P (pvar));
16474 tree new_var = lookup_decl (pvar, ctx);
16475 x = build_receiver_ref (var, false, ctx);
16476 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16477 gimple_seq_add_stmt (&new_body,
16478 gimple_build_assign (new_var, x));
16480 break;
16481 case OMP_CLAUSE_PRIVATE:
16482 if (is_gimple_omp_oacc (ctx->stmt))
16483 break;
16484 var = OMP_CLAUSE_DECL (c);
16485 if (is_reference (var))
16487 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16488 tree new_var = lookup_decl (var, ctx);
16489 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16490 if (TREE_CONSTANT (x))
16492 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16493 get_name (var));
16494 gimple_add_tmp_var (x);
16495 TREE_ADDRESSABLE (x) = 1;
16496 x = build_fold_addr_expr_loc (clause_loc, x);
16498 else
16499 break;
16501 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16502 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16503 gimple_seq_add_stmt (&new_body,
16504 gimple_build_assign (new_var, x));
16506 break;
16507 case OMP_CLAUSE_USE_DEVICE_PTR:
16508 case OMP_CLAUSE_IS_DEVICE_PTR:
16509 var = OMP_CLAUSE_DECL (c);
16510 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16511 x = build_sender_ref (var, ctx);
16512 else
16513 x = build_receiver_ref (var, false, ctx);
16514 if (is_variable_sized (var))
16516 tree pvar = DECL_VALUE_EXPR (var);
16517 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16518 pvar = TREE_OPERAND (pvar, 0);
16519 gcc_assert (DECL_P (pvar));
16520 tree new_var = lookup_decl (pvar, ctx);
16521 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16522 gimple_seq_add_stmt (&new_body,
16523 gimple_build_assign (new_var, x));
16525 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16527 tree new_var = lookup_decl (var, ctx);
16528 new_var = DECL_VALUE_EXPR (new_var);
16529 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16530 new_var = TREE_OPERAND (new_var, 0);
16531 gcc_assert (DECL_P (new_var));
16532 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16533 gimple_seq_add_stmt (&new_body,
16534 gimple_build_assign (new_var, x));
16536 else
16538 tree type = TREE_TYPE (var);
16539 tree new_var = lookup_decl (var, ctx);
16540 if (is_reference (var))
16542 type = TREE_TYPE (type);
16543 if (TREE_CODE (type) != ARRAY_TYPE)
16545 tree v = create_tmp_var_raw (type, get_name (var));
16546 gimple_add_tmp_var (v);
16547 TREE_ADDRESSABLE (v) = 1;
16548 x = fold_convert (type, x);
16549 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16550 fb_rvalue);
16551 gimple_seq_add_stmt (&new_body,
16552 gimple_build_assign (v, x));
16553 x = build_fold_addr_expr (v);
16556 new_var = DECL_VALUE_EXPR (new_var);
16557 x = fold_convert (TREE_TYPE (new_var), x);
16558 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16559 gimple_seq_add_stmt (&new_body,
16560 gimple_build_assign (new_var, x));
16562 break;
16564 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16565 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16566 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16567 or references to VLAs. */
16568 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16569 switch (OMP_CLAUSE_CODE (c))
16571 tree var;
16572 default:
16573 break;
16574 case OMP_CLAUSE_MAP:
16575 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16576 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16578 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16579 HOST_WIDE_INT offset = 0;
16580 gcc_assert (prev);
16581 var = OMP_CLAUSE_DECL (c);
16582 if (DECL_P (var)
16583 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16584 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16585 ctx))
16586 && varpool_node::get_create (var)->offloadable)
16587 break;
16588 if (TREE_CODE (var) == INDIRECT_REF
16589 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16590 var = TREE_OPERAND (var, 0);
16591 if (TREE_CODE (var) == COMPONENT_REF)
16593 var = get_addr_base_and_unit_offset (var, &offset);
16594 gcc_assert (var != NULL_TREE && DECL_P (var));
16596 else if (DECL_SIZE (var)
16597 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16599 tree var2 = DECL_VALUE_EXPR (var);
16600 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16601 var2 = TREE_OPERAND (var2, 0);
16602 gcc_assert (DECL_P (var2));
16603 var = var2;
16605 tree new_var = lookup_decl (var, ctx), x;
16606 tree type = TREE_TYPE (new_var);
16607 bool is_ref;
16608 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16609 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16610 == COMPONENT_REF))
16612 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16613 is_ref = true;
16614 new_var = build2 (MEM_REF, type,
16615 build_fold_addr_expr (new_var),
16616 build_int_cst (build_pointer_type (type),
16617 offset));
16619 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16621 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16622 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16623 new_var = build2 (MEM_REF, type,
16624 build_fold_addr_expr (new_var),
16625 build_int_cst (build_pointer_type (type),
16626 offset));
16628 else
16629 is_ref = is_reference (var);
16630 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16631 is_ref = false;
16632 bool ref_to_array = false;
16633 if (is_ref)
16635 type = TREE_TYPE (type);
16636 if (TREE_CODE (type) == ARRAY_TYPE)
16638 type = build_pointer_type (type);
16639 ref_to_array = true;
16642 else if (TREE_CODE (type) == ARRAY_TYPE)
16644 tree decl2 = DECL_VALUE_EXPR (new_var);
16645 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16646 decl2 = TREE_OPERAND (decl2, 0);
16647 gcc_assert (DECL_P (decl2));
16648 new_var = decl2;
16649 type = TREE_TYPE (new_var);
16651 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16652 x = fold_convert_loc (clause_loc, type, x);
16653 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16655 tree bias = OMP_CLAUSE_SIZE (c);
16656 if (DECL_P (bias))
16657 bias = lookup_decl (bias, ctx);
16658 bias = fold_convert_loc (clause_loc, sizetype, bias);
16659 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16660 bias);
16661 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16662 TREE_TYPE (x), x, bias);
16664 if (ref_to_array)
16665 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16666 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16667 if (is_ref && !ref_to_array)
16669 tree t = create_tmp_var_raw (type, get_name (var));
16670 gimple_add_tmp_var (t);
16671 TREE_ADDRESSABLE (t) = 1;
16672 gimple_seq_add_stmt (&new_body,
16673 gimple_build_assign (t, x));
16674 x = build_fold_addr_expr_loc (clause_loc, t);
16676 gimple_seq_add_stmt (&new_body,
16677 gimple_build_assign (new_var, x));
16678 prev = NULL_TREE;
16680 else if (OMP_CLAUSE_CHAIN (c)
16681 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16682 == OMP_CLAUSE_MAP
16683 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16684 == GOMP_MAP_FIRSTPRIVATE_POINTER
16685 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16686 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16687 prev = c;
16688 break;
16689 case OMP_CLAUSE_PRIVATE:
16690 var = OMP_CLAUSE_DECL (c);
16691 if (is_variable_sized (var))
16693 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16694 tree new_var = lookup_decl (var, ctx);
16695 tree pvar = DECL_VALUE_EXPR (var);
16696 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16697 pvar = TREE_OPERAND (pvar, 0);
16698 gcc_assert (DECL_P (pvar));
16699 tree new_pvar = lookup_decl (pvar, ctx);
16700 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16701 tree al = size_int (DECL_ALIGN (var));
16702 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16703 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16704 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16705 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16706 gimple_seq_add_stmt (&new_body,
16707 gimple_build_assign (new_pvar, x));
16709 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16711 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16712 tree new_var = lookup_decl (var, ctx);
16713 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16714 if (TREE_CONSTANT (x))
16715 break;
16716 else
16718 tree atmp
16719 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16720 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16721 tree al = size_int (TYPE_ALIGN (rtype));
16722 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16725 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16726 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16727 gimple_seq_add_stmt (&new_body,
16728 gimple_build_assign (new_var, x));
16730 break;
16733 gimple_seq fork_seq = NULL;
16734 gimple_seq join_seq = NULL;
16736 if (is_oacc_parallel (ctx))
16738 /* If there are reductions on the offloaded region itself, treat
16739 them as a dummy GANG loop. */
16740 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16742 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16743 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16746 gimple_seq_add_seq (&new_body, fork_seq);
16747 gimple_seq_add_seq (&new_body, tgt_body);
16748 gimple_seq_add_seq (&new_body, join_seq);
16750 if (offloaded)
16751 new_body = maybe_catch_exception (new_body);
16753 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16754 gimple_omp_set_body (stmt, new_body);
16757 bind = gimple_build_bind (NULL, NULL,
16758 tgt_bind ? gimple_bind_block (tgt_bind)
16759 : NULL_TREE);
16760 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16761 gimple_bind_add_seq (bind, ilist);
16762 gimple_bind_add_stmt (bind, stmt);
16763 gimple_bind_add_seq (bind, olist);
16765 pop_gimplify_context (NULL);
16767 if (dep_bind)
16769 gimple_bind_add_seq (dep_bind, dep_ilist);
16770 gimple_bind_add_stmt (dep_bind, bind);
16771 gimple_bind_add_seq (dep_bind, dep_olist);
16772 pop_gimplify_context (dep_bind);
16776 /* Expand code for an OpenMP teams directive. */
16778 static void
16779 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16781 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16782 push_gimplify_context ();
16784 tree block = make_node (BLOCK);
16785 gbind *bind = gimple_build_bind (NULL, NULL, block);
16786 gsi_replace (gsi_p, bind, true);
16787 gimple_seq bind_body = NULL;
16788 gimple_seq dlist = NULL;
16789 gimple_seq olist = NULL;
16791 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16792 OMP_CLAUSE_NUM_TEAMS);
16793 if (num_teams == NULL_TREE)
16794 num_teams = build_int_cst (unsigned_type_node, 0);
16795 else
16797 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16798 num_teams = fold_convert (unsigned_type_node, num_teams);
16799 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16801 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16802 OMP_CLAUSE_THREAD_LIMIT);
16803 if (thread_limit == NULL_TREE)
16804 thread_limit = build_int_cst (unsigned_type_node, 0);
16805 else
16807 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16808 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16809 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16810 fb_rvalue);
16813 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16814 &bind_body, &dlist, ctx, NULL);
16815 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16816 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16817 if (!gimple_omp_teams_grid_phony (teams_stmt))
16819 gimple_seq_add_stmt (&bind_body, teams_stmt);
16820 location_t loc = gimple_location (teams_stmt);
16821 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16822 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16823 gimple_set_location (call, loc);
16824 gimple_seq_add_stmt (&bind_body, call);
16827 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16828 gimple_omp_set_body (teams_stmt, NULL);
16829 gimple_seq_add_seq (&bind_body, olist);
16830 gimple_seq_add_seq (&bind_body, dlist);
16831 if (!gimple_omp_teams_grid_phony (teams_stmt))
16832 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16833 gimple_bind_set_body (bind, bind_body);
16835 pop_gimplify_context (bind);
16837 gimple_bind_append_vars (bind, ctx->block_vars);
16838 BLOCK_VARS (block) = ctx->block_vars;
16839 if (BLOCK_VARS (block))
16840 TREE_USED (block) = 1;
16843 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16845 static void
16846 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16848 gimple *stmt = gsi_stmt (*gsi_p);
16849 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16850 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16851 gimple_build_omp_return (false));
16855 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16856 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16857 of OMP context, but with task_shared_vars set. */
16859 static tree
16860 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16861 void *data)
16863 tree t = *tp;
16865 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16866 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16867 return t;
16869 if (task_shared_vars
16870 && DECL_P (t)
16871 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16872 return t;
16874 /* If a global variable has been privatized, TREE_CONSTANT on
16875 ADDR_EXPR might be wrong. */
16876 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16877 recompute_tree_invariant_for_addr_expr (t);
16879 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16880 return NULL_TREE;
16883 /* Data to be communicated between lower_omp_regimplify_operands and
16884 lower_omp_regimplify_operands_p. */
16886 struct lower_omp_regimplify_operands_data
16888 omp_context *ctx;
16889 vec<tree> *decls;
16892 /* Helper function for lower_omp_regimplify_operands. Find
16893 omp_member_access_dummy_var vars and adjust temporarily their
16894 DECL_VALUE_EXPRs if needed. */
16896 static tree
16897 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16898 void *data)
16900 tree t = omp_member_access_dummy_var (*tp);
16901 if (t)
16903 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16904 lower_omp_regimplify_operands_data *ldata
16905 = (lower_omp_regimplify_operands_data *) wi->info;
16906 tree o = maybe_lookup_decl (t, ldata->ctx);
16907 if (o != t)
16909 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16910 ldata->decls->safe_push (*tp);
16911 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16912 SET_DECL_VALUE_EXPR (*tp, v);
16915 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16916 return NULL_TREE;
16919 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16920 of omp_member_access_dummy_var vars during regimplification. */
16922 static void
16923 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16924 gimple_stmt_iterator *gsi_p)
16926 auto_vec<tree, 10> decls;
16927 if (ctx)
16929 struct walk_stmt_info wi;
16930 memset (&wi, '\0', sizeof (wi));
16931 struct lower_omp_regimplify_operands_data data;
16932 data.ctx = ctx;
16933 data.decls = &decls;
16934 wi.info = &data;
16935 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16937 gimple_regimplify_operands (stmt, gsi_p);
16938 while (!decls.is_empty ())
16940 tree t = decls.pop ();
16941 tree v = decls.pop ();
16942 SET_DECL_VALUE_EXPR (t, v);
16946 static void
16947 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16949 gimple *stmt = gsi_stmt (*gsi_p);
16950 struct walk_stmt_info wi;
16951 gcall *call_stmt;
16953 if (gimple_has_location (stmt))
16954 input_location = gimple_location (stmt);
16956 if (task_shared_vars)
16957 memset (&wi, '\0', sizeof (wi));
16959 /* If we have issued syntax errors, avoid doing any heavy lifting.
16960 Just replace the OMP directives with a NOP to avoid
16961 confusing RTL expansion. */
16962 if (seen_error () && is_gimple_omp (stmt))
16964 gsi_replace (gsi_p, gimple_build_nop (), true);
16965 return;
16968 switch (gimple_code (stmt))
16970 case GIMPLE_COND:
16972 gcond *cond_stmt = as_a <gcond *> (stmt);
16973 if ((ctx || task_shared_vars)
16974 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16975 lower_omp_regimplify_p,
16976 ctx ? NULL : &wi, NULL)
16977 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16978 lower_omp_regimplify_p,
16979 ctx ? NULL : &wi, NULL)))
16980 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16982 break;
16983 case GIMPLE_CATCH:
16984 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16985 break;
16986 case GIMPLE_EH_FILTER:
16987 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16988 break;
16989 case GIMPLE_TRY:
16990 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16991 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16992 break;
16993 case GIMPLE_TRANSACTION:
16994 lower_omp (gimple_transaction_body_ptr (
16995 as_a <gtransaction *> (stmt)),
16996 ctx);
16997 break;
16998 case GIMPLE_BIND:
16999 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17000 break;
17001 case GIMPLE_OMP_PARALLEL:
17002 case GIMPLE_OMP_TASK:
17003 ctx = maybe_lookup_ctx (stmt);
17004 gcc_assert (ctx);
17005 if (ctx->cancellable)
17006 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17007 lower_omp_taskreg (gsi_p, ctx);
17008 break;
17009 case GIMPLE_OMP_FOR:
17010 ctx = maybe_lookup_ctx (stmt);
17011 gcc_assert (ctx);
17012 if (ctx->cancellable)
17013 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17014 lower_omp_for (gsi_p, ctx);
17015 break;
17016 case GIMPLE_OMP_SECTIONS:
17017 ctx = maybe_lookup_ctx (stmt);
17018 gcc_assert (ctx);
17019 if (ctx->cancellable)
17020 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17021 lower_omp_sections (gsi_p, ctx);
17022 break;
17023 case GIMPLE_OMP_SINGLE:
17024 ctx = maybe_lookup_ctx (stmt);
17025 gcc_assert (ctx);
17026 lower_omp_single (gsi_p, ctx);
17027 break;
17028 case GIMPLE_OMP_MASTER:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 lower_omp_master (gsi_p, ctx);
17032 break;
17033 case GIMPLE_OMP_TASKGROUP:
17034 ctx = maybe_lookup_ctx (stmt);
17035 gcc_assert (ctx);
17036 lower_omp_taskgroup (gsi_p, ctx);
17037 break;
17038 case GIMPLE_OMP_ORDERED:
17039 ctx = maybe_lookup_ctx (stmt);
17040 gcc_assert (ctx);
17041 lower_omp_ordered (gsi_p, ctx);
17042 break;
17043 case GIMPLE_OMP_CRITICAL:
17044 ctx = maybe_lookup_ctx (stmt);
17045 gcc_assert (ctx);
17046 lower_omp_critical (gsi_p, ctx);
17047 break;
17048 case GIMPLE_OMP_ATOMIC_LOAD:
17049 if ((ctx || task_shared_vars)
17050 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17051 as_a <gomp_atomic_load *> (stmt)),
17052 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17053 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17054 break;
17055 case GIMPLE_OMP_TARGET:
17056 ctx = maybe_lookup_ctx (stmt);
17057 gcc_assert (ctx);
17058 lower_omp_target (gsi_p, ctx);
17059 break;
17060 case GIMPLE_OMP_TEAMS:
17061 ctx = maybe_lookup_ctx (stmt);
17062 gcc_assert (ctx);
17063 lower_omp_teams (gsi_p, ctx);
17064 break;
17065 case GIMPLE_OMP_GRID_BODY:
17066 ctx = maybe_lookup_ctx (stmt);
17067 gcc_assert (ctx);
17068 lower_omp_grid_body (gsi_p, ctx);
17069 break;
17070 case GIMPLE_CALL:
17071 tree fndecl;
17072 call_stmt = as_a <gcall *> (stmt);
17073 fndecl = gimple_call_fndecl (call_stmt);
17074 if (fndecl
17075 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17076 switch (DECL_FUNCTION_CODE (fndecl))
17078 case BUILT_IN_GOMP_BARRIER:
17079 if (ctx == NULL)
17080 break;
17081 /* FALLTHRU */
17082 case BUILT_IN_GOMP_CANCEL:
17083 case BUILT_IN_GOMP_CANCELLATION_POINT:
17084 omp_context *cctx;
17085 cctx = ctx;
17086 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17087 cctx = cctx->outer;
17088 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17089 if (!cctx->cancellable)
17091 if (DECL_FUNCTION_CODE (fndecl)
17092 == BUILT_IN_GOMP_CANCELLATION_POINT)
17094 stmt = gimple_build_nop ();
17095 gsi_replace (gsi_p, stmt, false);
17097 break;
17099 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17101 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17102 gimple_call_set_fndecl (call_stmt, fndecl);
17103 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17105 tree lhs;
17106 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17107 gimple_call_set_lhs (call_stmt, lhs);
17108 tree fallthru_label;
17109 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17110 gimple *g;
17111 g = gimple_build_label (fallthru_label);
17112 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17113 g = gimple_build_cond (NE_EXPR, lhs,
17114 fold_convert (TREE_TYPE (lhs),
17115 boolean_false_node),
17116 cctx->cancel_label, fallthru_label);
17117 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17118 break;
17119 default:
17120 break;
17122 /* FALLTHRU */
17123 default:
17124 if ((ctx || task_shared_vars)
17125 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17126 ctx ? NULL : &wi))
17128 /* Just remove clobbers, this should happen only if we have
17129 "privatized" local addressable variables in SIMD regions,
17130 the clobber isn't needed in that case and gimplifying address
17131 of the ARRAY_REF into a pointer and creating MEM_REF based
17132 clobber would create worse code than we get with the clobber
17133 dropped. */
17134 if (gimple_clobber_p (stmt))
17136 gsi_replace (gsi_p, gimple_build_nop (), true);
17137 break;
17139 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17141 break;
17145 static void
17146 lower_omp (gimple_seq *body, omp_context *ctx)
17148 location_t saved_location = input_location;
17149 gimple_stmt_iterator gsi;
17150 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17151 lower_omp_1 (&gsi, ctx);
17152 /* During gimplification, we haven't folded statments inside offloading
17153 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17154 if (target_nesting_level || taskreg_nesting_level)
17155 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17156 fold_stmt (&gsi);
17157 input_location = saved_location;
17160 /* Returen true if STMT is an assignment of a register-type into a local
17161 VAR_DECL. */
17163 static bool
17164 grid_reg_assignment_to_local_var_p (gimple *stmt)
17166 gassign *assign = dyn_cast <gassign *> (stmt);
17167 if (!assign)
17168 return false;
17169 tree lhs = gimple_assign_lhs (assign);
17170 if (TREE_CODE (lhs) != VAR_DECL
17171 || !is_gimple_reg_type (TREE_TYPE (lhs))
17172 || is_global_var (lhs))
17173 return false;
17174 return true;
17177 /* Return true if all statements in SEQ are assignments to local register-type
17178 variables. */
17180 static bool
17181 grid_seq_only_contains_local_assignments (gimple_seq seq)
17183 if (!seq)
17184 return true;
17186 gimple_stmt_iterator gsi;
17187 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17188 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17189 return false;
17190 return true;
17193 /* Scan statements in SEQ and call itself recursively on any bind. If during
17194 whole search only assignments to register-type local variables and one
17195 single OMP statement is encountered, return true, otherwise return false.
17196 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17197 are used for dumping a note about a failure. */
17199 static bool
17200 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17201 const char *name, gimple **ret)
17203 gimple_stmt_iterator gsi;
17204 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17206 gimple *stmt = gsi_stmt (gsi);
17208 if (grid_reg_assignment_to_local_var_p (stmt))
17209 continue;
17210 if (gbind *bind = dyn_cast <gbind *> (stmt))
17212 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17213 target_loc, name, ret))
17214 return false;
17216 else if (is_gimple_omp (stmt))
17218 if (*ret)
17220 if (dump_enabled_p ())
17221 dump_printf_loc (MSG_NOTE, target_loc,
17222 "Will not turn target construct into a simple "
17223 "GPGPU kernel because %s construct contains "
17224 "multiple OpenMP constructs\n", name);
17225 return false;
17227 *ret = stmt;
17229 else
17231 if (dump_enabled_p ())
17232 dump_printf_loc (MSG_NOTE, target_loc,
17233 "Will not turn target construct into a simple "
17234 "GPGPU kernel because %s construct contains "
17235 "a complex statement\n", name);
17236 return false;
17239 return true;
17242 /* Scan statements in SEQ and make sure that it and any binds in it contain
17243 only assignments to local register-type variables and one OMP construct. If
17244 so, return that construct, otherwise return NULL. If dumping is enabled and
17245 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17246 failure. */
17248 static gimple *
17249 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17250 const char *name)
17252 if (!seq)
17254 if (dump_enabled_p ())
17255 dump_printf_loc (MSG_NOTE, target_loc,
17256 "Will not turn target construct into a simple "
17257 "GPGPU kernel because %s construct has empty "
17258 "body\n",
17259 name);
17260 return NULL;
17263 gimple *ret = NULL;
17264 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17266 if (!ret && dump_enabled_p ())
17267 dump_printf_loc (MSG_NOTE, target_loc,
17268 "Will not turn target construct into a simple "
17269 "GPGPU kernel because %s construct does not contain"
17270 "any other OpenMP construct\n", name);
17271 return ret;
17273 else
17274 return NULL;
17277 /* Walker function looking for statements there is no point gridifying (and for
17278 noreturn function calls which we cannot do). Return non-NULL if such a
17279 function is found. */
17281 static tree
17282 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17283 bool *handled_ops_p,
17284 struct walk_stmt_info *wi)
17286 *handled_ops_p = false;
17287 gimple *stmt = gsi_stmt (*gsi);
17288 switch (gimple_code (stmt))
17290 case GIMPLE_CALL:
17291 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17293 *handled_ops_p = true;
17294 wi->info = stmt;
17295 return error_mark_node;
17297 break;
17299 /* We may reduce the following list if we find a way to implement the
17300 clauses, but now there is no point trying further. */
17301 case GIMPLE_OMP_CRITICAL:
17302 case GIMPLE_OMP_TASKGROUP:
17303 case GIMPLE_OMP_TASK:
17304 case GIMPLE_OMP_SECTION:
17305 case GIMPLE_OMP_SECTIONS:
17306 case GIMPLE_OMP_SECTIONS_SWITCH:
17307 case GIMPLE_OMP_TARGET:
17308 case GIMPLE_OMP_ORDERED:
17309 *handled_ops_p = true;
17310 wi->info = stmt;
17311 return error_mark_node;
17313 case GIMPLE_OMP_FOR:
17314 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17315 && gimple_omp_for_combined_into_p (stmt))
17317 *handled_ops_p = true;
17318 wi->info = stmt;
17319 return error_mark_node;
17321 break;
17323 default:
17324 break;
17326 return NULL;
17330 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17331 kernel, return true, otherwise return false. In the case of success, also
17332 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17333 none. */
17335 static bool
17336 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17338 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17339 return false;
17341 location_t tloc = gimple_location (target);
17342 gimple *stmt
17343 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17344 tloc, "target");
17345 if (!stmt)
17346 return false;
17347 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17348 tree group_size = NULL;
17349 if (!teams)
17351 dump_printf_loc (MSG_NOTE, tloc,
17352 "Will not turn target construct into a simple "
17353 "GPGPU kernel because it does not have a sole teams "
17354 "construct in it.\n");
17355 return false;
17358 tree clauses = gimple_omp_teams_clauses (teams);
17359 while (clauses)
17361 switch (OMP_CLAUSE_CODE (clauses))
17363 case OMP_CLAUSE_NUM_TEAMS:
17364 if (dump_enabled_p ())
17365 dump_printf_loc (MSG_NOTE, tloc,
17366 "Will not turn target construct into a "
17367 "gridified GPGPU kernel because we cannot "
17368 "handle num_teams clause of teams "
17369 "construct\n ");
17370 return false;
17372 case OMP_CLAUSE_REDUCTION:
17373 if (dump_enabled_p ())
17374 dump_printf_loc (MSG_NOTE, tloc,
17375 "Will not turn target construct into a "
17376 "gridified GPGPU kernel because a reduction "
17377 "clause is present\n ");
17378 return false;
17380 case OMP_CLAUSE_LASTPRIVATE:
17381 if (dump_enabled_p ())
17382 dump_printf_loc (MSG_NOTE, tloc,
17383 "Will not turn target construct into a "
17384 "gridified GPGPU kernel because a lastprivate "
17385 "clause is present\n ");
17386 return false;
17388 case OMP_CLAUSE_THREAD_LIMIT:
17389 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17390 break;
17392 default:
17393 break;
17395 clauses = OMP_CLAUSE_CHAIN (clauses);
17398 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17399 "teams");
17400 if (!stmt)
17401 return false;
17402 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17403 if (!dist)
17405 dump_printf_loc (MSG_NOTE, tloc,
17406 "Will not turn target construct into a simple "
17407 "GPGPU kernel because the teams construct does not have "
17408 "a sole distribute construct in it.\n");
17409 return false;
17412 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17413 if (!gimple_omp_for_combined_p (dist))
17415 if (dump_enabled_p ())
17416 dump_printf_loc (MSG_NOTE, tloc,
17417 "Will not turn target construct into a gridified GPGPU "
17418 "kernel because we cannot handle a standalone "
17419 "distribute construct\n ");
17420 return false;
17422 if (dist->collapse > 1)
17424 if (dump_enabled_p ())
17425 dump_printf_loc (MSG_NOTE, tloc,
17426 "Will not turn target construct into a gridified GPGPU "
17427 "kernel because the distribute construct contains "
17428 "collapse clause\n");
17429 return false;
17431 struct omp_for_data fd;
17432 extract_omp_for_data (dist, &fd, NULL);
17433 if (fd.chunk_size)
17435 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17437 if (dump_enabled_p ())
17438 dump_printf_loc (MSG_NOTE, tloc,
17439 "Will not turn target construct into a "
17440 "gridified GPGPU kernel because the teams "
17441 "thread limit is different from distribute "
17442 "schedule chunk\n");
17443 return false;
17445 group_size = fd.chunk_size;
17447 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17448 "distribute");
17449 gomp_parallel *par;
17450 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17451 return false;
17453 clauses = gimple_omp_parallel_clauses (par);
17454 while (clauses)
17456 switch (OMP_CLAUSE_CODE (clauses))
17458 case OMP_CLAUSE_NUM_THREADS:
17459 if (dump_enabled_p ())
17460 dump_printf_loc (MSG_NOTE, tloc,
17461 "Will not turn target construct into a gridified"
17462 "GPGPU kernel because there is a num_threads "
17463 "clause of the parallel construct\n");
17464 return false;
17466 case OMP_CLAUSE_REDUCTION:
17467 if (dump_enabled_p ())
17468 dump_printf_loc (MSG_NOTE, tloc,
17469 "Will not turn target construct into a "
17470 "gridified GPGPU kernel because a reduction "
17471 "clause is present\n ");
17472 return false;
17474 case OMP_CLAUSE_LASTPRIVATE:
17475 if (dump_enabled_p ())
17476 dump_printf_loc (MSG_NOTE, tloc,
17477 "Will not turn target construct into a "
17478 "gridified GPGPU kernel because a lastprivate "
17479 "clause is present\n ");
17480 return false;
17482 default:
17483 break;
17485 clauses = OMP_CLAUSE_CHAIN (clauses);
17488 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17489 "parallel");
17490 gomp_for *gfor;
17491 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17492 return false;
17494 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17496 if (dump_enabled_p ())
17497 dump_printf_loc (MSG_NOTE, tloc,
17498 "Will not turn target construct into a gridified GPGPU "
17499 "kernel because the inner loop is not a simple for "
17500 "loop\n");
17501 return false;
17503 if (gfor->collapse > 1)
17505 if (dump_enabled_p ())
17506 dump_printf_loc (MSG_NOTE, tloc,
17507 "Will not turn target construct into a gridified GPGPU "
17508 "kernel because the inner loop contains collapse "
17509 "clause\n");
17510 return false;
17513 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17515 if (dump_enabled_p ())
17516 dump_printf_loc (MSG_NOTE, tloc,
17517 "Will not turn target construct into a gridified GPGPU "
17518 "kernel because the inner loop pre_body contains"
17519 "a complex instruction\n");
17520 return false;
17523 clauses = gimple_omp_for_clauses (gfor);
17524 while (clauses)
17526 switch (OMP_CLAUSE_CODE (clauses))
17528 case OMP_CLAUSE_SCHEDULE:
17529 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17531 if (dump_enabled_p ())
17532 dump_printf_loc (MSG_NOTE, tloc,
17533 "Will not turn target construct into a "
17534 "gridified GPGPU kernel because the inner "
17535 "loop has a non-automatic scheduling clause\n");
17536 return false;
17538 break;
17540 case OMP_CLAUSE_REDUCTION:
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a "
17544 "gridified GPGPU kernel because a reduction "
17545 "clause is present\n ");
17546 return false;
17548 case OMP_CLAUSE_LASTPRIVATE:
17549 if (dump_enabled_p ())
17550 dump_printf_loc (MSG_NOTE, tloc,
17551 "Will not turn target construct into a "
17552 "gridified GPGPU kernel because a lastprivate "
17553 "clause is present\n ");
17554 return false;
17556 default:
17557 break;
17559 clauses = OMP_CLAUSE_CHAIN (clauses);
17562 struct walk_stmt_info wi;
17563 memset (&wi, 0, sizeof (wi));
17564 if (walk_gimple_seq (gimple_omp_body (gfor),
17565 grid_find_ungridifiable_statement,
17566 NULL, &wi))
17568 gimple *bad = (gimple *) wi.info;
17569 if (dump_enabled_p ())
17571 if (is_gimple_call (bad))
17572 dump_printf_loc (MSG_NOTE, tloc,
17573 "Will not turn target construct into a gridified "
17574 " GPGPU kernel because the inner loop contains "
17575 "call to a noreturn function\n");
17576 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17577 dump_printf_loc (MSG_NOTE, tloc,
17578 "Will not turn target construct into a gridified "
17579 " GPGPU kernel because the inner loop contains "
17580 "a simd construct\n");
17581 else
17582 dump_printf_loc (MSG_NOTE, tloc,
17583 "Will not turn target construct into a gridified "
17584 "GPGPU kernel because the inner loop contains "
17585 "statement %s which cannot be transformed\n",
17586 gimple_code_name[(int) gimple_code (bad)]);
17588 return false;
17591 *group_size_p = group_size;
17592 return true;
17595 /* Operand walker, used to remap pre-body declarations according to a hash map
17596 provided in DATA. */
17598 static tree
17599 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17601 tree t = *tp;
17603 if (DECL_P (t) || TYPE_P (t))
17604 *walk_subtrees = 0;
17605 else
17606 *walk_subtrees = 1;
17608 if (TREE_CODE (t) == VAR_DECL)
17610 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17611 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17612 tree *repl = declmap->get (t);
17613 if (repl)
17614 *tp = *repl;
17616 return NULL_TREE;
17619 /* Copy leading register-type assignments to local variables in SRC to just
17620 before DST, Creating temporaries, adjusting mapping of operands in WI and
17621 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17622 Return the first statement that does not conform to
17623 grid_reg_assignment_to_local_var_p or NULL. */
17625 static gimple *
17626 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17627 gbind *tgt_bind, struct walk_stmt_info *wi)
17629 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17630 gimple_stmt_iterator gsi;
17631 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17633 gimple *stmt = gsi_stmt (gsi);
17634 if (gbind *bind = dyn_cast <gbind *> (stmt))
17636 gimple *r = grid_copy_leading_local_assignments
17637 (gimple_bind_body (bind), dst, tgt_bind, wi);
17638 if (r)
17639 return r;
17640 else
17641 continue;
17643 if (!grid_reg_assignment_to_local_var_p (stmt))
17644 return stmt;
17645 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17646 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17647 TREE_TYPE (lhs));
17648 DECL_CONTEXT (repl) = current_function_decl;
17649 gimple_bind_append_vars (tgt_bind, repl);
17651 declmap->put (lhs, repl);
17652 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17653 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17654 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17656 return NULL;
17659 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17660 components, mark them as part of kernel and return the inner loop, and copy
17661 assignment leading to them just before DST, remapping them using WI and
17662 adding new temporaries to TGT_BIND. */
17664 static gomp_for *
17665 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17666 gbind *tgt_bind, struct walk_stmt_info *wi)
17668 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17669 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17670 gcc_assert (teams);
17671 gimple_omp_teams_set_grid_phony (teams, true);
17672 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17673 tgt_bind, wi);
17674 gcc_checking_assert (stmt);
17675 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17676 gcc_assert (dist);
17677 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17678 if (prebody)
17679 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17680 gimple_omp_for_set_grid_phony (dist, true);
17681 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17682 tgt_bind, wi);
17683 gcc_checking_assert (stmt);
17685 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17686 gimple_omp_parallel_set_grid_phony (parallel, true);
17687 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17688 tgt_bind, wi);
17689 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17690 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17691 prebody = gimple_omp_for_pre_body (inner_loop);
17692 if (prebody)
17693 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17695 return inner_loop;
17698 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17699 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17700 is the bind into which temporaries inserted before TARGET should be
17701 added. */
17703 static void
17704 grid_attempt_target_gridification (gomp_target *target,
17705 gimple_stmt_iterator *gsi,
17706 gbind *tgt_bind)
17708 tree group_size;
17709 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17710 return;
17712 location_t loc = gimple_location (target);
17713 if (dump_enabled_p ())
17714 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17715 "Target construct will be turned into a gridified GPGPU "
17716 "kernel\n");
17718 /* Copy target body to a GPUKERNEL construct: */
17719 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17720 (gimple_omp_body (target));
17722 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17723 struct walk_stmt_info wi;
17724 memset (&wi, 0, sizeof (struct walk_stmt_info));
17725 wi.info = declmap;
17727 /* Copy assignments in between OMP statements before target, mark OMP
17728 statements within copy appropriatly. */
17729 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17730 tgt_bind, &wi);
17732 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17733 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17734 tree new_block = gimple_bind_block (new_bind);
17735 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17736 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17737 BLOCK_SUBBLOCKS (enc_block) = new_block;
17738 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17739 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17740 gimple_seq_add_stmt
17741 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17742 gpukernel);
17744 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17745 push_gimplify_context ();
17746 size_t collapse = gimple_omp_for_collapse (inner_loop);
17747 for (size_t i = 0; i < collapse; i++)
17749 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17750 if (POINTER_TYPE_P (type))
17751 itype = signed_type_for (type);
17752 else
17753 itype = type;
17755 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17756 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17757 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17758 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17759 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17760 adjust_for_condition (loc, &cond_code, &n2);
17761 tree step;
17762 step = get_omp_for_step_from_incr (loc,
17763 gimple_omp_for_incr (inner_loop, i));
17764 gimple_seq tmpseq = NULL;
17765 n1 = fold_convert (itype, n1);
17766 n2 = fold_convert (itype, n2);
17767 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17768 t = fold_build2 (PLUS_EXPR, itype, step, t);
17769 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17770 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17771 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17772 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17773 fold_build1 (NEGATE_EXPR, itype, t),
17774 fold_build1 (NEGATE_EXPR, itype, step));
17775 else
17776 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17777 tree gs = fold_convert (uint32_type_node, t);
17778 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17779 if (!gimple_seq_empty_p (tmpseq))
17780 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17782 tree ws;
17783 if (i == 0 && group_size)
17785 ws = fold_convert (uint32_type_node, group_size);
17786 tmpseq = NULL;
17787 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17788 if (!gimple_seq_empty_p (tmpseq))
17789 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17791 else
17792 ws = build_zero_cst (uint32_type_node);
17794 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17795 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17796 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17797 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17798 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17799 gimple_omp_target_set_clauses (target, c);
17801 pop_gimplify_context (tgt_bind);
17802 delete declmap;
17803 return;
17806 /* Walker function doing all the work for create_target_kernels. */
17808 static tree
17809 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17810 bool *handled_ops_p,
17811 struct walk_stmt_info *incoming)
17813 *handled_ops_p = false;
17815 gimple *stmt = gsi_stmt (*gsi);
17816 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17817 if (target)
17819 gbind *tgt_bind = (gbind *) incoming->info;
17820 gcc_checking_assert (tgt_bind);
17821 grid_attempt_target_gridification (target, gsi, tgt_bind);
17822 return NULL_TREE;
17824 gbind *bind = dyn_cast <gbind *> (stmt);
17825 if (bind)
17827 *handled_ops_p = true;
17828 struct walk_stmt_info wi;
17829 memset (&wi, 0, sizeof (wi));
17830 wi.info = bind;
17831 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17832 grid_gridify_all_targets_stmt, NULL, &wi);
17834 return NULL_TREE;
17837 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17838 have their bodies duplicated, with the new copy being put into a
17839 gimple_omp_grid_body statement. All kernel-related construct within the
17840 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17841 re-structuring is often needed, such as copying pre-bodies before the target
17842 construct so that kernel grid sizes can be computed. */
17844 static void
17845 grid_gridify_all_targets (gimple_seq *body_p)
17847 struct walk_stmt_info wi;
17848 memset (&wi, 0, sizeof (wi));
17849 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17853 /* Main entry point. */
17855 static unsigned int
17856 execute_lower_omp (void)
17858 gimple_seq body;
17859 int i;
17860 omp_context *ctx;
17862 /* This pass always runs, to provide PROP_gimple_lomp.
17863 But often, there is nothing to do. */
17864 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17865 && flag_openmp_simd == 0)
17866 return 0;
17868 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17869 delete_omp_context);
17871 body = gimple_body (current_function_decl);
17873 if (hsa_gen_requested_p ())
17874 grid_gridify_all_targets (&body);
17876 scan_omp (&body, NULL);
17877 gcc_assert (taskreg_nesting_level == 0);
17878 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17879 finish_taskreg_scan (ctx);
17880 taskreg_contexts.release ();
17882 if (all_contexts->root)
17884 if (task_shared_vars)
17885 push_gimplify_context ();
17886 lower_omp (&body, NULL);
17887 if (task_shared_vars)
17888 pop_gimplify_context (NULL);
17891 if (all_contexts)
17893 splay_tree_delete (all_contexts);
17894 all_contexts = NULL;
17896 BITMAP_FREE (task_shared_vars);
17897 return 0;
17900 namespace {
17902 const pass_data pass_data_lower_omp =
17904 GIMPLE_PASS, /* type */
17905 "omplower", /* name */
17906 OPTGROUP_NONE, /* optinfo_flags */
17907 TV_NONE, /* tv_id */
17908 PROP_gimple_any, /* properties_required */
17909 PROP_gimple_lomp, /* properties_provided */
17910 0, /* properties_destroyed */
17911 0, /* todo_flags_start */
17912 0, /* todo_flags_finish */
17915 class pass_lower_omp : public gimple_opt_pass
17917 public:
17918 pass_lower_omp (gcc::context *ctxt)
17919 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17922 /* opt_pass methods: */
17923 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17925 }; // class pass_lower_omp
17927 } // anon namespace
17929 gimple_opt_pass *
17930 make_pass_lower_omp (gcc::context *ctxt)
17932 return new pass_lower_omp (ctxt);
17935 /* The following is a utility to diagnose structured block violations.
17936 It is not part of the "omplower" pass, as that's invoked too late. It
17937 should be invoked by the respective front ends after gimplification. */
17939 static splay_tree all_labels;
17941 /* Check for mismatched contexts and generate an error if needed. Return
17942 true if an error is detected. */
17944 static bool
17945 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17946 gimple *branch_ctx, gimple *label_ctx)
17948 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17949 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17951 if (label_ctx == branch_ctx)
17952 return false;
17954 const char* kind = NULL;
17956 if (flag_cilkplus)
17958 if ((branch_ctx
17959 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17960 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17961 || (label_ctx
17962 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17963 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17964 kind = "Cilk Plus";
17966 if (flag_openacc)
17968 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17969 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17971 gcc_checking_assert (kind == NULL);
17972 kind = "OpenACC";
17975 if (kind == NULL)
17977 gcc_checking_assert (flag_openmp);
17978 kind = "OpenMP";
17982 Previously we kept track of the label's entire context in diagnose_sb_[12]
17983 so we could traverse it and issue a correct "exit" or "enter" error
17984 message upon a structured block violation.
17986 We built the context by building a list with tree_cons'ing, but there is
17987 no easy counterpart in gimple tuples. It seems like far too much work
17988 for issuing exit/enter error messages. If someone really misses the
17989 distinct error message... patches welcome.
17992 #if 0
17993 /* Try to avoid confusing the user by producing and error message
17994 with correct "exit" or "enter" verbiage. We prefer "exit"
17995 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17996 if (branch_ctx == NULL)
17997 exit_p = false;
17998 else
18000 while (label_ctx)
18002 if (TREE_VALUE (label_ctx) == branch_ctx)
18004 exit_p = false;
18005 break;
18007 label_ctx = TREE_CHAIN (label_ctx);
18011 if (exit_p)
18012 error ("invalid exit from %s structured block", kind);
18013 else
18014 error ("invalid entry to %s structured block", kind);
18015 #endif
18017 /* If it's obvious we have an invalid entry, be specific about the error. */
18018 if (branch_ctx == NULL)
18019 error ("invalid entry to %s structured block", kind);
18020 else
18022 /* Otherwise, be vague and lazy, but efficient. */
18023 error ("invalid branch to/from %s structured block", kind);
18026 gsi_replace (gsi_p, gimple_build_nop (), false);
18027 return true;
18030 /* Pass 1: Create a minimal tree of structured blocks, and record
18031 where each label is found. */
18033 static tree
18034 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18035 struct walk_stmt_info *wi)
18037 gimple *context = (gimple *) wi->info;
18038 gimple *inner_context;
18039 gimple *stmt = gsi_stmt (*gsi_p);
18041 *handled_ops_p = true;
18043 switch (gimple_code (stmt))
18045 WALK_SUBSTMTS;
18047 case GIMPLE_OMP_PARALLEL:
18048 case GIMPLE_OMP_TASK:
18049 case GIMPLE_OMP_SECTIONS:
18050 case GIMPLE_OMP_SINGLE:
18051 case GIMPLE_OMP_SECTION:
18052 case GIMPLE_OMP_MASTER:
18053 case GIMPLE_OMP_ORDERED:
18054 case GIMPLE_OMP_CRITICAL:
18055 case GIMPLE_OMP_TARGET:
18056 case GIMPLE_OMP_TEAMS:
18057 case GIMPLE_OMP_TASKGROUP:
18058 /* The minimal context here is just the current OMP construct. */
18059 inner_context = stmt;
18060 wi->info = inner_context;
18061 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18062 wi->info = context;
18063 break;
18065 case GIMPLE_OMP_FOR:
18066 inner_context = stmt;
18067 wi->info = inner_context;
18068 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18069 walk them. */
18070 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18071 diagnose_sb_1, NULL, wi);
18072 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18073 wi->info = context;
18074 break;
18076 case GIMPLE_LABEL:
18077 splay_tree_insert (all_labels,
18078 (splay_tree_key) gimple_label_label (
18079 as_a <glabel *> (stmt)),
18080 (splay_tree_value) context);
18081 break;
18083 default:
18084 break;
18087 return NULL_TREE;
18090 /* Pass 2: Check each branch and see if its context differs from that of
18091 the destination label's context. */
18093 static tree
18094 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18095 struct walk_stmt_info *wi)
18097 gimple *context = (gimple *) wi->info;
18098 splay_tree_node n;
18099 gimple *stmt = gsi_stmt (*gsi_p);
18101 *handled_ops_p = true;
18103 switch (gimple_code (stmt))
18105 WALK_SUBSTMTS;
18107 case GIMPLE_OMP_PARALLEL:
18108 case GIMPLE_OMP_TASK:
18109 case GIMPLE_OMP_SECTIONS:
18110 case GIMPLE_OMP_SINGLE:
18111 case GIMPLE_OMP_SECTION:
18112 case GIMPLE_OMP_MASTER:
18113 case GIMPLE_OMP_ORDERED:
18114 case GIMPLE_OMP_CRITICAL:
18115 case GIMPLE_OMP_TARGET:
18116 case GIMPLE_OMP_TEAMS:
18117 case GIMPLE_OMP_TASKGROUP:
18118 wi->info = stmt;
18119 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18120 wi->info = context;
18121 break;
18123 case GIMPLE_OMP_FOR:
18124 wi->info = stmt;
18125 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18126 walk them. */
18127 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18128 diagnose_sb_2, NULL, wi);
18129 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18130 wi->info = context;
18131 break;
18133 case GIMPLE_COND:
18135 gcond *cond_stmt = as_a <gcond *> (stmt);
18136 tree lab = gimple_cond_true_label (cond_stmt);
18137 if (lab)
18139 n = splay_tree_lookup (all_labels,
18140 (splay_tree_key) lab);
18141 diagnose_sb_0 (gsi_p, context,
18142 n ? (gimple *) n->value : NULL);
18144 lab = gimple_cond_false_label (cond_stmt);
18145 if (lab)
18147 n = splay_tree_lookup (all_labels,
18148 (splay_tree_key) lab);
18149 diagnose_sb_0 (gsi_p, context,
18150 n ? (gimple *) n->value : NULL);
18153 break;
18155 case GIMPLE_GOTO:
18157 tree lab = gimple_goto_dest (stmt);
18158 if (TREE_CODE (lab) != LABEL_DECL)
18159 break;
18161 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18162 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18164 break;
18166 case GIMPLE_SWITCH:
18168 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18169 unsigned int i;
18170 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18172 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18173 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18174 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18175 break;
18178 break;
18180 case GIMPLE_RETURN:
18181 diagnose_sb_0 (gsi_p, context, NULL);
18182 break;
18184 default:
18185 break;
18188 return NULL_TREE;
18191 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18192 GIMPLE_* codes. */
18193 bool
18194 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18195 int *region_idx)
18197 gimple *last = last_stmt (bb);
18198 enum gimple_code code = gimple_code (last);
18199 struct omp_region *cur_region = *region;
18200 bool fallthru = false;
18202 switch (code)
18204 case GIMPLE_OMP_PARALLEL:
18205 case GIMPLE_OMP_TASK:
18206 case GIMPLE_OMP_FOR:
18207 case GIMPLE_OMP_SINGLE:
18208 case GIMPLE_OMP_TEAMS:
18209 case GIMPLE_OMP_MASTER:
18210 case GIMPLE_OMP_TASKGROUP:
18211 case GIMPLE_OMP_CRITICAL:
18212 case GIMPLE_OMP_SECTION:
18213 case GIMPLE_OMP_GRID_BODY:
18214 cur_region = new_omp_region (bb, code, cur_region);
18215 fallthru = true;
18216 break;
18218 case GIMPLE_OMP_ORDERED:
18219 cur_region = new_omp_region (bb, code, cur_region);
18220 fallthru = true;
18221 if (find_omp_clause (gimple_omp_ordered_clauses
18222 (as_a <gomp_ordered *> (last)),
18223 OMP_CLAUSE_DEPEND))
18224 cur_region = cur_region->outer;
18225 break;
18227 case GIMPLE_OMP_TARGET:
18228 cur_region = new_omp_region (bb, code, cur_region);
18229 fallthru = true;
18230 switch (gimple_omp_target_kind (last))
18232 case GF_OMP_TARGET_KIND_REGION:
18233 case GF_OMP_TARGET_KIND_DATA:
18234 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18235 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18236 case GF_OMP_TARGET_KIND_OACC_DATA:
18237 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18238 break;
18239 case GF_OMP_TARGET_KIND_UPDATE:
18240 case GF_OMP_TARGET_KIND_ENTER_DATA:
18241 case GF_OMP_TARGET_KIND_EXIT_DATA:
18242 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18243 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18244 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18245 cur_region = cur_region->outer;
18246 break;
18247 default:
18248 gcc_unreachable ();
18250 break;
18252 case GIMPLE_OMP_SECTIONS:
18253 cur_region = new_omp_region (bb, code, cur_region);
18254 fallthru = true;
18255 break;
18257 case GIMPLE_OMP_SECTIONS_SWITCH:
18258 fallthru = false;
18259 break;
18261 case GIMPLE_OMP_ATOMIC_LOAD:
18262 case GIMPLE_OMP_ATOMIC_STORE:
18263 fallthru = true;
18264 break;
18266 case GIMPLE_OMP_RETURN:
18267 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18268 somewhere other than the next block. This will be
18269 created later. */
18270 cur_region->exit = bb;
18271 if (cur_region->type == GIMPLE_OMP_TASK)
18272 /* Add an edge corresponding to not scheduling the task
18273 immediately. */
18274 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18275 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18276 cur_region = cur_region->outer;
18277 break;
18279 case GIMPLE_OMP_CONTINUE:
18280 cur_region->cont = bb;
18281 switch (cur_region->type)
18283 case GIMPLE_OMP_FOR:
18284 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18285 succs edges as abnormal to prevent splitting
18286 them. */
18287 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18288 /* Make the loopback edge. */
18289 make_edge (bb, single_succ (cur_region->entry),
18290 EDGE_ABNORMAL);
18292 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18293 corresponds to the case that the body of the loop
18294 is not executed at all. */
18295 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18296 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18297 fallthru = false;
18298 break;
18300 case GIMPLE_OMP_SECTIONS:
18301 /* Wire up the edges into and out of the nested sections. */
18303 basic_block switch_bb = single_succ (cur_region->entry);
18305 struct omp_region *i;
18306 for (i = cur_region->inner; i ; i = i->next)
18308 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18309 make_edge (switch_bb, i->entry, 0);
18310 make_edge (i->exit, bb, EDGE_FALLTHRU);
18313 /* Make the loopback edge to the block with
18314 GIMPLE_OMP_SECTIONS_SWITCH. */
18315 make_edge (bb, switch_bb, 0);
18317 /* Make the edge from the switch to exit. */
18318 make_edge (switch_bb, bb->next_bb, 0);
18319 fallthru = false;
18321 break;
18323 case GIMPLE_OMP_TASK:
18324 fallthru = true;
18325 break;
18327 default:
18328 gcc_unreachable ();
18330 break;
18332 default:
18333 gcc_unreachable ();
18336 if (*region != cur_region)
18338 *region = cur_region;
18339 if (cur_region)
18340 *region_idx = cur_region->entry->index;
18341 else
18342 *region_idx = 0;
18345 return fallthru;
18348 static unsigned int
18349 diagnose_omp_structured_block_errors (void)
18351 struct walk_stmt_info wi;
18352 gimple_seq body = gimple_body (current_function_decl);
18354 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18356 memset (&wi, 0, sizeof (wi));
18357 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18359 memset (&wi, 0, sizeof (wi));
18360 wi.want_locations = true;
18361 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18363 gimple_set_body (current_function_decl, body);
18365 splay_tree_delete (all_labels);
18366 all_labels = NULL;
18368 return 0;
18371 namespace {
18373 const pass_data pass_data_diagnose_omp_blocks =
18375 GIMPLE_PASS, /* type */
18376 "*diagnose_omp_blocks", /* name */
18377 OPTGROUP_NONE, /* optinfo_flags */
18378 TV_NONE, /* tv_id */
18379 PROP_gimple_any, /* properties_required */
18380 0, /* properties_provided */
18381 0, /* properties_destroyed */
18382 0, /* todo_flags_start */
18383 0, /* todo_flags_finish */
18386 class pass_diagnose_omp_blocks : public gimple_opt_pass
18388 public:
18389 pass_diagnose_omp_blocks (gcc::context *ctxt)
18390 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18393 /* opt_pass methods: */
18394 virtual bool gate (function *)
18396 return flag_cilkplus || flag_openacc || flag_openmp;
18398 virtual unsigned int execute (function *)
18400 return diagnose_omp_structured_block_errors ();
18403 }; // class pass_diagnose_omp_blocks
18405 } // anon namespace
18407 gimple_opt_pass *
18408 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18410 return new pass_diagnose_omp_blocks (ctxt);
18413 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18414 adds their addresses and sizes to constructor-vector V_CTOR. */
18415 static void
18416 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18417 vec<constructor_elt, va_gc> *v_ctor)
18419 unsigned len = vec_safe_length (v_decls);
18420 for (unsigned i = 0; i < len; i++)
18422 tree it = (*v_decls)[i];
18423 bool is_var = TREE_CODE (it) == VAR_DECL;
18424 bool is_link_var
18425 = is_var
18426 #ifdef ACCEL_COMPILER
18427 && DECL_HAS_VALUE_EXPR_P (it)
18428 #endif
18429 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18431 tree size = NULL_TREE;
18432 if (is_var)
18433 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18435 tree addr;
18436 if (!is_link_var)
18437 addr = build_fold_addr_expr (it);
18438 else
18440 #ifdef ACCEL_COMPILER
18441 /* For "omp declare target link" vars add address of the pointer to
18442 the target table, instead of address of the var. */
18443 tree value_expr = DECL_VALUE_EXPR (it);
18444 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18445 varpool_node::finalize_decl (link_ptr_decl);
18446 addr = build_fold_addr_expr (link_ptr_decl);
18447 #else
18448 addr = build_fold_addr_expr (it);
18449 #endif
18451 /* Most significant bit of the size marks "omp declare target link"
18452 vars in host and target tables. */
18453 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18454 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18455 * BITS_PER_UNIT - 1);
18456 size = wide_int_to_tree (const_ptr_type_node, isize);
18459 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18460 if (is_var)
18461 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18465 /* Create new symbols containing (address, size) pairs for global variables,
18466 marked with "omp declare target" attribute, as well as addresses for the
18467 functions, which are outlined offloading regions. */
18468 void
18469 omp_finish_file (void)
18471 unsigned num_funcs = vec_safe_length (offload_funcs);
18472 unsigned num_vars = vec_safe_length (offload_vars);
18474 if (num_funcs == 0 && num_vars == 0)
18475 return;
18477 if (targetm_common.have_named_sections)
18479 vec<constructor_elt, va_gc> *v_f, *v_v;
18480 vec_alloc (v_f, num_funcs);
18481 vec_alloc (v_v, num_vars * 2);
18483 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18484 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18486 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18487 num_vars * 2);
18488 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18489 num_funcs);
18490 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18491 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18492 tree ctor_v = build_constructor (vars_decl_type, v_v);
18493 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18494 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18495 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18496 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18497 get_identifier (".offload_func_table"),
18498 funcs_decl_type);
18499 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18500 get_identifier (".offload_var_table"),
18501 vars_decl_type);
18502 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18503 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18504 otherwise a joint table in a binary will contain padding between
18505 tables from multiple object files. */
18506 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18507 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18508 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18509 DECL_INITIAL (funcs_decl) = ctor_f;
18510 DECL_INITIAL (vars_decl) = ctor_v;
18511 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18512 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18514 varpool_node::finalize_decl (vars_decl);
18515 varpool_node::finalize_decl (funcs_decl);
18517 else
18519 for (unsigned i = 0; i < num_funcs; i++)
18521 tree it = (*offload_funcs)[i];
18522 targetm.record_offload_symbol (it);
18524 for (unsigned i = 0; i < num_vars; i++)
18526 tree it = (*offload_vars)[i];
18527 targetm.record_offload_symbol (it);
18532 /* Find the number of threads (POS = false), or thread number (POS =
18533 true) for an OpenACC region partitioned as MASK. Setup code
18534 required for the calculation is added to SEQ. */
18536 static tree
18537 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18539 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18540 unsigned ix;
18542 /* Start at gang level, and examine relevant dimension indices. */
18543 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18544 if (GOMP_DIM_MASK (ix) & mask)
18546 tree arg = build_int_cst (unsigned_type_node, ix);
18548 if (res)
18550 /* We had an outer index, so scale that by the size of
18551 this dimension. */
18552 tree n = create_tmp_var (integer_type_node);
18553 gimple *call
18554 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18556 gimple_call_set_lhs (call, n);
18557 gimple_seq_add_stmt (seq, call);
18558 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18560 if (pos)
18562 /* Determine index in this dimension. */
18563 tree id = create_tmp_var (integer_type_node);
18564 gimple *call = gimple_build_call_internal
18565 (IFN_GOACC_DIM_POS, 1, arg);
18567 gimple_call_set_lhs (call, id);
18568 gimple_seq_add_stmt (seq, call);
18569 if (res)
18570 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18571 else
18572 res = id;
18576 if (res == NULL_TREE)
18577 res = integer_zero_node;
18579 return res;
18582 /* Transform IFN_GOACC_LOOP calls to actual code. See
18583 expand_oacc_for for where these are generated. At the vector
18584 level, we stride loops, such that each member of a warp will
18585 operate on adjacent iterations. At the worker and gang level,
18586 each gang/warp executes a set of contiguous iterations. Chunking
18587 can override this such that each iteration engine executes a
18588 contiguous chunk, and then moves on to stride to the next chunk. */
18590 static void
18591 oacc_xform_loop (gcall *call)
18593 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18594 enum ifn_goacc_loop_kind code
18595 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18596 tree dir = gimple_call_arg (call, 1);
18597 tree range = gimple_call_arg (call, 2);
18598 tree step = gimple_call_arg (call, 3);
18599 tree chunk_size = NULL_TREE;
18600 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18601 tree lhs = gimple_call_lhs (call);
18602 tree type = TREE_TYPE (lhs);
18603 tree diff_type = TREE_TYPE (range);
18604 tree r = NULL_TREE;
18605 gimple_seq seq = NULL;
18606 bool chunking = false, striding = true;
18607 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18608 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18610 #ifdef ACCEL_COMPILER
18611 chunk_size = gimple_call_arg (call, 4);
18612 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18613 || integer_zerop (chunk_size)) /* Default (also static). */
18615 /* If we're at the gang level, we want each to execute a
18616 contiguous run of iterations. Otherwise we want each element
18617 to stride. */
18618 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18619 chunking = false;
18621 else
18623 /* Chunk of size 1 is striding. */
18624 striding = integer_onep (chunk_size);
18625 chunking = !striding;
18627 #endif
18629 /* striding=true, chunking=true
18630 -> invalid.
18631 striding=true, chunking=false
18632 -> chunks=1
18633 striding=false,chunking=true
18634 -> chunks=ceil (range/(chunksize*threads*step))
18635 striding=false,chunking=false
18636 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18637 push_gimplify_context (true);
18639 switch (code)
18641 default: gcc_unreachable ();
18643 case IFN_GOACC_LOOP_CHUNKS:
18644 if (!chunking)
18645 r = build_int_cst (type, 1);
18646 else
18648 /* chunk_max
18649 = (range - dir) / (chunks * step * num_threads) + dir */
18650 tree per = oacc_thread_numbers (false, mask, &seq);
18651 per = fold_convert (type, per);
18652 chunk_size = fold_convert (type, chunk_size);
18653 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18654 per = fold_build2 (MULT_EXPR, type, per, step);
18655 r = build2 (MINUS_EXPR, type, range, dir);
18656 r = build2 (PLUS_EXPR, type, r, per);
18657 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18659 break;
18661 case IFN_GOACC_LOOP_STEP:
18663 /* If striding, step by the entire compute volume, otherwise
18664 step by the inner volume. */
18665 unsigned volume = striding ? mask : inner_mask;
18667 r = oacc_thread_numbers (false, volume, &seq);
18668 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18670 break;
18672 case IFN_GOACC_LOOP_OFFSET:
18673 if (striding)
18675 r = oacc_thread_numbers (true, mask, &seq);
18676 r = fold_convert (diff_type, r);
18678 else
18680 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18681 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18682 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18683 inner_size, outer_size);
18685 volume = fold_convert (diff_type, volume);
18686 if (chunking)
18687 chunk_size = fold_convert (diff_type, chunk_size);
18688 else
18690 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18692 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18693 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18694 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18697 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18698 fold_convert (diff_type, inner_size));
18699 r = oacc_thread_numbers (true, outer_mask, &seq);
18700 r = fold_convert (diff_type, r);
18701 r = build2 (MULT_EXPR, diff_type, r, span);
18703 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18704 inner = fold_convert (diff_type, inner);
18705 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18707 if (chunking)
18709 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18710 tree per
18711 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18712 per = build2 (MULT_EXPR, diff_type, per, chunk);
18714 r = build2 (PLUS_EXPR, diff_type, r, per);
18717 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18718 if (type != diff_type)
18719 r = fold_convert (type, r);
18720 break;
18722 case IFN_GOACC_LOOP_BOUND:
18723 if (striding)
18724 r = range;
18725 else
18727 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18728 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18729 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18730 inner_size, outer_size);
18732 volume = fold_convert (diff_type, volume);
18733 if (chunking)
18734 chunk_size = fold_convert (diff_type, chunk_size);
18735 else
18737 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18739 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18740 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18741 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18744 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18745 fold_convert (diff_type, inner_size));
18747 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18749 tree offset = gimple_call_arg (call, 6);
18750 r = build2 (PLUS_EXPR, diff_type, r,
18751 fold_convert (diff_type, offset));
18752 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18753 diff_type, r, range);
18755 if (diff_type != type)
18756 r = fold_convert (type, r);
18757 break;
18760 gimplify_assign (lhs, r, &seq);
18762 pop_gimplify_context (NULL);
18764 gsi_replace_with_seq (&gsi, seq, true);
18767 /* Default partitioned and minimum partitioned dimensions. */
18769 static int oacc_default_dims[GOMP_DIM_MAX];
18770 static int oacc_min_dims[GOMP_DIM_MAX];
18772 /* Parse the default dimension parameter. This is a set of
18773 :-separated optional compute dimensions. Each specified dimension
18774 is a positive integer. When device type support is added, it is
18775 planned to be a comma separated list of such compute dimensions,
18776 with all but the first prefixed by the colon-terminated device
18777 type. */
18779 static void
18780 oacc_parse_default_dims (const char *dims)
18782 int ix;
18784 for (ix = GOMP_DIM_MAX; ix--;)
18786 oacc_default_dims[ix] = -1;
18787 oacc_min_dims[ix] = 1;
18790 #ifndef ACCEL_COMPILER
18791 /* Cannot be overridden on the host. */
18792 dims = NULL;
18793 #endif
18794 if (dims)
18796 const char *pos = dims;
18798 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18800 if (ix)
18802 if (*pos != ':')
18803 goto malformed;
18804 pos++;
18807 if (*pos != ':')
18809 long val;
18810 const char *eptr;
18812 errno = 0;
18813 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18814 if (errno || val <= 0 || (int) val != val)
18815 goto malformed;
18816 pos = eptr;
18817 oacc_default_dims[ix] = (int) val;
18820 if (*pos)
18822 malformed:
18823 error_at (UNKNOWN_LOCATION,
18824 "-fopenacc-dim operand is malformed at '%s'", pos);
18828 /* Allow the backend to validate the dimensions. */
18829 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18830 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18833 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18834 raw attribute. DIMS is an array of dimensions, which is filled in.
18835 LEVEL is the partitioning level of a routine, or -1 for an offload
18836 region itself. USED is the mask of partitioned execution in the
18837 function. */
18839 static void
18840 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18842 tree purpose[GOMP_DIM_MAX];
18843 unsigned ix;
18844 tree pos = TREE_VALUE (attrs);
18845 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18847 /* Make sure the attribute creator attached the dimension
18848 information. */
18849 gcc_assert (pos);
18851 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18853 purpose[ix] = TREE_PURPOSE (pos);
18854 tree val = TREE_VALUE (pos);
18855 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18856 pos = TREE_CHAIN (pos);
18859 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18861 /* Default anything left to 1 or a partitioned default. */
18862 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18863 if (dims[ix] < 0)
18865 /* The OpenACC spec says 'If the [num_gangs] clause is not
18866 specified, an implementation-defined default will be used;
18867 the default may depend on the code within the construct.'
18868 (2.5.6). Thus an implementation is free to choose
18869 non-unity default for a parallel region that doesn't have
18870 any gang-partitioned loops. However, it appears that there
18871 is a sufficient body of user code that expects non-gang
18872 partitioned regions to not execute in gang-redundant mode.
18873 So we (a) don't warn about the non-portability and (b) pick
18874 the minimum permissible dimension size when there is no
18875 partitioned execution. Otherwise we pick the global
18876 default for the dimension, which the user can control. The
18877 same wording and logic applies to num_workers and
18878 vector_length, however the worker- or vector- single
18879 execution doesn't have the same impact as gang-redundant
18880 execution. (If the minimum gang-level partioning is not 1,
18881 the target is probably too confusing.) */
18882 dims[ix] = (used & GOMP_DIM_MASK (ix)
18883 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18884 changed = true;
18887 if (changed)
18889 /* Replace the attribute with new values. */
18890 pos = NULL_TREE;
18891 for (ix = GOMP_DIM_MAX; ix--;)
18893 pos = tree_cons (purpose[ix],
18894 build_int_cst (integer_type_node, dims[ix]),
18895 pos);
18896 if (is_kernel)
18897 TREE_PUBLIC (pos) = 1;
18899 replace_oacc_fn_attrib (fn, pos);
18903 /* Create an empty OpenACC loop structure at LOC. */
18905 static oacc_loop *
18906 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18908 oacc_loop *loop = XCNEW (oacc_loop);
18910 loop->parent = parent;
18911 loop->child = loop->sibling = NULL;
18913 if (parent)
18915 loop->sibling = parent->child;
18916 parent->child = loop;
18919 loop->loc = loc;
18920 loop->marker = NULL;
18921 memset (loop->heads, 0, sizeof (loop->heads));
18922 memset (loop->tails, 0, sizeof (loop->tails));
18923 loop->routine = NULL_TREE;
18925 loop->mask = loop->flags = loop->inner = 0;
18926 loop->ifns = 0;
18927 loop->chunk_size = 0;
18928 loop->head_end = NULL;
18930 return loop;
18933 /* Create an outermost, dummy OpenACC loop for offloaded function
18934 DECL. */
18936 static oacc_loop *
18937 new_oacc_loop_outer (tree decl)
18939 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18942 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18943 Link into PARENT loop. Return the new loop. */
18945 static oacc_loop *
18946 new_oacc_loop (oacc_loop *parent, gcall *marker)
18948 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18950 loop->marker = marker;
18952 /* TODO: This is where device_type flattening would occur for the loop
18953 flags. */
18955 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18957 tree chunk_size = integer_zero_node;
18958 if (loop->flags & OLF_GANG_STATIC)
18959 chunk_size = gimple_call_arg (marker, 4);
18960 loop->chunk_size = chunk_size;
18962 return loop;
18965 /* Create a dummy loop encompassing a call to a openACC routine.
18966 Extract the routine's partitioning requirements. */
18968 static void
18969 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18971 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18972 int level = oacc_fn_attrib_level (attrs);
18974 gcc_assert (level >= 0);
18976 loop->marker = call;
18977 loop->routine = decl;
18978 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18979 ^ (GOMP_DIM_MASK (level) - 1));
18982 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18983 Return the parent loop. */
18985 static oacc_loop *
18986 finish_oacc_loop (oacc_loop *loop)
18988 /* If the loop has been collapsed, don't partition it. */
18989 if (!loop->ifns)
18990 loop->mask = loop->flags = 0;
18991 return loop->parent;
18994 /* Free all OpenACC loop structures within LOOP (inclusive). */
18996 static void
18997 free_oacc_loop (oacc_loop *loop)
18999 if (loop->sibling)
19000 free_oacc_loop (loop->sibling);
19001 if (loop->child)
19002 free_oacc_loop (loop->child);
19004 free (loop);
19007 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19009 static void
19010 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19011 const char *title, int level)
19013 enum ifn_unique_kind kind
19014 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19016 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19017 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19019 gimple *stmt = gsi_stmt (gsi);
19021 if (is_gimple_call (stmt)
19022 && gimple_call_internal_p (stmt)
19023 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19025 enum ifn_unique_kind k
19026 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19027 (gimple_call_arg (stmt, 0)));
19029 if (k == kind && stmt != from)
19030 break;
19032 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19034 gsi_next (&gsi);
19035 while (gsi_end_p (gsi))
19036 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19040 /* Dump OpenACC loops LOOP, its siblings and its children. */
19042 static void
19043 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19045 int ix;
19047 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19048 loop->flags, loop->mask,
19049 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19051 if (loop->marker)
19052 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19054 if (loop->routine)
19055 fprintf (file, "%*sRoutine %s:%u:%s\n",
19056 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19057 DECL_SOURCE_LINE (loop->routine),
19058 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19060 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19061 if (loop->heads[ix])
19062 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19063 for (ix = GOMP_DIM_MAX; ix--;)
19064 if (loop->tails[ix])
19065 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19067 if (loop->child)
19068 dump_oacc_loop (file, loop->child, depth + 1);
19069 if (loop->sibling)
19070 dump_oacc_loop (file, loop->sibling, depth);
19073 void debug_oacc_loop (oacc_loop *);
19075 /* Dump loops to stderr. */
19077 DEBUG_FUNCTION void
19078 debug_oacc_loop (oacc_loop *loop)
19080 dump_oacc_loop (stderr, loop, 0);
19083 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19084 structures as we go. By construction these loops are properly
19085 nested. */
19087 static void
19088 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19090 int marker = 0;
19091 int remaining = 0;
19093 if (bb->flags & BB_VISITED)
19094 return;
19096 follow:
19097 bb->flags |= BB_VISITED;
19099 /* Scan for loop markers. */
19100 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19101 gsi_next (&gsi))
19103 gimple *stmt = gsi_stmt (gsi);
19105 if (!is_gimple_call (stmt))
19106 continue;
19108 gcall *call = as_a <gcall *> (stmt);
19110 /* If this is a routine, make a dummy loop for it. */
19111 if (tree decl = gimple_call_fndecl (call))
19112 if (tree attrs = get_oacc_fn_attrib (decl))
19114 gcc_assert (!marker);
19115 new_oacc_loop_routine (loop, call, decl, attrs);
19118 if (!gimple_call_internal_p (call))
19119 continue;
19121 switch (gimple_call_internal_fn (call))
19123 default:
19124 break;
19126 case IFN_GOACC_LOOP:
19127 /* Count the goacc loop abstraction fns, to determine if the
19128 loop was collapsed already. */
19129 loop->ifns++;
19130 break;
19132 case IFN_UNIQUE:
19133 enum ifn_unique_kind kind
19134 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19135 (gimple_call_arg (call, 0)));
19136 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19137 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19139 if (gimple_call_num_args (call) == 2)
19141 gcc_assert (marker && !remaining);
19142 marker = 0;
19143 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19144 loop = finish_oacc_loop (loop);
19145 else
19146 loop->head_end = call;
19148 else
19150 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19152 if (!marker)
19154 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19155 loop = new_oacc_loop (loop, call);
19156 remaining = count;
19158 gcc_assert (count == remaining);
19159 if (remaining)
19161 remaining--;
19162 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19163 loop->heads[marker] = call;
19164 else
19165 loop->tails[remaining] = call;
19167 marker++;
19172 if (remaining || marker)
19174 bb = single_succ (bb);
19175 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19176 goto follow;
19179 /* Walk successor blocks. */
19180 edge e;
19181 edge_iterator ei;
19183 FOR_EACH_EDGE (e, ei, bb->succs)
19184 oacc_loop_discover_walk (loop, e->dest);
19187 /* LOOP is the first sibling. Reverse the order in place and return
19188 the new first sibling. Recurse to child loops. */
19190 static oacc_loop *
19191 oacc_loop_sibling_nreverse (oacc_loop *loop)
19193 oacc_loop *last = NULL;
19196 if (loop->child)
19197 loop->child = oacc_loop_sibling_nreverse (loop->child);
19199 oacc_loop *next = loop->sibling;
19200 loop->sibling = last;
19201 last = loop;
19202 loop = next;
19204 while (loop);
19206 return last;
19209 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19210 the current function. */
19212 static oacc_loop *
19213 oacc_loop_discovery ()
19215 basic_block bb;
19217 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19218 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19220 /* The siblings were constructed in reverse order, reverse them so
19221 that diagnostics come out in an unsurprising order. */
19222 top = oacc_loop_sibling_nreverse (top);
19224 /* Reset the visited flags. */
19225 FOR_ALL_BB_FN (bb, cfun)
19226 bb->flags &= ~BB_VISITED;
19228 return top;
19231 /* Transform the abstract internal function markers starting at FROM
19232 to be for partitioning level LEVEL. Stop when we meet another HEAD
19233 or TAIL marker. */
19235 static void
19236 oacc_loop_xform_head_tail (gcall *from, int level)
19238 enum ifn_unique_kind kind
19239 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19240 tree replacement = build_int_cst (unsigned_type_node, level);
19242 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19244 gimple *stmt = gsi_stmt (gsi);
19246 if (is_gimple_call (stmt)
19247 && gimple_call_internal_p (stmt)
19248 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19250 enum ifn_unique_kind k
19251 = ((enum ifn_unique_kind)
19252 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19254 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19255 *gimple_call_arg_ptr (stmt, 2) = replacement;
19256 else if (k == kind && stmt != from)
19257 break;
19259 else if (is_gimple_call (stmt)
19260 && gimple_call_internal_p (stmt)
19261 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19262 *gimple_call_arg_ptr (stmt, 3) = replacement;
19264 gsi_next (&gsi);
19265 while (gsi_end_p (gsi))
19266 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19270 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19271 determined partitioning mask and chunking argument. END_MARKER
19272 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19273 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19274 the replacement partitioning mask and CHUNK_ARG is the replacement
19275 chunking arg. */
19277 static void
19278 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19279 tree mask_arg, tree chunk_arg)
19281 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19283 gcc_checking_assert (ifns);
19284 for (;;)
19286 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19288 gimple *stmt = gsi_stmt (gsi);
19290 if (!is_gimple_call (stmt))
19291 continue;
19293 gcall *call = as_a <gcall *> (stmt);
19295 if (!gimple_call_internal_p (call))
19296 continue;
19298 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19299 continue;
19301 *gimple_call_arg_ptr (call, 5) = mask_arg;
19302 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19303 ifns--;
19304 if (!ifns)
19305 return;
19308 /* The LOOP_BOUND ifn could be in the single successor
19309 block. */
19310 basic_block bb = single_succ (gsi_bb (gsi));
19311 gsi = gsi_start_bb (bb);
19315 /* Process the discovered OpenACC loops, setting the correct
19316 partitioning level etc. */
19318 static void
19319 oacc_loop_process (oacc_loop *loop)
19321 if (loop->child)
19322 oacc_loop_process (loop->child);
19324 if (loop->mask && !loop->routine)
19326 int ix;
19327 unsigned mask = loop->mask;
19328 unsigned dim = GOMP_DIM_GANG;
19329 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19330 tree chunk_arg = loop->chunk_size;
19332 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19334 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19336 while (!(GOMP_DIM_MASK (dim) & mask))
19337 dim++;
19339 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19340 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19342 mask ^= GOMP_DIM_MASK (dim);
19346 if (loop->sibling)
19347 oacc_loop_process (loop->sibling);
19350 /* Walk the OpenACC loop heirarchy checking and assigning the
19351 programmer-specified partitionings. OUTER_MASK is the partitioning
19352 this loop is contained within. Return mask of partitioning
19353 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19354 bit. */
19356 static unsigned
19357 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19359 unsigned this_mask = loop->mask;
19360 unsigned mask_all = 0;
19361 bool noisy = true;
19363 #ifdef ACCEL_COMPILER
19364 /* When device_type is supported, we want the device compiler to be
19365 noisy, if the loop parameters are device_type-specific. */
19366 noisy = false;
19367 #endif
19369 if (!loop->routine)
19371 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19372 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19374 this_mask = ((loop->flags >> OLF_DIM_BASE)
19375 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19377 if ((this_mask != 0) + auto_par + seq_par > 1)
19379 if (noisy)
19380 error_at (loop->loc,
19381 seq_par
19382 ? "%<seq%> overrides other OpenACC loop specifiers"
19383 : "%<auto%> conflicts with other OpenACC loop specifiers");
19384 auto_par = false;
19385 loop->flags &= ~OLF_AUTO;
19386 if (seq_par)
19388 loop->flags &=
19389 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19390 this_mask = 0;
19393 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19394 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19397 if (this_mask & outer_mask)
19399 const oacc_loop *outer;
19400 for (outer = loop->parent; outer; outer = outer->parent)
19401 if (outer->mask & this_mask)
19402 break;
19404 if (noisy)
19406 if (outer)
19408 error_at (loop->loc,
19409 "%s uses same OpenACC parallelism as containing loop",
19410 loop->routine ? "routine call" : "inner loop");
19411 inform (outer->loc, "containing loop here");
19413 else
19414 error_at (loop->loc,
19415 "%s uses OpenACC parallelism disallowed by containing routine",
19416 loop->routine ? "routine call" : "loop");
19418 if (loop->routine)
19419 inform (DECL_SOURCE_LOCATION (loop->routine),
19420 "routine %qD declared here", loop->routine);
19422 this_mask &= ~outer_mask;
19424 else
19426 unsigned outermost = this_mask & -this_mask;
19428 if (outermost && outermost <= outer_mask)
19430 if (noisy)
19432 error_at (loop->loc,
19433 "incorrectly nested OpenACC loop parallelism");
19435 const oacc_loop *outer;
19436 for (outer = loop->parent;
19437 outer->flags && outer->flags < outermost;
19438 outer = outer->parent)
19439 continue;
19440 inform (outer->loc, "containing loop here");
19443 this_mask &= ~outermost;
19447 loop->mask = this_mask;
19448 mask_all |= this_mask;
19450 if (loop->child)
19452 loop->inner = oacc_loop_fixed_partitions (loop->child,
19453 outer_mask | this_mask);
19454 mask_all |= loop->inner;
19457 if (loop->sibling)
19458 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19460 return mask_all;
19463 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19464 OUTER_MASK is the partitioning this loop is contained within.
19465 Return the cumulative partitioning used by this loop, siblings and
19466 children. */
19468 static unsigned
19469 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19471 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19472 bool noisy = true;
19474 #ifdef ACCEL_COMPILER
19475 /* When device_type is supported, we want the device compiler to be
19476 noisy, if the loop parameters are device_type-specific. */
19477 noisy = false;
19478 #endif
19480 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19482 /* Allocate the outermost loop at the outermost available
19483 level. */
19484 unsigned this_mask = outer_mask + 1;
19486 if (!(this_mask & loop->inner))
19487 loop->mask = this_mask;
19490 if (loop->child)
19492 unsigned child_mask = outer_mask | loop->mask;
19494 if (loop->mask || assign)
19495 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19497 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19500 if (assign && !loop->mask)
19502 /* Allocate the loop at the innermost available level. */
19503 unsigned this_mask = 0;
19505 /* Determine the outermost partitioning used within this loop. */
19506 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19507 this_mask = (this_mask & -this_mask);
19509 /* Pick the partitioning just inside that one. */
19510 this_mask >>= 1;
19512 /* And avoid picking one use by an outer loop. */
19513 this_mask &= ~outer_mask;
19515 if (!this_mask && noisy)
19516 warning_at (loop->loc, 0,
19517 "insufficient partitioning available to parallelize loop");
19519 loop->mask = this_mask;
19522 if (assign && dump_file)
19523 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19524 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19525 loop->mask);
19527 unsigned inner_mask = 0;
19529 if (loop->sibling)
19530 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19532 inner_mask |= loop->inner | loop->mask;
19534 return inner_mask;
19537 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19538 axes. Return mask of partitioning. */
19540 static unsigned
19541 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19543 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19545 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19547 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19548 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19550 return mask_all;
19553 /* Default fork/join early expander. Delete the function calls if
19554 there is no RTL expander. */
19556 bool
19557 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19558 const int *ARG_UNUSED (dims), bool is_fork)
19560 if (is_fork)
19561 return targetm.have_oacc_fork ();
19562 else
19563 return targetm.have_oacc_join ();
19566 /* Default goacc.reduction early expander.
19568 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19569 If RES_PTR is not integer-zerop:
19570 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19571 TEARDOWN - emit '*RES_PTR = VAR'
19572 If LHS is not NULL
19573 emit 'LHS = VAR' */
19575 void
19576 default_goacc_reduction (gcall *call)
19578 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19579 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19580 tree lhs = gimple_call_lhs (call);
19581 tree var = gimple_call_arg (call, 2);
19582 gimple_seq seq = NULL;
19584 if (code == IFN_GOACC_REDUCTION_SETUP
19585 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19587 /* Setup and Teardown need to copy from/to the receiver object,
19588 if there is one. */
19589 tree ref_to_res = gimple_call_arg (call, 1);
19591 if (!integer_zerop (ref_to_res))
19593 tree dst = build_simple_mem_ref (ref_to_res);
19594 tree src = var;
19596 if (code == IFN_GOACC_REDUCTION_SETUP)
19598 src = dst;
19599 dst = lhs;
19600 lhs = NULL;
19602 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19606 /* Copy VAR to LHS, if there is an LHS. */
19607 if (lhs)
19608 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19610 gsi_replace_with_seq (&gsi, seq, true);
19613 /* Main entry point for oacc transformations which run on the device
19614 compiler after LTO, so we know what the target device is at this
19615 point (including the host fallback). */
19617 static unsigned int
19618 execute_oacc_device_lower ()
19620 tree attrs = get_oacc_fn_attrib (current_function_decl);
19622 if (!attrs)
19623 /* Not an offloaded function. */
19624 return 0;
19626 /* Parse the default dim argument exactly once. */
19627 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19629 oacc_parse_default_dims (flag_openacc_dims);
19630 flag_openacc_dims = (char *)&flag_openacc_dims;
19633 /* Discover, partition and process the loops. */
19634 oacc_loop *loops = oacc_loop_discovery ();
19635 int fn_level = oacc_fn_attrib_level (attrs);
19637 if (dump_file)
19638 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19639 ? "Function is kernels offload\n"
19640 : fn_level < 0 ? "Function is parallel offload\n"
19641 : "Function is routine level %d\n", fn_level);
19643 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19644 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19645 int dims[GOMP_DIM_MAX];
19647 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19649 if (dump_file)
19651 const char *comma = "Compute dimensions [";
19652 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19653 fprintf (dump_file, "%s%d", comma, dims[ix]);
19654 fprintf (dump_file, "]\n");
19657 oacc_loop_process (loops);
19658 if (dump_file)
19660 fprintf (dump_file, "OpenACC loops\n");
19661 dump_oacc_loop (dump_file, loops, 0);
19662 fprintf (dump_file, "\n");
19665 /* Offloaded targets may introduce new basic blocks, which require
19666 dominance information to update SSA. */
19667 calculate_dominance_info (CDI_DOMINATORS);
19669 /* Now lower internal loop functions to target-specific code
19670 sequences. */
19671 basic_block bb;
19672 FOR_ALL_BB_FN (bb, cfun)
19673 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19675 gimple *stmt = gsi_stmt (gsi);
19676 if (!is_gimple_call (stmt))
19678 gsi_next (&gsi);
19679 continue;
19682 gcall *call = as_a <gcall *> (stmt);
19683 if (!gimple_call_internal_p (call))
19685 gsi_next (&gsi);
19686 continue;
19689 /* Rewind to allow rescan. */
19690 gsi_prev (&gsi);
19691 bool rescan = false, remove = false;
19692 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19694 switch (ifn_code)
19696 default: break;
19698 case IFN_GOACC_LOOP:
19699 oacc_xform_loop (call);
19700 rescan = true;
19701 break;
19703 case IFN_GOACC_REDUCTION:
19704 /* Mark the function for SSA renaming. */
19705 mark_virtual_operands_for_renaming (cfun);
19707 /* If the level is -1, this ended up being an unused
19708 axis. Handle as a default. */
19709 if (integer_minus_onep (gimple_call_arg (call, 3)))
19710 default_goacc_reduction (call);
19711 else
19712 targetm.goacc.reduction (call);
19713 rescan = true;
19714 break;
19716 case IFN_UNIQUE:
19718 enum ifn_unique_kind kind
19719 = ((enum ifn_unique_kind)
19720 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19722 switch (kind)
19724 default:
19725 gcc_unreachable ();
19727 case IFN_UNIQUE_OACC_FORK:
19728 case IFN_UNIQUE_OACC_JOIN:
19729 if (integer_minus_onep (gimple_call_arg (call, 2)))
19730 remove = true;
19731 else if (!targetm.goacc.fork_join
19732 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19733 remove = true;
19734 break;
19736 case IFN_UNIQUE_OACC_HEAD_MARK:
19737 case IFN_UNIQUE_OACC_TAIL_MARK:
19738 remove = true;
19739 break;
19741 break;
19745 if (gsi_end_p (gsi))
19746 /* We rewound past the beginning of the BB. */
19747 gsi = gsi_start_bb (bb);
19748 else
19749 /* Undo the rewind. */
19750 gsi_next (&gsi);
19752 if (remove)
19754 if (gimple_vdef (call))
19755 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19756 if (gimple_call_lhs (call))
19758 /* Propagate the data dependency var. */
19759 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19760 gimple_call_arg (call, 1));
19761 gsi_replace (&gsi, ass, false);
19763 else
19764 gsi_remove (&gsi, true);
19766 else if (!rescan)
19767 /* If not rescanning, advance over the call. */
19768 gsi_next (&gsi);
19771 free_oacc_loop (loops);
19773 return 0;
19776 /* Default launch dimension validator. Force everything to 1. A
19777 backend that wants to provide larger dimensions must override this
19778 hook. */
19780 bool
19781 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19782 int ARG_UNUSED (fn_level))
19784 bool changed = false;
19786 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19788 if (dims[ix] != 1)
19790 dims[ix] = 1;
19791 changed = true;
19795 return changed;
19798 /* Default dimension bound is unknown on accelerator and 1 on host. */
19801 default_goacc_dim_limit (int ARG_UNUSED (axis))
19803 #ifdef ACCEL_COMPILER
19804 return 0;
19805 #else
19806 return 1;
19807 #endif
19810 namespace {
19812 const pass_data pass_data_oacc_device_lower =
19814 GIMPLE_PASS, /* type */
19815 "oaccdevlow", /* name */
19816 OPTGROUP_NONE, /* optinfo_flags */
19817 TV_NONE, /* tv_id */
19818 PROP_cfg, /* properties_required */
19819 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19820 0, /* properties_destroyed */
19821 0, /* todo_flags_start */
19822 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19825 class pass_oacc_device_lower : public gimple_opt_pass
19827 public:
19828 pass_oacc_device_lower (gcc::context *ctxt)
19829 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19832 /* opt_pass methods: */
19833 virtual unsigned int execute (function *)
19835 bool gate = flag_openacc != 0;
19837 if (!gate)
19838 return 0;
19840 return execute_oacc_device_lower ();
19843 }; // class pass_oacc_device_lower
19845 } // anon namespace
19847 gimple_opt_pass *
19848 make_pass_oacc_device_lower (gcc::context *ctxt)
19850 return new pass_oacc_device_lower (ctxt);
19853 /* "omp declare target link" handling pass. */
19855 namespace {
19857 const pass_data pass_data_omp_target_link =
19859 GIMPLE_PASS, /* type */
19860 "omptargetlink", /* name */
19861 OPTGROUP_NONE, /* optinfo_flags */
19862 TV_NONE, /* tv_id */
19863 PROP_ssa, /* properties_required */
19864 0, /* properties_provided */
19865 0, /* properties_destroyed */
19866 0, /* todo_flags_start */
19867 TODO_update_ssa, /* todo_flags_finish */
19870 class pass_omp_target_link : public gimple_opt_pass
19872 public:
19873 pass_omp_target_link (gcc::context *ctxt)
19874 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19877 /* opt_pass methods: */
19878 virtual bool gate (function *fun)
19880 #ifdef ACCEL_COMPILER
19881 tree attrs = DECL_ATTRIBUTES (fun->decl);
19882 return lookup_attribute ("omp declare target", attrs)
19883 || lookup_attribute ("omp target entrypoint", attrs);
19884 #else
19885 (void) fun;
19886 return false;
19887 #endif
19890 virtual unsigned execute (function *);
19893 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19895 static tree
19896 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19898 tree t = *tp;
19900 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19901 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19903 *walk_subtrees = 0;
19904 return t;
19907 return NULL_TREE;
19910 unsigned
19911 pass_omp_target_link::execute (function *fun)
19913 basic_block bb;
19914 FOR_EACH_BB_FN (bb, fun)
19916 gimple_stmt_iterator gsi;
19917 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19918 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19919 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19922 return 0;
19925 } // anon namespace
19927 gimple_opt_pass *
19928 make_pass_omp_target_link (gcc::context *ctxt)
19930 return new pass_omp_target_link (ctxt);
19933 #include "gt-omp-low.h"