* sr.po: Update.
[official-gcc.git] / gcc / omp-low.c
blobc69fe448da62f320fc91e95ce171d80f437575ef
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83 #include "symbol-summary.h"
84 #include "hsa.h"
85 #include "params.h"
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
92 expressions.
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
102 struct omp_region
104 /* The enclosing region. */
105 struct omp_region *outer;
107 /* First child region. */
108 struct omp_region *inner;
110 /* Next peer region. */
111 struct omp_region *next;
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 basic_block exit;
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 basic_block cont;
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind;
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple *stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
201 struct omp_for_data_loop
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
207 /* A structure describing the main elements of a parallel loop. */
209 struct omp_for_data
211 struct omp_for_data_loop loop;
212 tree chunk_size;
213 gomp_for *for_stmt;
214 tree pre, iter_type;
215 int collapse;
216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
218 unsigned char sched_modifiers;
219 enum omp_clause_schedule_kind sched_kind;
220 struct omp_for_data_loop *loops;
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
226 struct oacc_loop
228 oacc_loop *parent; /* Containing loop. */
230 oacc_loop *child; /* First inner loop. */
232 oacc_loop *sibling; /* Next loop within same parent. */
234 location_t loc; /* Location of the loop start. */
236 gcall *marker; /* Initial head marker. */
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
241 tree routine; /* Pseudo-loop enclosing a routine. */
243 unsigned mask; /* Partitioning mask. */
244 unsigned flags; /* Partitioning flags. */
245 tree chunk_size; /* Chunk size. */
246 gcall *head_end; /* Final marker of head sequence. */
249 /* Flags for an OpenACC loop. */
251 enum oacc_loop_flags {
252 OLF_SEQ = 1u << 0, /* Explicitly sequential */
253 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
254 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
255 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
257 /* Explicitly specified loop axes. */
258 OLF_DIM_BASE = 4,
259 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
260 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
261 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
263 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
267 static splay_tree all_contexts;
268 static int taskreg_nesting_level;
269 static int target_nesting_level;
270 static struct omp_region *root_omp_region;
271 static bitmap task_shared_vars;
272 static vec<omp_context *> taskreg_contexts;
273 static bool omp_any_child_fn_dumped;
275 static void scan_omp (gimple_seq *, omp_context *);
276 static tree scan_omp_1_op (tree *, int *, void *);
277 static gphi *find_phi_with_arg_on_edge (tree, edge);
279 #define WALK_SUBSTMTS \
280 case GIMPLE_BIND: \
281 case GIMPLE_TRY: \
282 case GIMPLE_CATCH: \
283 case GIMPLE_EH_FILTER: \
284 case GIMPLE_TRANSACTION: \
285 /* The sub-statements for these should be walked. */ \
286 *handled_ops_p = false; \
287 break;
289 /* Return true if CTX corresponds to an oacc parallel region. */
291 static bool
292 is_oacc_parallel (omp_context *ctx)
294 enum gimple_code outer_type = gimple_code (ctx->stmt);
295 return ((outer_type == GIMPLE_OMP_TARGET)
296 && (gimple_omp_target_kind (ctx->stmt)
297 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
300 /* Return true if CTX corresponds to an oacc kernels region. */
302 static bool
303 is_oacc_kernels (omp_context *ctx)
305 enum gimple_code outer_type = gimple_code (ctx->stmt);
306 return ((outer_type == GIMPLE_OMP_TARGET)
307 && (gimple_omp_target_kind (ctx->stmt)
308 == GF_OMP_TARGET_KIND_OACC_KERNELS));
311 /* If DECL is the artificial dummy VAR_DECL created for non-static
312 data member privatization, return the underlying "this" parameter,
313 otherwise return NULL. */
315 tree
316 omp_member_access_dummy_var (tree decl)
318 if (!VAR_P (decl)
319 || !DECL_ARTIFICIAL (decl)
320 || !DECL_IGNORED_P (decl)
321 || !DECL_HAS_VALUE_EXPR_P (decl)
322 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
323 return NULL_TREE;
325 tree v = DECL_VALUE_EXPR (decl);
326 if (TREE_CODE (v) != COMPONENT_REF)
327 return NULL_TREE;
329 while (1)
330 switch (TREE_CODE (v))
332 case COMPONENT_REF:
333 case MEM_REF:
334 case INDIRECT_REF:
335 CASE_CONVERT:
336 case POINTER_PLUS_EXPR:
337 v = TREE_OPERAND (v, 0);
338 continue;
339 case PARM_DECL:
340 if (DECL_CONTEXT (v) == current_function_decl
341 && DECL_ARTIFICIAL (v)
342 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
343 return v;
344 return NULL_TREE;
345 default:
346 return NULL_TREE;
350 /* Helper for unshare_and_remap, called through walk_tree. */
352 static tree
353 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
355 tree *pair = (tree *) data;
356 if (*tp == pair[0])
358 *tp = unshare_expr (pair[1]);
359 *walk_subtrees = 0;
361 else if (IS_TYPE_OR_DECL_P (*tp))
362 *walk_subtrees = 0;
363 return NULL_TREE;
366 /* Return unshare_expr (X) with all occurrences of FROM
367 replaced with TO. */
369 static tree
370 unshare_and_remap (tree x, tree from, tree to)
372 tree pair[2] = { from, to };
373 x = unshare_expr (x);
374 walk_tree (&x, unshare_and_remap_1, pair, NULL);
375 return x;
378 /* Holds offload tables with decls. */
379 vec<tree, va_gc> *offload_funcs, *offload_vars;
381 /* Convenience function for calling scan_omp_1_op on tree operands. */
383 static inline tree
384 scan_omp_op (tree *tp, omp_context *ctx)
386 struct walk_stmt_info wi;
388 memset (&wi, 0, sizeof (wi));
389 wi.info = ctx;
390 wi.want_locations = true;
392 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
395 static void lower_omp (gimple_seq *, omp_context *);
396 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
397 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
399 /* Find an OMP clause of type KIND within CLAUSES. */
401 tree
402 find_omp_clause (tree clauses, enum omp_clause_code kind)
404 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
405 if (OMP_CLAUSE_CODE (clauses) == kind)
406 return clauses;
408 return NULL_TREE;
411 /* Return true if CTX is for an omp parallel. */
413 static inline bool
414 is_parallel_ctx (omp_context *ctx)
416 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
420 /* Return true if CTX is for an omp task. */
422 static inline bool
423 is_task_ctx (omp_context *ctx)
425 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
429 /* Return true if CTX is for an omp taskloop. */
431 static inline bool
432 is_taskloop_ctx (omp_context *ctx)
434 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
435 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
439 /* Return true if CTX is for an omp parallel or omp task. */
441 static inline bool
442 is_taskreg_ctx (omp_context *ctx)
444 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
448 /* Return true if REGION is a combined parallel+workshare region. */
450 static inline bool
451 is_combined_parallel (struct omp_region *region)
453 return region->is_combined_parallel;
456 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
457 GT_EXPR. */
459 static void
460 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
462 switch (*cond_code)
464 case LT_EXPR:
465 case GT_EXPR:
466 case NE_EXPR:
467 break;
468 case LE_EXPR:
469 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
470 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
471 else
472 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
473 build_int_cst (TREE_TYPE (*n2), 1));
474 *cond_code = LT_EXPR;
475 break;
476 case GE_EXPR:
477 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
478 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
479 else
480 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
481 build_int_cst (TREE_TYPE (*n2), 1));
482 *cond_code = GT_EXPR;
483 break;
484 default:
485 gcc_unreachable ();
489 /* Return the looping step from INCR, extracted from the step of a gimple omp
490 for statement. */
492 static tree
493 get_omp_for_step_from_incr (location_t loc, tree incr)
495 tree step;
496 switch (TREE_CODE (incr))
498 case PLUS_EXPR:
499 step = TREE_OPERAND (incr, 1);
500 break;
501 case POINTER_PLUS_EXPR:
502 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
503 break;
504 case MINUS_EXPR:
505 step = TREE_OPERAND (incr, 1);
506 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
507 break;
508 default:
509 gcc_unreachable ();
511 return step;
514 /* Extract the header elements of parallel loop FOR_STMT and store
515 them into *FD. */
517 static void
518 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
519 struct omp_for_data_loop *loops)
521 tree t, var, *collapse_iter, *collapse_count;
522 tree count = NULL_TREE, iter_type = long_integer_type_node;
523 struct omp_for_data_loop *loop;
524 int i;
525 struct omp_for_data_loop dummy_loop;
526 location_t loc = gimple_location (for_stmt);
527 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
528 bool distribute = gimple_omp_for_kind (for_stmt)
529 == GF_OMP_FOR_KIND_DISTRIBUTE;
530 bool taskloop = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_TASKLOOP;
532 tree iterv, countv;
534 fd->for_stmt = for_stmt;
535 fd->pre = NULL;
536 if (gimple_omp_for_collapse (for_stmt) > 1)
537 fd->loops = loops;
538 else
539 fd->loops = &fd->loop;
541 fd->have_nowait = distribute || simd;
542 fd->have_ordered = false;
543 fd->collapse = 1;
544 fd->ordered = 0;
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 fd->sched_modifiers = 0;
547 fd->chunk_size = NULL_TREE;
548 fd->simd_schedule = false;
549 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
551 collapse_iter = NULL;
552 collapse_count = NULL;
554 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
555 switch (OMP_CLAUSE_CODE (t))
557 case OMP_CLAUSE_NOWAIT:
558 fd->have_nowait = true;
559 break;
560 case OMP_CLAUSE_ORDERED:
561 fd->have_ordered = true;
562 if (OMP_CLAUSE_ORDERED_EXPR (t))
563 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
564 break;
565 case OMP_CLAUSE_SCHEDULE:
566 gcc_assert (!distribute && !taskloop);
567 fd->sched_kind
568 = (enum omp_clause_schedule_kind)
569 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
570 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
571 & ~OMP_CLAUSE_SCHEDULE_MASK);
572 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
573 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
574 break;
575 case OMP_CLAUSE_DIST_SCHEDULE:
576 gcc_assert (distribute);
577 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
578 break;
579 case OMP_CLAUSE_COLLAPSE:
580 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
581 if (fd->collapse > 1)
583 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
584 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
586 break;
587 default:
588 break;
590 if (fd->ordered && fd->collapse == 1 && loops != NULL)
592 fd->loops = loops;
593 iterv = NULL_TREE;
594 countv = NULL_TREE;
595 collapse_iter = &iterv;
596 collapse_count = &countv;
599 /* FIXME: for now map schedule(auto) to schedule(static).
600 There should be analysis to determine whether all iterations
601 are approximately the same amount of work (then schedule(static)
602 is best) or if it varies (then schedule(dynamic,N) is better). */
603 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
605 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
606 gcc_assert (fd->chunk_size == NULL);
608 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
609 if (taskloop)
610 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
611 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
612 gcc_assert (fd->chunk_size == NULL);
613 else if (fd->chunk_size == NULL)
615 /* We only need to compute a default chunk size for ordered
616 static loops and dynamic loops. */
617 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
618 || fd->have_ordered)
619 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
620 ? integer_zero_node : integer_one_node;
623 int cnt = fd->ordered ? fd->ordered : fd->collapse;
624 for (i = 0; i < cnt; i++)
626 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
627 loop = &fd->loop;
628 else if (loops != NULL)
629 loop = loops + i;
630 else
631 loop = &dummy_loop;
633 loop->v = gimple_omp_for_index (for_stmt, i);
634 gcc_assert (SSA_VAR_P (loop->v));
635 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
636 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
637 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
638 loop->n1 = gimple_omp_for_initial (for_stmt, i);
640 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
641 loop->n2 = gimple_omp_for_final (for_stmt, i);
642 gcc_assert (loop->cond_code != NE_EXPR
643 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
644 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
645 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
647 t = gimple_omp_for_incr (for_stmt, i);
648 gcc_assert (TREE_OPERAND (t, 0) == var);
649 loop->step = get_omp_for_step_from_incr (loc, t);
651 if (simd
652 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
653 && !fd->have_ordered))
655 if (fd->collapse == 1)
656 iter_type = TREE_TYPE (loop->v);
657 else if (i == 0
658 || TYPE_PRECISION (iter_type)
659 < TYPE_PRECISION (TREE_TYPE (loop->v)))
660 iter_type
661 = build_nonstandard_integer_type
662 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
664 else if (iter_type != long_long_unsigned_type_node)
666 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
667 iter_type = long_long_unsigned_type_node;
668 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
669 && TYPE_PRECISION (TREE_TYPE (loop->v))
670 >= TYPE_PRECISION (iter_type))
672 tree n;
674 if (loop->cond_code == LT_EXPR)
675 n = fold_build2_loc (loc,
676 PLUS_EXPR, TREE_TYPE (loop->v),
677 loop->n2, loop->step);
678 else
679 n = loop->n1;
680 if (TREE_CODE (n) != INTEGER_CST
681 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
682 iter_type = long_long_unsigned_type_node;
684 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
685 > TYPE_PRECISION (iter_type))
687 tree n1, n2;
689 if (loop->cond_code == LT_EXPR)
691 n1 = loop->n1;
692 n2 = fold_build2_loc (loc,
693 PLUS_EXPR, TREE_TYPE (loop->v),
694 loop->n2, loop->step);
696 else
698 n1 = fold_build2_loc (loc,
699 MINUS_EXPR, TREE_TYPE (loop->v),
700 loop->n2, loop->step);
701 n2 = loop->n1;
703 if (TREE_CODE (n1) != INTEGER_CST
704 || TREE_CODE (n2) != INTEGER_CST
705 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
706 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
707 iter_type = long_long_unsigned_type_node;
711 if (i >= fd->collapse)
712 continue;
714 if (collapse_count && *collapse_count == NULL)
716 t = fold_binary (loop->cond_code, boolean_type_node,
717 fold_convert (TREE_TYPE (loop->v), loop->n1),
718 fold_convert (TREE_TYPE (loop->v), loop->n2));
719 if (t && integer_zerop (t))
720 count = build_zero_cst (long_long_unsigned_type_node);
721 else if ((i == 0 || count != NULL_TREE)
722 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
723 && TREE_CONSTANT (loop->n1)
724 && TREE_CONSTANT (loop->n2)
725 && TREE_CODE (loop->step) == INTEGER_CST)
727 tree itype = TREE_TYPE (loop->v);
729 if (POINTER_TYPE_P (itype))
730 itype = signed_type_for (itype);
731 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
732 t = fold_build2_loc (loc,
733 PLUS_EXPR, itype,
734 fold_convert_loc (loc, itype, loop->step), t);
735 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
736 fold_convert_loc (loc, itype, loop->n2));
737 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
738 fold_convert_loc (loc, itype, loop->n1));
739 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
740 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
741 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
742 fold_build1_loc (loc, NEGATE_EXPR, itype,
743 fold_convert_loc (loc, itype,
744 loop->step)));
745 else
746 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
747 fold_convert_loc (loc, itype, loop->step));
748 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
749 if (count != NULL_TREE)
750 count = fold_build2_loc (loc,
751 MULT_EXPR, long_long_unsigned_type_node,
752 count, t);
753 else
754 count = t;
755 if (TREE_CODE (count) != INTEGER_CST)
756 count = NULL_TREE;
758 else if (count && !integer_zerop (count))
759 count = NULL_TREE;
763 if (count
764 && !simd
765 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
766 || fd->have_ordered))
768 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
769 iter_type = long_long_unsigned_type_node;
770 else
771 iter_type = long_integer_type_node;
773 else if (collapse_iter && *collapse_iter != NULL)
774 iter_type = TREE_TYPE (*collapse_iter);
775 fd->iter_type = iter_type;
776 if (collapse_iter && *collapse_iter == NULL)
777 *collapse_iter = create_tmp_var (iter_type, ".iter");
778 if (collapse_count && *collapse_count == NULL)
780 if (count)
781 *collapse_count = fold_convert_loc (loc, iter_type, count);
782 else
783 *collapse_count = create_tmp_var (iter_type, ".count");
786 if (fd->collapse > 1 || (fd->ordered && loops))
788 fd->loop.v = *collapse_iter;
789 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
790 fd->loop.n2 = *collapse_count;
791 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
792 fd->loop.cond_code = LT_EXPR;
794 else if (loops)
795 loops[0] = fd->loop;
799 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
800 is the immediate dominator of PAR_ENTRY_BB, return true if there
801 are no data dependencies that would prevent expanding the parallel
802 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
804 When expanding a combined parallel+workshare region, the call to
805 the child function may need additional arguments in the case of
806 GIMPLE_OMP_FOR regions. In some cases, these arguments are
807 computed out of variables passed in from the parent to the child
808 via 'struct .omp_data_s'. For instance:
810 #pragma omp parallel for schedule (guided, i * 4)
811 for (j ...)
813 Is lowered into:
815 # BLOCK 2 (PAR_ENTRY_BB)
816 .omp_data_o.i = i;
817 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
819 # BLOCK 3 (WS_ENTRY_BB)
820 .omp_data_i = &.omp_data_o;
821 D.1667 = .omp_data_i->i;
822 D.1598 = D.1667 * 4;
823 #pragma omp for schedule (guided, D.1598)
825 When we outline the parallel region, the call to the child function
826 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
827 that value is computed *after* the call site. So, in principle we
828 cannot do the transformation.
830 To see whether the code in WS_ENTRY_BB blocks the combined
831 parallel+workshare call, we collect all the variables used in the
832 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
833 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
834 call.
836 FIXME. If we had the SSA form built at this point, we could merely
837 hoist the code in block 3 into block 2 and be done with it. But at
838 this point we don't have dataflow information and though we could
839 hack something up here, it is really not worth the aggravation. */
841 static bool
842 workshare_safe_to_combine_p (basic_block ws_entry_bb)
844 struct omp_for_data fd;
845 gimple *ws_stmt = last_stmt (ws_entry_bb);
847 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
848 return true;
850 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
852 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
854 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
855 return false;
856 if (fd.iter_type != long_integer_type_node)
857 return false;
859 /* FIXME. We give up too easily here. If any of these arguments
860 are not constants, they will likely involve variables that have
861 been mapped into fields of .omp_data_s for sharing with the child
862 function. With appropriate data flow, it would be possible to
863 see through this. */
864 if (!is_gimple_min_invariant (fd.loop.n1)
865 || !is_gimple_min_invariant (fd.loop.n2)
866 || !is_gimple_min_invariant (fd.loop.step)
867 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
868 return false;
870 return true;
874 static int omp_max_vf (void);
876 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
877 presence (SIMD_SCHEDULE). */
879 static tree
880 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
882 if (!simd_schedule)
883 return chunk_size;
885 int vf = omp_max_vf ();
886 if (vf == 1)
887 return chunk_size;
889 tree type = TREE_TYPE (chunk_size);
890 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
891 build_int_cst (type, vf - 1));
892 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
893 build_int_cst (type, -vf));
897 /* Collect additional arguments needed to emit a combined
898 parallel+workshare call. WS_STMT is the workshare directive being
899 expanded. */
901 static vec<tree, va_gc> *
902 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
904 tree t;
905 location_t loc = gimple_location (ws_stmt);
906 vec<tree, va_gc> *ws_args;
908 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
910 struct omp_for_data fd;
911 tree n1, n2;
913 extract_omp_for_data (for_stmt, &fd, NULL);
914 n1 = fd.loop.n1;
915 n2 = fd.loop.n2;
917 if (gimple_omp_for_combined_into_p (for_stmt))
919 tree innerc
920 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
921 OMP_CLAUSE__LOOPTEMP_);
922 gcc_assert (innerc);
923 n1 = OMP_CLAUSE_DECL (innerc);
924 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
925 OMP_CLAUSE__LOOPTEMP_);
926 gcc_assert (innerc);
927 n2 = OMP_CLAUSE_DECL (innerc);
930 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
932 t = fold_convert_loc (loc, long_integer_type_node, n1);
933 ws_args->quick_push (t);
935 t = fold_convert_loc (loc, long_integer_type_node, n2);
936 ws_args->quick_push (t);
938 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
939 ws_args->quick_push (t);
941 if (fd.chunk_size)
943 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
944 t = omp_adjust_chunk_size (t, fd.simd_schedule);
945 ws_args->quick_push (t);
948 return ws_args;
950 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
952 /* Number of sections is equal to the number of edges from the
953 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
954 the exit of the sections region. */
955 basic_block bb = single_succ (gimple_bb (ws_stmt));
956 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
957 vec_alloc (ws_args, 1);
958 ws_args->quick_push (t);
959 return ws_args;
962 gcc_unreachable ();
966 /* Discover whether REGION is a combined parallel+workshare region. */
968 static void
969 determine_parallel_type (struct omp_region *region)
971 basic_block par_entry_bb, par_exit_bb;
972 basic_block ws_entry_bb, ws_exit_bb;
974 if (region == NULL || region->inner == NULL
975 || region->exit == NULL || region->inner->exit == NULL
976 || region->inner->cont == NULL)
977 return;
979 /* We only support parallel+for and parallel+sections. */
980 if (region->type != GIMPLE_OMP_PARALLEL
981 || (region->inner->type != GIMPLE_OMP_FOR
982 && region->inner->type != GIMPLE_OMP_SECTIONS))
983 return;
985 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
986 WS_EXIT_BB -> PAR_EXIT_BB. */
987 par_entry_bb = region->entry;
988 par_exit_bb = region->exit;
989 ws_entry_bb = region->inner->entry;
990 ws_exit_bb = region->inner->exit;
992 if (single_succ (par_entry_bb) == ws_entry_bb
993 && single_succ (ws_exit_bb) == par_exit_bb
994 && workshare_safe_to_combine_p (ws_entry_bb)
995 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
996 || (last_and_only_stmt (ws_entry_bb)
997 && last_and_only_stmt (par_exit_bb))))
999 gimple *par_stmt = last_stmt (par_entry_bb);
1000 gimple *ws_stmt = last_stmt (ws_entry_bb);
1002 if (region->inner->type == GIMPLE_OMP_FOR)
1004 /* If this is a combined parallel loop, we need to determine
1005 whether or not to use the combined library calls. There
1006 are two cases where we do not apply the transformation:
1007 static loops and any kind of ordered loop. In the first
1008 case, we already open code the loop so there is no need
1009 to do anything else. In the latter case, the combined
1010 parallel loop call would still need extra synchronization
1011 to implement ordered semantics, so there would not be any
1012 gain in using the combined call. */
1013 tree clauses = gimple_omp_for_clauses (ws_stmt);
1014 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1015 if (c == NULL
1016 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1017 == OMP_CLAUSE_SCHEDULE_STATIC)
1018 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1020 region->is_combined_parallel = false;
1021 region->inner->is_combined_parallel = false;
1022 return;
1026 region->is_combined_parallel = true;
1027 region->inner->is_combined_parallel = true;
1028 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1033 /* Return true if EXPR is variable sized. */
1035 static inline bool
1036 is_variable_sized (const_tree expr)
1038 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1041 /* Return true if DECL is a reference type. */
1043 static inline bool
1044 is_reference (tree decl)
1046 return lang_hooks.decls.omp_privatize_by_reference (decl);
1049 /* Return the type of a decl. If the decl is reference type,
1050 return its base type. */
1051 static inline tree
1052 get_base_type (tree decl)
1054 tree type = TREE_TYPE (decl);
1055 if (is_reference (decl))
1056 type = TREE_TYPE (type);
1057 return type;
1060 /* Lookup variables. The "maybe" form
1061 allows for the variable form to not have been entered, otherwise we
1062 assert that the variable must have been entered. */
1064 static inline tree
1065 lookup_decl (tree var, omp_context *ctx)
1067 tree *n = ctx->cb.decl_map->get (var);
1068 return *n;
1071 static inline tree
1072 maybe_lookup_decl (const_tree var, omp_context *ctx)
1074 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1075 return n ? *n : NULL_TREE;
1078 static inline tree
1079 lookup_field (tree var, omp_context *ctx)
1081 splay_tree_node n;
1082 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1083 return (tree) n->value;
1086 static inline tree
1087 lookup_sfield (splay_tree_key key, omp_context *ctx)
1089 splay_tree_node n;
1090 n = splay_tree_lookup (ctx->sfield_map
1091 ? ctx->sfield_map : ctx->field_map, key);
1092 return (tree) n->value;
1095 static inline tree
1096 lookup_sfield (tree var, omp_context *ctx)
1098 return lookup_sfield ((splay_tree_key) var, ctx);
1101 static inline tree
1102 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1104 splay_tree_node n;
1105 n = splay_tree_lookup (ctx->field_map, key);
1106 return n ? (tree) n->value : NULL_TREE;
1109 static inline tree
1110 maybe_lookup_field (tree var, omp_context *ctx)
1112 return maybe_lookup_field ((splay_tree_key) var, ctx);
1115 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1116 the parallel context if DECL is to be shared. */
1118 static bool
1119 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1121 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1122 return true;
1124 /* We can only use copy-in/copy-out semantics for shared variables
1125 when we know the value is not accessible from an outer scope. */
1126 if (shared_ctx)
1128 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1130 /* ??? Trivially accessible from anywhere. But why would we even
1131 be passing an address in this case? Should we simply assert
1132 this to be false, or should we have a cleanup pass that removes
1133 these from the list of mappings? */
1134 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1135 return true;
1137 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1138 without analyzing the expression whether or not its location
1139 is accessible to anyone else. In the case of nested parallel
1140 regions it certainly may be. */
1141 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1142 return true;
1144 /* Do not use copy-in/copy-out for variables that have their
1145 address taken. */
1146 if (TREE_ADDRESSABLE (decl))
1147 return true;
1149 /* lower_send_shared_vars only uses copy-in, but not copy-out
1150 for these. */
1151 if (TREE_READONLY (decl)
1152 || ((TREE_CODE (decl) == RESULT_DECL
1153 || TREE_CODE (decl) == PARM_DECL)
1154 && DECL_BY_REFERENCE (decl)))
1155 return false;
1157 /* Disallow copy-in/out in nested parallel if
1158 decl is shared in outer parallel, otherwise
1159 each thread could store the shared variable
1160 in its own copy-in location, making the
1161 variable no longer really shared. */
1162 if (shared_ctx->is_nested)
1164 omp_context *up;
1166 for (up = shared_ctx->outer; up; up = up->outer)
1167 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1168 break;
1170 if (up)
1172 tree c;
1174 for (c = gimple_omp_taskreg_clauses (up->stmt);
1175 c; c = OMP_CLAUSE_CHAIN (c))
1176 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1177 && OMP_CLAUSE_DECL (c) == decl)
1178 break;
1180 if (c)
1181 goto maybe_mark_addressable_and_ret;
1185 /* For tasks avoid using copy-in/out. As tasks can be
1186 deferred or executed in different thread, when GOMP_task
1187 returns, the task hasn't necessarily terminated. */
1188 if (is_task_ctx (shared_ctx))
1190 tree outer;
1191 maybe_mark_addressable_and_ret:
1192 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1193 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1195 /* Taking address of OUTER in lower_send_shared_vars
1196 might need regimplification of everything that uses the
1197 variable. */
1198 if (!task_shared_vars)
1199 task_shared_vars = BITMAP_ALLOC (NULL);
1200 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1201 TREE_ADDRESSABLE (outer) = 1;
1203 return true;
1207 return false;
1210 /* Construct a new automatic decl similar to VAR. */
1212 static tree
1213 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1215 tree copy = copy_var_decl (var, name, type);
1217 DECL_CONTEXT (copy) = current_function_decl;
1218 DECL_CHAIN (copy) = ctx->block_vars;
1219 /* If VAR is listed in task_shared_vars, it means it wasn't
1220 originally addressable and is just because task needs to take
1221 it's address. But we don't need to take address of privatizations
1222 from that var. */
1223 if (TREE_ADDRESSABLE (var)
1224 && task_shared_vars
1225 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1226 TREE_ADDRESSABLE (copy) = 0;
1227 ctx->block_vars = copy;
1229 return copy;
1232 static tree
1233 omp_copy_decl_1 (tree var, omp_context *ctx)
1235 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1238 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1239 as appropriate. */
1240 static tree
1241 omp_build_component_ref (tree obj, tree field)
1243 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1244 if (TREE_THIS_VOLATILE (field))
1245 TREE_THIS_VOLATILE (ret) |= 1;
1246 if (TREE_READONLY (field))
1247 TREE_READONLY (ret) |= 1;
1248 return ret;
1251 /* Build tree nodes to access the field for VAR on the receiver side. */
1253 static tree
1254 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1256 tree x, field = lookup_field (var, ctx);
1258 /* If the receiver record type was remapped in the child function,
1259 remap the field into the new record type. */
1260 x = maybe_lookup_field (field, ctx);
1261 if (x != NULL)
1262 field = x;
1264 x = build_simple_mem_ref (ctx->receiver_decl);
1265 TREE_THIS_NOTRAP (x) = 1;
1266 x = omp_build_component_ref (x, field);
1267 if (by_ref)
1269 x = build_simple_mem_ref (x);
1270 TREE_THIS_NOTRAP (x) = 1;
1273 return x;
1276 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1277 of a parallel, this is a component reference; for workshare constructs
1278 this is some variable. */
1280 static tree
1281 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1283 tree x;
1285 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1286 x = var;
1287 else if (is_variable_sized (var))
1289 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1290 x = build_outer_var_ref (x, ctx, lastprivate);
1291 x = build_simple_mem_ref (x);
1293 else if (is_taskreg_ctx (ctx))
1295 bool by_ref = use_pointer_for_field (var, NULL);
1296 x = build_receiver_ref (var, by_ref, ctx);
1298 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1299 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1301 /* #pragma omp simd isn't a worksharing construct, and can reference even
1302 private vars in its linear etc. clauses. */
1303 x = NULL_TREE;
1304 if (ctx->outer && is_taskreg_ctx (ctx))
1305 x = lookup_decl (var, ctx->outer);
1306 else if (ctx->outer)
1307 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1308 if (x == NULL_TREE)
1309 x = var;
1311 else if (lastprivate && is_taskloop_ctx (ctx))
1313 gcc_assert (ctx->outer);
1314 splay_tree_node n
1315 = splay_tree_lookup (ctx->outer->field_map,
1316 (splay_tree_key) &DECL_UID (var));
1317 if (n == NULL)
1319 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1320 x = var;
1321 else
1322 x = lookup_decl (var, ctx->outer);
1324 else
1326 tree field = (tree) n->value;
1327 /* If the receiver record type was remapped in the child function,
1328 remap the field into the new record type. */
1329 x = maybe_lookup_field (field, ctx->outer);
1330 if (x != NULL)
1331 field = x;
1333 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1334 x = omp_build_component_ref (x, field);
1335 if (use_pointer_for_field (var, ctx->outer))
1336 x = build_simple_mem_ref (x);
1339 else if (ctx->outer)
1341 omp_context *outer = ctx->outer;
1342 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1344 outer = outer->outer;
1345 gcc_assert (outer
1346 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1348 x = lookup_decl (var, outer);
1350 else if (is_reference (var))
1351 /* This can happen with orphaned constructs. If var is reference, it is
1352 possible it is shared and as such valid. */
1353 x = var;
1354 else if (omp_member_access_dummy_var (var))
1355 x = var;
1356 else
1357 gcc_unreachable ();
1359 if (x == var)
1361 tree t = omp_member_access_dummy_var (var);
1362 if (t)
1364 x = DECL_VALUE_EXPR (var);
1365 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1366 if (o != t)
1367 x = unshare_and_remap (x, t, o);
1368 else
1369 x = unshare_expr (x);
1373 if (is_reference (var))
1374 x = build_simple_mem_ref (x);
1376 return x;
1379 /* Build tree nodes to access the field for VAR on the sender side. */
1381 static tree
1382 build_sender_ref (splay_tree_key key, omp_context *ctx)
1384 tree field = lookup_sfield (key, ctx);
1385 return omp_build_component_ref (ctx->sender_decl, field);
1388 static tree
1389 build_sender_ref (tree var, omp_context *ctx)
1391 return build_sender_ref ((splay_tree_key) var, ctx);
1394 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1395 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1397 static void
1398 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1399 bool base_pointers_restrict = false)
1401 tree field, type, sfield = NULL_TREE;
1402 splay_tree_key key = (splay_tree_key) var;
1404 if ((mask & 8) != 0)
1406 key = (splay_tree_key) &DECL_UID (var);
1407 gcc_checking_assert (key != (splay_tree_key) var);
1409 gcc_assert ((mask & 1) == 0
1410 || !splay_tree_lookup (ctx->field_map, key));
1411 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1412 || !splay_tree_lookup (ctx->sfield_map, key));
1413 gcc_assert ((mask & 3) == 3
1414 || !is_gimple_omp_oacc (ctx->stmt));
1416 type = TREE_TYPE (var);
1417 /* Prevent redeclaring the var in the split-off function with a restrict
1418 pointer type. Note that we only clear type itself, restrict qualifiers in
1419 the pointed-to type will be ignored by points-to analysis. */
1420 if (POINTER_TYPE_P (type)
1421 && TYPE_RESTRICT (type))
1422 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1424 if (mask & 4)
1426 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1427 type = build_pointer_type (build_pointer_type (type));
1429 else if (by_ref)
1431 type = build_pointer_type (type);
1432 if (base_pointers_restrict)
1433 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1435 else if ((mask & 3) == 1 && is_reference (var))
1436 type = TREE_TYPE (type);
1438 field = build_decl (DECL_SOURCE_LOCATION (var),
1439 FIELD_DECL, DECL_NAME (var), type);
1441 /* Remember what variable this field was created for. This does have a
1442 side effect of making dwarf2out ignore this member, so for helpful
1443 debugging we clear it later in delete_omp_context. */
1444 DECL_ABSTRACT_ORIGIN (field) = var;
1445 if (type == TREE_TYPE (var))
1447 DECL_ALIGN (field) = DECL_ALIGN (var);
1448 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1449 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1451 else
1452 DECL_ALIGN (field) = TYPE_ALIGN (type);
1454 if ((mask & 3) == 3)
1456 insert_field_into_struct (ctx->record_type, field);
1457 if (ctx->srecord_type)
1459 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1460 FIELD_DECL, DECL_NAME (var), type);
1461 DECL_ABSTRACT_ORIGIN (sfield) = var;
1462 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1463 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1464 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1465 insert_field_into_struct (ctx->srecord_type, sfield);
1468 else
1470 if (ctx->srecord_type == NULL_TREE)
1472 tree t;
1474 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1475 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1476 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1478 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1479 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1480 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1481 insert_field_into_struct (ctx->srecord_type, sfield);
1482 splay_tree_insert (ctx->sfield_map,
1483 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1484 (splay_tree_value) sfield);
1487 sfield = field;
1488 insert_field_into_struct ((mask & 1) ? ctx->record_type
1489 : ctx->srecord_type, field);
1492 if (mask & 1)
1493 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1494 if ((mask & 2) && ctx->sfield_map)
1495 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1498 static tree
1499 install_var_local (tree var, omp_context *ctx)
1501 tree new_var = omp_copy_decl_1 (var, ctx);
1502 insert_decl_map (&ctx->cb, var, new_var);
1503 return new_var;
1506 /* Adjust the replacement for DECL in CTX for the new context. This means
1507 copying the DECL_VALUE_EXPR, and fixing up the type. */
1509 static void
1510 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1512 tree new_decl, size;
1514 new_decl = lookup_decl (decl, ctx);
1516 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1518 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1519 && DECL_HAS_VALUE_EXPR_P (decl))
1521 tree ve = DECL_VALUE_EXPR (decl);
1522 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1523 SET_DECL_VALUE_EXPR (new_decl, ve);
1524 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1527 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1529 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1530 if (size == error_mark_node)
1531 size = TYPE_SIZE (TREE_TYPE (new_decl));
1532 DECL_SIZE (new_decl) = size;
1534 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1535 if (size == error_mark_node)
1536 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1537 DECL_SIZE_UNIT (new_decl) = size;
1541 /* The callback for remap_decl. Search all containing contexts for a
1542 mapping of the variable; this avoids having to duplicate the splay
1543 tree ahead of time. We know a mapping doesn't already exist in the
1544 given context. Create new mappings to implement default semantics. */
1546 static tree
1547 omp_copy_decl (tree var, copy_body_data *cb)
1549 omp_context *ctx = (omp_context *) cb;
1550 tree new_var;
1552 if (TREE_CODE (var) == LABEL_DECL)
1554 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1555 DECL_CONTEXT (new_var) = current_function_decl;
1556 insert_decl_map (&ctx->cb, var, new_var);
1557 return new_var;
1560 while (!is_taskreg_ctx (ctx))
1562 ctx = ctx->outer;
1563 if (ctx == NULL)
1564 return var;
1565 new_var = maybe_lookup_decl (var, ctx);
1566 if (new_var)
1567 return new_var;
1570 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1571 return var;
1573 return error_mark_node;
1577 /* Debugging dumps for parallel regions. */
1578 void dump_omp_region (FILE *, struct omp_region *, int);
1579 void debug_omp_region (struct omp_region *);
1580 void debug_all_omp_regions (void);
1582 /* Dump the parallel region tree rooted at REGION. */
1584 void
1585 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1587 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1588 gimple_code_name[region->type]);
1590 if (region->inner)
1591 dump_omp_region (file, region->inner, indent + 4);
1593 if (region->cont)
1595 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1596 region->cont->index);
1599 if (region->exit)
1600 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1601 region->exit->index);
1602 else
1603 fprintf (file, "%*s[no exit marker]\n", indent, "");
1605 if (region->next)
1606 dump_omp_region (file, region->next, indent);
1609 DEBUG_FUNCTION void
1610 debug_omp_region (struct omp_region *region)
1612 dump_omp_region (stderr, region, 0);
1615 DEBUG_FUNCTION void
1616 debug_all_omp_regions (void)
1618 dump_omp_region (stderr, root_omp_region, 0);
1622 /* Create a new parallel region starting at STMT inside region PARENT. */
1624 static struct omp_region *
1625 new_omp_region (basic_block bb, enum gimple_code type,
1626 struct omp_region *parent)
1628 struct omp_region *region = XCNEW (struct omp_region);
1630 region->outer = parent;
1631 region->entry = bb;
1632 region->type = type;
1634 if (parent)
1636 /* This is a nested region. Add it to the list of inner
1637 regions in PARENT. */
1638 region->next = parent->inner;
1639 parent->inner = region;
1641 else
1643 /* This is a toplevel region. Add it to the list of toplevel
1644 regions in ROOT_OMP_REGION. */
1645 region->next = root_omp_region;
1646 root_omp_region = region;
1649 return region;
1652 /* Release the memory associated with the region tree rooted at REGION. */
1654 static void
1655 free_omp_region_1 (struct omp_region *region)
1657 struct omp_region *i, *n;
1659 for (i = region->inner; i ; i = n)
1661 n = i->next;
1662 free_omp_region_1 (i);
1665 free (region);
1668 /* Release the memory for the entire omp region tree. */
1670 void
1671 free_omp_regions (void)
1673 struct omp_region *r, *n;
1674 for (r = root_omp_region; r ; r = n)
1676 n = r->next;
1677 free_omp_region_1 (r);
1679 root_omp_region = NULL;
1683 /* Create a new context, with OUTER_CTX being the surrounding context. */
1685 static omp_context *
1686 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1688 omp_context *ctx = XCNEW (omp_context);
1690 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1691 (splay_tree_value) ctx);
1692 ctx->stmt = stmt;
1694 if (outer_ctx)
1696 ctx->outer = outer_ctx;
1697 ctx->cb = outer_ctx->cb;
1698 ctx->cb.block = NULL;
1699 ctx->depth = outer_ctx->depth + 1;
1701 else
1703 ctx->cb.src_fn = current_function_decl;
1704 ctx->cb.dst_fn = current_function_decl;
1705 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1706 gcc_checking_assert (ctx->cb.src_node);
1707 ctx->cb.dst_node = ctx->cb.src_node;
1708 ctx->cb.src_cfun = cfun;
1709 ctx->cb.copy_decl = omp_copy_decl;
1710 ctx->cb.eh_lp_nr = 0;
1711 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1712 ctx->depth = 1;
1715 ctx->cb.decl_map = new hash_map<tree, tree>;
1717 return ctx;
1720 static gimple_seq maybe_catch_exception (gimple_seq);
1722 /* Finalize task copyfn. */
1724 static void
1725 finalize_task_copyfn (gomp_task *task_stmt)
1727 struct function *child_cfun;
1728 tree child_fn;
1729 gimple_seq seq = NULL, new_seq;
1730 gbind *bind;
1732 child_fn = gimple_omp_task_copy_fn (task_stmt);
1733 if (child_fn == NULL_TREE)
1734 return;
1736 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1737 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1739 push_cfun (child_cfun);
1740 bind = gimplify_body (child_fn, false);
1741 gimple_seq_add_stmt (&seq, bind);
1742 new_seq = maybe_catch_exception (seq);
1743 if (new_seq != seq)
1745 bind = gimple_build_bind (NULL, new_seq, NULL);
1746 seq = NULL;
1747 gimple_seq_add_stmt (&seq, bind);
1749 gimple_set_body (child_fn, seq);
1750 pop_cfun ();
1752 /* Inform the callgraph about the new function. */
1753 cgraph_node *node = cgraph_node::get_create (child_fn);
1754 node->parallelized_function = 1;
1755 cgraph_node::add_new_function (child_fn, false);
1758 /* Destroy a omp_context data structures. Called through the splay tree
1759 value delete callback. */
1761 static void
1762 delete_omp_context (splay_tree_value value)
1764 omp_context *ctx = (omp_context *) value;
1766 delete ctx->cb.decl_map;
1768 if (ctx->field_map)
1769 splay_tree_delete (ctx->field_map);
1770 if (ctx->sfield_map)
1771 splay_tree_delete (ctx->sfield_map);
1773 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1774 it produces corrupt debug information. */
1775 if (ctx->record_type)
1777 tree t;
1778 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1779 DECL_ABSTRACT_ORIGIN (t) = NULL;
1781 if (ctx->srecord_type)
1783 tree t;
1784 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1785 DECL_ABSTRACT_ORIGIN (t) = NULL;
1788 if (is_task_ctx (ctx))
1789 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1791 XDELETE (ctx);
1794 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1795 context. */
1797 static void
1798 fixup_child_record_type (omp_context *ctx)
1800 tree f, type = ctx->record_type;
1802 if (!ctx->receiver_decl)
1803 return;
1804 /* ??? It isn't sufficient to just call remap_type here, because
1805 variably_modified_type_p doesn't work the way we expect for
1806 record types. Testing each field for whether it needs remapping
1807 and creating a new record by hand works, however. */
1808 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1809 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1810 break;
1811 if (f)
1813 tree name, new_fields = NULL;
1815 type = lang_hooks.types.make_type (RECORD_TYPE);
1816 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1817 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1818 TYPE_DECL, name, type);
1819 TYPE_NAME (type) = name;
1821 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1823 tree new_f = copy_node (f);
1824 DECL_CONTEXT (new_f) = type;
1825 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1826 DECL_CHAIN (new_f) = new_fields;
1827 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1828 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1829 &ctx->cb, NULL);
1830 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1831 &ctx->cb, NULL);
1832 new_fields = new_f;
1834 /* Arrange to be able to look up the receiver field
1835 given the sender field. */
1836 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1837 (splay_tree_value) new_f);
1839 TYPE_FIELDS (type) = nreverse (new_fields);
1840 layout_type (type);
1843 /* In a target region we never modify any of the pointers in *.omp_data_i,
1844 so attempt to help the optimizers. */
1845 if (is_gimple_omp_offloaded (ctx->stmt))
1846 type = build_qualified_type (type, TYPE_QUAL_CONST);
1848 TREE_TYPE (ctx->receiver_decl)
1849 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1852 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1853 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1854 restrict. */
1856 static void
1857 scan_sharing_clauses (tree clauses, omp_context *ctx,
1858 bool base_pointers_restrict = false)
1860 tree c, decl;
1861 bool scan_array_reductions = false;
1863 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1865 bool by_ref;
1867 switch (OMP_CLAUSE_CODE (c))
1869 case OMP_CLAUSE_PRIVATE:
1870 decl = OMP_CLAUSE_DECL (c);
1871 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1872 goto do_private;
1873 else if (!is_variable_sized (decl))
1874 install_var_local (decl, ctx);
1875 break;
1877 case OMP_CLAUSE_SHARED:
1878 decl = OMP_CLAUSE_DECL (c);
1879 /* Ignore shared directives in teams construct. */
1880 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1882 /* Global variables don't need to be copied,
1883 the receiver side will use them directly. */
1884 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1885 if (is_global_var (odecl))
1886 break;
1887 insert_decl_map (&ctx->cb, decl, odecl);
1888 break;
1890 gcc_assert (is_taskreg_ctx (ctx));
1891 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1892 || !is_variable_sized (decl));
1893 /* Global variables don't need to be copied,
1894 the receiver side will use them directly. */
1895 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1896 break;
1897 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1899 use_pointer_for_field (decl, ctx);
1900 break;
1902 by_ref = use_pointer_for_field (decl, NULL);
1903 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1904 || TREE_ADDRESSABLE (decl)
1905 || by_ref
1906 || is_reference (decl))
1908 by_ref = use_pointer_for_field (decl, ctx);
1909 install_var_field (decl, by_ref, 3, ctx);
1910 install_var_local (decl, ctx);
1911 break;
1913 /* We don't need to copy const scalar vars back. */
1914 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1915 goto do_private;
1917 case OMP_CLAUSE_REDUCTION:
1918 decl = OMP_CLAUSE_DECL (c);
1919 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1920 && TREE_CODE (decl) == MEM_REF)
1922 tree t = TREE_OPERAND (decl, 0);
1923 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1924 t = TREE_OPERAND (t, 0);
1925 if (TREE_CODE (t) == INDIRECT_REF
1926 || TREE_CODE (t) == ADDR_EXPR)
1927 t = TREE_OPERAND (t, 0);
1928 install_var_local (t, ctx);
1929 if (is_taskreg_ctx (ctx)
1930 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1931 && !is_variable_sized (t))
1933 by_ref = use_pointer_for_field (t, ctx);
1934 install_var_field (t, by_ref, 3, ctx);
1936 break;
1938 goto do_private;
1940 case OMP_CLAUSE_LASTPRIVATE:
1941 /* Let the corresponding firstprivate clause create
1942 the variable. */
1943 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1944 break;
1945 /* FALLTHRU */
1947 case OMP_CLAUSE_FIRSTPRIVATE:
1948 case OMP_CLAUSE_LINEAR:
1949 decl = OMP_CLAUSE_DECL (c);
1950 do_private:
1951 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1952 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1953 && is_gimple_omp_offloaded (ctx->stmt))
1955 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1956 install_var_field (decl, !is_reference (decl), 3, ctx);
1957 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1958 install_var_field (decl, true, 3, ctx);
1959 else
1960 install_var_field (decl, false, 3, ctx);
1962 if (is_variable_sized (decl))
1964 if (is_task_ctx (ctx))
1965 install_var_field (decl, false, 1, ctx);
1966 break;
1968 else if (is_taskreg_ctx (ctx))
1970 bool global
1971 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1972 by_ref = use_pointer_for_field (decl, NULL);
1974 if (is_task_ctx (ctx)
1975 && (global || by_ref || is_reference (decl)))
1977 install_var_field (decl, false, 1, ctx);
1978 if (!global)
1979 install_var_field (decl, by_ref, 2, ctx);
1981 else if (!global)
1982 install_var_field (decl, by_ref, 3, ctx);
1984 install_var_local (decl, ctx);
1985 break;
1987 case OMP_CLAUSE_USE_DEVICE_PTR:
1988 decl = OMP_CLAUSE_DECL (c);
1989 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1990 install_var_field (decl, true, 3, ctx);
1991 else
1992 install_var_field (decl, false, 3, ctx);
1993 if (DECL_SIZE (decl)
1994 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1996 tree decl2 = DECL_VALUE_EXPR (decl);
1997 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1998 decl2 = TREE_OPERAND (decl2, 0);
1999 gcc_assert (DECL_P (decl2));
2000 install_var_local (decl2, ctx);
2002 install_var_local (decl, ctx);
2003 break;
2005 case OMP_CLAUSE_IS_DEVICE_PTR:
2006 decl = OMP_CLAUSE_DECL (c);
2007 goto do_private;
2009 case OMP_CLAUSE__LOOPTEMP_:
2010 gcc_assert (is_taskreg_ctx (ctx));
2011 decl = OMP_CLAUSE_DECL (c);
2012 install_var_field (decl, false, 3, ctx);
2013 install_var_local (decl, ctx);
2014 break;
2016 case OMP_CLAUSE_COPYPRIVATE:
2017 case OMP_CLAUSE_COPYIN:
2018 decl = OMP_CLAUSE_DECL (c);
2019 by_ref = use_pointer_for_field (decl, NULL);
2020 install_var_field (decl, by_ref, 3, ctx);
2021 break;
2023 case OMP_CLAUSE_DEFAULT:
2024 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2025 break;
2027 case OMP_CLAUSE_FINAL:
2028 case OMP_CLAUSE_IF:
2029 case OMP_CLAUSE_NUM_THREADS:
2030 case OMP_CLAUSE_NUM_TEAMS:
2031 case OMP_CLAUSE_THREAD_LIMIT:
2032 case OMP_CLAUSE_DEVICE:
2033 case OMP_CLAUSE_SCHEDULE:
2034 case OMP_CLAUSE_DIST_SCHEDULE:
2035 case OMP_CLAUSE_DEPEND:
2036 case OMP_CLAUSE_PRIORITY:
2037 case OMP_CLAUSE_GRAINSIZE:
2038 case OMP_CLAUSE_NUM_TASKS:
2039 case OMP_CLAUSE__CILK_FOR_COUNT_:
2040 case OMP_CLAUSE_NUM_GANGS:
2041 case OMP_CLAUSE_NUM_WORKERS:
2042 case OMP_CLAUSE_VECTOR_LENGTH:
2043 if (ctx->outer)
2044 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2045 break;
2047 case OMP_CLAUSE_TO:
2048 case OMP_CLAUSE_FROM:
2049 case OMP_CLAUSE_MAP:
2050 if (ctx->outer)
2051 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2052 decl = OMP_CLAUSE_DECL (c);
2053 /* Global variables with "omp declare target" attribute
2054 don't need to be copied, the receiver side will use them
2055 directly. However, global variables with "omp declare target link"
2056 attribute need to be copied. */
2057 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2058 && DECL_P (decl)
2059 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2060 && (OMP_CLAUSE_MAP_KIND (c)
2061 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2062 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2063 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2064 && varpool_node::get_create (decl)->offloadable
2065 && !lookup_attribute ("omp declare target link",
2066 DECL_ATTRIBUTES (decl)))
2067 break;
2068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2069 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2071 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2072 not offloaded; there is nothing to map for those. */
2073 if (!is_gimple_omp_offloaded (ctx->stmt)
2074 && !POINTER_TYPE_P (TREE_TYPE (decl))
2075 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2076 break;
2078 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2079 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2080 || (OMP_CLAUSE_MAP_KIND (c)
2081 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2083 if (TREE_CODE (decl) == COMPONENT_REF
2084 || (TREE_CODE (decl) == INDIRECT_REF
2085 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2086 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2087 == REFERENCE_TYPE)))
2088 break;
2089 if (DECL_SIZE (decl)
2090 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2092 tree decl2 = DECL_VALUE_EXPR (decl);
2093 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2094 decl2 = TREE_OPERAND (decl2, 0);
2095 gcc_assert (DECL_P (decl2));
2096 install_var_local (decl2, ctx);
2098 install_var_local (decl, ctx);
2099 break;
2101 if (DECL_P (decl))
2103 if (DECL_SIZE (decl)
2104 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2106 tree decl2 = DECL_VALUE_EXPR (decl);
2107 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2108 decl2 = TREE_OPERAND (decl2, 0);
2109 gcc_assert (DECL_P (decl2));
2110 install_var_field (decl2, true, 3, ctx);
2111 install_var_local (decl2, ctx);
2112 install_var_local (decl, ctx);
2114 else
2116 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2117 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2118 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2119 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2120 install_var_field (decl, true, 7, ctx);
2121 else
2122 install_var_field (decl, true, 3, ctx,
2123 base_pointers_restrict);
2124 if (is_gimple_omp_offloaded (ctx->stmt))
2125 install_var_local (decl, ctx);
2128 else
2130 tree base = get_base_address (decl);
2131 tree nc = OMP_CLAUSE_CHAIN (c);
2132 if (DECL_P (base)
2133 && nc != NULL_TREE
2134 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2135 && OMP_CLAUSE_DECL (nc) == base
2136 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2137 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2139 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2140 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2142 else
2144 if (ctx->outer)
2146 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2147 decl = OMP_CLAUSE_DECL (c);
2149 gcc_assert (!splay_tree_lookup (ctx->field_map,
2150 (splay_tree_key) decl));
2151 tree field
2152 = build_decl (OMP_CLAUSE_LOCATION (c),
2153 FIELD_DECL, NULL_TREE, ptr_type_node);
2154 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2155 insert_field_into_struct (ctx->record_type, field);
2156 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2157 (splay_tree_value) field);
2160 break;
2162 case OMP_CLAUSE__GRIDDIM_:
2163 if (ctx->outer)
2165 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2166 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2168 break;
2170 case OMP_CLAUSE_NOWAIT:
2171 case OMP_CLAUSE_ORDERED:
2172 case OMP_CLAUSE_COLLAPSE:
2173 case OMP_CLAUSE_UNTIED:
2174 case OMP_CLAUSE_MERGEABLE:
2175 case OMP_CLAUSE_PROC_BIND:
2176 case OMP_CLAUSE_SAFELEN:
2177 case OMP_CLAUSE_SIMDLEN:
2178 case OMP_CLAUSE_THREADS:
2179 case OMP_CLAUSE_SIMD:
2180 case OMP_CLAUSE_NOGROUP:
2181 case OMP_CLAUSE_DEFAULTMAP:
2182 case OMP_CLAUSE_ASYNC:
2183 case OMP_CLAUSE_WAIT:
2184 case OMP_CLAUSE_GANG:
2185 case OMP_CLAUSE_WORKER:
2186 case OMP_CLAUSE_VECTOR:
2187 case OMP_CLAUSE_TILE:
2188 case OMP_CLAUSE_INDEPENDENT:
2189 case OMP_CLAUSE_AUTO:
2190 case OMP_CLAUSE_SEQ:
2191 break;
2193 case OMP_CLAUSE_ALIGNED:
2194 decl = OMP_CLAUSE_DECL (c);
2195 if (is_global_var (decl)
2196 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2197 install_var_local (decl, ctx);
2198 break;
2200 case OMP_CLAUSE_DEVICE_RESIDENT:
2201 case OMP_CLAUSE__CACHE_:
2202 sorry ("Clause not supported yet");
2203 break;
2205 default:
2206 gcc_unreachable ();
2210 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2212 switch (OMP_CLAUSE_CODE (c))
2214 case OMP_CLAUSE_LASTPRIVATE:
2215 /* Let the corresponding firstprivate clause create
2216 the variable. */
2217 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2218 scan_array_reductions = true;
2219 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2220 break;
2221 /* FALLTHRU */
2223 case OMP_CLAUSE_FIRSTPRIVATE:
2224 case OMP_CLAUSE_PRIVATE:
2225 case OMP_CLAUSE_LINEAR:
2226 case OMP_CLAUSE_IS_DEVICE_PTR:
2227 decl = OMP_CLAUSE_DECL (c);
2228 if (is_variable_sized (decl))
2230 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2231 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2232 && is_gimple_omp_offloaded (ctx->stmt))
2234 tree decl2 = DECL_VALUE_EXPR (decl);
2235 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2236 decl2 = TREE_OPERAND (decl2, 0);
2237 gcc_assert (DECL_P (decl2));
2238 install_var_local (decl2, ctx);
2239 fixup_remapped_decl (decl2, ctx, false);
2241 install_var_local (decl, ctx);
2243 fixup_remapped_decl (decl, ctx,
2244 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2245 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2246 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2247 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2248 scan_array_reductions = true;
2249 break;
2251 case OMP_CLAUSE_REDUCTION:
2252 decl = OMP_CLAUSE_DECL (c);
2253 if (TREE_CODE (decl) != MEM_REF)
2255 if (is_variable_sized (decl))
2256 install_var_local (decl, ctx);
2257 fixup_remapped_decl (decl, ctx, false);
2259 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2260 scan_array_reductions = true;
2261 break;
2263 case OMP_CLAUSE_SHARED:
2264 /* Ignore shared directives in teams construct. */
2265 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2266 break;
2267 decl = OMP_CLAUSE_DECL (c);
2268 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2269 break;
2270 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2272 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2273 ctx->outer)))
2274 break;
2275 bool by_ref = use_pointer_for_field (decl, ctx);
2276 install_var_field (decl, by_ref, 11, ctx);
2277 break;
2279 fixup_remapped_decl (decl, ctx, false);
2280 break;
2282 case OMP_CLAUSE_MAP:
2283 if (!is_gimple_omp_offloaded (ctx->stmt))
2284 break;
2285 decl = OMP_CLAUSE_DECL (c);
2286 if (DECL_P (decl)
2287 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2288 && (OMP_CLAUSE_MAP_KIND (c)
2289 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2290 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2291 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2292 && varpool_node::get_create (decl)->offloadable)
2293 break;
2294 if (DECL_P (decl))
2296 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2297 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2298 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2299 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2301 tree new_decl = lookup_decl (decl, ctx);
2302 TREE_TYPE (new_decl)
2303 = remap_type (TREE_TYPE (decl), &ctx->cb);
2305 else if (DECL_SIZE (decl)
2306 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2308 tree decl2 = DECL_VALUE_EXPR (decl);
2309 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2310 decl2 = TREE_OPERAND (decl2, 0);
2311 gcc_assert (DECL_P (decl2));
2312 fixup_remapped_decl (decl2, ctx, false);
2313 fixup_remapped_decl (decl, ctx, true);
2315 else
2316 fixup_remapped_decl (decl, ctx, false);
2318 break;
2320 case OMP_CLAUSE_COPYPRIVATE:
2321 case OMP_CLAUSE_COPYIN:
2322 case OMP_CLAUSE_DEFAULT:
2323 case OMP_CLAUSE_IF:
2324 case OMP_CLAUSE_NUM_THREADS:
2325 case OMP_CLAUSE_NUM_TEAMS:
2326 case OMP_CLAUSE_THREAD_LIMIT:
2327 case OMP_CLAUSE_DEVICE:
2328 case OMP_CLAUSE_SCHEDULE:
2329 case OMP_CLAUSE_DIST_SCHEDULE:
2330 case OMP_CLAUSE_NOWAIT:
2331 case OMP_CLAUSE_ORDERED:
2332 case OMP_CLAUSE_COLLAPSE:
2333 case OMP_CLAUSE_UNTIED:
2334 case OMP_CLAUSE_FINAL:
2335 case OMP_CLAUSE_MERGEABLE:
2336 case OMP_CLAUSE_PROC_BIND:
2337 case OMP_CLAUSE_SAFELEN:
2338 case OMP_CLAUSE_SIMDLEN:
2339 case OMP_CLAUSE_ALIGNED:
2340 case OMP_CLAUSE_DEPEND:
2341 case OMP_CLAUSE__LOOPTEMP_:
2342 case OMP_CLAUSE_TO:
2343 case OMP_CLAUSE_FROM:
2344 case OMP_CLAUSE_PRIORITY:
2345 case OMP_CLAUSE_GRAINSIZE:
2346 case OMP_CLAUSE_NUM_TASKS:
2347 case OMP_CLAUSE_THREADS:
2348 case OMP_CLAUSE_SIMD:
2349 case OMP_CLAUSE_NOGROUP:
2350 case OMP_CLAUSE_DEFAULTMAP:
2351 case OMP_CLAUSE_USE_DEVICE_PTR:
2352 case OMP_CLAUSE__CILK_FOR_COUNT_:
2353 case OMP_CLAUSE_ASYNC:
2354 case OMP_CLAUSE_WAIT:
2355 case OMP_CLAUSE_NUM_GANGS:
2356 case OMP_CLAUSE_NUM_WORKERS:
2357 case OMP_CLAUSE_VECTOR_LENGTH:
2358 case OMP_CLAUSE_GANG:
2359 case OMP_CLAUSE_WORKER:
2360 case OMP_CLAUSE_VECTOR:
2361 case OMP_CLAUSE_TILE:
2362 case OMP_CLAUSE_INDEPENDENT:
2363 case OMP_CLAUSE_AUTO:
2364 case OMP_CLAUSE_SEQ:
2365 case OMP_CLAUSE__GRIDDIM_:
2366 break;
2368 case OMP_CLAUSE_DEVICE_RESIDENT:
2369 case OMP_CLAUSE__CACHE_:
2370 sorry ("Clause not supported yet");
2371 break;
2373 default:
2374 gcc_unreachable ();
2378 gcc_checking_assert (!scan_array_reductions
2379 || !is_gimple_omp_oacc (ctx->stmt));
2380 if (scan_array_reductions)
2381 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2383 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2385 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2386 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2388 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2389 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2390 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2391 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2392 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2393 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2396 /* Create a new name for omp child function. Returns an identifier. If
2397 IS_CILK_FOR is true then the suffix for the child function is
2398 "_cilk_for_fn." */
2400 static tree
2401 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2403 if (is_cilk_for)
2404 return clone_function_name (current_function_decl, "_cilk_for_fn");
2405 return clone_function_name (current_function_decl,
2406 task_copy ? "_omp_cpyfn" : "_omp_fn");
2409 /* Returns the type of the induction variable for the child function for
2410 _Cilk_for and the types for _high and _low variables based on TYPE. */
2412 static tree
2413 cilk_for_check_loop_diff_type (tree type)
2415 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2417 if (TYPE_UNSIGNED (type))
2418 return uint32_type_node;
2419 else
2420 return integer_type_node;
2422 else
2424 if (TYPE_UNSIGNED (type))
2425 return uint64_type_node;
2426 else
2427 return long_long_integer_type_node;
2431 /* Build a decl for the omp child function. It'll not contain a body
2432 yet, just the bare decl. */
2434 static void
2435 create_omp_child_function (omp_context *ctx, bool task_copy)
2437 tree decl, type, name, t;
2439 tree cilk_for_count
2440 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2441 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2442 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2443 tree cilk_var_type = NULL_TREE;
2445 name = create_omp_child_function_name (task_copy,
2446 cilk_for_count != NULL_TREE);
2447 if (task_copy)
2448 type = build_function_type_list (void_type_node, ptr_type_node,
2449 ptr_type_node, NULL_TREE);
2450 else if (cilk_for_count)
2452 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2453 cilk_var_type = cilk_for_check_loop_diff_type (type);
2454 type = build_function_type_list (void_type_node, ptr_type_node,
2455 cilk_var_type, cilk_var_type, NULL_TREE);
2457 else
2458 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2460 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2462 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2463 || !task_copy);
2464 if (!task_copy)
2465 ctx->cb.dst_fn = decl;
2466 else
2467 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2469 TREE_STATIC (decl) = 1;
2470 TREE_USED (decl) = 1;
2471 DECL_ARTIFICIAL (decl) = 1;
2472 DECL_IGNORED_P (decl) = 0;
2473 TREE_PUBLIC (decl) = 0;
2474 DECL_UNINLINABLE (decl) = 1;
2475 DECL_EXTERNAL (decl) = 0;
2476 DECL_CONTEXT (decl) = NULL_TREE;
2477 DECL_INITIAL (decl) = make_node (BLOCK);
2478 if (cgraph_node::get (current_function_decl)->offloadable)
2479 cgraph_node::get_create (decl)->offloadable = 1;
2480 else
2482 omp_context *octx;
2483 for (octx = ctx; octx; octx = octx->outer)
2484 if (is_gimple_omp_offloaded (octx->stmt))
2486 cgraph_node::get_create (decl)->offloadable = 1;
2487 if (ENABLE_OFFLOADING)
2488 g->have_offload = true;
2490 break;
2494 if (cgraph_node::get_create (decl)->offloadable
2495 && !lookup_attribute ("omp declare target",
2496 DECL_ATTRIBUTES (current_function_decl)))
2497 DECL_ATTRIBUTES (decl)
2498 = tree_cons (get_identifier ("omp target entrypoint"),
2499 NULL_TREE, DECL_ATTRIBUTES (decl));
2501 t = build_decl (DECL_SOURCE_LOCATION (decl),
2502 RESULT_DECL, NULL_TREE, void_type_node);
2503 DECL_ARTIFICIAL (t) = 1;
2504 DECL_IGNORED_P (t) = 1;
2505 DECL_CONTEXT (t) = decl;
2506 DECL_RESULT (decl) = t;
2508 /* _Cilk_for's child function requires two extra parameters called
2509 __low and __high that are set the by Cilk runtime when it calls this
2510 function. */
2511 if (cilk_for_count)
2513 t = build_decl (DECL_SOURCE_LOCATION (decl),
2514 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2515 DECL_ARTIFICIAL (t) = 1;
2516 DECL_NAMELESS (t) = 1;
2517 DECL_ARG_TYPE (t) = ptr_type_node;
2518 DECL_CONTEXT (t) = current_function_decl;
2519 TREE_USED (t) = 1;
2520 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2521 DECL_ARGUMENTS (decl) = t;
2523 t = build_decl (DECL_SOURCE_LOCATION (decl),
2524 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2525 DECL_ARTIFICIAL (t) = 1;
2526 DECL_NAMELESS (t) = 1;
2527 DECL_ARG_TYPE (t) = ptr_type_node;
2528 DECL_CONTEXT (t) = current_function_decl;
2529 TREE_USED (t) = 1;
2530 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2531 DECL_ARGUMENTS (decl) = t;
2534 tree data_name = get_identifier (".omp_data_i");
2535 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2536 ptr_type_node);
2537 DECL_ARTIFICIAL (t) = 1;
2538 DECL_NAMELESS (t) = 1;
2539 DECL_ARG_TYPE (t) = ptr_type_node;
2540 DECL_CONTEXT (t) = current_function_decl;
2541 TREE_USED (t) = 1;
2542 TREE_READONLY (t) = 1;
2543 if (cilk_for_count)
2544 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2545 DECL_ARGUMENTS (decl) = t;
2546 if (!task_copy)
2547 ctx->receiver_decl = t;
2548 else
2550 t = build_decl (DECL_SOURCE_LOCATION (decl),
2551 PARM_DECL, get_identifier (".omp_data_o"),
2552 ptr_type_node);
2553 DECL_ARTIFICIAL (t) = 1;
2554 DECL_NAMELESS (t) = 1;
2555 DECL_ARG_TYPE (t) = ptr_type_node;
2556 DECL_CONTEXT (t) = current_function_decl;
2557 TREE_USED (t) = 1;
2558 TREE_ADDRESSABLE (t) = 1;
2559 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2560 DECL_ARGUMENTS (decl) = t;
2563 /* Allocate memory for the function structure. The call to
2564 allocate_struct_function clobbers CFUN, so we need to restore
2565 it afterward. */
2566 push_struct_function (decl);
2567 cfun->function_end_locus = gimple_location (ctx->stmt);
2568 pop_cfun ();
2571 /* Callback for walk_gimple_seq. Check if combined parallel
2572 contains gimple_omp_for_combined_into_p OMP_FOR. */
2574 static tree
2575 find_combined_for (gimple_stmt_iterator *gsi_p,
2576 bool *handled_ops_p,
2577 struct walk_stmt_info *wi)
2579 gimple *stmt = gsi_stmt (*gsi_p);
2581 *handled_ops_p = true;
2582 switch (gimple_code (stmt))
2584 WALK_SUBSTMTS;
2586 case GIMPLE_OMP_FOR:
2587 if (gimple_omp_for_combined_into_p (stmt)
2588 && gimple_omp_for_kind (stmt)
2589 == *(const enum gf_mask *) (wi->info))
2591 wi->info = stmt;
2592 return integer_zero_node;
2594 break;
2595 default:
2596 break;
2598 return NULL;
2601 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2603 static void
2604 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2605 omp_context *outer_ctx)
2607 struct walk_stmt_info wi;
2609 memset (&wi, 0, sizeof (wi));
2610 wi.val_only = true;
2611 wi.info = (void *) &msk;
2612 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2613 if (wi.info != (void *) &msk)
2615 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2616 struct omp_for_data fd;
2617 extract_omp_for_data (for_stmt, &fd, NULL);
2618 /* We need two temporaries with fd.loop.v type (istart/iend)
2619 and then (fd.collapse - 1) temporaries with the same
2620 type for count2 ... countN-1 vars if not constant. */
2621 size_t count = 2, i;
2622 tree type = fd.iter_type;
2623 if (fd.collapse > 1
2624 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2626 count += fd.collapse - 1;
2627 /* If there are lastprivate clauses on the inner
2628 GIMPLE_OMP_FOR, add one more temporaries for the total number
2629 of iterations (product of count1 ... countN-1). */
2630 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2631 OMP_CLAUSE_LASTPRIVATE))
2632 count++;
2633 else if (msk == GF_OMP_FOR_KIND_FOR
2634 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2635 OMP_CLAUSE_LASTPRIVATE))
2636 count++;
2638 for (i = 0; i < count; i++)
2640 tree temp = create_tmp_var (type);
2641 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2642 insert_decl_map (&outer_ctx->cb, temp, temp);
2643 OMP_CLAUSE_DECL (c) = temp;
2644 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2645 gimple_omp_taskreg_set_clauses (stmt, c);
2650 /* Scan an OpenMP parallel directive. */
2652 static void
2653 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2655 omp_context *ctx;
2656 tree name;
2657 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2659 /* Ignore parallel directives with empty bodies, unless there
2660 are copyin clauses. */
2661 if (optimize > 0
2662 && empty_body_p (gimple_omp_body (stmt))
2663 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2664 OMP_CLAUSE_COPYIN) == NULL)
2666 gsi_replace (gsi, gimple_build_nop (), false);
2667 return;
2670 if (gimple_omp_parallel_combined_p (stmt))
2671 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2673 ctx = new_omp_context (stmt, outer_ctx);
2674 taskreg_contexts.safe_push (ctx);
2675 if (taskreg_nesting_level > 1)
2676 ctx->is_nested = true;
2677 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2678 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2679 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2680 name = create_tmp_var_name (".omp_data_s");
2681 name = build_decl (gimple_location (stmt),
2682 TYPE_DECL, name, ctx->record_type);
2683 DECL_ARTIFICIAL (name) = 1;
2684 DECL_NAMELESS (name) = 1;
2685 TYPE_NAME (ctx->record_type) = name;
2686 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2687 if (!gimple_omp_parallel_grid_phony (stmt))
2689 create_omp_child_function (ctx, false);
2690 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2693 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2694 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2696 if (TYPE_FIELDS (ctx->record_type) == NULL)
2697 ctx->record_type = ctx->receiver_decl = NULL;
2700 /* Scan an OpenMP task directive. */
2702 static void
2703 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2705 omp_context *ctx;
2706 tree name, t;
2707 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2709 /* Ignore task directives with empty bodies. */
2710 if (optimize > 0
2711 && empty_body_p (gimple_omp_body (stmt)))
2713 gsi_replace (gsi, gimple_build_nop (), false);
2714 return;
2717 if (gimple_omp_task_taskloop_p (stmt))
2718 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2720 ctx = new_omp_context (stmt, outer_ctx);
2721 taskreg_contexts.safe_push (ctx);
2722 if (taskreg_nesting_level > 1)
2723 ctx->is_nested = true;
2724 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2725 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2726 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2727 name = create_tmp_var_name (".omp_data_s");
2728 name = build_decl (gimple_location (stmt),
2729 TYPE_DECL, name, ctx->record_type);
2730 DECL_ARTIFICIAL (name) = 1;
2731 DECL_NAMELESS (name) = 1;
2732 TYPE_NAME (ctx->record_type) = name;
2733 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2734 create_omp_child_function (ctx, false);
2735 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2737 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2739 if (ctx->srecord_type)
2741 name = create_tmp_var_name (".omp_data_a");
2742 name = build_decl (gimple_location (stmt),
2743 TYPE_DECL, name, ctx->srecord_type);
2744 DECL_ARTIFICIAL (name) = 1;
2745 DECL_NAMELESS (name) = 1;
2746 TYPE_NAME (ctx->srecord_type) = name;
2747 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2748 create_omp_child_function (ctx, true);
2751 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2753 if (TYPE_FIELDS (ctx->record_type) == NULL)
2755 ctx->record_type = ctx->receiver_decl = NULL;
2756 t = build_int_cst (long_integer_type_node, 0);
2757 gimple_omp_task_set_arg_size (stmt, t);
2758 t = build_int_cst (long_integer_type_node, 1);
2759 gimple_omp_task_set_arg_align (stmt, t);
2764 /* If any decls have been made addressable during scan_omp,
2765 adjust their fields if needed, and layout record types
2766 of parallel/task constructs. */
2768 static void
2769 finish_taskreg_scan (omp_context *ctx)
2771 if (ctx->record_type == NULL_TREE)
2772 return;
2774 /* If any task_shared_vars were needed, verify all
2775 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2776 statements if use_pointer_for_field hasn't changed
2777 because of that. If it did, update field types now. */
2778 if (task_shared_vars)
2780 tree c;
2782 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2783 c; c = OMP_CLAUSE_CHAIN (c))
2784 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2785 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2787 tree decl = OMP_CLAUSE_DECL (c);
2789 /* Global variables don't need to be copied,
2790 the receiver side will use them directly. */
2791 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2792 continue;
2793 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2794 || !use_pointer_for_field (decl, ctx))
2795 continue;
2796 tree field = lookup_field (decl, ctx);
2797 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2798 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2799 continue;
2800 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2801 TREE_THIS_VOLATILE (field) = 0;
2802 DECL_USER_ALIGN (field) = 0;
2803 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2804 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2805 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2806 if (ctx->srecord_type)
2808 tree sfield = lookup_sfield (decl, ctx);
2809 TREE_TYPE (sfield) = TREE_TYPE (field);
2810 TREE_THIS_VOLATILE (sfield) = 0;
2811 DECL_USER_ALIGN (sfield) = 0;
2812 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2813 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2814 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2819 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2821 layout_type (ctx->record_type);
2822 fixup_child_record_type (ctx);
2824 else
2826 location_t loc = gimple_location (ctx->stmt);
2827 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2828 /* Move VLA fields to the end. */
2829 p = &TYPE_FIELDS (ctx->record_type);
2830 while (*p)
2831 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2832 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2834 *q = *p;
2835 *p = TREE_CHAIN (*p);
2836 TREE_CHAIN (*q) = NULL_TREE;
2837 q = &TREE_CHAIN (*q);
2839 else
2840 p = &DECL_CHAIN (*p);
2841 *p = vla_fields;
2842 if (gimple_omp_task_taskloop_p (ctx->stmt))
2844 /* Move fields corresponding to first and second _looptemp_
2845 clause first. There are filled by GOMP_taskloop
2846 and thus need to be in specific positions. */
2847 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2848 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2849 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2850 OMP_CLAUSE__LOOPTEMP_);
2851 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2852 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2853 p = &TYPE_FIELDS (ctx->record_type);
2854 while (*p)
2855 if (*p == f1 || *p == f2)
2856 *p = DECL_CHAIN (*p);
2857 else
2858 p = &DECL_CHAIN (*p);
2859 DECL_CHAIN (f1) = f2;
2860 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2861 TYPE_FIELDS (ctx->record_type) = f1;
2862 if (ctx->srecord_type)
2864 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2865 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2866 p = &TYPE_FIELDS (ctx->srecord_type);
2867 while (*p)
2868 if (*p == f1 || *p == f2)
2869 *p = DECL_CHAIN (*p);
2870 else
2871 p = &DECL_CHAIN (*p);
2872 DECL_CHAIN (f1) = f2;
2873 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2874 TYPE_FIELDS (ctx->srecord_type) = f1;
2877 layout_type (ctx->record_type);
2878 fixup_child_record_type (ctx);
2879 if (ctx->srecord_type)
2880 layout_type (ctx->srecord_type);
2881 tree t = fold_convert_loc (loc, long_integer_type_node,
2882 TYPE_SIZE_UNIT (ctx->record_type));
2883 gimple_omp_task_set_arg_size (ctx->stmt, t);
2884 t = build_int_cst (long_integer_type_node,
2885 TYPE_ALIGN_UNIT (ctx->record_type));
2886 gimple_omp_task_set_arg_align (ctx->stmt, t);
2890 /* Find the enclosing offload context. */
2892 static omp_context *
2893 enclosing_target_ctx (omp_context *ctx)
2895 for (; ctx; ctx = ctx->outer)
2896 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2897 break;
2899 return ctx;
2902 /* Return true if ctx is part of an oacc kernels region. */
2904 static bool
2905 ctx_in_oacc_kernels_region (omp_context *ctx)
2907 for (;ctx != NULL; ctx = ctx->outer)
2909 gimple *stmt = ctx->stmt;
2910 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2911 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2912 return true;
2915 return false;
2918 /* Check the parallelism clauses inside a kernels regions.
2919 Until kernels handling moves to use the same loop indirection
2920 scheme as parallel, we need to do this checking early. */
2922 static unsigned
2923 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2925 bool checking = true;
2926 unsigned outer_mask = 0;
2927 unsigned this_mask = 0;
2928 bool has_seq = false, has_auto = false;
2930 if (ctx->outer)
2931 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2932 if (!stmt)
2934 checking = false;
2935 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2936 return outer_mask;
2937 stmt = as_a <gomp_for *> (ctx->stmt);
2940 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2942 switch (OMP_CLAUSE_CODE (c))
2944 case OMP_CLAUSE_GANG:
2945 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2946 break;
2947 case OMP_CLAUSE_WORKER:
2948 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2949 break;
2950 case OMP_CLAUSE_VECTOR:
2951 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2952 break;
2953 case OMP_CLAUSE_SEQ:
2954 has_seq = true;
2955 break;
2956 case OMP_CLAUSE_AUTO:
2957 has_auto = true;
2958 break;
2959 default:
2960 break;
2964 if (checking)
2966 if (has_seq && (this_mask || has_auto))
2967 error_at (gimple_location (stmt), "%<seq%> overrides other"
2968 " OpenACC loop specifiers");
2969 else if (has_auto && this_mask)
2970 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2971 " OpenACC loop specifiers");
2973 if (this_mask & outer_mask)
2974 error_at (gimple_location (stmt), "inner loop uses same"
2975 " OpenACC parallelism as containing loop");
2978 return outer_mask | this_mask;
2981 /* Scan a GIMPLE_OMP_FOR. */
2983 static void
2984 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2986 omp_context *ctx;
2987 size_t i;
2988 tree clauses = gimple_omp_for_clauses (stmt);
2990 ctx = new_omp_context (stmt, outer_ctx);
2992 if (is_gimple_omp_oacc (stmt))
2994 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2996 if (!tgt || is_oacc_parallel (tgt))
2997 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2999 char const *check = NULL;
3001 switch (OMP_CLAUSE_CODE (c))
3003 case OMP_CLAUSE_GANG:
3004 check = "gang";
3005 break;
3007 case OMP_CLAUSE_WORKER:
3008 check = "worker";
3009 break;
3011 case OMP_CLAUSE_VECTOR:
3012 check = "vector";
3013 break;
3015 default:
3016 break;
3019 if (check && OMP_CLAUSE_OPERAND (c, 0))
3020 error_at (gimple_location (stmt),
3021 "argument not permitted on %qs clause in"
3022 " OpenACC %<parallel%>", check);
3025 if (tgt && is_oacc_kernels (tgt))
3027 /* Strip out reductions, as they are not handled yet. */
3028 tree *prev_ptr = &clauses;
3030 while (tree probe = *prev_ptr)
3032 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3034 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3035 *prev_ptr = *next_ptr;
3036 else
3037 prev_ptr = next_ptr;
3040 gimple_omp_for_set_clauses (stmt, clauses);
3041 check_oacc_kernel_gwv (stmt, ctx);
3045 scan_sharing_clauses (clauses, ctx);
3047 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3048 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3050 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3053 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3055 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3058 /* Scan an OpenMP sections directive. */
3060 static void
3061 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3063 omp_context *ctx;
3065 ctx = new_omp_context (stmt, outer_ctx);
3066 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3067 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3070 /* Scan an OpenMP single directive. */
3072 static void
3073 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3075 omp_context *ctx;
3076 tree name;
3078 ctx = new_omp_context (stmt, outer_ctx);
3079 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3080 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3081 name = create_tmp_var_name (".omp_copy_s");
3082 name = build_decl (gimple_location (stmt),
3083 TYPE_DECL, name, ctx->record_type);
3084 TYPE_NAME (ctx->record_type) = name;
3086 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3087 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3089 if (TYPE_FIELDS (ctx->record_type) == NULL)
3090 ctx->record_type = NULL;
3091 else
3092 layout_type (ctx->record_type);
3095 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3096 used in the corresponding offloaded function are restrict. */
3098 static bool
3099 omp_target_base_pointers_restrict_p (tree clauses)
3101 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3102 used by OpenACC. */
3103 if (flag_openacc == 0)
3104 return false;
3106 /* I. Basic example:
3108 void foo (void)
3110 unsigned int a[2], b[2];
3112 #pragma acc kernels \
3113 copyout (a) \
3114 copyout (b)
3116 a[0] = 0;
3117 b[0] = 1;
3121 After gimplification, we have:
3123 #pragma omp target oacc_kernels \
3124 map(force_from:a [len: 8]) \
3125 map(force_from:b [len: 8])
3127 a[0] = 0;
3128 b[0] = 1;
3131 Because both mappings have the force prefix, we know that they will be
3132 allocated when calling the corresponding offloaded function, which means we
3133 can mark the base pointers for a and b in the offloaded function as
3134 restrict. */
3136 tree c;
3137 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3139 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3140 return false;
3142 switch (OMP_CLAUSE_MAP_KIND (c))
3144 case GOMP_MAP_FORCE_ALLOC:
3145 case GOMP_MAP_FORCE_TO:
3146 case GOMP_MAP_FORCE_FROM:
3147 case GOMP_MAP_FORCE_TOFROM:
3148 break;
3149 default:
3150 return false;
3154 return true;
3157 /* Scan a GIMPLE_OMP_TARGET. */
3159 static void
3160 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3162 omp_context *ctx;
3163 tree name;
3164 bool offloaded = is_gimple_omp_offloaded (stmt);
3165 tree clauses = gimple_omp_target_clauses (stmt);
3167 ctx = new_omp_context (stmt, outer_ctx);
3168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3171 name = create_tmp_var_name (".omp_data_t");
3172 name = build_decl (gimple_location (stmt),
3173 TYPE_DECL, name, ctx->record_type);
3174 DECL_ARTIFICIAL (name) = 1;
3175 DECL_NAMELESS (name) = 1;
3176 TYPE_NAME (ctx->record_type) = name;
3177 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3179 bool base_pointers_restrict = false;
3180 if (offloaded)
3182 create_omp_child_function (ctx, false);
3183 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3185 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3186 if (base_pointers_restrict
3187 && dump_file && (dump_flags & TDF_DETAILS))
3188 fprintf (dump_file,
3189 "Base pointers in offloaded function are restrict\n");
3192 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3195 if (TYPE_FIELDS (ctx->record_type) == NULL)
3196 ctx->record_type = ctx->receiver_decl = NULL;
3197 else
3199 TYPE_FIELDS (ctx->record_type)
3200 = nreverse (TYPE_FIELDS (ctx->record_type));
3201 if (flag_checking)
3203 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3204 for (tree field = TYPE_FIELDS (ctx->record_type);
3205 field;
3206 field = DECL_CHAIN (field))
3207 gcc_assert (DECL_ALIGN (field) == align);
3209 layout_type (ctx->record_type);
3210 if (offloaded)
3211 fixup_child_record_type (ctx);
3215 /* Scan an OpenMP teams directive. */
3217 static void
3218 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3220 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3221 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3222 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3225 /* Check nesting restrictions. */
3226 static bool
3227 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3229 tree c;
3231 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3232 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3233 the original copy of its contents. */
3234 return true;
3236 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3237 inside an OpenACC CTX. */
3238 if (!(is_gimple_omp (stmt)
3239 && is_gimple_omp_oacc (stmt))
3240 /* Except for atomic codes that we share with OpenMP. */
3241 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3242 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3244 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3246 error_at (gimple_location (stmt),
3247 "non-OpenACC construct inside of OpenACC routine");
3248 return false;
3250 else
3251 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3252 if (is_gimple_omp (octx->stmt)
3253 && is_gimple_omp_oacc (octx->stmt))
3255 error_at (gimple_location (stmt),
3256 "non-OpenACC construct inside of OpenACC region");
3257 return false;
3261 if (ctx != NULL)
3263 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3264 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3266 c = NULL_TREE;
3267 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3269 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3270 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3272 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3273 && (ctx->outer == NULL
3274 || !gimple_omp_for_combined_into_p (ctx->stmt)
3275 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3276 || (gimple_omp_for_kind (ctx->outer->stmt)
3277 != GF_OMP_FOR_KIND_FOR)
3278 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3280 error_at (gimple_location (stmt),
3281 "%<ordered simd threads%> must be closely "
3282 "nested inside of %<for simd%> region");
3283 return false;
3285 return true;
3288 error_at (gimple_location (stmt),
3289 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3290 " may not be nested inside %<simd%> region");
3291 return false;
3293 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3295 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3296 || (gimple_omp_for_kind (stmt)
3297 != GF_OMP_FOR_KIND_DISTRIBUTE))
3298 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3300 error_at (gimple_location (stmt),
3301 "only %<distribute%> or %<parallel%> regions are "
3302 "allowed to be strictly nested inside %<teams%> "
3303 "region");
3304 return false;
3308 switch (gimple_code (stmt))
3310 case GIMPLE_OMP_FOR:
3311 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3312 return true;
3313 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3315 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3317 error_at (gimple_location (stmt),
3318 "%<distribute%> region must be strictly nested "
3319 "inside %<teams%> construct");
3320 return false;
3322 return true;
3324 /* We split taskloop into task and nested taskloop in it. */
3325 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3326 return true;
3327 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3329 bool ok = false;
3331 if (ctx)
3332 switch (gimple_code (ctx->stmt))
3334 case GIMPLE_OMP_FOR:
3335 ok = (gimple_omp_for_kind (ctx->stmt)
3336 == GF_OMP_FOR_KIND_OACC_LOOP);
3337 break;
3339 case GIMPLE_OMP_TARGET:
3340 switch (gimple_omp_target_kind (ctx->stmt))
3342 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3343 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3344 ok = true;
3345 break;
3347 default:
3348 break;
3351 default:
3352 break;
3354 else if (get_oacc_fn_attrib (current_function_decl))
3355 ok = true;
3356 if (!ok)
3358 error_at (gimple_location (stmt),
3359 "OpenACC loop directive must be associated with"
3360 " an OpenACC compute region");
3361 return false;
3364 /* FALLTHRU */
3365 case GIMPLE_CALL:
3366 if (is_gimple_call (stmt)
3367 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3368 == BUILT_IN_GOMP_CANCEL
3369 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3370 == BUILT_IN_GOMP_CANCELLATION_POINT))
3372 const char *bad = NULL;
3373 const char *kind = NULL;
3374 const char *construct
3375 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376 == BUILT_IN_GOMP_CANCEL)
3377 ? "#pragma omp cancel"
3378 : "#pragma omp cancellation point";
3379 if (ctx == NULL)
3381 error_at (gimple_location (stmt), "orphaned %qs construct",
3382 construct);
3383 return false;
3385 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3386 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3387 : 0)
3389 case 1:
3390 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3391 bad = "#pragma omp parallel";
3392 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3393 == BUILT_IN_GOMP_CANCEL
3394 && !integer_zerop (gimple_call_arg (stmt, 1)))
3395 ctx->cancellable = true;
3396 kind = "parallel";
3397 break;
3398 case 2:
3399 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3400 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3401 bad = "#pragma omp for";
3402 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3403 == BUILT_IN_GOMP_CANCEL
3404 && !integer_zerop (gimple_call_arg (stmt, 1)))
3406 ctx->cancellable = true;
3407 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3408 OMP_CLAUSE_NOWAIT))
3409 warning_at (gimple_location (stmt), 0,
3410 "%<#pragma omp cancel for%> inside "
3411 "%<nowait%> for construct");
3412 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3413 OMP_CLAUSE_ORDERED))
3414 warning_at (gimple_location (stmt), 0,
3415 "%<#pragma omp cancel for%> inside "
3416 "%<ordered%> for construct");
3418 kind = "for";
3419 break;
3420 case 4:
3421 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3422 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3423 bad = "#pragma omp sections";
3424 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3425 == BUILT_IN_GOMP_CANCEL
3426 && !integer_zerop (gimple_call_arg (stmt, 1)))
3428 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3430 ctx->cancellable = true;
3431 if (find_omp_clause (gimple_omp_sections_clauses
3432 (ctx->stmt),
3433 OMP_CLAUSE_NOWAIT))
3434 warning_at (gimple_location (stmt), 0,
3435 "%<#pragma omp cancel sections%> inside "
3436 "%<nowait%> sections construct");
3438 else
3440 gcc_assert (ctx->outer
3441 && gimple_code (ctx->outer->stmt)
3442 == GIMPLE_OMP_SECTIONS);
3443 ctx->outer->cancellable = true;
3444 if (find_omp_clause (gimple_omp_sections_clauses
3445 (ctx->outer->stmt),
3446 OMP_CLAUSE_NOWAIT))
3447 warning_at (gimple_location (stmt), 0,
3448 "%<#pragma omp cancel sections%> inside "
3449 "%<nowait%> sections construct");
3452 kind = "sections";
3453 break;
3454 case 8:
3455 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3456 bad = "#pragma omp task";
3457 else
3459 for (omp_context *octx = ctx->outer;
3460 octx; octx = octx->outer)
3462 switch (gimple_code (octx->stmt))
3464 case GIMPLE_OMP_TASKGROUP:
3465 break;
3466 case GIMPLE_OMP_TARGET:
3467 if (gimple_omp_target_kind (octx->stmt)
3468 != GF_OMP_TARGET_KIND_REGION)
3469 continue;
3470 /* FALLTHRU */
3471 case GIMPLE_OMP_PARALLEL:
3472 case GIMPLE_OMP_TEAMS:
3473 error_at (gimple_location (stmt),
3474 "%<%s taskgroup%> construct not closely "
3475 "nested inside of %<taskgroup%> region",
3476 construct);
3477 return false;
3478 default:
3479 continue;
3481 break;
3483 ctx->cancellable = true;
3485 kind = "taskgroup";
3486 break;
3487 default:
3488 error_at (gimple_location (stmt), "invalid arguments");
3489 return false;
3491 if (bad)
3493 error_at (gimple_location (stmt),
3494 "%<%s %s%> construct not closely nested inside of %qs",
3495 construct, kind, bad);
3496 return false;
3499 /* FALLTHRU */
3500 case GIMPLE_OMP_SECTIONS:
3501 case GIMPLE_OMP_SINGLE:
3502 for (; ctx != NULL; ctx = ctx->outer)
3503 switch (gimple_code (ctx->stmt))
3505 case GIMPLE_OMP_FOR:
3506 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3507 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3508 break;
3509 /* FALLTHRU */
3510 case GIMPLE_OMP_SECTIONS:
3511 case GIMPLE_OMP_SINGLE:
3512 case GIMPLE_OMP_ORDERED:
3513 case GIMPLE_OMP_MASTER:
3514 case GIMPLE_OMP_TASK:
3515 case GIMPLE_OMP_CRITICAL:
3516 if (is_gimple_call (stmt))
3518 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3519 != BUILT_IN_GOMP_BARRIER)
3520 return true;
3521 error_at (gimple_location (stmt),
3522 "barrier region may not be closely nested inside "
3523 "of work-sharing, %<critical%>, %<ordered%>, "
3524 "%<master%>, explicit %<task%> or %<taskloop%> "
3525 "region");
3526 return false;
3528 error_at (gimple_location (stmt),
3529 "work-sharing region may not be closely nested inside "
3530 "of work-sharing, %<critical%>, %<ordered%>, "
3531 "%<master%>, explicit %<task%> or %<taskloop%> region");
3532 return false;
3533 case GIMPLE_OMP_PARALLEL:
3534 case GIMPLE_OMP_TEAMS:
3535 return true;
3536 case GIMPLE_OMP_TARGET:
3537 if (gimple_omp_target_kind (ctx->stmt)
3538 == GF_OMP_TARGET_KIND_REGION)
3539 return true;
3540 break;
3541 default:
3542 break;
3544 break;
3545 case GIMPLE_OMP_MASTER:
3546 for (; ctx != NULL; ctx = ctx->outer)
3547 switch (gimple_code (ctx->stmt))
3549 case GIMPLE_OMP_FOR:
3550 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3551 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3552 break;
3553 /* FALLTHRU */
3554 case GIMPLE_OMP_SECTIONS:
3555 case GIMPLE_OMP_SINGLE:
3556 case GIMPLE_OMP_TASK:
3557 error_at (gimple_location (stmt),
3558 "%<master%> region may not be closely nested inside "
3559 "of work-sharing, explicit %<task%> or %<taskloop%> "
3560 "region");
3561 return false;
3562 case GIMPLE_OMP_PARALLEL:
3563 case GIMPLE_OMP_TEAMS:
3564 return true;
3565 case GIMPLE_OMP_TARGET:
3566 if (gimple_omp_target_kind (ctx->stmt)
3567 == GF_OMP_TARGET_KIND_REGION)
3568 return true;
3569 break;
3570 default:
3571 break;
3573 break;
3574 case GIMPLE_OMP_TASK:
3575 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3576 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3577 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3578 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3580 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3581 error_at (OMP_CLAUSE_LOCATION (c),
3582 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3583 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3584 return false;
3586 break;
3587 case GIMPLE_OMP_ORDERED:
3588 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3589 c; c = OMP_CLAUSE_CHAIN (c))
3591 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3593 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3594 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3595 continue;
3597 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3598 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3599 || kind == OMP_CLAUSE_DEPEND_SINK)
3601 tree oclause;
3602 /* Look for containing ordered(N) loop. */
3603 if (ctx == NULL
3604 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3605 || (oclause
3606 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3607 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3609 error_at (OMP_CLAUSE_LOCATION (c),
3610 "%<ordered%> construct with %<depend%> clause "
3611 "must be closely nested inside an %<ordered%> "
3612 "loop");
3613 return false;
3615 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3617 error_at (OMP_CLAUSE_LOCATION (c),
3618 "%<ordered%> construct with %<depend%> clause "
3619 "must be closely nested inside a loop with "
3620 "%<ordered%> clause with a parameter");
3621 return false;
3624 else
3626 error_at (OMP_CLAUSE_LOCATION (c),
3627 "invalid depend kind in omp %<ordered%> %<depend%>");
3628 return false;
3631 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3632 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3634 /* ordered simd must be closely nested inside of simd region,
3635 and simd region must not encounter constructs other than
3636 ordered simd, therefore ordered simd may be either orphaned,
3637 or ctx->stmt must be simd. The latter case is handled already
3638 earlier. */
3639 if (ctx != NULL)
3641 error_at (gimple_location (stmt),
3642 "%<ordered%> %<simd%> must be closely nested inside "
3643 "%<simd%> region");
3644 return false;
3647 for (; ctx != NULL; ctx = ctx->outer)
3648 switch (gimple_code (ctx->stmt))
3650 case GIMPLE_OMP_CRITICAL:
3651 case GIMPLE_OMP_TASK:
3652 case GIMPLE_OMP_ORDERED:
3653 ordered_in_taskloop:
3654 error_at (gimple_location (stmt),
3655 "%<ordered%> region may not be closely nested inside "
3656 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3657 "%<taskloop%> region");
3658 return false;
3659 case GIMPLE_OMP_FOR:
3660 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3661 goto ordered_in_taskloop;
3662 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3663 OMP_CLAUSE_ORDERED) == NULL)
3665 error_at (gimple_location (stmt),
3666 "%<ordered%> region must be closely nested inside "
3667 "a loop region with an %<ordered%> clause");
3668 return false;
3670 return true;
3671 case GIMPLE_OMP_TARGET:
3672 if (gimple_omp_target_kind (ctx->stmt)
3673 != GF_OMP_TARGET_KIND_REGION)
3674 break;
3675 /* FALLTHRU */
3676 case GIMPLE_OMP_PARALLEL:
3677 case GIMPLE_OMP_TEAMS:
3678 error_at (gimple_location (stmt),
3679 "%<ordered%> region must be closely nested inside "
3680 "a loop region with an %<ordered%> clause");
3681 return false;
3682 default:
3683 break;
3685 break;
3686 case GIMPLE_OMP_CRITICAL:
3688 tree this_stmt_name
3689 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3690 for (; ctx != NULL; ctx = ctx->outer)
3691 if (gomp_critical *other_crit
3692 = dyn_cast <gomp_critical *> (ctx->stmt))
3693 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3695 error_at (gimple_location (stmt),
3696 "%<critical%> region may not be nested inside "
3697 "a %<critical%> region with the same name");
3698 return false;
3701 break;
3702 case GIMPLE_OMP_TEAMS:
3703 if (ctx == NULL
3704 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3705 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3707 error_at (gimple_location (stmt),
3708 "%<teams%> construct not closely nested inside of "
3709 "%<target%> construct");
3710 return false;
3712 break;
3713 case GIMPLE_OMP_TARGET:
3714 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3715 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3716 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3717 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3719 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3720 error_at (OMP_CLAUSE_LOCATION (c),
3721 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3722 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3723 return false;
3725 if (is_gimple_omp_offloaded (stmt)
3726 && get_oacc_fn_attrib (cfun->decl) != NULL)
3728 error_at (gimple_location (stmt),
3729 "OpenACC region inside of OpenACC routine, nested "
3730 "parallelism not supported yet");
3731 return false;
3733 for (; ctx != NULL; ctx = ctx->outer)
3735 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3737 if (is_gimple_omp (stmt)
3738 && is_gimple_omp_oacc (stmt)
3739 && is_gimple_omp (ctx->stmt))
3741 error_at (gimple_location (stmt),
3742 "OpenACC construct inside of non-OpenACC region");
3743 return false;
3745 continue;
3748 const char *stmt_name, *ctx_stmt_name;
3749 switch (gimple_omp_target_kind (stmt))
3751 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3752 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3753 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3754 case GF_OMP_TARGET_KIND_ENTER_DATA:
3755 stmt_name = "target enter data"; break;
3756 case GF_OMP_TARGET_KIND_EXIT_DATA:
3757 stmt_name = "target exit data"; break;
3758 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3759 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3760 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3761 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3762 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3763 stmt_name = "enter/exit data"; break;
3764 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3765 break;
3766 default: gcc_unreachable ();
3768 switch (gimple_omp_target_kind (ctx->stmt))
3770 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3771 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3772 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3773 ctx_stmt_name = "parallel"; break;
3774 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3775 ctx_stmt_name = "kernels"; break;
3776 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3777 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3778 ctx_stmt_name = "host_data"; break;
3779 default: gcc_unreachable ();
3782 /* OpenACC/OpenMP mismatch? */
3783 if (is_gimple_omp_oacc (stmt)
3784 != is_gimple_omp_oacc (ctx->stmt))
3786 error_at (gimple_location (stmt),
3787 "%s %qs construct inside of %s %qs region",
3788 (is_gimple_omp_oacc (stmt)
3789 ? "OpenACC" : "OpenMP"), stmt_name,
3790 (is_gimple_omp_oacc (ctx->stmt)
3791 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3792 return false;
3794 if (is_gimple_omp_offloaded (ctx->stmt))
3796 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3797 if (is_gimple_omp_oacc (ctx->stmt))
3799 error_at (gimple_location (stmt),
3800 "%qs construct inside of %qs region",
3801 stmt_name, ctx_stmt_name);
3802 return false;
3804 else
3806 warning_at (gimple_location (stmt), 0,
3807 "%qs construct inside of %qs region",
3808 stmt_name, ctx_stmt_name);
3812 break;
3813 default:
3814 break;
3816 return true;
3820 /* Helper function scan_omp.
3822 Callback for walk_tree or operators in walk_gimple_stmt used to
3823 scan for OMP directives in TP. */
3825 static tree
3826 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3828 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3829 omp_context *ctx = (omp_context *) wi->info;
3830 tree t = *tp;
3832 switch (TREE_CODE (t))
3834 case VAR_DECL:
3835 case PARM_DECL:
3836 case LABEL_DECL:
3837 case RESULT_DECL:
3838 if (ctx)
3840 tree repl = remap_decl (t, &ctx->cb);
3841 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3842 *tp = repl;
3844 break;
3846 default:
3847 if (ctx && TYPE_P (t))
3848 *tp = remap_type (t, &ctx->cb);
3849 else if (!DECL_P (t))
3851 *walk_subtrees = 1;
3852 if (ctx)
3854 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3855 if (tem != TREE_TYPE (t))
3857 if (TREE_CODE (t) == INTEGER_CST)
3858 *tp = wide_int_to_tree (tem, t);
3859 else
3860 TREE_TYPE (t) = tem;
3864 break;
3867 return NULL_TREE;
3870 /* Return true if FNDECL is a setjmp or a longjmp. */
3872 static bool
3873 setjmp_or_longjmp_p (const_tree fndecl)
3875 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3876 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3877 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3878 return true;
3880 tree declname = DECL_NAME (fndecl);
3881 if (!declname)
3882 return false;
3883 const char *name = IDENTIFIER_POINTER (declname);
3884 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3888 /* Helper function for scan_omp.
3890 Callback for walk_gimple_stmt used to scan for OMP directives in
3891 the current statement in GSI. */
3893 static tree
3894 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3895 struct walk_stmt_info *wi)
3897 gimple *stmt = gsi_stmt (*gsi);
3898 omp_context *ctx = (omp_context *) wi->info;
3900 if (gimple_has_location (stmt))
3901 input_location = gimple_location (stmt);
3903 /* Check the nesting restrictions. */
3904 bool remove = false;
3905 if (is_gimple_omp (stmt))
3906 remove = !check_omp_nesting_restrictions (stmt, ctx);
3907 else if (is_gimple_call (stmt))
3909 tree fndecl = gimple_call_fndecl (stmt);
3910 if (fndecl)
3912 if (setjmp_or_longjmp_p (fndecl)
3913 && ctx
3914 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3915 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3917 remove = true;
3918 error_at (gimple_location (stmt),
3919 "setjmp/longjmp inside simd construct");
3921 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3922 switch (DECL_FUNCTION_CODE (fndecl))
3924 case BUILT_IN_GOMP_BARRIER:
3925 case BUILT_IN_GOMP_CANCEL:
3926 case BUILT_IN_GOMP_CANCELLATION_POINT:
3927 case BUILT_IN_GOMP_TASKYIELD:
3928 case BUILT_IN_GOMP_TASKWAIT:
3929 case BUILT_IN_GOMP_TASKGROUP_START:
3930 case BUILT_IN_GOMP_TASKGROUP_END:
3931 remove = !check_omp_nesting_restrictions (stmt, ctx);
3932 break;
3933 default:
3934 break;
3938 if (remove)
3940 stmt = gimple_build_nop ();
3941 gsi_replace (gsi, stmt, false);
3944 *handled_ops_p = true;
3946 switch (gimple_code (stmt))
3948 case GIMPLE_OMP_PARALLEL:
3949 taskreg_nesting_level++;
3950 scan_omp_parallel (gsi, ctx);
3951 taskreg_nesting_level--;
3952 break;
3954 case GIMPLE_OMP_TASK:
3955 taskreg_nesting_level++;
3956 scan_omp_task (gsi, ctx);
3957 taskreg_nesting_level--;
3958 break;
3960 case GIMPLE_OMP_FOR:
3961 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3962 break;
3964 case GIMPLE_OMP_SECTIONS:
3965 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3966 break;
3968 case GIMPLE_OMP_SINGLE:
3969 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3970 break;
3972 case GIMPLE_OMP_SECTION:
3973 case GIMPLE_OMP_MASTER:
3974 case GIMPLE_OMP_TASKGROUP:
3975 case GIMPLE_OMP_ORDERED:
3976 case GIMPLE_OMP_CRITICAL:
3977 case GIMPLE_OMP_GRID_BODY:
3978 ctx = new_omp_context (stmt, ctx);
3979 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3980 break;
3982 case GIMPLE_OMP_TARGET:
3983 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3984 break;
3986 case GIMPLE_OMP_TEAMS:
3987 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3988 break;
3990 case GIMPLE_BIND:
3992 tree var;
3994 *handled_ops_p = false;
3995 if (ctx)
3996 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3997 var ;
3998 var = DECL_CHAIN (var))
3999 insert_decl_map (&ctx->cb, var, var);
4001 break;
4002 default:
4003 *handled_ops_p = false;
4004 break;
4007 return NULL_TREE;
4011 /* Scan all the statements starting at the current statement. CTX
4012 contains context information about the OMP directives and
4013 clauses found during the scan. */
4015 static void
4016 scan_omp (gimple_seq *body_p, omp_context *ctx)
4018 location_t saved_location;
4019 struct walk_stmt_info wi;
4021 memset (&wi, 0, sizeof (wi));
4022 wi.info = ctx;
4023 wi.want_locations = true;
4025 saved_location = input_location;
4026 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4027 input_location = saved_location;
4030 /* Re-gimplification and code generation routines. */
4032 /* Build a call to GOMP_barrier. */
4034 static gimple *
4035 build_omp_barrier (tree lhs)
4037 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4038 : BUILT_IN_GOMP_BARRIER);
4039 gcall *g = gimple_build_call (fndecl, 0);
4040 if (lhs)
4041 gimple_call_set_lhs (g, lhs);
4042 return g;
4045 /* If a context was created for STMT when it was scanned, return it. */
4047 static omp_context *
4048 maybe_lookup_ctx (gimple *stmt)
4050 splay_tree_node n;
4051 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4052 return n ? (omp_context *) n->value : NULL;
4056 /* Find the mapping for DECL in CTX or the immediately enclosing
4057 context that has a mapping for DECL.
4059 If CTX is a nested parallel directive, we may have to use the decl
4060 mappings created in CTX's parent context. Suppose that we have the
4061 following parallel nesting (variable UIDs showed for clarity):
4063 iD.1562 = 0;
4064 #omp parallel shared(iD.1562) -> outer parallel
4065 iD.1562 = iD.1562 + 1;
4067 #omp parallel shared (iD.1562) -> inner parallel
4068 iD.1562 = iD.1562 - 1;
4070 Each parallel structure will create a distinct .omp_data_s structure
4071 for copying iD.1562 in/out of the directive:
4073 outer parallel .omp_data_s.1.i -> iD.1562
4074 inner parallel .omp_data_s.2.i -> iD.1562
4076 A shared variable mapping will produce a copy-out operation before
4077 the parallel directive and a copy-in operation after it. So, in
4078 this case we would have:
4080 iD.1562 = 0;
4081 .omp_data_o.1.i = iD.1562;
4082 #omp parallel shared(iD.1562) -> outer parallel
4083 .omp_data_i.1 = &.omp_data_o.1
4084 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4086 .omp_data_o.2.i = iD.1562; -> **
4087 #omp parallel shared(iD.1562) -> inner parallel
4088 .omp_data_i.2 = &.omp_data_o.2
4089 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4092 ** This is a problem. The symbol iD.1562 cannot be referenced
4093 inside the body of the outer parallel region. But since we are
4094 emitting this copy operation while expanding the inner parallel
4095 directive, we need to access the CTX structure of the outer
4096 parallel directive to get the correct mapping:
4098 .omp_data_o.2.i = .omp_data_i.1->i
4100 Since there may be other workshare or parallel directives enclosing
4101 the parallel directive, it may be necessary to walk up the context
4102 parent chain. This is not a problem in general because nested
4103 parallelism happens only rarely. */
4105 static tree
4106 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4108 tree t;
4109 omp_context *up;
4111 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4112 t = maybe_lookup_decl (decl, up);
4114 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4116 return t ? t : decl;
4120 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4121 in outer contexts. */
4123 static tree
4124 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4126 tree t = NULL;
4127 omp_context *up;
4129 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4130 t = maybe_lookup_decl (decl, up);
4132 return t ? t : decl;
4136 /* Construct the initialization value for reduction operation OP. */
4138 tree
4139 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4141 switch (op)
4143 case PLUS_EXPR:
4144 case MINUS_EXPR:
4145 case BIT_IOR_EXPR:
4146 case BIT_XOR_EXPR:
4147 case TRUTH_OR_EXPR:
4148 case TRUTH_ORIF_EXPR:
4149 case TRUTH_XOR_EXPR:
4150 case NE_EXPR:
4151 return build_zero_cst (type);
4153 case MULT_EXPR:
4154 case TRUTH_AND_EXPR:
4155 case TRUTH_ANDIF_EXPR:
4156 case EQ_EXPR:
4157 return fold_convert_loc (loc, type, integer_one_node);
4159 case BIT_AND_EXPR:
4160 return fold_convert_loc (loc, type, integer_minus_one_node);
4162 case MAX_EXPR:
4163 if (SCALAR_FLOAT_TYPE_P (type))
4165 REAL_VALUE_TYPE max, min;
4166 if (HONOR_INFINITIES (type))
4168 real_inf (&max);
4169 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4171 else
4172 real_maxval (&min, 1, TYPE_MODE (type));
4173 return build_real (type, min);
4175 else if (POINTER_TYPE_P (type))
4177 wide_int min
4178 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4179 return wide_int_to_tree (type, min);
4181 else
4183 gcc_assert (INTEGRAL_TYPE_P (type));
4184 return TYPE_MIN_VALUE (type);
4187 case MIN_EXPR:
4188 if (SCALAR_FLOAT_TYPE_P (type))
4190 REAL_VALUE_TYPE max;
4191 if (HONOR_INFINITIES (type))
4192 real_inf (&max);
4193 else
4194 real_maxval (&max, 0, TYPE_MODE (type));
4195 return build_real (type, max);
4197 else if (POINTER_TYPE_P (type))
4199 wide_int max
4200 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4201 return wide_int_to_tree (type, max);
4203 else
4205 gcc_assert (INTEGRAL_TYPE_P (type));
4206 return TYPE_MAX_VALUE (type);
4209 default:
4210 gcc_unreachable ();
4214 /* Construct the initialization value for reduction CLAUSE. */
4216 tree
4217 omp_reduction_init (tree clause, tree type)
4219 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4220 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4223 /* Return alignment to be assumed for var in CLAUSE, which should be
4224 OMP_CLAUSE_ALIGNED. */
4226 static tree
4227 omp_clause_aligned_alignment (tree clause)
4229 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4230 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4232 /* Otherwise return implementation defined alignment. */
4233 unsigned int al = 1;
4234 machine_mode mode, vmode;
4235 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4236 if (vs)
4237 vs = 1 << floor_log2 (vs);
4238 static enum mode_class classes[]
4239 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4240 for (int i = 0; i < 4; i += 2)
4241 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4242 mode != VOIDmode;
4243 mode = GET_MODE_WIDER_MODE (mode))
4245 vmode = targetm.vectorize.preferred_simd_mode (mode);
4246 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4247 continue;
4248 while (vs
4249 && GET_MODE_SIZE (vmode) < vs
4250 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4251 vmode = GET_MODE_2XWIDER_MODE (vmode);
4253 tree type = lang_hooks.types.type_for_mode (mode, 1);
4254 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4255 continue;
4256 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4257 / GET_MODE_SIZE (mode));
4258 if (TYPE_MODE (type) != vmode)
4259 continue;
4260 if (TYPE_ALIGN_UNIT (type) > al)
4261 al = TYPE_ALIGN_UNIT (type);
4263 return build_int_cst (integer_type_node, al);
4266 /* Return maximum possible vectorization factor for the target. */
4268 static int
4269 omp_max_vf (void)
4271 if (!optimize
4272 || optimize_debug
4273 || !flag_tree_loop_optimize
4274 || (!flag_tree_loop_vectorize
4275 && (global_options_set.x_flag_tree_loop_vectorize
4276 || global_options_set.x_flag_tree_vectorize)))
4277 return 1;
4279 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4280 if (vs)
4282 vs = 1 << floor_log2 (vs);
4283 return vs;
4285 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4286 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4287 return GET_MODE_NUNITS (vqimode);
4288 return 1;
4291 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4292 privatization. */
4294 static bool
4295 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4296 tree &idx, tree &lane, tree &ivar, tree &lvar)
4298 if (max_vf == 0)
4300 max_vf = omp_max_vf ();
4301 if (max_vf > 1)
4303 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4304 OMP_CLAUSE_SAFELEN);
4305 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4306 max_vf = 1;
4307 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4308 max_vf) == -1)
4309 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4311 if (max_vf > 1)
4313 idx = create_tmp_var (unsigned_type_node);
4314 lane = create_tmp_var (unsigned_type_node);
4317 if (max_vf == 1)
4318 return false;
4320 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4321 tree avar = create_tmp_var_raw (atype);
4322 if (TREE_ADDRESSABLE (new_var))
4323 TREE_ADDRESSABLE (avar) = 1;
4324 DECL_ATTRIBUTES (avar)
4325 = tree_cons (get_identifier ("omp simd array"), NULL,
4326 DECL_ATTRIBUTES (avar));
4327 gimple_add_tmp_var (avar);
4328 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4329 NULL_TREE, NULL_TREE);
4330 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4331 NULL_TREE, NULL_TREE);
4332 if (DECL_P (new_var))
4334 SET_DECL_VALUE_EXPR (new_var, lvar);
4335 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4337 return true;
4340 /* Helper function of lower_rec_input_clauses. For a reference
4341 in simd reduction, add an underlying variable it will reference. */
4343 static void
4344 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4346 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4347 if (TREE_CONSTANT (z))
4349 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4350 get_name (new_vard));
4351 gimple_add_tmp_var (z);
4352 TREE_ADDRESSABLE (z) = 1;
4353 z = build_fold_addr_expr_loc (loc, z);
4354 gimplify_assign (new_vard, z, ilist);
4358 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4359 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4360 private variables. Initialization statements go in ILIST, while calls
4361 to destructors go in DLIST. */
4363 static void
4364 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4365 omp_context *ctx, struct omp_for_data *fd)
4367 tree c, dtor, copyin_seq, x, ptr;
4368 bool copyin_by_ref = false;
4369 bool lastprivate_firstprivate = false;
4370 bool reduction_omp_orig_ref = false;
4371 int pass;
4372 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4373 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4374 int max_vf = 0;
4375 tree lane = NULL_TREE, idx = NULL_TREE;
4376 tree ivar = NULL_TREE, lvar = NULL_TREE;
4377 gimple_seq llist[2] = { NULL, NULL };
4379 copyin_seq = NULL;
4381 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4382 with data sharing clauses referencing variable sized vars. That
4383 is unnecessarily hard to support and very unlikely to result in
4384 vectorized code anyway. */
4385 if (is_simd)
4386 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4387 switch (OMP_CLAUSE_CODE (c))
4389 case OMP_CLAUSE_LINEAR:
4390 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4391 max_vf = 1;
4392 /* FALLTHRU */
4393 case OMP_CLAUSE_PRIVATE:
4394 case OMP_CLAUSE_FIRSTPRIVATE:
4395 case OMP_CLAUSE_LASTPRIVATE:
4396 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4397 max_vf = 1;
4398 break;
4399 case OMP_CLAUSE_REDUCTION:
4400 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4401 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4402 max_vf = 1;
4403 break;
4404 default:
4405 continue;
4408 /* Do all the fixed sized types in the first pass, and the variable sized
4409 types in the second pass. This makes sure that the scalar arguments to
4410 the variable sized types are processed before we use them in the
4411 variable sized operations. */
4412 for (pass = 0; pass < 2; ++pass)
4414 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4416 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4417 tree var, new_var;
4418 bool by_ref;
4419 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4421 switch (c_kind)
4423 case OMP_CLAUSE_PRIVATE:
4424 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4425 continue;
4426 break;
4427 case OMP_CLAUSE_SHARED:
4428 /* Ignore shared directives in teams construct. */
4429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4430 continue;
4431 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4433 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4434 || is_global_var (OMP_CLAUSE_DECL (c)));
4435 continue;
4437 case OMP_CLAUSE_FIRSTPRIVATE:
4438 case OMP_CLAUSE_COPYIN:
4439 break;
4440 case OMP_CLAUSE_LINEAR:
4441 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4442 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4443 lastprivate_firstprivate = true;
4444 break;
4445 case OMP_CLAUSE_REDUCTION:
4446 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4447 reduction_omp_orig_ref = true;
4448 break;
4449 case OMP_CLAUSE__LOOPTEMP_:
4450 /* Handle _looptemp_ clauses only on parallel/task. */
4451 if (fd)
4452 continue;
4453 break;
4454 case OMP_CLAUSE_LASTPRIVATE:
4455 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4457 lastprivate_firstprivate = true;
4458 if (pass != 0 || is_taskloop_ctx (ctx))
4459 continue;
4461 /* Even without corresponding firstprivate, if
4462 decl is Fortran allocatable, it needs outer var
4463 reference. */
4464 else if (pass == 0
4465 && lang_hooks.decls.omp_private_outer_ref
4466 (OMP_CLAUSE_DECL (c)))
4467 lastprivate_firstprivate = true;
4468 break;
4469 case OMP_CLAUSE_ALIGNED:
4470 if (pass == 0)
4471 continue;
4472 var = OMP_CLAUSE_DECL (c);
4473 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4474 && !is_global_var (var))
4476 new_var = maybe_lookup_decl (var, ctx);
4477 if (new_var == NULL_TREE)
4478 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4479 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4480 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4481 omp_clause_aligned_alignment (c));
4482 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4483 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4484 gimplify_and_add (x, ilist);
4486 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4487 && is_global_var (var))
4489 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4490 new_var = lookup_decl (var, ctx);
4491 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4492 t = build_fold_addr_expr_loc (clause_loc, t);
4493 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4494 t = build_call_expr_loc (clause_loc, t2, 2, t,
4495 omp_clause_aligned_alignment (c));
4496 t = fold_convert_loc (clause_loc, ptype, t);
4497 x = create_tmp_var (ptype);
4498 t = build2 (MODIFY_EXPR, ptype, x, t);
4499 gimplify_and_add (t, ilist);
4500 t = build_simple_mem_ref_loc (clause_loc, x);
4501 SET_DECL_VALUE_EXPR (new_var, t);
4502 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4504 continue;
4505 default:
4506 continue;
4509 new_var = var = OMP_CLAUSE_DECL (c);
4510 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4512 var = TREE_OPERAND (var, 0);
4513 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4514 var = TREE_OPERAND (var, 0);
4515 if (TREE_CODE (var) == INDIRECT_REF
4516 || TREE_CODE (var) == ADDR_EXPR)
4517 var = TREE_OPERAND (var, 0);
4518 if (is_variable_sized (var))
4520 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4521 var = DECL_VALUE_EXPR (var);
4522 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4523 var = TREE_OPERAND (var, 0);
4524 gcc_assert (DECL_P (var));
4526 new_var = var;
4528 if (c_kind != OMP_CLAUSE_COPYIN)
4529 new_var = lookup_decl (var, ctx);
4531 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4533 if (pass != 0)
4534 continue;
4536 /* C/C++ array section reductions. */
4537 else if (c_kind == OMP_CLAUSE_REDUCTION
4538 && var != OMP_CLAUSE_DECL (c))
4540 if (pass == 0)
4541 continue;
4543 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4544 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4545 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4547 tree b = TREE_OPERAND (orig_var, 1);
4548 b = maybe_lookup_decl (b, ctx);
4549 if (b == NULL)
4551 b = TREE_OPERAND (orig_var, 1);
4552 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4554 if (integer_zerop (bias))
4555 bias = b;
4556 else
4558 bias = fold_convert_loc (clause_loc,
4559 TREE_TYPE (b), bias);
4560 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4561 TREE_TYPE (b), b, bias);
4563 orig_var = TREE_OPERAND (orig_var, 0);
4565 if (TREE_CODE (orig_var) == INDIRECT_REF
4566 || TREE_CODE (orig_var) == ADDR_EXPR)
4567 orig_var = TREE_OPERAND (orig_var, 0);
4568 tree d = OMP_CLAUSE_DECL (c);
4569 tree type = TREE_TYPE (d);
4570 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4571 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4572 const char *name = get_name (orig_var);
4573 if (TREE_CONSTANT (v))
4575 x = create_tmp_var_raw (type, name);
4576 gimple_add_tmp_var (x);
4577 TREE_ADDRESSABLE (x) = 1;
4578 x = build_fold_addr_expr_loc (clause_loc, x);
4580 else
4582 tree atmp
4583 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4584 tree t = maybe_lookup_decl (v, ctx);
4585 if (t)
4586 v = t;
4587 else
4588 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4589 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4590 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4591 TREE_TYPE (v), v,
4592 build_int_cst (TREE_TYPE (v), 1));
4593 t = fold_build2_loc (clause_loc, MULT_EXPR,
4594 TREE_TYPE (v), t,
4595 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4596 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4597 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4600 tree ptype = build_pointer_type (TREE_TYPE (type));
4601 x = fold_convert_loc (clause_loc, ptype, x);
4602 tree y = create_tmp_var (ptype, name);
4603 gimplify_assign (y, x, ilist);
4604 x = y;
4605 tree yb = y;
4607 if (!integer_zerop (bias))
4609 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4610 bias);
4611 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4613 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4614 pointer_sized_int_node, yb, bias);
4615 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4616 yb = create_tmp_var (ptype, name);
4617 gimplify_assign (yb, x, ilist);
4618 x = yb;
4621 d = TREE_OPERAND (d, 0);
4622 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4623 d = TREE_OPERAND (d, 0);
4624 if (TREE_CODE (d) == ADDR_EXPR)
4626 if (orig_var != var)
4628 gcc_assert (is_variable_sized (orig_var));
4629 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4631 gimplify_assign (new_var, x, ilist);
4632 tree new_orig_var = lookup_decl (orig_var, ctx);
4633 tree t = build_fold_indirect_ref (new_var);
4634 DECL_IGNORED_P (new_var) = 0;
4635 TREE_THIS_NOTRAP (t);
4636 SET_DECL_VALUE_EXPR (new_orig_var, t);
4637 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4639 else
4641 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4642 build_int_cst (ptype, 0));
4643 SET_DECL_VALUE_EXPR (new_var, x);
4644 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4647 else
4649 gcc_assert (orig_var == var);
4650 if (TREE_CODE (d) == INDIRECT_REF)
4652 x = create_tmp_var (ptype, name);
4653 TREE_ADDRESSABLE (x) = 1;
4654 gimplify_assign (x, yb, ilist);
4655 x = build_fold_addr_expr_loc (clause_loc, x);
4657 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4658 gimplify_assign (new_var, x, ilist);
4660 tree y1 = create_tmp_var (ptype, NULL);
4661 gimplify_assign (y1, y, ilist);
4662 tree i2 = NULL_TREE, y2 = NULL_TREE;
4663 tree body2 = NULL_TREE, end2 = NULL_TREE;
4664 tree y3 = NULL_TREE, y4 = NULL_TREE;
4665 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4667 y2 = create_tmp_var (ptype, NULL);
4668 gimplify_assign (y2, y, ilist);
4669 tree ref = build_outer_var_ref (var, ctx);
4670 /* For ref build_outer_var_ref already performs this. */
4671 if (TREE_CODE (d) == INDIRECT_REF)
4672 gcc_assert (is_reference (var));
4673 else if (TREE_CODE (d) == ADDR_EXPR)
4674 ref = build_fold_addr_expr (ref);
4675 else if (is_reference (var))
4676 ref = build_fold_addr_expr (ref);
4677 ref = fold_convert_loc (clause_loc, ptype, ref);
4678 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4679 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4681 y3 = create_tmp_var (ptype, NULL);
4682 gimplify_assign (y3, unshare_expr (ref), ilist);
4684 if (is_simd)
4686 y4 = create_tmp_var (ptype, NULL);
4687 gimplify_assign (y4, ref, dlist);
4690 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4691 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4692 tree body = create_artificial_label (UNKNOWN_LOCATION);
4693 tree end = create_artificial_label (UNKNOWN_LOCATION);
4694 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4695 if (y2)
4697 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4698 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4699 body2 = create_artificial_label (UNKNOWN_LOCATION);
4700 end2 = create_artificial_label (UNKNOWN_LOCATION);
4701 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4703 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4705 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4706 tree decl_placeholder
4707 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4708 SET_DECL_VALUE_EXPR (decl_placeholder,
4709 build_simple_mem_ref (y1));
4710 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4711 SET_DECL_VALUE_EXPR (placeholder,
4712 y3 ? build_simple_mem_ref (y3)
4713 : error_mark_node);
4714 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4715 x = lang_hooks.decls.omp_clause_default_ctor
4716 (c, build_simple_mem_ref (y1),
4717 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4718 if (x)
4719 gimplify_and_add (x, ilist);
4720 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4722 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4723 lower_omp (&tseq, ctx);
4724 gimple_seq_add_seq (ilist, tseq);
4726 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4727 if (is_simd)
4729 SET_DECL_VALUE_EXPR (decl_placeholder,
4730 build_simple_mem_ref (y2));
4731 SET_DECL_VALUE_EXPR (placeholder,
4732 build_simple_mem_ref (y4));
4733 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4734 lower_omp (&tseq, ctx);
4735 gimple_seq_add_seq (dlist, tseq);
4736 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4738 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4739 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4740 x = lang_hooks.decls.omp_clause_dtor
4741 (c, build_simple_mem_ref (y2));
4742 if (x)
4744 gimple_seq tseq = NULL;
4745 dtor = x;
4746 gimplify_stmt (&dtor, &tseq);
4747 gimple_seq_add_seq (dlist, tseq);
4750 else
4752 x = omp_reduction_init (c, TREE_TYPE (type));
4753 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4755 /* reduction(-:var) sums up the partial results, so it
4756 acts identically to reduction(+:var). */
4757 if (code == MINUS_EXPR)
4758 code = PLUS_EXPR;
4760 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4761 if (is_simd)
4763 x = build2 (code, TREE_TYPE (type),
4764 build_simple_mem_ref (y4),
4765 build_simple_mem_ref (y2));
4766 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4769 gimple *g
4770 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4771 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4772 gimple_seq_add_stmt (ilist, g);
4773 if (y3)
4775 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4776 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4777 gimple_seq_add_stmt (ilist, g);
4779 g = gimple_build_assign (i, PLUS_EXPR, i,
4780 build_int_cst (TREE_TYPE (i), 1));
4781 gimple_seq_add_stmt (ilist, g);
4782 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4783 gimple_seq_add_stmt (ilist, g);
4784 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4785 if (y2)
4787 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4788 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4789 gimple_seq_add_stmt (dlist, g);
4790 if (y4)
4792 g = gimple_build_assign
4793 (y4, POINTER_PLUS_EXPR, y4,
4794 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4795 gimple_seq_add_stmt (dlist, g);
4797 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4798 build_int_cst (TREE_TYPE (i2), 1));
4799 gimple_seq_add_stmt (dlist, g);
4800 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4801 gimple_seq_add_stmt (dlist, g);
4802 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4804 continue;
4806 else if (is_variable_sized (var))
4808 /* For variable sized types, we need to allocate the
4809 actual storage here. Call alloca and store the
4810 result in the pointer decl that we created elsewhere. */
4811 if (pass == 0)
4812 continue;
4814 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4816 gcall *stmt;
4817 tree tmp, atmp;
4819 ptr = DECL_VALUE_EXPR (new_var);
4820 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4821 ptr = TREE_OPERAND (ptr, 0);
4822 gcc_assert (DECL_P (ptr));
4823 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4825 /* void *tmp = __builtin_alloca */
4826 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4827 stmt = gimple_build_call (atmp, 2, x,
4828 size_int (DECL_ALIGN (var)));
4829 tmp = create_tmp_var_raw (ptr_type_node);
4830 gimple_add_tmp_var (tmp);
4831 gimple_call_set_lhs (stmt, tmp);
4833 gimple_seq_add_stmt (ilist, stmt);
4835 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4836 gimplify_assign (ptr, x, ilist);
4839 else if (is_reference (var) && !is_oacc_parallel (ctx))
4841 /* For references that are being privatized for Fortran,
4842 allocate new backing storage for the new pointer
4843 variable. This allows us to avoid changing all the
4844 code that expects a pointer to something that expects
4845 a direct variable. */
4846 if (pass == 0)
4847 continue;
4849 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4850 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4852 x = build_receiver_ref (var, false, ctx);
4853 x = build_fold_addr_expr_loc (clause_loc, x);
4855 else if (TREE_CONSTANT (x))
4857 /* For reduction in SIMD loop, defer adding the
4858 initialization of the reference, because if we decide
4859 to use SIMD array for it, the initilization could cause
4860 expansion ICE. */
4861 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4862 x = NULL_TREE;
4863 else
4865 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4866 get_name (var));
4867 gimple_add_tmp_var (x);
4868 TREE_ADDRESSABLE (x) = 1;
4869 x = build_fold_addr_expr_loc (clause_loc, x);
4872 else
4874 tree atmp
4875 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4876 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4877 tree al = size_int (TYPE_ALIGN (rtype));
4878 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4881 if (x)
4883 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4884 gimplify_assign (new_var, x, ilist);
4887 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4889 else if (c_kind == OMP_CLAUSE_REDUCTION
4890 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4892 if (pass == 0)
4893 continue;
4895 else if (pass != 0)
4896 continue;
4898 switch (OMP_CLAUSE_CODE (c))
4900 case OMP_CLAUSE_SHARED:
4901 /* Ignore shared directives in teams construct. */
4902 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4903 continue;
4904 /* Shared global vars are just accessed directly. */
4905 if (is_global_var (new_var))
4906 break;
4907 /* For taskloop firstprivate/lastprivate, represented
4908 as firstprivate and shared clause on the task, new_var
4909 is the firstprivate var. */
4910 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4911 break;
4912 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4913 needs to be delayed until after fixup_child_record_type so
4914 that we get the correct type during the dereference. */
4915 by_ref = use_pointer_for_field (var, ctx);
4916 x = build_receiver_ref (var, by_ref, ctx);
4917 SET_DECL_VALUE_EXPR (new_var, x);
4918 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4920 /* ??? If VAR is not passed by reference, and the variable
4921 hasn't been initialized yet, then we'll get a warning for
4922 the store into the omp_data_s structure. Ideally, we'd be
4923 able to notice this and not store anything at all, but
4924 we're generating code too early. Suppress the warning. */
4925 if (!by_ref)
4926 TREE_NO_WARNING (var) = 1;
4927 break;
4929 case OMP_CLAUSE_LASTPRIVATE:
4930 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4931 break;
4932 /* FALLTHRU */
4934 case OMP_CLAUSE_PRIVATE:
4935 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4936 x = build_outer_var_ref (var, ctx);
4937 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4939 if (is_task_ctx (ctx))
4940 x = build_receiver_ref (var, false, ctx);
4941 else
4942 x = build_outer_var_ref (var, ctx);
4944 else
4945 x = NULL;
4946 do_private:
4947 tree nx;
4948 nx = lang_hooks.decls.omp_clause_default_ctor
4949 (c, unshare_expr (new_var), x);
4950 if (is_simd)
4952 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4953 if ((TREE_ADDRESSABLE (new_var) || nx || y
4954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4955 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4956 idx, lane, ivar, lvar))
4958 if (nx)
4959 x = lang_hooks.decls.omp_clause_default_ctor
4960 (c, unshare_expr (ivar), x);
4961 if (nx && x)
4962 gimplify_and_add (x, &llist[0]);
4963 if (y)
4965 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4966 if (y)
4968 gimple_seq tseq = NULL;
4970 dtor = y;
4971 gimplify_stmt (&dtor, &tseq);
4972 gimple_seq_add_seq (&llist[1], tseq);
4975 break;
4978 if (nx)
4979 gimplify_and_add (nx, ilist);
4980 /* FALLTHRU */
4982 do_dtor:
4983 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4984 if (x)
4986 gimple_seq tseq = NULL;
4988 dtor = x;
4989 gimplify_stmt (&dtor, &tseq);
4990 gimple_seq_add_seq (dlist, tseq);
4992 break;
4994 case OMP_CLAUSE_LINEAR:
4995 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4996 goto do_firstprivate;
4997 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4998 x = NULL;
4999 else
5000 x = build_outer_var_ref (var, ctx);
5001 goto do_private;
5003 case OMP_CLAUSE_FIRSTPRIVATE:
5004 if (is_task_ctx (ctx))
5006 if (is_reference (var) || is_variable_sized (var))
5007 goto do_dtor;
5008 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5009 ctx))
5010 || use_pointer_for_field (var, NULL))
5012 x = build_receiver_ref (var, false, ctx);
5013 SET_DECL_VALUE_EXPR (new_var, x);
5014 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5015 goto do_dtor;
5018 do_firstprivate:
5019 x = build_outer_var_ref (var, ctx);
5020 if (is_simd)
5022 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5023 && gimple_omp_for_combined_into_p (ctx->stmt))
5025 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5026 tree stept = TREE_TYPE (t);
5027 tree ct = find_omp_clause (clauses,
5028 OMP_CLAUSE__LOOPTEMP_);
5029 gcc_assert (ct);
5030 tree l = OMP_CLAUSE_DECL (ct);
5031 tree n1 = fd->loop.n1;
5032 tree step = fd->loop.step;
5033 tree itype = TREE_TYPE (l);
5034 if (POINTER_TYPE_P (itype))
5035 itype = signed_type_for (itype);
5036 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5037 if (TYPE_UNSIGNED (itype)
5038 && fd->loop.cond_code == GT_EXPR)
5039 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5040 fold_build1 (NEGATE_EXPR, itype, l),
5041 fold_build1 (NEGATE_EXPR,
5042 itype, step));
5043 else
5044 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5045 t = fold_build2 (MULT_EXPR, stept,
5046 fold_convert (stept, l), t);
5048 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5050 x = lang_hooks.decls.omp_clause_linear_ctor
5051 (c, new_var, x, t);
5052 gimplify_and_add (x, ilist);
5053 goto do_dtor;
5056 if (POINTER_TYPE_P (TREE_TYPE (x)))
5057 x = fold_build2 (POINTER_PLUS_EXPR,
5058 TREE_TYPE (x), x, t);
5059 else
5060 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5063 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5064 || TREE_ADDRESSABLE (new_var))
5065 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5066 idx, lane, ivar, lvar))
5068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5070 tree iv = create_tmp_var (TREE_TYPE (new_var));
5071 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5072 gimplify_and_add (x, ilist);
5073 gimple_stmt_iterator gsi
5074 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5075 gassign *g
5076 = gimple_build_assign (unshare_expr (lvar), iv);
5077 gsi_insert_before_without_update (&gsi, g,
5078 GSI_SAME_STMT);
5079 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5080 enum tree_code code = PLUS_EXPR;
5081 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5082 code = POINTER_PLUS_EXPR;
5083 g = gimple_build_assign (iv, code, iv, t);
5084 gsi_insert_before_without_update (&gsi, g,
5085 GSI_SAME_STMT);
5086 break;
5088 x = lang_hooks.decls.omp_clause_copy_ctor
5089 (c, unshare_expr (ivar), x);
5090 gimplify_and_add (x, &llist[0]);
5091 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5092 if (x)
5094 gimple_seq tseq = NULL;
5096 dtor = x;
5097 gimplify_stmt (&dtor, &tseq);
5098 gimple_seq_add_seq (&llist[1], tseq);
5100 break;
5103 x = lang_hooks.decls.omp_clause_copy_ctor
5104 (c, unshare_expr (new_var), x);
5105 gimplify_and_add (x, ilist);
5106 goto do_dtor;
5108 case OMP_CLAUSE__LOOPTEMP_:
5109 gcc_assert (is_taskreg_ctx (ctx));
5110 x = build_outer_var_ref (var, ctx);
5111 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5112 gimplify_and_add (x, ilist);
5113 break;
5115 case OMP_CLAUSE_COPYIN:
5116 by_ref = use_pointer_for_field (var, NULL);
5117 x = build_receiver_ref (var, by_ref, ctx);
5118 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5119 append_to_statement_list (x, &copyin_seq);
5120 copyin_by_ref |= by_ref;
5121 break;
5123 case OMP_CLAUSE_REDUCTION:
5124 /* OpenACC reductions are initialized using the
5125 GOACC_REDUCTION internal function. */
5126 if (is_gimple_omp_oacc (ctx->stmt))
5127 break;
5128 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5130 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5131 gimple *tseq;
5132 x = build_outer_var_ref (var, ctx);
5134 if (is_reference (var)
5135 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5136 TREE_TYPE (x)))
5137 x = build_fold_addr_expr_loc (clause_loc, x);
5138 SET_DECL_VALUE_EXPR (placeholder, x);
5139 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5140 tree new_vard = new_var;
5141 if (is_reference (var))
5143 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5144 new_vard = TREE_OPERAND (new_var, 0);
5145 gcc_assert (DECL_P (new_vard));
5147 if (is_simd
5148 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5149 idx, lane, ivar, lvar))
5151 if (new_vard == new_var)
5153 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5154 SET_DECL_VALUE_EXPR (new_var, ivar);
5156 else
5158 SET_DECL_VALUE_EXPR (new_vard,
5159 build_fold_addr_expr (ivar));
5160 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5162 x = lang_hooks.decls.omp_clause_default_ctor
5163 (c, unshare_expr (ivar),
5164 build_outer_var_ref (var, ctx));
5165 if (x)
5166 gimplify_and_add (x, &llist[0]);
5167 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5169 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5170 lower_omp (&tseq, ctx);
5171 gimple_seq_add_seq (&llist[0], tseq);
5173 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5174 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5175 lower_omp (&tseq, ctx);
5176 gimple_seq_add_seq (&llist[1], tseq);
5177 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5178 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5179 if (new_vard == new_var)
5180 SET_DECL_VALUE_EXPR (new_var, lvar);
5181 else
5182 SET_DECL_VALUE_EXPR (new_vard,
5183 build_fold_addr_expr (lvar));
5184 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5185 if (x)
5187 tseq = NULL;
5188 dtor = x;
5189 gimplify_stmt (&dtor, &tseq);
5190 gimple_seq_add_seq (&llist[1], tseq);
5192 break;
5194 /* If this is a reference to constant size reduction var
5195 with placeholder, we haven't emitted the initializer
5196 for it because it is undesirable if SIMD arrays are used.
5197 But if they aren't used, we need to emit the deferred
5198 initialization now. */
5199 else if (is_reference (var) && is_simd)
5200 handle_simd_reference (clause_loc, new_vard, ilist);
5201 x = lang_hooks.decls.omp_clause_default_ctor
5202 (c, unshare_expr (new_var),
5203 build_outer_var_ref (var, ctx));
5204 if (x)
5205 gimplify_and_add (x, ilist);
5206 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5208 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5209 lower_omp (&tseq, ctx);
5210 gimple_seq_add_seq (ilist, tseq);
5212 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5213 if (is_simd)
5215 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5216 lower_omp (&tseq, ctx);
5217 gimple_seq_add_seq (dlist, tseq);
5218 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5220 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5221 goto do_dtor;
5223 else
5225 x = omp_reduction_init (c, TREE_TYPE (new_var));
5226 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5227 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5229 /* reduction(-:var) sums up the partial results, so it
5230 acts identically to reduction(+:var). */
5231 if (code == MINUS_EXPR)
5232 code = PLUS_EXPR;
5234 tree new_vard = new_var;
5235 if (is_simd && is_reference (var))
5237 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5238 new_vard = TREE_OPERAND (new_var, 0);
5239 gcc_assert (DECL_P (new_vard));
5241 if (is_simd
5242 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5243 idx, lane, ivar, lvar))
5245 tree ref = build_outer_var_ref (var, ctx);
5247 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5249 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5250 ref = build_outer_var_ref (var, ctx);
5251 gimplify_assign (ref, x, &llist[1]);
5253 if (new_vard != new_var)
5255 SET_DECL_VALUE_EXPR (new_vard,
5256 build_fold_addr_expr (lvar));
5257 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5260 else
5262 if (is_reference (var) && is_simd)
5263 handle_simd_reference (clause_loc, new_vard, ilist);
5264 gimplify_assign (new_var, x, ilist);
5265 if (is_simd)
5267 tree ref = build_outer_var_ref (var, ctx);
5269 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5270 ref = build_outer_var_ref (var, ctx);
5271 gimplify_assign (ref, x, dlist);
5275 break;
5277 default:
5278 gcc_unreachable ();
5283 if (lane)
5285 tree uid = create_tmp_var (ptr_type_node, "simduid");
5286 /* Don't want uninit warnings on simduid, it is always uninitialized,
5287 but we use it not for the value, but for the DECL_UID only. */
5288 TREE_NO_WARNING (uid) = 1;
5289 gimple *g
5290 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5291 gimple_call_set_lhs (g, lane);
5292 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5293 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5294 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5295 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5296 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5297 gimple_omp_for_set_clauses (ctx->stmt, c);
5298 g = gimple_build_assign (lane, INTEGER_CST,
5299 build_int_cst (unsigned_type_node, 0));
5300 gimple_seq_add_stmt (ilist, g);
5301 for (int i = 0; i < 2; i++)
5302 if (llist[i])
5304 tree vf = create_tmp_var (unsigned_type_node);
5305 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5306 gimple_call_set_lhs (g, vf);
5307 gimple_seq *seq = i == 0 ? ilist : dlist;
5308 gimple_seq_add_stmt (seq, g);
5309 tree t = build_int_cst (unsigned_type_node, 0);
5310 g = gimple_build_assign (idx, INTEGER_CST, t);
5311 gimple_seq_add_stmt (seq, g);
5312 tree body = create_artificial_label (UNKNOWN_LOCATION);
5313 tree header = create_artificial_label (UNKNOWN_LOCATION);
5314 tree end = create_artificial_label (UNKNOWN_LOCATION);
5315 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5316 gimple_seq_add_stmt (seq, gimple_build_label (body));
5317 gimple_seq_add_seq (seq, llist[i]);
5318 t = build_int_cst (unsigned_type_node, 1);
5319 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5320 gimple_seq_add_stmt (seq, g);
5321 gimple_seq_add_stmt (seq, gimple_build_label (header));
5322 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5323 gimple_seq_add_stmt (seq, g);
5324 gimple_seq_add_stmt (seq, gimple_build_label (end));
5328 /* The copyin sequence is not to be executed by the main thread, since
5329 that would result in self-copies. Perhaps not visible to scalars,
5330 but it certainly is to C++ operator=. */
5331 if (copyin_seq)
5333 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5335 x = build2 (NE_EXPR, boolean_type_node, x,
5336 build_int_cst (TREE_TYPE (x), 0));
5337 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5338 gimplify_and_add (x, ilist);
5341 /* If any copyin variable is passed by reference, we must ensure the
5342 master thread doesn't modify it before it is copied over in all
5343 threads. Similarly for variables in both firstprivate and
5344 lastprivate clauses we need to ensure the lastprivate copying
5345 happens after firstprivate copying in all threads. And similarly
5346 for UDRs if initializer expression refers to omp_orig. */
5347 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5349 /* Don't add any barrier for #pragma omp simd or
5350 #pragma omp distribute. */
5351 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5352 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5353 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5356 /* If max_vf is non-zero, then we can use only a vectorization factor
5357 up to the max_vf we chose. So stick it into the safelen clause. */
5358 if (max_vf)
5360 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5361 OMP_CLAUSE_SAFELEN);
5362 if (c == NULL_TREE
5363 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5364 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5365 max_vf) == 1))
5367 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5368 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5369 max_vf);
5370 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5371 gimple_omp_for_set_clauses (ctx->stmt, c);
5377 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5378 both parallel and workshare constructs. PREDICATE may be NULL if it's
5379 always true. */
5381 static void
5382 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5383 omp_context *ctx)
5385 tree x, c, label = NULL, orig_clauses = clauses;
5386 bool par_clauses = false;
5387 tree simduid = NULL, lastlane = NULL;
5389 /* Early exit if there are no lastprivate or linear clauses. */
5390 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5391 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5392 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5393 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5394 break;
5395 if (clauses == NULL)
5397 /* If this was a workshare clause, see if it had been combined
5398 with its parallel. In that case, look for the clauses on the
5399 parallel statement itself. */
5400 if (is_parallel_ctx (ctx))
5401 return;
5403 ctx = ctx->outer;
5404 if (ctx == NULL || !is_parallel_ctx (ctx))
5405 return;
5407 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5408 OMP_CLAUSE_LASTPRIVATE);
5409 if (clauses == NULL)
5410 return;
5411 par_clauses = true;
5414 if (predicate)
5416 gcond *stmt;
5417 tree label_true, arm1, arm2;
5419 label = create_artificial_label (UNKNOWN_LOCATION);
5420 label_true = create_artificial_label (UNKNOWN_LOCATION);
5421 arm1 = TREE_OPERAND (predicate, 0);
5422 arm2 = TREE_OPERAND (predicate, 1);
5423 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5424 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5425 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5426 label_true, label);
5427 gimple_seq_add_stmt (stmt_list, stmt);
5428 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5431 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5432 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5434 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5435 if (simduid)
5436 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5439 for (c = clauses; c ;)
5441 tree var, new_var;
5442 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5444 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5445 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5446 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5448 var = OMP_CLAUSE_DECL (c);
5449 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5450 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5451 && is_taskloop_ctx (ctx))
5453 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5454 new_var = lookup_decl (var, ctx->outer);
5456 else
5457 new_var = lookup_decl (var, ctx);
5459 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5461 tree val = DECL_VALUE_EXPR (new_var);
5462 if (TREE_CODE (val) == ARRAY_REF
5463 && VAR_P (TREE_OPERAND (val, 0))
5464 && lookup_attribute ("omp simd array",
5465 DECL_ATTRIBUTES (TREE_OPERAND (val,
5466 0))))
5468 if (lastlane == NULL)
5470 lastlane = create_tmp_var (unsigned_type_node);
5471 gcall *g
5472 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5473 2, simduid,
5474 TREE_OPERAND (val, 1));
5475 gimple_call_set_lhs (g, lastlane);
5476 gimple_seq_add_stmt (stmt_list, g);
5478 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5479 TREE_OPERAND (val, 0), lastlane,
5480 NULL_TREE, NULL_TREE);
5484 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5485 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5487 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5488 gimple_seq_add_seq (stmt_list,
5489 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5490 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5492 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5493 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5495 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5496 gimple_seq_add_seq (stmt_list,
5497 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5498 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5501 x = NULL_TREE;
5502 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5503 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5505 gcc_checking_assert (is_taskloop_ctx (ctx));
5506 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5507 ctx->outer->outer);
5508 if (is_global_var (ovar))
5509 x = ovar;
5511 if (!x)
5512 x = build_outer_var_ref (var, ctx, true);
5513 if (is_reference (var))
5514 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5515 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5516 gimplify_and_add (x, stmt_list);
5518 c = OMP_CLAUSE_CHAIN (c);
5519 if (c == NULL && !par_clauses)
5521 /* If this was a workshare clause, see if it had been combined
5522 with its parallel. In that case, continue looking for the
5523 clauses also on the parallel statement itself. */
5524 if (is_parallel_ctx (ctx))
5525 break;
5527 ctx = ctx->outer;
5528 if (ctx == NULL || !is_parallel_ctx (ctx))
5529 break;
5531 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5532 OMP_CLAUSE_LASTPRIVATE);
5533 par_clauses = true;
5537 if (label)
5538 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5541 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5542 (which might be a placeholder). INNER is true if this is an inner
5543 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5544 join markers. Generate the before-loop forking sequence in
5545 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5546 general form of these sequences is
5548 GOACC_REDUCTION_SETUP
5549 GOACC_FORK
5550 GOACC_REDUCTION_INIT
5552 GOACC_REDUCTION_FINI
5553 GOACC_JOIN
5554 GOACC_REDUCTION_TEARDOWN. */
5556 static void
5557 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5558 gcall *fork, gcall *join, gimple_seq *fork_seq,
5559 gimple_seq *join_seq, omp_context *ctx)
5561 gimple_seq before_fork = NULL;
5562 gimple_seq after_fork = NULL;
5563 gimple_seq before_join = NULL;
5564 gimple_seq after_join = NULL;
5565 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5566 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5567 unsigned offset = 0;
5569 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5572 tree orig = OMP_CLAUSE_DECL (c);
5573 tree var = maybe_lookup_decl (orig, ctx);
5574 tree ref_to_res = NULL_TREE;
5575 tree incoming, outgoing;
5577 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5578 if (rcode == MINUS_EXPR)
5579 rcode = PLUS_EXPR;
5580 else if (rcode == TRUTH_ANDIF_EXPR)
5581 rcode = BIT_AND_EXPR;
5582 else if (rcode == TRUTH_ORIF_EXPR)
5583 rcode = BIT_IOR_EXPR;
5584 tree op = build_int_cst (unsigned_type_node, rcode);
5586 if (!var)
5587 var = orig;
5588 gcc_assert (!is_reference (var));
5590 incoming = outgoing = var;
5592 if (!inner)
5594 /* See if an outer construct also reduces this variable. */
5595 omp_context *outer = ctx;
5597 while (omp_context *probe = outer->outer)
5599 enum gimple_code type = gimple_code (probe->stmt);
5600 tree cls;
5602 switch (type)
5604 case GIMPLE_OMP_FOR:
5605 cls = gimple_omp_for_clauses (probe->stmt);
5606 break;
5608 case GIMPLE_OMP_TARGET:
5609 if (gimple_omp_target_kind (probe->stmt)
5610 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5611 goto do_lookup;
5613 cls = gimple_omp_target_clauses (probe->stmt);
5614 break;
5616 default:
5617 goto do_lookup;
5620 outer = probe;
5621 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5622 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5623 && orig == OMP_CLAUSE_DECL (cls))
5624 goto has_outer_reduction;
5627 do_lookup:
5628 /* This is the outermost construct with this reduction,
5629 see if there's a mapping for it. */
5630 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5631 && maybe_lookup_field (orig, outer))
5633 ref_to_res = build_receiver_ref (orig, false, outer);
5634 if (is_reference (orig))
5635 ref_to_res = build_simple_mem_ref (ref_to_res);
5637 outgoing = var;
5638 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5640 else
5641 incoming = outgoing = orig;
5643 has_outer_reduction:;
5646 if (!ref_to_res)
5647 ref_to_res = integer_zero_node;
5649 /* Determine position in reduction buffer, which may be used
5650 by target. */
5651 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5652 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5653 offset = (offset + align - 1) & ~(align - 1);
5654 tree off = build_int_cst (sizetype, offset);
5655 offset += GET_MODE_SIZE (mode);
5657 if (!init_code)
5659 init_code = build_int_cst (integer_type_node,
5660 IFN_GOACC_REDUCTION_INIT);
5661 fini_code = build_int_cst (integer_type_node,
5662 IFN_GOACC_REDUCTION_FINI);
5663 setup_code = build_int_cst (integer_type_node,
5664 IFN_GOACC_REDUCTION_SETUP);
5665 teardown_code = build_int_cst (integer_type_node,
5666 IFN_GOACC_REDUCTION_TEARDOWN);
5669 tree setup_call
5670 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5671 TREE_TYPE (var), 6, setup_code,
5672 unshare_expr (ref_to_res),
5673 incoming, level, op, off);
5674 tree init_call
5675 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5676 TREE_TYPE (var), 6, init_code,
5677 unshare_expr (ref_to_res),
5678 var, level, op, off);
5679 tree fini_call
5680 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5681 TREE_TYPE (var), 6, fini_code,
5682 unshare_expr (ref_to_res),
5683 var, level, op, off);
5684 tree teardown_call
5685 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5686 TREE_TYPE (var), 6, teardown_code,
5687 ref_to_res, var, level, op, off);
5689 gimplify_assign (var, setup_call, &before_fork);
5690 gimplify_assign (var, init_call, &after_fork);
5691 gimplify_assign (var, fini_call, &before_join);
5692 gimplify_assign (outgoing, teardown_call, &after_join);
5695 /* Now stitch things together. */
5696 gimple_seq_add_seq (fork_seq, before_fork);
5697 if (fork)
5698 gimple_seq_add_stmt (fork_seq, fork);
5699 gimple_seq_add_seq (fork_seq, after_fork);
5701 gimple_seq_add_seq (join_seq, before_join);
5702 if (join)
5703 gimple_seq_add_stmt (join_seq, join);
5704 gimple_seq_add_seq (join_seq, after_join);
5707 /* Generate code to implement the REDUCTION clauses. */
5709 static void
5710 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5712 gimple_seq sub_seq = NULL;
5713 gimple *stmt;
5714 tree x, c;
5715 int count = 0;
5717 /* OpenACC loop reductions are handled elsewhere. */
5718 if (is_gimple_omp_oacc (ctx->stmt))
5719 return;
5721 /* SIMD reductions are handled in lower_rec_input_clauses. */
5722 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5723 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5724 return;
5726 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5727 update in that case, otherwise use a lock. */
5728 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5729 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5731 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5732 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5734 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5735 count = -1;
5736 break;
5738 count++;
5741 if (count == 0)
5742 return;
5744 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5746 tree var, ref, new_var, orig_var;
5747 enum tree_code code;
5748 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5750 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5751 continue;
5753 orig_var = var = OMP_CLAUSE_DECL (c);
5754 if (TREE_CODE (var) == MEM_REF)
5756 var = TREE_OPERAND (var, 0);
5757 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5758 var = TREE_OPERAND (var, 0);
5759 if (TREE_CODE (var) == INDIRECT_REF
5760 || TREE_CODE (var) == ADDR_EXPR)
5761 var = TREE_OPERAND (var, 0);
5762 orig_var = var;
5763 if (is_variable_sized (var))
5765 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5766 var = DECL_VALUE_EXPR (var);
5767 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5768 var = TREE_OPERAND (var, 0);
5769 gcc_assert (DECL_P (var));
5772 new_var = lookup_decl (var, ctx);
5773 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5774 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5775 ref = build_outer_var_ref (var, ctx);
5776 code = OMP_CLAUSE_REDUCTION_CODE (c);
5778 /* reduction(-:var) sums up the partial results, so it acts
5779 identically to reduction(+:var). */
5780 if (code == MINUS_EXPR)
5781 code = PLUS_EXPR;
5783 if (count == 1)
5785 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5787 addr = save_expr (addr);
5788 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5789 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5790 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5791 gimplify_and_add (x, stmt_seqp);
5792 return;
5794 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5796 tree d = OMP_CLAUSE_DECL (c);
5797 tree type = TREE_TYPE (d);
5798 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5799 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5800 tree ptype = build_pointer_type (TREE_TYPE (type));
5801 tree bias = TREE_OPERAND (d, 1);
5802 d = TREE_OPERAND (d, 0);
5803 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5805 tree b = TREE_OPERAND (d, 1);
5806 b = maybe_lookup_decl (b, ctx);
5807 if (b == NULL)
5809 b = TREE_OPERAND (d, 1);
5810 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5812 if (integer_zerop (bias))
5813 bias = b;
5814 else
5816 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5817 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5818 TREE_TYPE (b), b, bias);
5820 d = TREE_OPERAND (d, 0);
5822 /* For ref build_outer_var_ref already performs this, so
5823 only new_var needs a dereference. */
5824 if (TREE_CODE (d) == INDIRECT_REF)
5826 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5827 gcc_assert (is_reference (var) && var == orig_var);
5829 else if (TREE_CODE (d) == ADDR_EXPR)
5831 if (orig_var == var)
5833 new_var = build_fold_addr_expr (new_var);
5834 ref = build_fold_addr_expr (ref);
5837 else
5839 gcc_assert (orig_var == var);
5840 if (is_reference (var))
5841 ref = build_fold_addr_expr (ref);
5843 if (DECL_P (v))
5845 tree t = maybe_lookup_decl (v, ctx);
5846 if (t)
5847 v = t;
5848 else
5849 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5850 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5852 if (!integer_zerop (bias))
5854 bias = fold_convert_loc (clause_loc, sizetype, bias);
5855 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5856 TREE_TYPE (new_var), new_var,
5857 unshare_expr (bias));
5858 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5859 TREE_TYPE (ref), ref, bias);
5861 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5862 ref = fold_convert_loc (clause_loc, ptype, ref);
5863 tree m = create_tmp_var (ptype, NULL);
5864 gimplify_assign (m, new_var, stmt_seqp);
5865 new_var = m;
5866 m = create_tmp_var (ptype, NULL);
5867 gimplify_assign (m, ref, stmt_seqp);
5868 ref = m;
5869 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5870 tree body = create_artificial_label (UNKNOWN_LOCATION);
5871 tree end = create_artificial_label (UNKNOWN_LOCATION);
5872 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5873 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5874 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5875 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5877 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5878 tree decl_placeholder
5879 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5880 SET_DECL_VALUE_EXPR (placeholder, out);
5881 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5882 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5883 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5884 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5885 gimple_seq_add_seq (&sub_seq,
5886 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5887 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5888 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5889 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5891 else
5893 x = build2 (code, TREE_TYPE (out), out, priv);
5894 out = unshare_expr (out);
5895 gimplify_assign (out, x, &sub_seq);
5897 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5898 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5899 gimple_seq_add_stmt (&sub_seq, g);
5900 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5901 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5902 gimple_seq_add_stmt (&sub_seq, g);
5903 g = gimple_build_assign (i, PLUS_EXPR, i,
5904 build_int_cst (TREE_TYPE (i), 1));
5905 gimple_seq_add_stmt (&sub_seq, g);
5906 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5907 gimple_seq_add_stmt (&sub_seq, g);
5908 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5910 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5912 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5914 if (is_reference (var)
5915 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5916 TREE_TYPE (ref)))
5917 ref = build_fold_addr_expr_loc (clause_loc, ref);
5918 SET_DECL_VALUE_EXPR (placeholder, ref);
5919 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5920 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5921 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5922 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5923 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5925 else
5927 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5928 ref = build_outer_var_ref (var, ctx);
5929 gimplify_assign (ref, x, &sub_seq);
5933 if (is_gimple_omp_oacc (ctx->stmt))
5934 return;
5936 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5938 gimple_seq_add_stmt (stmt_seqp, stmt);
5940 gimple_seq_add_seq (stmt_seqp, sub_seq);
5942 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5944 gimple_seq_add_stmt (stmt_seqp, stmt);
5948 /* Generate code to implement the COPYPRIVATE clauses. */
5950 static void
5951 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5952 omp_context *ctx)
5954 tree c;
5956 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5958 tree var, new_var, ref, x;
5959 bool by_ref;
5960 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5962 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5963 continue;
5965 var = OMP_CLAUSE_DECL (c);
5966 by_ref = use_pointer_for_field (var, NULL);
5968 ref = build_sender_ref (var, ctx);
5969 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5970 if (by_ref)
5972 x = build_fold_addr_expr_loc (clause_loc, new_var);
5973 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5975 gimplify_assign (ref, x, slist);
5977 ref = build_receiver_ref (var, false, ctx);
5978 if (by_ref)
5980 ref = fold_convert_loc (clause_loc,
5981 build_pointer_type (TREE_TYPE (new_var)),
5982 ref);
5983 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5985 if (is_reference (var))
5987 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5988 ref = build_simple_mem_ref_loc (clause_loc, ref);
5989 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5991 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5992 gimplify_and_add (x, rlist);
5997 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5998 and REDUCTION from the sender (aka parent) side. */
6000 static void
6001 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6002 omp_context *ctx)
6004 tree c, t;
6005 int ignored_looptemp = 0;
6006 bool is_taskloop = false;
6008 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6009 by GOMP_taskloop. */
6010 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6012 ignored_looptemp = 2;
6013 is_taskloop = true;
6016 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6018 tree val, ref, x, var;
6019 bool by_ref, do_in = false, do_out = false;
6020 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6022 switch (OMP_CLAUSE_CODE (c))
6024 case OMP_CLAUSE_PRIVATE:
6025 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6026 break;
6027 continue;
6028 case OMP_CLAUSE_FIRSTPRIVATE:
6029 case OMP_CLAUSE_COPYIN:
6030 case OMP_CLAUSE_LASTPRIVATE:
6031 case OMP_CLAUSE_REDUCTION:
6032 break;
6033 case OMP_CLAUSE_SHARED:
6034 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6035 break;
6036 continue;
6037 case OMP_CLAUSE__LOOPTEMP_:
6038 if (ignored_looptemp)
6040 ignored_looptemp--;
6041 continue;
6043 break;
6044 default:
6045 continue;
6048 val = OMP_CLAUSE_DECL (c);
6049 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6050 && TREE_CODE (val) == MEM_REF)
6052 val = TREE_OPERAND (val, 0);
6053 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6054 val = TREE_OPERAND (val, 0);
6055 if (TREE_CODE (val) == INDIRECT_REF
6056 || TREE_CODE (val) == ADDR_EXPR)
6057 val = TREE_OPERAND (val, 0);
6058 if (is_variable_sized (val))
6059 continue;
6062 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6063 outer taskloop region. */
6064 omp_context *ctx_for_o = ctx;
6065 if (is_taskloop
6066 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6067 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6068 ctx_for_o = ctx->outer;
6070 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6072 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6073 && is_global_var (var))
6074 continue;
6076 t = omp_member_access_dummy_var (var);
6077 if (t)
6079 var = DECL_VALUE_EXPR (var);
6080 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6081 if (o != t)
6082 var = unshare_and_remap (var, t, o);
6083 else
6084 var = unshare_expr (var);
6087 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6089 /* Handle taskloop firstprivate/lastprivate, where the
6090 lastprivate on GIMPLE_OMP_TASK is represented as
6091 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6092 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6093 x = omp_build_component_ref (ctx->sender_decl, f);
6094 if (use_pointer_for_field (val, ctx))
6095 var = build_fold_addr_expr (var);
6096 gimplify_assign (x, var, ilist);
6097 DECL_ABSTRACT_ORIGIN (f) = NULL;
6098 continue;
6101 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6102 || val == OMP_CLAUSE_DECL (c))
6103 && is_variable_sized (val))
6104 continue;
6105 by_ref = use_pointer_for_field (val, NULL);
6107 switch (OMP_CLAUSE_CODE (c))
6109 case OMP_CLAUSE_PRIVATE:
6110 case OMP_CLAUSE_FIRSTPRIVATE:
6111 case OMP_CLAUSE_COPYIN:
6112 case OMP_CLAUSE__LOOPTEMP_:
6113 do_in = true;
6114 break;
6116 case OMP_CLAUSE_LASTPRIVATE:
6117 if (by_ref || is_reference (val))
6119 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6120 continue;
6121 do_in = true;
6123 else
6125 do_out = true;
6126 if (lang_hooks.decls.omp_private_outer_ref (val))
6127 do_in = true;
6129 break;
6131 case OMP_CLAUSE_REDUCTION:
6132 do_in = true;
6133 if (val == OMP_CLAUSE_DECL (c))
6134 do_out = !(by_ref || is_reference (val));
6135 else
6136 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6137 break;
6139 default:
6140 gcc_unreachable ();
6143 if (do_in)
6145 ref = build_sender_ref (val, ctx);
6146 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6147 gimplify_assign (ref, x, ilist);
6148 if (is_task_ctx (ctx))
6149 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6152 if (do_out)
6154 ref = build_sender_ref (val, ctx);
6155 gimplify_assign (var, ref, olist);
6160 /* Generate code to implement SHARED from the sender (aka parent)
6161 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6162 list things that got automatically shared. */
6164 static void
6165 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6167 tree var, ovar, nvar, t, f, x, record_type;
6169 if (ctx->record_type == NULL)
6170 return;
6172 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6173 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6175 ovar = DECL_ABSTRACT_ORIGIN (f);
6176 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6177 continue;
6179 nvar = maybe_lookup_decl (ovar, ctx);
6180 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6181 continue;
6183 /* If CTX is a nested parallel directive. Find the immediately
6184 enclosing parallel or workshare construct that contains a
6185 mapping for OVAR. */
6186 var = lookup_decl_in_outer_ctx (ovar, ctx);
6188 t = omp_member_access_dummy_var (var);
6189 if (t)
6191 var = DECL_VALUE_EXPR (var);
6192 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6193 if (o != t)
6194 var = unshare_and_remap (var, t, o);
6195 else
6196 var = unshare_expr (var);
6199 if (use_pointer_for_field (ovar, ctx))
6201 x = build_sender_ref (ovar, ctx);
6202 var = build_fold_addr_expr (var);
6203 gimplify_assign (x, var, ilist);
6205 else
6207 x = build_sender_ref (ovar, ctx);
6208 gimplify_assign (x, var, ilist);
6210 if (!TREE_READONLY (var)
6211 /* We don't need to receive a new reference to a result
6212 or parm decl. In fact we may not store to it as we will
6213 invalidate any pending RSO and generate wrong gimple
6214 during inlining. */
6215 && !((TREE_CODE (var) == RESULT_DECL
6216 || TREE_CODE (var) == PARM_DECL)
6217 && DECL_BY_REFERENCE (var)))
6219 x = build_sender_ref (ovar, ctx);
6220 gimplify_assign (var, x, olist);
6226 /* Emit an OpenACC head marker call, encapulating the partitioning and
6227 other information that must be processed by the target compiler.
6228 Return the maximum number of dimensions the associated loop might
6229 be partitioned over. */
6231 static unsigned
6232 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6233 gimple_seq *seq, omp_context *ctx)
6235 unsigned levels = 0;
6236 unsigned tag = 0;
6237 tree gang_static = NULL_TREE;
6238 auto_vec<tree, 5> args;
6240 args.quick_push (build_int_cst
6241 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6242 args.quick_push (ddvar);
6243 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6245 switch (OMP_CLAUSE_CODE (c))
6247 case OMP_CLAUSE_GANG:
6248 tag |= OLF_DIM_GANG;
6249 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6250 /* static:* is represented by -1, and we can ignore it, as
6251 scheduling is always static. */
6252 if (gang_static && integer_minus_onep (gang_static))
6253 gang_static = NULL_TREE;
6254 levels++;
6255 break;
6257 case OMP_CLAUSE_WORKER:
6258 tag |= OLF_DIM_WORKER;
6259 levels++;
6260 break;
6262 case OMP_CLAUSE_VECTOR:
6263 tag |= OLF_DIM_VECTOR;
6264 levels++;
6265 break;
6267 case OMP_CLAUSE_SEQ:
6268 tag |= OLF_SEQ;
6269 break;
6271 case OMP_CLAUSE_AUTO:
6272 tag |= OLF_AUTO;
6273 break;
6275 case OMP_CLAUSE_INDEPENDENT:
6276 tag |= OLF_INDEPENDENT;
6277 break;
6279 default:
6280 continue;
6284 if (gang_static)
6286 if (DECL_P (gang_static))
6287 gang_static = build_outer_var_ref (gang_static, ctx);
6288 tag |= OLF_GANG_STATIC;
6291 /* In a parallel region, loops are implicitly INDEPENDENT. */
6292 omp_context *tgt = enclosing_target_ctx (ctx);
6293 if (!tgt || is_oacc_parallel (tgt))
6294 tag |= OLF_INDEPENDENT;
6296 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6297 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6298 | OLF_SEQ)))
6299 tag |= OLF_AUTO;
6301 /* Ensure at least one level. */
6302 if (!levels)
6303 levels++;
6305 args.quick_push (build_int_cst (integer_type_node, levels));
6306 args.quick_push (build_int_cst (integer_type_node, tag));
6307 if (gang_static)
6308 args.quick_push (gang_static);
6310 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6311 gimple_set_location (call, loc);
6312 gimple_set_lhs (call, ddvar);
6313 gimple_seq_add_stmt (seq, call);
6315 return levels;
6318 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6319 partitioning level of the enclosed region. */
6321 static void
6322 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6323 tree tofollow, gimple_seq *seq)
6325 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6326 : IFN_UNIQUE_OACC_TAIL_MARK);
6327 tree marker = build_int_cst (integer_type_node, marker_kind);
6328 int nargs = 2 + (tofollow != NULL_TREE);
6329 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6330 marker, ddvar, tofollow);
6331 gimple_set_location (call, loc);
6332 gimple_set_lhs (call, ddvar);
6333 gimple_seq_add_stmt (seq, call);
6336 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6337 the loop clauses, from which we extract reductions. Initialize
6338 HEAD and TAIL. */
6340 static void
6341 lower_oacc_head_tail (location_t loc, tree clauses,
6342 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6344 bool inner = false;
6345 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6346 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6348 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6349 if (!count)
6350 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6352 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6353 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6355 for (unsigned done = 1; count; count--, done++)
6357 gimple_seq fork_seq = NULL;
6358 gimple_seq join_seq = NULL;
6360 tree place = build_int_cst (integer_type_node, -1);
6361 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6362 fork_kind, ddvar, place);
6363 gimple_set_location (fork, loc);
6364 gimple_set_lhs (fork, ddvar);
6366 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6367 join_kind, ddvar, place);
6368 gimple_set_location (join, loc);
6369 gimple_set_lhs (join, ddvar);
6371 /* Mark the beginning of this level sequence. */
6372 if (inner)
6373 lower_oacc_loop_marker (loc, ddvar, true,
6374 build_int_cst (integer_type_node, count),
6375 &fork_seq);
6376 lower_oacc_loop_marker (loc, ddvar, false,
6377 build_int_cst (integer_type_node, done),
6378 &join_seq);
6380 lower_oacc_reductions (loc, clauses, place, inner,
6381 fork, join, &fork_seq, &join_seq, ctx);
6383 /* Append this level to head. */
6384 gimple_seq_add_seq (head, fork_seq);
6385 /* Prepend it to tail. */
6386 gimple_seq_add_seq (&join_seq, *tail);
6387 *tail = join_seq;
6389 inner = true;
6392 /* Mark the end of the sequence. */
6393 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6394 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6397 /* A convenience function to build an empty GIMPLE_COND with just the
6398 condition. */
6400 static gcond *
6401 gimple_build_cond_empty (tree cond)
6403 enum tree_code pred_code;
6404 tree lhs, rhs;
6406 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6407 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6410 /* Return true if a parallel REGION is within a declare target function or
6411 within a target region and is not a part of a gridified target. */
6413 static bool
6414 parallel_needs_hsa_kernel_p (struct omp_region *region)
6416 bool indirect = false;
6417 for (region = region->outer; region; region = region->outer)
6419 if (region->type == GIMPLE_OMP_PARALLEL)
6420 indirect = true;
6421 else if (region->type == GIMPLE_OMP_TARGET)
6423 gomp_target *tgt_stmt
6424 = as_a <gomp_target *> (last_stmt (region->entry));
6426 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6427 OMP_CLAUSE__GRIDDIM_))
6428 return indirect;
6429 else
6430 return true;
6434 if (lookup_attribute ("omp declare target",
6435 DECL_ATTRIBUTES (current_function_decl)))
6436 return true;
6438 return false;
6441 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6442 bool = false);
6444 /* Build the function calls to GOMP_parallel_start etc to actually
6445 generate the parallel operation. REGION is the parallel region
6446 being expanded. BB is the block where to insert the code. WS_ARGS
6447 will be set if this is a call to a combined parallel+workshare
6448 construct, it contains the list of additional arguments needed by
6449 the workshare construct. */
6451 static void
6452 expand_parallel_call (struct omp_region *region, basic_block bb,
6453 gomp_parallel *entry_stmt,
6454 vec<tree, va_gc> *ws_args)
6456 tree t, t1, t2, val, cond, c, clauses, flags;
6457 gimple_stmt_iterator gsi;
6458 gimple *stmt;
6459 enum built_in_function start_ix;
6460 int start_ix2;
6461 location_t clause_loc;
6462 vec<tree, va_gc> *args;
6464 clauses = gimple_omp_parallel_clauses (entry_stmt);
6466 /* Determine what flavor of GOMP_parallel we will be
6467 emitting. */
6468 start_ix = BUILT_IN_GOMP_PARALLEL;
6469 if (is_combined_parallel (region))
6471 switch (region->inner->type)
6473 case GIMPLE_OMP_FOR:
6474 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6475 switch (region->inner->sched_kind)
6477 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6478 start_ix2 = 3;
6479 break;
6480 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6481 case OMP_CLAUSE_SCHEDULE_GUIDED:
6482 if (region->inner->sched_modifiers
6483 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6485 start_ix2 = 3 + region->inner->sched_kind;
6486 break;
6488 /* FALLTHRU */
6489 default:
6490 start_ix2 = region->inner->sched_kind;
6491 break;
6493 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6494 start_ix = (enum built_in_function) start_ix2;
6495 break;
6496 case GIMPLE_OMP_SECTIONS:
6497 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6498 break;
6499 default:
6500 gcc_unreachable ();
6504 /* By default, the value of NUM_THREADS is zero (selected at run time)
6505 and there is no conditional. */
6506 cond = NULL_TREE;
6507 val = build_int_cst (unsigned_type_node, 0);
6508 flags = build_int_cst (unsigned_type_node, 0);
6510 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6511 if (c)
6512 cond = OMP_CLAUSE_IF_EXPR (c);
6514 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6515 if (c)
6517 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6518 clause_loc = OMP_CLAUSE_LOCATION (c);
6520 else
6521 clause_loc = gimple_location (entry_stmt);
6523 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6524 if (c)
6525 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6527 /* Ensure 'val' is of the correct type. */
6528 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6530 /* If we found the clause 'if (cond)', build either
6531 (cond != 0) or (cond ? val : 1u). */
6532 if (cond)
6534 cond = gimple_boolify (cond);
6536 if (integer_zerop (val))
6537 val = fold_build2_loc (clause_loc,
6538 EQ_EXPR, unsigned_type_node, cond,
6539 build_int_cst (TREE_TYPE (cond), 0));
6540 else
6542 basic_block cond_bb, then_bb, else_bb;
6543 edge e, e_then, e_else;
6544 tree tmp_then, tmp_else, tmp_join, tmp_var;
6546 tmp_var = create_tmp_var (TREE_TYPE (val));
6547 if (gimple_in_ssa_p (cfun))
6549 tmp_then = make_ssa_name (tmp_var);
6550 tmp_else = make_ssa_name (tmp_var);
6551 tmp_join = make_ssa_name (tmp_var);
6553 else
6555 tmp_then = tmp_var;
6556 tmp_else = tmp_var;
6557 tmp_join = tmp_var;
6560 e = split_block_after_labels (bb);
6561 cond_bb = e->src;
6562 bb = e->dest;
6563 remove_edge (e);
6565 then_bb = create_empty_bb (cond_bb);
6566 else_bb = create_empty_bb (then_bb);
6567 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6568 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6570 stmt = gimple_build_cond_empty (cond);
6571 gsi = gsi_start_bb (cond_bb);
6572 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6574 gsi = gsi_start_bb (then_bb);
6575 expand_omp_build_assign (&gsi, tmp_then, val, true);
6577 gsi = gsi_start_bb (else_bb);
6578 expand_omp_build_assign (&gsi, tmp_else,
6579 build_int_cst (unsigned_type_node, 1),
6580 true);
6582 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6583 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6584 add_bb_to_loop (then_bb, cond_bb->loop_father);
6585 add_bb_to_loop (else_bb, cond_bb->loop_father);
6586 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6587 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6589 if (gimple_in_ssa_p (cfun))
6591 gphi *phi = create_phi_node (tmp_join, bb);
6592 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6593 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6596 val = tmp_join;
6599 gsi = gsi_start_bb (bb);
6600 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6601 false, GSI_CONTINUE_LINKING);
6604 gsi = gsi_last_bb (bb);
6605 t = gimple_omp_parallel_data_arg (entry_stmt);
6606 if (t == NULL)
6607 t1 = null_pointer_node;
6608 else
6609 t1 = build_fold_addr_expr (t);
6610 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6611 t2 = build_fold_addr_expr (child_fndecl);
6613 vec_alloc (args, 4 + vec_safe_length (ws_args));
6614 args->quick_push (t2);
6615 args->quick_push (t1);
6616 args->quick_push (val);
6617 if (ws_args)
6618 args->splice (*ws_args);
6619 args->quick_push (flags);
6621 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6622 builtin_decl_explicit (start_ix), args);
6624 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6625 false, GSI_CONTINUE_LINKING);
6627 if (hsa_gen_requested_p ()
6628 && parallel_needs_hsa_kernel_p (region))
6630 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6631 hsa_register_kernel (child_cnode);
6635 /* Insert a function call whose name is FUNC_NAME with the information from
6636 ENTRY_STMT into the basic_block BB. */
6638 static void
6639 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6640 vec <tree, va_gc> *ws_args)
6642 tree t, t1, t2;
6643 gimple_stmt_iterator gsi;
6644 vec <tree, va_gc> *args;
6646 gcc_assert (vec_safe_length (ws_args) == 2);
6647 tree func_name = (*ws_args)[0];
6648 tree grain = (*ws_args)[1];
6650 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6651 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6652 gcc_assert (count != NULL_TREE);
6653 count = OMP_CLAUSE_OPERAND (count, 0);
6655 gsi = gsi_last_bb (bb);
6656 t = gimple_omp_parallel_data_arg (entry_stmt);
6657 if (t == NULL)
6658 t1 = null_pointer_node;
6659 else
6660 t1 = build_fold_addr_expr (t);
6661 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6663 vec_alloc (args, 4);
6664 args->quick_push (t2);
6665 args->quick_push (t1);
6666 args->quick_push (count);
6667 args->quick_push (grain);
6668 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6670 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6671 GSI_CONTINUE_LINKING);
6674 /* Build the function call to GOMP_task to actually
6675 generate the task operation. BB is the block where to insert the code. */
6677 static void
6678 expand_task_call (struct omp_region *region, basic_block bb,
6679 gomp_task *entry_stmt)
6681 tree t1, t2, t3;
6682 gimple_stmt_iterator gsi;
6683 location_t loc = gimple_location (entry_stmt);
6685 tree clauses = gimple_omp_task_clauses (entry_stmt);
6687 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6688 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6689 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6690 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6691 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6692 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6694 unsigned int iflags
6695 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6696 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6697 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6699 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6700 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6701 tree num_tasks = NULL_TREE;
6702 bool ull = false;
6703 if (taskloop_p)
6705 gimple *g = last_stmt (region->outer->entry);
6706 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6707 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6708 struct omp_for_data fd;
6709 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6710 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6711 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6712 OMP_CLAUSE__LOOPTEMP_);
6713 startvar = OMP_CLAUSE_DECL (startvar);
6714 endvar = OMP_CLAUSE_DECL (endvar);
6715 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6716 if (fd.loop.cond_code == LT_EXPR)
6717 iflags |= GOMP_TASK_FLAG_UP;
6718 tree tclauses = gimple_omp_for_clauses (g);
6719 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6720 if (num_tasks)
6721 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6722 else
6724 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6725 if (num_tasks)
6727 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6728 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6730 else
6731 num_tasks = integer_zero_node;
6733 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6734 if (ifc == NULL_TREE)
6735 iflags |= GOMP_TASK_FLAG_IF;
6736 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6737 iflags |= GOMP_TASK_FLAG_NOGROUP;
6738 ull = fd.iter_type == long_long_unsigned_type_node;
6740 else if (priority)
6741 iflags |= GOMP_TASK_FLAG_PRIORITY;
6743 tree flags = build_int_cst (unsigned_type_node, iflags);
6745 tree cond = boolean_true_node;
6746 if (ifc)
6748 if (taskloop_p)
6750 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6751 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6752 build_int_cst (unsigned_type_node,
6753 GOMP_TASK_FLAG_IF),
6754 build_int_cst (unsigned_type_node, 0));
6755 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6756 flags, t);
6758 else
6759 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6762 if (finalc)
6764 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6765 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6766 build_int_cst (unsigned_type_node,
6767 GOMP_TASK_FLAG_FINAL),
6768 build_int_cst (unsigned_type_node, 0));
6769 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6771 if (depend)
6772 depend = OMP_CLAUSE_DECL (depend);
6773 else
6774 depend = build_int_cst (ptr_type_node, 0);
6775 if (priority)
6776 priority = fold_convert (integer_type_node,
6777 OMP_CLAUSE_PRIORITY_EXPR (priority));
6778 else
6779 priority = integer_zero_node;
6781 gsi = gsi_last_bb (bb);
6782 tree t = gimple_omp_task_data_arg (entry_stmt);
6783 if (t == NULL)
6784 t2 = null_pointer_node;
6785 else
6786 t2 = build_fold_addr_expr_loc (loc, t);
6787 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6788 t = gimple_omp_task_copy_fn (entry_stmt);
6789 if (t == NULL)
6790 t3 = null_pointer_node;
6791 else
6792 t3 = build_fold_addr_expr_loc (loc, t);
6794 if (taskloop_p)
6795 t = build_call_expr (ull
6796 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6797 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6798 11, t1, t2, t3,
6799 gimple_omp_task_arg_size (entry_stmt),
6800 gimple_omp_task_arg_align (entry_stmt), flags,
6801 num_tasks, priority, startvar, endvar, step);
6802 else
6803 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6804 9, t1, t2, t3,
6805 gimple_omp_task_arg_size (entry_stmt),
6806 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6807 depend, priority);
6809 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6810 false, GSI_CONTINUE_LINKING);
6814 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6815 catch handler and return it. This prevents programs from violating the
6816 structured block semantics with throws. */
6818 static gimple_seq
6819 maybe_catch_exception (gimple_seq body)
6821 gimple *g;
6822 tree decl;
6824 if (!flag_exceptions)
6825 return body;
6827 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6828 decl = lang_hooks.eh_protect_cleanup_actions ();
6829 else
6830 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6832 g = gimple_build_eh_must_not_throw (decl);
6833 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6834 GIMPLE_TRY_CATCH);
6836 return gimple_seq_alloc_with_stmt (g);
6839 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6841 static tree
6842 vec2chain (vec<tree, va_gc> *v)
6844 tree chain = NULL_TREE, t;
6845 unsigned ix;
6847 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6849 DECL_CHAIN (t) = chain;
6850 chain = t;
6853 return chain;
6857 /* Remove barriers in REGION->EXIT's block. Note that this is only
6858 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6859 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6860 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6861 removed. */
6863 static void
6864 remove_exit_barrier (struct omp_region *region)
6866 gimple_stmt_iterator gsi;
6867 basic_block exit_bb;
6868 edge_iterator ei;
6869 edge e;
6870 gimple *stmt;
6871 int any_addressable_vars = -1;
6873 exit_bb = region->exit;
6875 /* If the parallel region doesn't return, we don't have REGION->EXIT
6876 block at all. */
6877 if (! exit_bb)
6878 return;
6880 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6881 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6882 statements that can appear in between are extremely limited -- no
6883 memory operations at all. Here, we allow nothing at all, so the
6884 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6885 gsi = gsi_last_bb (exit_bb);
6886 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6887 gsi_prev (&gsi);
6888 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6889 return;
6891 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6893 gsi = gsi_last_bb (e->src);
6894 if (gsi_end_p (gsi))
6895 continue;
6896 stmt = gsi_stmt (gsi);
6897 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6898 && !gimple_omp_return_nowait_p (stmt))
6900 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6901 in many cases. If there could be tasks queued, the barrier
6902 might be needed to let the tasks run before some local
6903 variable of the parallel that the task uses as shared
6904 runs out of scope. The task can be spawned either
6905 from within current function (this would be easy to check)
6906 or from some function it calls and gets passed an address
6907 of such a variable. */
6908 if (any_addressable_vars < 0)
6910 gomp_parallel *parallel_stmt
6911 = as_a <gomp_parallel *> (last_stmt (region->entry));
6912 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6913 tree local_decls, block, decl;
6914 unsigned ix;
6916 any_addressable_vars = 0;
6917 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6918 if (TREE_ADDRESSABLE (decl))
6920 any_addressable_vars = 1;
6921 break;
6923 for (block = gimple_block (stmt);
6924 !any_addressable_vars
6925 && block
6926 && TREE_CODE (block) == BLOCK;
6927 block = BLOCK_SUPERCONTEXT (block))
6929 for (local_decls = BLOCK_VARS (block);
6930 local_decls;
6931 local_decls = DECL_CHAIN (local_decls))
6932 if (TREE_ADDRESSABLE (local_decls))
6934 any_addressable_vars = 1;
6935 break;
6937 if (block == gimple_block (parallel_stmt))
6938 break;
6941 if (!any_addressable_vars)
6942 gimple_omp_return_set_nowait (stmt);
6947 static void
6948 remove_exit_barriers (struct omp_region *region)
6950 if (region->type == GIMPLE_OMP_PARALLEL)
6951 remove_exit_barrier (region);
6953 if (region->inner)
6955 region = region->inner;
6956 remove_exit_barriers (region);
6957 while (region->next)
6959 region = region->next;
6960 remove_exit_barriers (region);
6965 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6966 calls. These can't be declared as const functions, but
6967 within one parallel body they are constant, so they can be
6968 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6969 which are declared const. Similarly for task body, except
6970 that in untied task omp_get_thread_num () can change at any task
6971 scheduling point. */
6973 static void
6974 optimize_omp_library_calls (gimple *entry_stmt)
6976 basic_block bb;
6977 gimple_stmt_iterator gsi;
6978 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6979 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6980 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6981 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6982 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6983 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6984 OMP_CLAUSE_UNTIED) != NULL);
6986 FOR_EACH_BB_FN (bb, cfun)
6987 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6989 gimple *call = gsi_stmt (gsi);
6990 tree decl;
6992 if (is_gimple_call (call)
6993 && (decl = gimple_call_fndecl (call))
6994 && DECL_EXTERNAL (decl)
6995 && TREE_PUBLIC (decl)
6996 && DECL_INITIAL (decl) == NULL)
6998 tree built_in;
7000 if (DECL_NAME (decl) == thr_num_id)
7002 /* In #pragma omp task untied omp_get_thread_num () can change
7003 during the execution of the task region. */
7004 if (untied_task)
7005 continue;
7006 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7008 else if (DECL_NAME (decl) == num_thr_id)
7009 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7010 else
7011 continue;
7013 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7014 || gimple_call_num_args (call) != 0)
7015 continue;
7017 if (flag_exceptions && !TREE_NOTHROW (decl))
7018 continue;
7020 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7021 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7022 TREE_TYPE (TREE_TYPE (built_in))))
7023 continue;
7025 gimple_call_set_fndecl (call, built_in);
7030 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7031 regimplified. */
7033 static tree
7034 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7036 tree t = *tp;
7038 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7039 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7040 return t;
7042 if (TREE_CODE (t) == ADDR_EXPR)
7043 recompute_tree_invariant_for_addr_expr (t);
7045 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7046 return NULL_TREE;
7049 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7051 static void
7052 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7053 bool after)
7055 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7056 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7057 !after, after ? GSI_CONTINUE_LINKING
7058 : GSI_SAME_STMT);
7059 gimple *stmt = gimple_build_assign (to, from);
7060 if (after)
7061 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7062 else
7063 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7064 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7065 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7067 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7068 gimple_regimplify_operands (stmt, &gsi);
7072 /* Expand the OpenMP parallel or task directive starting at REGION. */
7074 static void
7075 expand_omp_taskreg (struct omp_region *region)
7077 basic_block entry_bb, exit_bb, new_bb;
7078 struct function *child_cfun;
7079 tree child_fn, block, t;
7080 gimple_stmt_iterator gsi;
7081 gimple *entry_stmt, *stmt;
7082 edge e;
7083 vec<tree, va_gc> *ws_args;
7085 entry_stmt = last_stmt (region->entry);
7086 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7087 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7089 entry_bb = region->entry;
7090 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7091 exit_bb = region->cont;
7092 else
7093 exit_bb = region->exit;
7095 bool is_cilk_for
7096 = (flag_cilkplus
7097 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7098 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7099 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7101 if (is_cilk_for)
7102 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7103 and the inner statement contains the name of the built-in function
7104 and grain. */
7105 ws_args = region->inner->ws_args;
7106 else if (is_combined_parallel (region))
7107 ws_args = region->ws_args;
7108 else
7109 ws_args = NULL;
7111 if (child_cfun->cfg)
7113 /* Due to inlining, it may happen that we have already outlined
7114 the region, in which case all we need to do is make the
7115 sub-graph unreachable and emit the parallel call. */
7116 edge entry_succ_e, exit_succ_e;
7118 entry_succ_e = single_succ_edge (entry_bb);
7120 gsi = gsi_last_bb (entry_bb);
7121 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7122 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7123 gsi_remove (&gsi, true);
7125 new_bb = entry_bb;
7126 if (exit_bb)
7128 exit_succ_e = single_succ_edge (exit_bb);
7129 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7131 remove_edge_and_dominated_blocks (entry_succ_e);
7133 else
7135 unsigned srcidx, dstidx, num;
7137 /* If the parallel region needs data sent from the parent
7138 function, then the very first statement (except possible
7139 tree profile counter updates) of the parallel body
7140 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7141 &.OMP_DATA_O is passed as an argument to the child function,
7142 we need to replace it with the argument as seen by the child
7143 function.
7145 In most cases, this will end up being the identity assignment
7146 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7147 a function call that has been inlined, the original PARM_DECL
7148 .OMP_DATA_I may have been converted into a different local
7149 variable. In which case, we need to keep the assignment. */
7150 if (gimple_omp_taskreg_data_arg (entry_stmt))
7152 basic_block entry_succ_bb
7153 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7154 : FALLTHRU_EDGE (entry_bb)->dest;
7155 tree arg;
7156 gimple *parcopy_stmt = NULL;
7158 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7160 gimple *stmt;
7162 gcc_assert (!gsi_end_p (gsi));
7163 stmt = gsi_stmt (gsi);
7164 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7165 continue;
7167 if (gimple_num_ops (stmt) == 2)
7169 tree arg = gimple_assign_rhs1 (stmt);
7171 /* We're ignore the subcode because we're
7172 effectively doing a STRIP_NOPS. */
7174 if (TREE_CODE (arg) == ADDR_EXPR
7175 && TREE_OPERAND (arg, 0)
7176 == gimple_omp_taskreg_data_arg (entry_stmt))
7178 parcopy_stmt = stmt;
7179 break;
7184 gcc_assert (parcopy_stmt != NULL);
7185 arg = DECL_ARGUMENTS (child_fn);
7187 if (!gimple_in_ssa_p (cfun))
7189 if (gimple_assign_lhs (parcopy_stmt) == arg)
7190 gsi_remove (&gsi, true);
7191 else
7193 /* ?? Is setting the subcode really necessary ?? */
7194 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7195 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7198 else
7200 tree lhs = gimple_assign_lhs (parcopy_stmt);
7201 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7202 /* We'd like to set the rhs to the default def in the child_fn,
7203 but it's too early to create ssa names in the child_fn.
7204 Instead, we set the rhs to the parm. In
7205 move_sese_region_to_fn, we introduce a default def for the
7206 parm, map the parm to it's default def, and once we encounter
7207 this stmt, replace the parm with the default def. */
7208 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7209 update_stmt (parcopy_stmt);
7213 /* Declare local variables needed in CHILD_CFUN. */
7214 block = DECL_INITIAL (child_fn);
7215 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7216 /* The gimplifier could record temporaries in parallel/task block
7217 rather than in containing function's local_decls chain,
7218 which would mean cgraph missed finalizing them. Do it now. */
7219 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7220 if (TREE_CODE (t) == VAR_DECL
7221 && TREE_STATIC (t)
7222 && !DECL_EXTERNAL (t))
7223 varpool_node::finalize_decl (t);
7224 DECL_SAVED_TREE (child_fn) = NULL;
7225 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7226 gimple_set_body (child_fn, NULL);
7227 TREE_USED (block) = 1;
7229 /* Reset DECL_CONTEXT on function arguments. */
7230 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7231 DECL_CONTEXT (t) = child_fn;
7233 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7234 so that it can be moved to the child function. */
7235 gsi = gsi_last_bb (entry_bb);
7236 stmt = gsi_stmt (gsi);
7237 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7238 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7239 e = split_block (entry_bb, stmt);
7240 gsi_remove (&gsi, true);
7241 entry_bb = e->dest;
7242 edge e2 = NULL;
7243 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7244 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7245 else
7247 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7248 gcc_assert (e2->dest == region->exit);
7249 remove_edge (BRANCH_EDGE (entry_bb));
7250 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7251 gsi = gsi_last_bb (region->exit);
7252 gcc_assert (!gsi_end_p (gsi)
7253 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7254 gsi_remove (&gsi, true);
7257 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7258 if (exit_bb)
7260 gsi = gsi_last_bb (exit_bb);
7261 gcc_assert (!gsi_end_p (gsi)
7262 && (gimple_code (gsi_stmt (gsi))
7263 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7264 stmt = gimple_build_return (NULL);
7265 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7266 gsi_remove (&gsi, true);
7269 /* Move the parallel region into CHILD_CFUN. */
7271 if (gimple_in_ssa_p (cfun))
7273 init_tree_ssa (child_cfun);
7274 init_ssa_operands (child_cfun);
7275 child_cfun->gimple_df->in_ssa_p = true;
7276 block = NULL_TREE;
7278 else
7279 block = gimple_block (entry_stmt);
7281 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7282 if (exit_bb)
7283 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7284 if (e2)
7286 basic_block dest_bb = e2->dest;
7287 if (!exit_bb)
7288 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7289 remove_edge (e2);
7290 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7292 /* When the OMP expansion process cannot guarantee an up-to-date
7293 loop tree arrange for the child function to fixup loops. */
7294 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7295 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7297 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7298 num = vec_safe_length (child_cfun->local_decls);
7299 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7301 t = (*child_cfun->local_decls)[srcidx];
7302 if (DECL_CONTEXT (t) == cfun->decl)
7303 continue;
7304 if (srcidx != dstidx)
7305 (*child_cfun->local_decls)[dstidx] = t;
7306 dstidx++;
7308 if (dstidx != num)
7309 vec_safe_truncate (child_cfun->local_decls, dstidx);
7311 /* Inform the callgraph about the new function. */
7312 child_cfun->curr_properties = cfun->curr_properties;
7313 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7314 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7315 cgraph_node *node = cgraph_node::get_create (child_fn);
7316 node->parallelized_function = 1;
7317 cgraph_node::add_new_function (child_fn, true);
7319 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7320 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7322 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7323 fixed in a following pass. */
7324 push_cfun (child_cfun);
7325 if (need_asm)
7326 assign_assembler_name_if_neeeded (child_fn);
7328 if (optimize)
7329 optimize_omp_library_calls (entry_stmt);
7330 cgraph_edge::rebuild_edges ();
7332 /* Some EH regions might become dead, see PR34608. If
7333 pass_cleanup_cfg isn't the first pass to happen with the
7334 new child, these dead EH edges might cause problems.
7335 Clean them up now. */
7336 if (flag_exceptions)
7338 basic_block bb;
7339 bool changed = false;
7341 FOR_EACH_BB_FN (bb, cfun)
7342 changed |= gimple_purge_dead_eh_edges (bb);
7343 if (changed)
7344 cleanup_tree_cfg ();
7346 if (gimple_in_ssa_p (cfun))
7347 update_ssa (TODO_update_ssa);
7348 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7349 verify_loop_structure ();
7350 pop_cfun ();
7352 if (dump_file && !gimple_in_ssa_p (cfun))
7354 omp_any_child_fn_dumped = true;
7355 dump_function_header (dump_file, child_fn, dump_flags);
7356 dump_function_to_file (child_fn, dump_file, dump_flags);
7360 /* Emit a library call to launch the children threads. */
7361 if (is_cilk_for)
7362 expand_cilk_for_call (new_bb,
7363 as_a <gomp_parallel *> (entry_stmt), ws_args);
7364 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7365 expand_parallel_call (region, new_bb,
7366 as_a <gomp_parallel *> (entry_stmt), ws_args);
7367 else
7368 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7369 if (gimple_in_ssa_p (cfun))
7370 update_ssa (TODO_update_ssa_only_virtuals);
7373 /* Information about members of an OpenACC collapsed loop nest. */
7375 struct oacc_collapse
7377 tree base; /* Base value. */
7378 tree iters; /* Number of steps. */
7379 tree step; /* step size. */
7382 /* Helper for expand_oacc_for. Determine collapsed loop information.
7383 Fill in COUNTS array. Emit any initialization code before GSI.
7384 Return the calculated outer loop bound of BOUND_TYPE. */
7386 static tree
7387 expand_oacc_collapse_init (const struct omp_for_data *fd,
7388 gimple_stmt_iterator *gsi,
7389 oacc_collapse *counts, tree bound_type)
7391 tree total = build_int_cst (bound_type, 1);
7392 int ix;
7394 gcc_assert (integer_onep (fd->loop.step));
7395 gcc_assert (integer_zerop (fd->loop.n1));
7397 for (ix = 0; ix != fd->collapse; ix++)
7399 const omp_for_data_loop *loop = &fd->loops[ix];
7401 tree iter_type = TREE_TYPE (loop->v);
7402 tree diff_type = iter_type;
7403 tree plus_type = iter_type;
7405 gcc_assert (loop->cond_code == fd->loop.cond_code);
7407 if (POINTER_TYPE_P (iter_type))
7408 plus_type = sizetype;
7409 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7410 diff_type = signed_type_for (diff_type);
7412 tree b = loop->n1;
7413 tree e = loop->n2;
7414 tree s = loop->step;
7415 bool up = loop->cond_code == LT_EXPR;
7416 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7417 bool negating;
7418 tree expr;
7420 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7421 true, GSI_SAME_STMT);
7422 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7423 true, GSI_SAME_STMT);
7425 /* Convert the step, avoiding possible unsigned->signed overflow. */
7426 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7427 if (negating)
7428 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7429 s = fold_convert (diff_type, s);
7430 if (negating)
7431 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7432 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7433 true, GSI_SAME_STMT);
7435 /* Determine the range, avoiding possible unsigned->signed overflow. */
7436 negating = !up && TYPE_UNSIGNED (iter_type);
7437 expr = fold_build2 (MINUS_EXPR, plus_type,
7438 fold_convert (plus_type, negating ? b : e),
7439 fold_convert (plus_type, negating ? e : b));
7440 expr = fold_convert (diff_type, expr);
7441 if (negating)
7442 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7443 tree range = force_gimple_operand_gsi
7444 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7446 /* Determine number of iterations. */
7447 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7448 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7449 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7451 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7452 true, GSI_SAME_STMT);
7454 counts[ix].base = b;
7455 counts[ix].iters = iters;
7456 counts[ix].step = s;
7458 total = fold_build2 (MULT_EXPR, bound_type, total,
7459 fold_convert (bound_type, iters));
7462 return total;
7465 /* Emit initializers for collapsed loop members. IVAR is the outer
7466 loop iteration variable, from which collapsed loop iteration values
7467 are calculated. COUNTS array has been initialized by
7468 expand_oacc_collapse_inits. */
7470 static void
7471 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7472 gimple_stmt_iterator *gsi,
7473 const oacc_collapse *counts, tree ivar)
7475 tree ivar_type = TREE_TYPE (ivar);
7477 /* The most rapidly changing iteration variable is the innermost
7478 one. */
7479 for (int ix = fd->collapse; ix--;)
7481 const omp_for_data_loop *loop = &fd->loops[ix];
7482 const oacc_collapse *collapse = &counts[ix];
7483 tree iter_type = TREE_TYPE (loop->v);
7484 tree diff_type = TREE_TYPE (collapse->step);
7485 tree plus_type = iter_type;
7486 enum tree_code plus_code = PLUS_EXPR;
7487 tree expr;
7489 if (POINTER_TYPE_P (iter_type))
7491 plus_code = POINTER_PLUS_EXPR;
7492 plus_type = sizetype;
7495 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7496 fold_convert (ivar_type, collapse->iters));
7497 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7498 collapse->step);
7499 expr = fold_build2 (plus_code, iter_type, collapse->base,
7500 fold_convert (plus_type, expr));
7501 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7502 true, GSI_SAME_STMT);
7503 gassign *ass = gimple_build_assign (loop->v, expr);
7504 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7506 if (ix)
7508 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7509 fold_convert (ivar_type, collapse->iters));
7510 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7511 true, GSI_SAME_STMT);
7517 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7518 of the combined collapse > 1 loop constructs, generate code like:
7519 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7520 if (cond3 is <)
7521 adj = STEP3 - 1;
7522 else
7523 adj = STEP3 + 1;
7524 count3 = (adj + N32 - N31) / STEP3;
7525 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7526 if (cond2 is <)
7527 adj = STEP2 - 1;
7528 else
7529 adj = STEP2 + 1;
7530 count2 = (adj + N22 - N21) / STEP2;
7531 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7532 if (cond1 is <)
7533 adj = STEP1 - 1;
7534 else
7535 adj = STEP1 + 1;
7536 count1 = (adj + N12 - N11) / STEP1;
7537 count = count1 * count2 * count3;
7538 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7539 count = 0;
7540 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7541 of the combined loop constructs, just initialize COUNTS array
7542 from the _looptemp_ clauses. */
7544 /* NOTE: It *could* be better to moosh all of the BBs together,
7545 creating one larger BB with all the computation and the unexpected
7546 jump at the end. I.e.
7548 bool zero3, zero2, zero1, zero;
7550 zero3 = N32 c3 N31;
7551 count3 = (N32 - N31) /[cl] STEP3;
7552 zero2 = N22 c2 N21;
7553 count2 = (N22 - N21) /[cl] STEP2;
7554 zero1 = N12 c1 N11;
7555 count1 = (N12 - N11) /[cl] STEP1;
7556 zero = zero3 || zero2 || zero1;
7557 count = count1 * count2 * count3;
7558 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7560 After all, we expect the zero=false, and thus we expect to have to
7561 evaluate all of the comparison expressions, so short-circuiting
7562 oughtn't be a win. Since the condition isn't protecting a
7563 denominator, we're not concerned about divide-by-zero, so we can
7564 fully evaluate count even if a numerator turned out to be wrong.
7566 It seems like putting this all together would create much better
7567 scheduling opportunities, and less pressure on the chip's branch
7568 predictor. */
7570 static void
7571 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7572 basic_block &entry_bb, tree *counts,
7573 basic_block &zero_iter1_bb, int &first_zero_iter1,
7574 basic_block &zero_iter2_bb, int &first_zero_iter2,
7575 basic_block &l2_dom_bb)
7577 tree t, type = TREE_TYPE (fd->loop.v);
7578 edge e, ne;
7579 int i;
7581 /* Collapsed loops need work for expansion into SSA form. */
7582 gcc_assert (!gimple_in_ssa_p (cfun));
7584 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7585 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7587 gcc_assert (fd->ordered == 0);
7588 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7589 isn't supposed to be handled, as the inner loop doesn't
7590 use it. */
7591 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7592 OMP_CLAUSE__LOOPTEMP_);
7593 gcc_assert (innerc);
7594 for (i = 0; i < fd->collapse; i++)
7596 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7597 OMP_CLAUSE__LOOPTEMP_);
7598 gcc_assert (innerc);
7599 if (i)
7600 counts[i] = OMP_CLAUSE_DECL (innerc);
7601 else
7602 counts[0] = NULL_TREE;
7604 return;
7607 for (i = fd->collapse; i < fd->ordered; i++)
7609 tree itype = TREE_TYPE (fd->loops[i].v);
7610 counts[i] = NULL_TREE;
7611 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7612 fold_convert (itype, fd->loops[i].n1),
7613 fold_convert (itype, fd->loops[i].n2));
7614 if (t && integer_zerop (t))
7616 for (i = fd->collapse; i < fd->ordered; i++)
7617 counts[i] = build_int_cst (type, 0);
7618 break;
7621 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7623 tree itype = TREE_TYPE (fd->loops[i].v);
7625 if (i >= fd->collapse && counts[i])
7626 continue;
7627 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7628 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7629 fold_convert (itype, fd->loops[i].n1),
7630 fold_convert (itype, fd->loops[i].n2)))
7631 == NULL_TREE || !integer_onep (t)))
7633 gcond *cond_stmt;
7634 tree n1, n2;
7635 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7636 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7637 true, GSI_SAME_STMT);
7638 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7639 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7640 true, GSI_SAME_STMT);
7641 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7642 NULL_TREE, NULL_TREE);
7643 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7644 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7645 expand_omp_regimplify_p, NULL, NULL)
7646 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7647 expand_omp_regimplify_p, NULL, NULL))
7649 *gsi = gsi_for_stmt (cond_stmt);
7650 gimple_regimplify_operands (cond_stmt, gsi);
7652 e = split_block (entry_bb, cond_stmt);
7653 basic_block &zero_iter_bb
7654 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7655 int &first_zero_iter
7656 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7657 if (zero_iter_bb == NULL)
7659 gassign *assign_stmt;
7660 first_zero_iter = i;
7661 zero_iter_bb = create_empty_bb (entry_bb);
7662 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7663 *gsi = gsi_after_labels (zero_iter_bb);
7664 if (i < fd->collapse)
7665 assign_stmt = gimple_build_assign (fd->loop.n2,
7666 build_zero_cst (type));
7667 else
7669 counts[i] = create_tmp_reg (type, ".count");
7670 assign_stmt
7671 = gimple_build_assign (counts[i], build_zero_cst (type));
7673 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7674 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7675 entry_bb);
7677 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7678 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7679 e->flags = EDGE_TRUE_VALUE;
7680 e->probability = REG_BR_PROB_BASE - ne->probability;
7681 if (l2_dom_bb == NULL)
7682 l2_dom_bb = entry_bb;
7683 entry_bb = e->dest;
7684 *gsi = gsi_last_bb (entry_bb);
7687 if (POINTER_TYPE_P (itype))
7688 itype = signed_type_for (itype);
7689 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7690 ? -1 : 1));
7691 t = fold_build2 (PLUS_EXPR, itype,
7692 fold_convert (itype, fd->loops[i].step), t);
7693 t = fold_build2 (PLUS_EXPR, itype, t,
7694 fold_convert (itype, fd->loops[i].n2));
7695 t = fold_build2 (MINUS_EXPR, itype, t,
7696 fold_convert (itype, fd->loops[i].n1));
7697 /* ?? We could probably use CEIL_DIV_EXPR instead of
7698 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7699 generate the same code in the end because generically we
7700 don't know that the values involved must be negative for
7701 GT?? */
7702 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7703 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7704 fold_build1 (NEGATE_EXPR, itype, t),
7705 fold_build1 (NEGATE_EXPR, itype,
7706 fold_convert (itype,
7707 fd->loops[i].step)));
7708 else
7709 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7710 fold_convert (itype, fd->loops[i].step));
7711 t = fold_convert (type, t);
7712 if (TREE_CODE (t) == INTEGER_CST)
7713 counts[i] = t;
7714 else
7716 if (i < fd->collapse || i != first_zero_iter2)
7717 counts[i] = create_tmp_reg (type, ".count");
7718 expand_omp_build_assign (gsi, counts[i], t);
7720 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7722 if (i == 0)
7723 t = counts[0];
7724 else
7725 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7726 expand_omp_build_assign (gsi, fd->loop.n2, t);
7732 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7733 T = V;
7734 V3 = N31 + (T % count3) * STEP3;
7735 T = T / count3;
7736 V2 = N21 + (T % count2) * STEP2;
7737 T = T / count2;
7738 V1 = N11 + T * STEP1;
7739 if this loop doesn't have an inner loop construct combined with it.
7740 If it does have an inner loop construct combined with it and the
7741 iteration count isn't known constant, store values from counts array
7742 into its _looptemp_ temporaries instead. */
7744 static void
7745 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7746 tree *counts, gimple *inner_stmt, tree startvar)
7748 int i;
7749 if (gimple_omp_for_combined_p (fd->for_stmt))
7751 /* If fd->loop.n2 is constant, then no propagation of the counts
7752 is needed, they are constant. */
7753 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7754 return;
7756 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7757 ? gimple_omp_taskreg_clauses (inner_stmt)
7758 : gimple_omp_for_clauses (inner_stmt);
7759 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7760 isn't supposed to be handled, as the inner loop doesn't
7761 use it. */
7762 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7763 gcc_assert (innerc);
7764 for (i = 0; i < fd->collapse; i++)
7766 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7767 OMP_CLAUSE__LOOPTEMP_);
7768 gcc_assert (innerc);
7769 if (i)
7771 tree tem = OMP_CLAUSE_DECL (innerc);
7772 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7773 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7774 false, GSI_CONTINUE_LINKING);
7775 gassign *stmt = gimple_build_assign (tem, t);
7776 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7779 return;
7782 tree type = TREE_TYPE (fd->loop.v);
7783 tree tem = create_tmp_reg (type, ".tem");
7784 gassign *stmt = gimple_build_assign (tem, startvar);
7785 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7787 for (i = fd->collapse - 1; i >= 0; i--)
7789 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7790 itype = vtype;
7791 if (POINTER_TYPE_P (vtype))
7792 itype = signed_type_for (vtype);
7793 if (i != 0)
7794 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7795 else
7796 t = tem;
7797 t = fold_convert (itype, t);
7798 t = fold_build2 (MULT_EXPR, itype, t,
7799 fold_convert (itype, fd->loops[i].step));
7800 if (POINTER_TYPE_P (vtype))
7801 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7802 else
7803 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7804 t = force_gimple_operand_gsi (gsi, t,
7805 DECL_P (fd->loops[i].v)
7806 && TREE_ADDRESSABLE (fd->loops[i].v),
7807 NULL_TREE, false,
7808 GSI_CONTINUE_LINKING);
7809 stmt = gimple_build_assign (fd->loops[i].v, t);
7810 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7811 if (i != 0)
7813 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7814 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7815 false, GSI_CONTINUE_LINKING);
7816 stmt = gimple_build_assign (tem, t);
7817 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7823 /* Helper function for expand_omp_for_*. Generate code like:
7824 L10:
7825 V3 += STEP3;
7826 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7827 L11:
7828 V3 = N31;
7829 V2 += STEP2;
7830 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7831 L12:
7832 V2 = N21;
7833 V1 += STEP1;
7834 goto BODY_BB; */
7836 static basic_block
7837 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7838 basic_block body_bb)
7840 basic_block last_bb, bb, collapse_bb = NULL;
7841 int i;
7842 gimple_stmt_iterator gsi;
7843 edge e;
7844 tree t;
7845 gimple *stmt;
7847 last_bb = cont_bb;
7848 for (i = fd->collapse - 1; i >= 0; i--)
7850 tree vtype = TREE_TYPE (fd->loops[i].v);
7852 bb = create_empty_bb (last_bb);
7853 add_bb_to_loop (bb, last_bb->loop_father);
7854 gsi = gsi_start_bb (bb);
7856 if (i < fd->collapse - 1)
7858 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7859 e->probability = REG_BR_PROB_BASE / 8;
7861 t = fd->loops[i + 1].n1;
7862 t = force_gimple_operand_gsi (&gsi, t,
7863 DECL_P (fd->loops[i + 1].v)
7864 && TREE_ADDRESSABLE (fd->loops[i
7865 + 1].v),
7866 NULL_TREE, false,
7867 GSI_CONTINUE_LINKING);
7868 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7869 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7871 else
7872 collapse_bb = bb;
7874 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7876 if (POINTER_TYPE_P (vtype))
7877 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7878 else
7879 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7880 t = force_gimple_operand_gsi (&gsi, t,
7881 DECL_P (fd->loops[i].v)
7882 && TREE_ADDRESSABLE (fd->loops[i].v),
7883 NULL_TREE, false, GSI_CONTINUE_LINKING);
7884 stmt = gimple_build_assign (fd->loops[i].v, t);
7885 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7887 if (i > 0)
7889 t = fd->loops[i].n2;
7890 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7891 false, GSI_CONTINUE_LINKING);
7892 tree v = fd->loops[i].v;
7893 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7894 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7895 false, GSI_CONTINUE_LINKING);
7896 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7897 stmt = gimple_build_cond_empty (t);
7898 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7899 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7900 e->probability = REG_BR_PROB_BASE * 7 / 8;
7902 else
7903 make_edge (bb, body_bb, EDGE_FALLTHRU);
7904 last_bb = bb;
7907 return collapse_bb;
7911 /* Expand #pragma omp ordered depend(source). */
7913 static void
7914 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7915 tree *counts, location_t loc)
7917 enum built_in_function source_ix
7918 = fd->iter_type == long_integer_type_node
7919 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7920 gimple *g
7921 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7922 build_fold_addr_expr (counts[fd->ordered]));
7923 gimple_set_location (g, loc);
7924 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7927 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7929 static void
7930 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7931 tree *counts, tree c, location_t loc)
7933 auto_vec<tree, 10> args;
7934 enum built_in_function sink_ix
7935 = fd->iter_type == long_integer_type_node
7936 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7937 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7938 int i;
7939 gimple_stmt_iterator gsi2 = *gsi;
7940 bool warned_step = false;
7942 for (i = 0; i < fd->ordered; i++)
7944 off = TREE_PURPOSE (deps);
7945 if (!integer_zerop (off))
7947 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7948 || fd->loops[i].cond_code == GT_EXPR);
7949 bool forward = fd->loops[i].cond_code == LT_EXPR;
7950 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7951 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7952 "lexically later iteration");
7953 break;
7955 deps = TREE_CHAIN (deps);
7957 /* If all offsets corresponding to the collapsed loops are zero,
7958 this depend clause can be ignored. FIXME: but there is still a
7959 flush needed. We need to emit one __sync_synchronize () for it
7960 though (perhaps conditionally)? Solve this together with the
7961 conservative dependence folding optimization.
7962 if (i >= fd->collapse)
7963 return; */
7965 deps = OMP_CLAUSE_DECL (c);
7966 gsi_prev (&gsi2);
7967 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7968 edge e2 = split_block_after_labels (e1->dest);
7970 *gsi = gsi_after_labels (e1->dest);
7971 for (i = 0; i < fd->ordered; i++)
7973 tree itype = TREE_TYPE (fd->loops[i].v);
7974 if (POINTER_TYPE_P (itype))
7975 itype = sizetype;
7976 if (i)
7977 deps = TREE_CHAIN (deps);
7978 off = TREE_PURPOSE (deps);
7979 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7981 if (integer_zerop (off))
7982 t = boolean_true_node;
7983 else
7985 tree a;
7986 tree co = fold_convert_loc (loc, itype, off);
7987 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7989 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7990 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7991 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7992 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7993 co);
7995 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7996 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7997 fd->loops[i].v, co);
7998 else
7999 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8000 fd->loops[i].v, co);
8001 if (fd->loops[i].cond_code == LT_EXPR)
8003 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8004 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8005 fd->loops[i].n1);
8006 else
8007 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8008 fd->loops[i].n2);
8010 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8011 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8012 fd->loops[i].n2);
8013 else
8014 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8015 fd->loops[i].n1);
8017 if (cond)
8018 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8019 else
8020 cond = t;
8022 off = fold_convert_loc (loc, itype, off);
8024 if (fd->loops[i].cond_code == LT_EXPR
8025 ? !integer_onep (fd->loops[i].step)
8026 : !integer_minus_onep (fd->loops[i].step))
8028 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8029 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8030 fold_build1_loc (loc, NEGATE_EXPR, itype,
8031 s));
8032 else
8033 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8034 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8035 build_int_cst (itype, 0));
8036 if (integer_zerop (t) && !warned_step)
8038 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8039 "in the iteration space");
8040 warned_step = true;
8042 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8043 cond, t);
8046 if (i <= fd->collapse - 1 && fd->collapse > 1)
8047 t = fd->loop.v;
8048 else if (counts[i])
8049 t = counts[i];
8050 else
8052 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8053 fd->loops[i].v, fd->loops[i].n1);
8054 t = fold_convert_loc (loc, fd->iter_type, t);
8056 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8057 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8058 fold_build1_loc (loc, NEGATE_EXPR, itype,
8059 s));
8060 else
8061 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8062 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8063 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8064 off = fold_convert_loc (loc, fd->iter_type, off);
8065 if (i <= fd->collapse - 1 && fd->collapse > 1)
8067 if (i)
8068 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8069 off);
8070 if (i < fd->collapse - 1)
8072 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8073 counts[i]);
8074 continue;
8077 off = unshare_expr (off);
8078 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8079 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8080 true, GSI_SAME_STMT);
8081 args.safe_push (t);
8083 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8084 gimple_set_location (g, loc);
8085 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8087 *gsi = gsi_last_bb (e1->src);
8088 cond = unshare_expr (cond);
8089 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8090 GSI_CONTINUE_LINKING);
8091 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8092 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8093 e3->probability = REG_BR_PROB_BASE / 8;
8094 e1->probability = REG_BR_PROB_BASE - e3->probability;
8095 e1->flags = EDGE_TRUE_VALUE;
8096 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8098 *gsi = gsi_after_labels (e2->dest);
8101 /* Expand all #pragma omp ordered depend(source) and
8102 #pragma omp ordered depend(sink:...) constructs in the current
8103 #pragma omp for ordered(n) region. */
8105 static void
8106 expand_omp_ordered_source_sink (struct omp_region *region,
8107 struct omp_for_data *fd, tree *counts,
8108 basic_block cont_bb)
8110 struct omp_region *inner;
8111 int i;
8112 for (i = fd->collapse - 1; i < fd->ordered; i++)
8113 if (i == fd->collapse - 1 && fd->collapse > 1)
8114 counts[i] = NULL_TREE;
8115 else if (i >= fd->collapse && !cont_bb)
8116 counts[i] = build_zero_cst (fd->iter_type);
8117 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8118 && integer_onep (fd->loops[i].step))
8119 counts[i] = NULL_TREE;
8120 else
8121 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8122 tree atype
8123 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8124 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8125 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8127 for (inner = region->inner; inner; inner = inner->next)
8128 if (inner->type == GIMPLE_OMP_ORDERED)
8130 gomp_ordered *ord_stmt = inner->ord_stmt;
8131 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8132 location_t loc = gimple_location (ord_stmt);
8133 tree c;
8134 for (c = gimple_omp_ordered_clauses (ord_stmt);
8135 c; c = OMP_CLAUSE_CHAIN (c))
8136 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8137 break;
8138 if (c)
8139 expand_omp_ordered_source (&gsi, fd, counts, loc);
8140 for (c = gimple_omp_ordered_clauses (ord_stmt);
8141 c; c = OMP_CLAUSE_CHAIN (c))
8142 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8143 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8144 gsi_remove (&gsi, true);
8148 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8149 collapsed. */
8151 static basic_block
8152 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8153 basic_block cont_bb, basic_block body_bb,
8154 bool ordered_lastprivate)
8156 if (fd->ordered == fd->collapse)
8157 return cont_bb;
8159 if (!cont_bb)
8161 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8162 for (int i = fd->collapse; i < fd->ordered; i++)
8164 tree type = TREE_TYPE (fd->loops[i].v);
8165 tree n1 = fold_convert (type, fd->loops[i].n1);
8166 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8167 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8168 size_int (i - fd->collapse + 1),
8169 NULL_TREE, NULL_TREE);
8170 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8172 return NULL;
8175 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8177 tree t, type = TREE_TYPE (fd->loops[i].v);
8178 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8179 expand_omp_build_assign (&gsi, fd->loops[i].v,
8180 fold_convert (type, fd->loops[i].n1));
8181 if (counts[i])
8182 expand_omp_build_assign (&gsi, counts[i],
8183 build_zero_cst (fd->iter_type));
8184 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8185 size_int (i - fd->collapse + 1),
8186 NULL_TREE, NULL_TREE);
8187 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8188 if (!gsi_end_p (gsi))
8189 gsi_prev (&gsi);
8190 else
8191 gsi = gsi_last_bb (body_bb);
8192 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8193 basic_block new_body = e1->dest;
8194 if (body_bb == cont_bb)
8195 cont_bb = new_body;
8196 edge e2 = NULL;
8197 basic_block new_header;
8198 if (EDGE_COUNT (cont_bb->preds) > 0)
8200 gsi = gsi_last_bb (cont_bb);
8201 if (POINTER_TYPE_P (type))
8202 t = fold_build_pointer_plus (fd->loops[i].v,
8203 fold_convert (sizetype,
8204 fd->loops[i].step));
8205 else
8206 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8207 fold_convert (type, fd->loops[i].step));
8208 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8209 if (counts[i])
8211 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8212 build_int_cst (fd->iter_type, 1));
8213 expand_omp_build_assign (&gsi, counts[i], t);
8214 t = counts[i];
8216 else
8218 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8219 fd->loops[i].v, fd->loops[i].n1);
8220 t = fold_convert (fd->iter_type, t);
8221 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8222 true, GSI_SAME_STMT);
8224 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8225 size_int (i - fd->collapse + 1),
8226 NULL_TREE, NULL_TREE);
8227 expand_omp_build_assign (&gsi, aref, t);
8228 gsi_prev (&gsi);
8229 e2 = split_block (cont_bb, gsi_stmt (gsi));
8230 new_header = e2->dest;
8232 else
8233 new_header = cont_bb;
8234 gsi = gsi_after_labels (new_header);
8235 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8236 true, GSI_SAME_STMT);
8237 tree n2
8238 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8239 true, NULL_TREE, true, GSI_SAME_STMT);
8240 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8241 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8242 edge e3 = split_block (new_header, gsi_stmt (gsi));
8243 cont_bb = e3->dest;
8244 remove_edge (e1);
8245 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8246 e3->flags = EDGE_FALSE_VALUE;
8247 e3->probability = REG_BR_PROB_BASE / 8;
8248 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8249 e1->probability = REG_BR_PROB_BASE - e3->probability;
8251 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8252 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8254 if (e2)
8256 struct loop *loop = alloc_loop ();
8257 loop->header = new_header;
8258 loop->latch = e2->src;
8259 add_loop (loop, body_bb->loop_father);
8263 /* If there are any lastprivate clauses and it is possible some loops
8264 might have zero iterations, ensure all the decls are initialized,
8265 otherwise we could crash evaluating C++ class iterators with lastprivate
8266 clauses. */
8267 bool need_inits = false;
8268 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8269 if (need_inits)
8271 tree type = TREE_TYPE (fd->loops[i].v);
8272 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8273 expand_omp_build_assign (&gsi, fd->loops[i].v,
8274 fold_convert (type, fd->loops[i].n1));
8276 else
8278 tree type = TREE_TYPE (fd->loops[i].v);
8279 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8280 boolean_type_node,
8281 fold_convert (type, fd->loops[i].n1),
8282 fold_convert (type, fd->loops[i].n2));
8283 if (!integer_onep (this_cond))
8284 need_inits = true;
8287 return cont_bb;
8291 /* A subroutine of expand_omp_for. Generate code for a parallel
8292 loop with any schedule. Given parameters:
8294 for (V = N1; V cond N2; V += STEP) BODY;
8296 where COND is "<" or ">", we generate pseudocode
8298 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8299 if (more) goto L0; else goto L3;
8301 V = istart0;
8302 iend = iend0;
8304 BODY;
8305 V += STEP;
8306 if (V cond iend) goto L1; else goto L2;
8308 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8311 If this is a combined omp parallel loop, instead of the call to
8312 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8313 If this is gimple_omp_for_combined_p loop, then instead of assigning
8314 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8315 inner GIMPLE_OMP_FOR and V += STEP; and
8316 if (V cond iend) goto L1; else goto L2; are removed.
8318 For collapsed loops, given parameters:
8319 collapse(3)
8320 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8321 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8322 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8323 BODY;
8325 we generate pseudocode
8327 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8328 if (cond3 is <)
8329 adj = STEP3 - 1;
8330 else
8331 adj = STEP3 + 1;
8332 count3 = (adj + N32 - N31) / STEP3;
8333 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8334 if (cond2 is <)
8335 adj = STEP2 - 1;
8336 else
8337 adj = STEP2 + 1;
8338 count2 = (adj + N22 - N21) / STEP2;
8339 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8340 if (cond1 is <)
8341 adj = STEP1 - 1;
8342 else
8343 adj = STEP1 + 1;
8344 count1 = (adj + N12 - N11) / STEP1;
8345 count = count1 * count2 * count3;
8346 goto Z1;
8348 count = 0;
8350 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8351 if (more) goto L0; else goto L3;
8353 V = istart0;
8354 T = V;
8355 V3 = N31 + (T % count3) * STEP3;
8356 T = T / count3;
8357 V2 = N21 + (T % count2) * STEP2;
8358 T = T / count2;
8359 V1 = N11 + T * STEP1;
8360 iend = iend0;
8362 BODY;
8363 V += 1;
8364 if (V < iend) goto L10; else goto L2;
8365 L10:
8366 V3 += STEP3;
8367 if (V3 cond3 N32) goto L1; else goto L11;
8368 L11:
8369 V3 = N31;
8370 V2 += STEP2;
8371 if (V2 cond2 N22) goto L1; else goto L12;
8372 L12:
8373 V2 = N21;
8374 V1 += STEP1;
8375 goto L1;
8377 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8382 static void
8383 expand_omp_for_generic (struct omp_region *region,
8384 struct omp_for_data *fd,
8385 enum built_in_function start_fn,
8386 enum built_in_function next_fn,
8387 gimple *inner_stmt)
8389 tree type, istart0, iend0, iend;
8390 tree t, vmain, vback, bias = NULL_TREE;
8391 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8392 basic_block l2_bb = NULL, l3_bb = NULL;
8393 gimple_stmt_iterator gsi;
8394 gassign *assign_stmt;
8395 bool in_combined_parallel = is_combined_parallel (region);
8396 bool broken_loop = region->cont == NULL;
8397 edge e, ne;
8398 tree *counts = NULL;
8399 int i;
8400 bool ordered_lastprivate = false;
8402 gcc_assert (!broken_loop || !in_combined_parallel);
8403 gcc_assert (fd->iter_type == long_integer_type_node
8404 || !in_combined_parallel);
8406 entry_bb = region->entry;
8407 cont_bb = region->cont;
8408 collapse_bb = NULL;
8409 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8410 gcc_assert (broken_loop
8411 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8412 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8413 l1_bb = single_succ (l0_bb);
8414 if (!broken_loop)
8416 l2_bb = create_empty_bb (cont_bb);
8417 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8418 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8419 == l1_bb));
8420 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8422 else
8423 l2_bb = NULL;
8424 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8425 exit_bb = region->exit;
8427 gsi = gsi_last_bb (entry_bb);
8429 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8430 if (fd->ordered
8431 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8432 OMP_CLAUSE_LASTPRIVATE))
8433 ordered_lastprivate = false;
8434 if (fd->collapse > 1 || fd->ordered)
8436 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8437 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8439 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8440 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8441 zero_iter1_bb, first_zero_iter1,
8442 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8444 if (zero_iter1_bb)
8446 /* Some counts[i] vars might be uninitialized if
8447 some loop has zero iterations. But the body shouldn't
8448 be executed in that case, so just avoid uninit warnings. */
8449 for (i = first_zero_iter1;
8450 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8451 if (SSA_VAR_P (counts[i]))
8452 TREE_NO_WARNING (counts[i]) = 1;
8453 gsi_prev (&gsi);
8454 e = split_block (entry_bb, gsi_stmt (gsi));
8455 entry_bb = e->dest;
8456 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8457 gsi = gsi_last_bb (entry_bb);
8458 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8459 get_immediate_dominator (CDI_DOMINATORS,
8460 zero_iter1_bb));
8462 if (zero_iter2_bb)
8464 /* Some counts[i] vars might be uninitialized if
8465 some loop has zero iterations. But the body shouldn't
8466 be executed in that case, so just avoid uninit warnings. */
8467 for (i = first_zero_iter2; i < fd->ordered; i++)
8468 if (SSA_VAR_P (counts[i]))
8469 TREE_NO_WARNING (counts[i]) = 1;
8470 if (zero_iter1_bb)
8471 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8472 else
8474 gsi_prev (&gsi);
8475 e = split_block (entry_bb, gsi_stmt (gsi));
8476 entry_bb = e->dest;
8477 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8478 gsi = gsi_last_bb (entry_bb);
8479 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8480 get_immediate_dominator
8481 (CDI_DOMINATORS, zero_iter2_bb));
8484 if (fd->collapse == 1)
8486 counts[0] = fd->loop.n2;
8487 fd->loop = fd->loops[0];
8491 type = TREE_TYPE (fd->loop.v);
8492 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8493 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8494 TREE_ADDRESSABLE (istart0) = 1;
8495 TREE_ADDRESSABLE (iend0) = 1;
8497 /* See if we need to bias by LLONG_MIN. */
8498 if (fd->iter_type == long_long_unsigned_type_node
8499 && TREE_CODE (type) == INTEGER_TYPE
8500 && !TYPE_UNSIGNED (type)
8501 && fd->ordered == 0)
8503 tree n1, n2;
8505 if (fd->loop.cond_code == LT_EXPR)
8507 n1 = fd->loop.n1;
8508 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8510 else
8512 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8513 n2 = fd->loop.n1;
8515 if (TREE_CODE (n1) != INTEGER_CST
8516 || TREE_CODE (n2) != INTEGER_CST
8517 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8518 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8521 gimple_stmt_iterator gsif = gsi;
8522 gsi_prev (&gsif);
8524 tree arr = NULL_TREE;
8525 if (in_combined_parallel)
8527 gcc_assert (fd->ordered == 0);
8528 /* In a combined parallel loop, emit a call to
8529 GOMP_loop_foo_next. */
8530 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8531 build_fold_addr_expr (istart0),
8532 build_fold_addr_expr (iend0));
8534 else
8536 tree t0, t1, t2, t3, t4;
8537 /* If this is not a combined parallel loop, emit a call to
8538 GOMP_loop_foo_start in ENTRY_BB. */
8539 t4 = build_fold_addr_expr (iend0);
8540 t3 = build_fold_addr_expr (istart0);
8541 if (fd->ordered)
8543 t0 = build_int_cst (unsigned_type_node,
8544 fd->ordered - fd->collapse + 1);
8545 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8546 fd->ordered
8547 - fd->collapse + 1),
8548 ".omp_counts");
8549 DECL_NAMELESS (arr) = 1;
8550 TREE_ADDRESSABLE (arr) = 1;
8551 TREE_STATIC (arr) = 1;
8552 vec<constructor_elt, va_gc> *v;
8553 vec_alloc (v, fd->ordered - fd->collapse + 1);
8554 int idx;
8556 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8558 tree c;
8559 if (idx == 0 && fd->collapse > 1)
8560 c = fd->loop.n2;
8561 else
8562 c = counts[idx + fd->collapse - 1];
8563 tree purpose = size_int (idx);
8564 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8565 if (TREE_CODE (c) != INTEGER_CST)
8566 TREE_STATIC (arr) = 0;
8569 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8570 if (!TREE_STATIC (arr))
8571 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8572 void_type_node, arr),
8573 true, NULL_TREE, true, GSI_SAME_STMT);
8574 t1 = build_fold_addr_expr (arr);
8575 t2 = NULL_TREE;
8577 else
8579 t2 = fold_convert (fd->iter_type, fd->loop.step);
8580 t1 = fd->loop.n2;
8581 t0 = fd->loop.n1;
8582 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8584 tree innerc
8585 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8586 OMP_CLAUSE__LOOPTEMP_);
8587 gcc_assert (innerc);
8588 t0 = OMP_CLAUSE_DECL (innerc);
8589 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8590 OMP_CLAUSE__LOOPTEMP_);
8591 gcc_assert (innerc);
8592 t1 = OMP_CLAUSE_DECL (innerc);
8594 if (POINTER_TYPE_P (TREE_TYPE (t0))
8595 && TYPE_PRECISION (TREE_TYPE (t0))
8596 != TYPE_PRECISION (fd->iter_type))
8598 /* Avoid casting pointers to integer of a different size. */
8599 tree itype = signed_type_for (type);
8600 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8601 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8603 else
8605 t1 = fold_convert (fd->iter_type, t1);
8606 t0 = fold_convert (fd->iter_type, t0);
8608 if (bias)
8610 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8611 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8614 if (fd->iter_type == long_integer_type_node || fd->ordered)
8616 if (fd->chunk_size)
8618 t = fold_convert (fd->iter_type, fd->chunk_size);
8619 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8620 if (fd->ordered)
8621 t = build_call_expr (builtin_decl_explicit (start_fn),
8622 5, t0, t1, t, t3, t4);
8623 else
8624 t = build_call_expr (builtin_decl_explicit (start_fn),
8625 6, t0, t1, t2, t, t3, t4);
8627 else if (fd->ordered)
8628 t = build_call_expr (builtin_decl_explicit (start_fn),
8629 4, t0, t1, t3, t4);
8630 else
8631 t = build_call_expr (builtin_decl_explicit (start_fn),
8632 5, t0, t1, t2, t3, t4);
8634 else
8636 tree t5;
8637 tree c_bool_type;
8638 tree bfn_decl;
8640 /* The GOMP_loop_ull_*start functions have additional boolean
8641 argument, true for < loops and false for > loops.
8642 In Fortran, the C bool type can be different from
8643 boolean_type_node. */
8644 bfn_decl = builtin_decl_explicit (start_fn);
8645 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8646 t5 = build_int_cst (c_bool_type,
8647 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8648 if (fd->chunk_size)
8650 tree bfn_decl = builtin_decl_explicit (start_fn);
8651 t = fold_convert (fd->iter_type, fd->chunk_size);
8652 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8653 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8655 else
8656 t = build_call_expr (builtin_decl_explicit (start_fn),
8657 6, t5, t0, t1, t2, t3, t4);
8660 if (TREE_TYPE (t) != boolean_type_node)
8661 t = fold_build2 (NE_EXPR, boolean_type_node,
8662 t, build_int_cst (TREE_TYPE (t), 0));
8663 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8664 true, GSI_SAME_STMT);
8665 if (arr && !TREE_STATIC (arr))
8667 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8668 TREE_THIS_VOLATILE (clobber) = 1;
8669 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8670 GSI_SAME_STMT);
8672 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8674 /* Remove the GIMPLE_OMP_FOR statement. */
8675 gsi_remove (&gsi, true);
8677 if (gsi_end_p (gsif))
8678 gsif = gsi_after_labels (gsi_bb (gsif));
8679 gsi_next (&gsif);
8681 /* Iteration setup for sequential loop goes in L0_BB. */
8682 tree startvar = fd->loop.v;
8683 tree endvar = NULL_TREE;
8685 if (gimple_omp_for_combined_p (fd->for_stmt))
8687 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8688 && gimple_omp_for_kind (inner_stmt)
8689 == GF_OMP_FOR_KIND_SIMD);
8690 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8691 OMP_CLAUSE__LOOPTEMP_);
8692 gcc_assert (innerc);
8693 startvar = OMP_CLAUSE_DECL (innerc);
8694 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8695 OMP_CLAUSE__LOOPTEMP_);
8696 gcc_assert (innerc);
8697 endvar = OMP_CLAUSE_DECL (innerc);
8700 gsi = gsi_start_bb (l0_bb);
8701 t = istart0;
8702 if (fd->ordered && fd->collapse == 1)
8703 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8704 fold_convert (fd->iter_type, fd->loop.step));
8705 else if (bias)
8706 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8707 if (fd->ordered && fd->collapse == 1)
8709 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8710 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8711 fd->loop.n1, fold_convert (sizetype, t));
8712 else
8714 t = fold_convert (TREE_TYPE (startvar), t);
8715 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8716 fd->loop.n1, t);
8719 else
8721 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8722 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8723 t = fold_convert (TREE_TYPE (startvar), t);
8725 t = force_gimple_operand_gsi (&gsi, t,
8726 DECL_P (startvar)
8727 && TREE_ADDRESSABLE (startvar),
8728 NULL_TREE, false, GSI_CONTINUE_LINKING);
8729 assign_stmt = gimple_build_assign (startvar, t);
8730 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8732 t = iend0;
8733 if (fd->ordered && fd->collapse == 1)
8734 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8735 fold_convert (fd->iter_type, fd->loop.step));
8736 else if (bias)
8737 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8738 if (fd->ordered && fd->collapse == 1)
8740 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8741 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8742 fd->loop.n1, fold_convert (sizetype, t));
8743 else
8745 t = fold_convert (TREE_TYPE (startvar), t);
8746 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8747 fd->loop.n1, t);
8750 else
8752 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8753 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8754 t = fold_convert (TREE_TYPE (startvar), t);
8756 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8757 false, GSI_CONTINUE_LINKING);
8758 if (endvar)
8760 assign_stmt = gimple_build_assign (endvar, iend);
8761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8762 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8763 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8764 else
8765 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8766 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8768 /* Handle linear clause adjustments. */
8769 tree itercnt = NULL_TREE;
8770 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8771 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8772 c; c = OMP_CLAUSE_CHAIN (c))
8773 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8774 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8776 tree d = OMP_CLAUSE_DECL (c);
8777 bool is_ref = is_reference (d);
8778 tree t = d, a, dest;
8779 if (is_ref)
8780 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8781 tree type = TREE_TYPE (t);
8782 if (POINTER_TYPE_P (type))
8783 type = sizetype;
8784 dest = unshare_expr (t);
8785 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8786 expand_omp_build_assign (&gsif, v, t);
8787 if (itercnt == NULL_TREE)
8789 itercnt = startvar;
8790 tree n1 = fd->loop.n1;
8791 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8793 itercnt
8794 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8795 itercnt);
8796 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8798 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8799 itercnt, n1);
8800 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8801 itercnt, fd->loop.step);
8802 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8803 NULL_TREE, false,
8804 GSI_CONTINUE_LINKING);
8806 a = fold_build2 (MULT_EXPR, type,
8807 fold_convert (type, itercnt),
8808 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8809 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8810 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8811 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8812 false, GSI_CONTINUE_LINKING);
8813 assign_stmt = gimple_build_assign (dest, t);
8814 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8816 if (fd->collapse > 1)
8817 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8819 if (fd->ordered)
8821 /* Until now, counts array contained number of iterations or
8822 variable containing it for ith loop. From now on, we need
8823 those counts only for collapsed loops, and only for the 2nd
8824 till the last collapsed one. Move those one element earlier,
8825 we'll use counts[fd->collapse - 1] for the first source/sink
8826 iteration counter and so on and counts[fd->ordered]
8827 as the array holding the current counter values for
8828 depend(source). */
8829 if (fd->collapse > 1)
8830 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8831 if (broken_loop)
8833 int i;
8834 for (i = fd->collapse; i < fd->ordered; i++)
8836 tree type = TREE_TYPE (fd->loops[i].v);
8837 tree this_cond
8838 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8839 fold_convert (type, fd->loops[i].n1),
8840 fold_convert (type, fd->loops[i].n2));
8841 if (!integer_onep (this_cond))
8842 break;
8844 if (i < fd->ordered)
8846 cont_bb
8847 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8848 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8849 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8850 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8851 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8852 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8853 make_edge (cont_bb, l1_bb, 0);
8854 l2_bb = create_empty_bb (cont_bb);
8855 broken_loop = false;
8858 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8859 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8860 ordered_lastprivate);
8861 if (counts[fd->collapse - 1])
8863 gcc_assert (fd->collapse == 1);
8864 gsi = gsi_last_bb (l0_bb);
8865 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8866 istart0, true);
8867 gsi = gsi_last_bb (cont_bb);
8868 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8869 build_int_cst (fd->iter_type, 1));
8870 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8871 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8872 size_zero_node, NULL_TREE, NULL_TREE);
8873 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8874 t = counts[fd->collapse - 1];
8876 else if (fd->collapse > 1)
8877 t = fd->loop.v;
8878 else
8880 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8881 fd->loops[0].v, fd->loops[0].n1);
8882 t = fold_convert (fd->iter_type, t);
8884 gsi = gsi_last_bb (l0_bb);
8885 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8886 size_zero_node, NULL_TREE, NULL_TREE);
8887 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8888 false, GSI_CONTINUE_LINKING);
8889 expand_omp_build_assign (&gsi, aref, t, true);
8892 if (!broken_loop)
8894 /* Code to control the increment and predicate for the sequential
8895 loop goes in the CONT_BB. */
8896 gsi = gsi_last_bb (cont_bb);
8897 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8898 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8899 vmain = gimple_omp_continue_control_use (cont_stmt);
8900 vback = gimple_omp_continue_control_def (cont_stmt);
8902 if (!gimple_omp_for_combined_p (fd->for_stmt))
8904 if (POINTER_TYPE_P (type))
8905 t = fold_build_pointer_plus (vmain, fd->loop.step);
8906 else
8907 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8908 t = force_gimple_operand_gsi (&gsi, t,
8909 DECL_P (vback)
8910 && TREE_ADDRESSABLE (vback),
8911 NULL_TREE, true, GSI_SAME_STMT);
8912 assign_stmt = gimple_build_assign (vback, t);
8913 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8915 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8917 if (fd->collapse > 1)
8918 t = fd->loop.v;
8919 else
8921 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8922 fd->loops[0].v, fd->loops[0].n1);
8923 t = fold_convert (fd->iter_type, t);
8925 tree aref = build4 (ARRAY_REF, fd->iter_type,
8926 counts[fd->ordered], size_zero_node,
8927 NULL_TREE, NULL_TREE);
8928 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8929 true, GSI_SAME_STMT);
8930 expand_omp_build_assign (&gsi, aref, t);
8933 t = build2 (fd->loop.cond_code, boolean_type_node,
8934 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8935 iend);
8936 gcond *cond_stmt = gimple_build_cond_empty (t);
8937 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8940 /* Remove GIMPLE_OMP_CONTINUE. */
8941 gsi_remove (&gsi, true);
8943 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8944 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8946 /* Emit code to get the next parallel iteration in L2_BB. */
8947 gsi = gsi_start_bb (l2_bb);
8949 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8950 build_fold_addr_expr (istart0),
8951 build_fold_addr_expr (iend0));
8952 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8953 false, GSI_CONTINUE_LINKING);
8954 if (TREE_TYPE (t) != boolean_type_node)
8955 t = fold_build2 (NE_EXPR, boolean_type_node,
8956 t, build_int_cst (TREE_TYPE (t), 0));
8957 gcond *cond_stmt = gimple_build_cond_empty (t);
8958 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8961 /* Add the loop cleanup function. */
8962 gsi = gsi_last_bb (exit_bb);
8963 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8964 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8965 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8966 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8967 else
8968 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8969 gcall *call_stmt = gimple_build_call (t, 0);
8970 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8971 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8972 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8973 if (fd->ordered)
8975 tree arr = counts[fd->ordered];
8976 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8977 TREE_THIS_VOLATILE (clobber) = 1;
8978 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8979 GSI_SAME_STMT);
8981 gsi_remove (&gsi, true);
8983 /* Connect the new blocks. */
8984 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8985 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8987 if (!broken_loop)
8989 gimple_seq phis;
8991 e = find_edge (cont_bb, l3_bb);
8992 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8994 phis = phi_nodes (l3_bb);
8995 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8997 gimple *phi = gsi_stmt (gsi);
8998 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8999 PHI_ARG_DEF_FROM_EDGE (phi, e));
9001 remove_edge (e);
9003 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9004 e = find_edge (cont_bb, l1_bb);
9005 if (e == NULL)
9007 e = BRANCH_EDGE (cont_bb);
9008 gcc_assert (single_succ (e->dest) == l1_bb);
9010 if (gimple_omp_for_combined_p (fd->for_stmt))
9012 remove_edge (e);
9013 e = NULL;
9015 else if (fd->collapse > 1)
9017 remove_edge (e);
9018 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9020 else
9021 e->flags = EDGE_TRUE_VALUE;
9022 if (e)
9024 e->probability = REG_BR_PROB_BASE * 7 / 8;
9025 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9027 else
9029 e = find_edge (cont_bb, l2_bb);
9030 e->flags = EDGE_FALLTHRU;
9032 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9034 if (gimple_in_ssa_p (cfun))
9036 /* Add phis to the outer loop that connect to the phis in the inner,
9037 original loop, and move the loop entry value of the inner phi to
9038 the loop entry value of the outer phi. */
9039 gphi_iterator psi;
9040 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9042 source_location locus;
9043 gphi *nphi;
9044 gphi *exit_phi = psi.phi ();
9046 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9047 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9049 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9050 edge latch_to_l1 = find_edge (latch, l1_bb);
9051 gphi *inner_phi
9052 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9054 tree t = gimple_phi_result (exit_phi);
9055 tree new_res = copy_ssa_name (t, NULL);
9056 nphi = create_phi_node (new_res, l0_bb);
9058 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9059 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9060 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9061 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9062 add_phi_arg (nphi, t, entry_to_l0, locus);
9064 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9065 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9067 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9071 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9072 recompute_dominator (CDI_DOMINATORS, l2_bb));
9073 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9074 recompute_dominator (CDI_DOMINATORS, l3_bb));
9075 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9076 recompute_dominator (CDI_DOMINATORS, l0_bb));
9077 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9078 recompute_dominator (CDI_DOMINATORS, l1_bb));
9080 /* We enter expand_omp_for_generic with a loop. This original loop may
9081 have its own loop struct, or it may be part of an outer loop struct
9082 (which may be the fake loop). */
9083 struct loop *outer_loop = entry_bb->loop_father;
9084 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9086 add_bb_to_loop (l2_bb, outer_loop);
9088 /* We've added a new loop around the original loop. Allocate the
9089 corresponding loop struct. */
9090 struct loop *new_loop = alloc_loop ();
9091 new_loop->header = l0_bb;
9092 new_loop->latch = l2_bb;
9093 add_loop (new_loop, outer_loop);
9095 /* Allocate a loop structure for the original loop unless we already
9096 had one. */
9097 if (!orig_loop_has_loop_struct
9098 && !gimple_omp_for_combined_p (fd->for_stmt))
9100 struct loop *orig_loop = alloc_loop ();
9101 orig_loop->header = l1_bb;
9102 /* The loop may have multiple latches. */
9103 add_loop (orig_loop, new_loop);
9109 /* A subroutine of expand_omp_for. Generate code for a parallel
9110 loop with static schedule and no specified chunk size. Given
9111 parameters:
9113 for (V = N1; V cond N2; V += STEP) BODY;
9115 where COND is "<" or ">", we generate pseudocode
9117 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9118 if (cond is <)
9119 adj = STEP - 1;
9120 else
9121 adj = STEP + 1;
9122 if ((__typeof (V)) -1 > 0 && cond is >)
9123 n = -(adj + N2 - N1) / -STEP;
9124 else
9125 n = (adj + N2 - N1) / STEP;
9126 q = n / nthreads;
9127 tt = n % nthreads;
9128 if (threadid < tt) goto L3; else goto L4;
9130 tt = 0;
9131 q = q + 1;
9133 s0 = q * threadid + tt;
9134 e0 = s0 + q;
9135 V = s0 * STEP + N1;
9136 if (s0 >= e0) goto L2; else goto L0;
9138 e = e0 * STEP + N1;
9140 BODY;
9141 V += STEP;
9142 if (V cond e) goto L1;
9146 static void
9147 expand_omp_for_static_nochunk (struct omp_region *region,
9148 struct omp_for_data *fd,
9149 gimple *inner_stmt)
9151 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9152 tree type, itype, vmain, vback;
9153 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9154 basic_block body_bb, cont_bb, collapse_bb = NULL;
9155 basic_block fin_bb;
9156 gimple_stmt_iterator gsi;
9157 edge ep;
9158 bool broken_loop = region->cont == NULL;
9159 tree *counts = NULL;
9160 tree n1, n2, step;
9162 itype = type = TREE_TYPE (fd->loop.v);
9163 if (POINTER_TYPE_P (type))
9164 itype = signed_type_for (type);
9166 entry_bb = region->entry;
9167 cont_bb = region->cont;
9168 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9169 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9170 gcc_assert (broken_loop
9171 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9172 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9173 body_bb = single_succ (seq_start_bb);
9174 if (!broken_loop)
9176 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9177 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9178 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9180 exit_bb = region->exit;
9182 /* Iteration space partitioning goes in ENTRY_BB. */
9183 gsi = gsi_last_bb (entry_bb);
9184 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9186 if (fd->collapse > 1)
9188 int first_zero_iter = -1, dummy = -1;
9189 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9191 counts = XALLOCAVEC (tree, fd->collapse);
9192 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9193 fin_bb, first_zero_iter,
9194 dummy_bb, dummy, l2_dom_bb);
9195 t = NULL_TREE;
9197 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9198 t = integer_one_node;
9199 else
9200 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9201 fold_convert (type, fd->loop.n1),
9202 fold_convert (type, fd->loop.n2));
9203 if (fd->collapse == 1
9204 && TYPE_UNSIGNED (type)
9205 && (t == NULL_TREE || !integer_onep (t)))
9207 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9208 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9209 true, GSI_SAME_STMT);
9210 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9211 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9212 true, GSI_SAME_STMT);
9213 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9214 NULL_TREE, NULL_TREE);
9215 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9216 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9217 expand_omp_regimplify_p, NULL, NULL)
9218 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9219 expand_omp_regimplify_p, NULL, NULL))
9221 gsi = gsi_for_stmt (cond_stmt);
9222 gimple_regimplify_operands (cond_stmt, &gsi);
9224 ep = split_block (entry_bb, cond_stmt);
9225 ep->flags = EDGE_TRUE_VALUE;
9226 entry_bb = ep->dest;
9227 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9228 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9229 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9230 if (gimple_in_ssa_p (cfun))
9232 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9233 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9234 !gsi_end_p (gpi); gsi_next (&gpi))
9236 gphi *phi = gpi.phi ();
9237 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9238 ep, UNKNOWN_LOCATION);
9241 gsi = gsi_last_bb (entry_bb);
9244 switch (gimple_omp_for_kind (fd->for_stmt))
9246 case GF_OMP_FOR_KIND_FOR:
9247 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9248 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9249 break;
9250 case GF_OMP_FOR_KIND_DISTRIBUTE:
9251 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9252 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9253 break;
9254 default:
9255 gcc_unreachable ();
9257 nthreads = build_call_expr (nthreads, 0);
9258 nthreads = fold_convert (itype, nthreads);
9259 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9260 true, GSI_SAME_STMT);
9261 threadid = build_call_expr (threadid, 0);
9262 threadid = fold_convert (itype, threadid);
9263 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9264 true, GSI_SAME_STMT);
9266 n1 = fd->loop.n1;
9267 n2 = fd->loop.n2;
9268 step = fd->loop.step;
9269 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9271 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9272 OMP_CLAUSE__LOOPTEMP_);
9273 gcc_assert (innerc);
9274 n1 = OMP_CLAUSE_DECL (innerc);
9275 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9276 OMP_CLAUSE__LOOPTEMP_);
9277 gcc_assert (innerc);
9278 n2 = OMP_CLAUSE_DECL (innerc);
9280 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9281 true, NULL_TREE, true, GSI_SAME_STMT);
9282 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9283 true, NULL_TREE, true, GSI_SAME_STMT);
9284 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9285 true, NULL_TREE, true, GSI_SAME_STMT);
9287 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9288 t = fold_build2 (PLUS_EXPR, itype, step, t);
9289 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9290 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9291 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9292 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9293 fold_build1 (NEGATE_EXPR, itype, t),
9294 fold_build1 (NEGATE_EXPR, itype, step));
9295 else
9296 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9297 t = fold_convert (itype, t);
9298 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9300 q = create_tmp_reg (itype, "q");
9301 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9302 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9303 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9305 tt = create_tmp_reg (itype, "tt");
9306 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9307 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9308 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9310 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9311 gcond *cond_stmt = gimple_build_cond_empty (t);
9312 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9314 second_bb = split_block (entry_bb, cond_stmt)->dest;
9315 gsi = gsi_last_bb (second_bb);
9316 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9318 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9319 GSI_SAME_STMT);
9320 gassign *assign_stmt
9321 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9322 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9324 third_bb = split_block (second_bb, assign_stmt)->dest;
9325 gsi = gsi_last_bb (third_bb);
9326 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9328 t = build2 (MULT_EXPR, itype, q, threadid);
9329 t = build2 (PLUS_EXPR, itype, t, tt);
9330 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9332 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9333 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9335 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9336 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9338 /* Remove the GIMPLE_OMP_FOR statement. */
9339 gsi_remove (&gsi, true);
9341 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9342 gsi = gsi_start_bb (seq_start_bb);
9344 tree startvar = fd->loop.v;
9345 tree endvar = NULL_TREE;
9347 if (gimple_omp_for_combined_p (fd->for_stmt))
9349 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9350 ? gimple_omp_parallel_clauses (inner_stmt)
9351 : gimple_omp_for_clauses (inner_stmt);
9352 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9353 gcc_assert (innerc);
9354 startvar = OMP_CLAUSE_DECL (innerc);
9355 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9356 OMP_CLAUSE__LOOPTEMP_);
9357 gcc_assert (innerc);
9358 endvar = OMP_CLAUSE_DECL (innerc);
9359 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9360 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9362 int i;
9363 for (i = 1; i < fd->collapse; i++)
9365 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9366 OMP_CLAUSE__LOOPTEMP_);
9367 gcc_assert (innerc);
9369 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9370 OMP_CLAUSE__LOOPTEMP_);
9371 if (innerc)
9373 /* If needed (distribute parallel for with lastprivate),
9374 propagate down the total number of iterations. */
9375 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9376 fd->loop.n2);
9377 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9378 GSI_CONTINUE_LINKING);
9379 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9380 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9384 t = fold_convert (itype, s0);
9385 t = fold_build2 (MULT_EXPR, itype, t, step);
9386 if (POINTER_TYPE_P (type))
9387 t = fold_build_pointer_plus (n1, t);
9388 else
9389 t = fold_build2 (PLUS_EXPR, type, t, n1);
9390 t = fold_convert (TREE_TYPE (startvar), t);
9391 t = force_gimple_operand_gsi (&gsi, t,
9392 DECL_P (startvar)
9393 && TREE_ADDRESSABLE (startvar),
9394 NULL_TREE, false, GSI_CONTINUE_LINKING);
9395 assign_stmt = gimple_build_assign (startvar, t);
9396 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9398 t = fold_convert (itype, e0);
9399 t = fold_build2 (MULT_EXPR, itype, t, step);
9400 if (POINTER_TYPE_P (type))
9401 t = fold_build_pointer_plus (n1, t);
9402 else
9403 t = fold_build2 (PLUS_EXPR, type, t, n1);
9404 t = fold_convert (TREE_TYPE (startvar), t);
9405 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9406 false, GSI_CONTINUE_LINKING);
9407 if (endvar)
9409 assign_stmt = gimple_build_assign (endvar, e);
9410 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9411 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9412 assign_stmt = gimple_build_assign (fd->loop.v, e);
9413 else
9414 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9415 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9417 /* Handle linear clause adjustments. */
9418 tree itercnt = NULL_TREE;
9419 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9420 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9421 c; c = OMP_CLAUSE_CHAIN (c))
9422 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9423 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9425 tree d = OMP_CLAUSE_DECL (c);
9426 bool is_ref = is_reference (d);
9427 tree t = d, a, dest;
9428 if (is_ref)
9429 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9430 if (itercnt == NULL_TREE)
9432 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9434 itercnt = fold_build2 (MINUS_EXPR, itype,
9435 fold_convert (itype, n1),
9436 fold_convert (itype, fd->loop.n1));
9437 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9438 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9439 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9440 NULL_TREE, false,
9441 GSI_CONTINUE_LINKING);
9443 else
9444 itercnt = s0;
9446 tree type = TREE_TYPE (t);
9447 if (POINTER_TYPE_P (type))
9448 type = sizetype;
9449 a = fold_build2 (MULT_EXPR, type,
9450 fold_convert (type, itercnt),
9451 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9452 dest = unshare_expr (t);
9453 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9454 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9455 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9456 false, GSI_CONTINUE_LINKING);
9457 assign_stmt = gimple_build_assign (dest, t);
9458 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9460 if (fd->collapse > 1)
9461 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9463 if (!broken_loop)
9465 /* The code controlling the sequential loop replaces the
9466 GIMPLE_OMP_CONTINUE. */
9467 gsi = gsi_last_bb (cont_bb);
9468 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9469 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9470 vmain = gimple_omp_continue_control_use (cont_stmt);
9471 vback = gimple_omp_continue_control_def (cont_stmt);
9473 if (!gimple_omp_for_combined_p (fd->for_stmt))
9475 if (POINTER_TYPE_P (type))
9476 t = fold_build_pointer_plus (vmain, step);
9477 else
9478 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9479 t = force_gimple_operand_gsi (&gsi, t,
9480 DECL_P (vback)
9481 && TREE_ADDRESSABLE (vback),
9482 NULL_TREE, true, GSI_SAME_STMT);
9483 assign_stmt = gimple_build_assign (vback, t);
9484 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9486 t = build2 (fd->loop.cond_code, boolean_type_node,
9487 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9488 ? t : vback, e);
9489 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9492 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9493 gsi_remove (&gsi, true);
9495 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9496 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9499 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9500 gsi = gsi_last_bb (exit_bb);
9501 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9503 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9504 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9506 gsi_remove (&gsi, true);
9508 /* Connect all the blocks. */
9509 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9510 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9511 ep = find_edge (entry_bb, second_bb);
9512 ep->flags = EDGE_TRUE_VALUE;
9513 ep->probability = REG_BR_PROB_BASE / 4;
9514 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9515 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9517 if (!broken_loop)
9519 ep = find_edge (cont_bb, body_bb);
9520 if (ep == NULL)
9522 ep = BRANCH_EDGE (cont_bb);
9523 gcc_assert (single_succ (ep->dest) == body_bb);
9525 if (gimple_omp_for_combined_p (fd->for_stmt))
9527 remove_edge (ep);
9528 ep = NULL;
9530 else if (fd->collapse > 1)
9532 remove_edge (ep);
9533 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9535 else
9536 ep->flags = EDGE_TRUE_VALUE;
9537 find_edge (cont_bb, fin_bb)->flags
9538 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9541 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9542 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9543 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9545 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9546 recompute_dominator (CDI_DOMINATORS, body_bb));
9547 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9548 recompute_dominator (CDI_DOMINATORS, fin_bb));
9550 struct loop *loop = body_bb->loop_father;
9551 if (loop != entry_bb->loop_father)
9553 gcc_assert (loop->header == body_bb);
9554 gcc_assert (broken_loop
9555 || loop->latch == region->cont
9556 || single_pred (loop->latch) == region->cont);
9557 return;
9560 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9562 loop = alloc_loop ();
9563 loop->header = body_bb;
9564 if (collapse_bb == NULL)
9565 loop->latch = cont_bb;
9566 add_loop (loop, body_bb->loop_father);
9570 /* Return phi in E->DEST with ARG on edge E. */
9572 static gphi *
9573 find_phi_with_arg_on_edge (tree arg, edge e)
9575 basic_block bb = e->dest;
9577 for (gphi_iterator gpi = gsi_start_phis (bb);
9578 !gsi_end_p (gpi);
9579 gsi_next (&gpi))
9581 gphi *phi = gpi.phi ();
9582 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9583 return phi;
9586 return NULL;
9589 /* A subroutine of expand_omp_for. Generate code for a parallel
9590 loop with static schedule and a specified chunk size. Given
9591 parameters:
9593 for (V = N1; V cond N2; V += STEP) BODY;
9595 where COND is "<" or ">", we generate pseudocode
9597 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9598 if (cond is <)
9599 adj = STEP - 1;
9600 else
9601 adj = STEP + 1;
9602 if ((__typeof (V)) -1 > 0 && cond is >)
9603 n = -(adj + N2 - N1) / -STEP;
9604 else
9605 n = (adj + N2 - N1) / STEP;
9606 trip = 0;
9607 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9608 here so that V is defined
9609 if the loop is not entered
9611 s0 = (trip * nthreads + threadid) * CHUNK;
9612 e0 = min(s0 + CHUNK, n);
9613 if (s0 < n) goto L1; else goto L4;
9615 V = s0 * STEP + N1;
9616 e = e0 * STEP + N1;
9618 BODY;
9619 V += STEP;
9620 if (V cond e) goto L2; else goto L3;
9622 trip += 1;
9623 goto L0;
9627 static void
9628 expand_omp_for_static_chunk (struct omp_region *region,
9629 struct omp_for_data *fd, gimple *inner_stmt)
9631 tree n, s0, e0, e, t;
9632 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9633 tree type, itype, vmain, vback, vextra;
9634 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9635 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9636 gimple_stmt_iterator gsi;
9637 edge se;
9638 bool broken_loop = region->cont == NULL;
9639 tree *counts = NULL;
9640 tree n1, n2, step;
9642 itype = type = TREE_TYPE (fd->loop.v);
9643 if (POINTER_TYPE_P (type))
9644 itype = signed_type_for (type);
9646 entry_bb = region->entry;
9647 se = split_block (entry_bb, last_stmt (entry_bb));
9648 entry_bb = se->src;
9649 iter_part_bb = se->dest;
9650 cont_bb = region->cont;
9651 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9652 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9653 gcc_assert (broken_loop
9654 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9655 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9656 body_bb = single_succ (seq_start_bb);
9657 if (!broken_loop)
9659 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9660 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9661 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9662 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9664 exit_bb = region->exit;
9666 /* Trip and adjustment setup goes in ENTRY_BB. */
9667 gsi = gsi_last_bb (entry_bb);
9668 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9670 if (fd->collapse > 1)
9672 int first_zero_iter = -1, dummy = -1;
9673 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9675 counts = XALLOCAVEC (tree, fd->collapse);
9676 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9677 fin_bb, first_zero_iter,
9678 dummy_bb, dummy, l2_dom_bb);
9679 t = NULL_TREE;
9681 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9682 t = integer_one_node;
9683 else
9684 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9685 fold_convert (type, fd->loop.n1),
9686 fold_convert (type, fd->loop.n2));
9687 if (fd->collapse == 1
9688 && TYPE_UNSIGNED (type)
9689 && (t == NULL_TREE || !integer_onep (t)))
9691 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9692 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9693 true, GSI_SAME_STMT);
9694 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9695 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9696 true, GSI_SAME_STMT);
9697 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9698 NULL_TREE, NULL_TREE);
9699 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9700 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9701 expand_omp_regimplify_p, NULL, NULL)
9702 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9703 expand_omp_regimplify_p, NULL, NULL))
9705 gsi = gsi_for_stmt (cond_stmt);
9706 gimple_regimplify_operands (cond_stmt, &gsi);
9708 se = split_block (entry_bb, cond_stmt);
9709 se->flags = EDGE_TRUE_VALUE;
9710 entry_bb = se->dest;
9711 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9712 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9713 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9714 if (gimple_in_ssa_p (cfun))
9716 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9717 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9718 !gsi_end_p (gpi); gsi_next (&gpi))
9720 gphi *phi = gpi.phi ();
9721 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9722 se, UNKNOWN_LOCATION);
9725 gsi = gsi_last_bb (entry_bb);
9728 switch (gimple_omp_for_kind (fd->for_stmt))
9730 case GF_OMP_FOR_KIND_FOR:
9731 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9732 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9733 break;
9734 case GF_OMP_FOR_KIND_DISTRIBUTE:
9735 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9736 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9737 break;
9738 default:
9739 gcc_unreachable ();
9741 nthreads = build_call_expr (nthreads, 0);
9742 nthreads = fold_convert (itype, nthreads);
9743 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9744 true, GSI_SAME_STMT);
9745 threadid = build_call_expr (threadid, 0);
9746 threadid = fold_convert (itype, threadid);
9747 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9748 true, GSI_SAME_STMT);
9750 n1 = fd->loop.n1;
9751 n2 = fd->loop.n2;
9752 step = fd->loop.step;
9753 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9755 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9756 OMP_CLAUSE__LOOPTEMP_);
9757 gcc_assert (innerc);
9758 n1 = OMP_CLAUSE_DECL (innerc);
9759 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9760 OMP_CLAUSE__LOOPTEMP_);
9761 gcc_assert (innerc);
9762 n2 = OMP_CLAUSE_DECL (innerc);
9764 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9765 true, NULL_TREE, true, GSI_SAME_STMT);
9766 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9767 true, NULL_TREE, true, GSI_SAME_STMT);
9768 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9769 true, NULL_TREE, true, GSI_SAME_STMT);
9770 tree chunk_size = fold_convert (itype, fd->chunk_size);
9771 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9772 chunk_size
9773 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9774 GSI_SAME_STMT);
9776 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9777 t = fold_build2 (PLUS_EXPR, itype, step, t);
9778 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9779 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9780 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9781 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9782 fold_build1 (NEGATE_EXPR, itype, t),
9783 fold_build1 (NEGATE_EXPR, itype, step));
9784 else
9785 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9786 t = fold_convert (itype, t);
9787 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9788 true, GSI_SAME_STMT);
9790 trip_var = create_tmp_reg (itype, ".trip");
9791 if (gimple_in_ssa_p (cfun))
9793 trip_init = make_ssa_name (trip_var);
9794 trip_main = make_ssa_name (trip_var);
9795 trip_back = make_ssa_name (trip_var);
9797 else
9799 trip_init = trip_var;
9800 trip_main = trip_var;
9801 trip_back = trip_var;
9804 gassign *assign_stmt
9805 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9806 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9808 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9809 t = fold_build2 (MULT_EXPR, itype, t, step);
9810 if (POINTER_TYPE_P (type))
9811 t = fold_build_pointer_plus (n1, t);
9812 else
9813 t = fold_build2 (PLUS_EXPR, type, t, n1);
9814 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9815 true, GSI_SAME_STMT);
9817 /* Remove the GIMPLE_OMP_FOR. */
9818 gsi_remove (&gsi, true);
9820 gimple_stmt_iterator gsif = gsi;
9822 /* Iteration space partitioning goes in ITER_PART_BB. */
9823 gsi = gsi_last_bb (iter_part_bb);
9825 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9826 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9827 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9828 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9829 false, GSI_CONTINUE_LINKING);
9831 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9832 t = fold_build2 (MIN_EXPR, itype, t, n);
9833 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9834 false, GSI_CONTINUE_LINKING);
9836 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9837 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9839 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9840 gsi = gsi_start_bb (seq_start_bb);
9842 tree startvar = fd->loop.v;
9843 tree endvar = NULL_TREE;
9845 if (gimple_omp_for_combined_p (fd->for_stmt))
9847 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9848 ? gimple_omp_parallel_clauses (inner_stmt)
9849 : gimple_omp_for_clauses (inner_stmt);
9850 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9851 gcc_assert (innerc);
9852 startvar = OMP_CLAUSE_DECL (innerc);
9853 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9854 OMP_CLAUSE__LOOPTEMP_);
9855 gcc_assert (innerc);
9856 endvar = OMP_CLAUSE_DECL (innerc);
9857 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9858 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9860 int i;
9861 for (i = 1; i < fd->collapse; i++)
9863 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9864 OMP_CLAUSE__LOOPTEMP_);
9865 gcc_assert (innerc);
9867 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9868 OMP_CLAUSE__LOOPTEMP_);
9869 if (innerc)
9871 /* If needed (distribute parallel for with lastprivate),
9872 propagate down the total number of iterations. */
9873 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9874 fd->loop.n2);
9875 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9876 GSI_CONTINUE_LINKING);
9877 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9878 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9883 t = fold_convert (itype, s0);
9884 t = fold_build2 (MULT_EXPR, itype, t, step);
9885 if (POINTER_TYPE_P (type))
9886 t = fold_build_pointer_plus (n1, t);
9887 else
9888 t = fold_build2 (PLUS_EXPR, type, t, n1);
9889 t = fold_convert (TREE_TYPE (startvar), t);
9890 t = force_gimple_operand_gsi (&gsi, t,
9891 DECL_P (startvar)
9892 && TREE_ADDRESSABLE (startvar),
9893 NULL_TREE, false, GSI_CONTINUE_LINKING);
9894 assign_stmt = gimple_build_assign (startvar, t);
9895 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9897 t = fold_convert (itype, e0);
9898 t = fold_build2 (MULT_EXPR, itype, t, step);
9899 if (POINTER_TYPE_P (type))
9900 t = fold_build_pointer_plus (n1, t);
9901 else
9902 t = fold_build2 (PLUS_EXPR, type, t, n1);
9903 t = fold_convert (TREE_TYPE (startvar), t);
9904 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9905 false, GSI_CONTINUE_LINKING);
9906 if (endvar)
9908 assign_stmt = gimple_build_assign (endvar, e);
9909 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9910 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9911 assign_stmt = gimple_build_assign (fd->loop.v, e);
9912 else
9913 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9914 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9916 /* Handle linear clause adjustments. */
9917 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9918 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9919 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9920 c; c = OMP_CLAUSE_CHAIN (c))
9921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9922 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9924 tree d = OMP_CLAUSE_DECL (c);
9925 bool is_ref = is_reference (d);
9926 tree t = d, a, dest;
9927 if (is_ref)
9928 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9929 tree type = TREE_TYPE (t);
9930 if (POINTER_TYPE_P (type))
9931 type = sizetype;
9932 dest = unshare_expr (t);
9933 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9934 expand_omp_build_assign (&gsif, v, t);
9935 if (itercnt == NULL_TREE)
9937 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9939 itercntbias
9940 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9941 fold_convert (itype, fd->loop.n1));
9942 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9943 itercntbias, step);
9944 itercntbias
9945 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9946 NULL_TREE, true,
9947 GSI_SAME_STMT);
9948 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9949 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9950 NULL_TREE, false,
9951 GSI_CONTINUE_LINKING);
9953 else
9954 itercnt = s0;
9956 a = fold_build2 (MULT_EXPR, type,
9957 fold_convert (type, itercnt),
9958 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9959 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9960 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9961 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9962 false, GSI_CONTINUE_LINKING);
9963 assign_stmt = gimple_build_assign (dest, t);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9966 if (fd->collapse > 1)
9967 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9969 if (!broken_loop)
9971 /* The code controlling the sequential loop goes in CONT_BB,
9972 replacing the GIMPLE_OMP_CONTINUE. */
9973 gsi = gsi_last_bb (cont_bb);
9974 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9975 vmain = gimple_omp_continue_control_use (cont_stmt);
9976 vback = gimple_omp_continue_control_def (cont_stmt);
9978 if (!gimple_omp_for_combined_p (fd->for_stmt))
9980 if (POINTER_TYPE_P (type))
9981 t = fold_build_pointer_plus (vmain, step);
9982 else
9983 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9984 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9985 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9986 true, GSI_SAME_STMT);
9987 assign_stmt = gimple_build_assign (vback, t);
9988 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9990 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9991 t = build2 (EQ_EXPR, boolean_type_node,
9992 build_int_cst (itype, 0),
9993 build_int_cst (itype, 1));
9994 else
9995 t = build2 (fd->loop.cond_code, boolean_type_node,
9996 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9997 ? t : vback, e);
9998 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10001 /* Remove GIMPLE_OMP_CONTINUE. */
10002 gsi_remove (&gsi, true);
10004 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10005 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10007 /* Trip update code goes into TRIP_UPDATE_BB. */
10008 gsi = gsi_start_bb (trip_update_bb);
10010 t = build_int_cst (itype, 1);
10011 t = build2 (PLUS_EXPR, itype, trip_main, t);
10012 assign_stmt = gimple_build_assign (trip_back, t);
10013 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10016 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10017 gsi = gsi_last_bb (exit_bb);
10018 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10020 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10021 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10023 gsi_remove (&gsi, true);
10025 /* Connect the new blocks. */
10026 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10027 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10029 if (!broken_loop)
10031 se = find_edge (cont_bb, body_bb);
10032 if (se == NULL)
10034 se = BRANCH_EDGE (cont_bb);
10035 gcc_assert (single_succ (se->dest) == body_bb);
10037 if (gimple_omp_for_combined_p (fd->for_stmt))
10039 remove_edge (se);
10040 se = NULL;
10042 else if (fd->collapse > 1)
10044 remove_edge (se);
10045 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10047 else
10048 se->flags = EDGE_TRUE_VALUE;
10049 find_edge (cont_bb, trip_update_bb)->flags
10050 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10052 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10055 if (gimple_in_ssa_p (cfun))
10057 gphi_iterator psi;
10058 gphi *phi;
10059 edge re, ene;
10060 edge_var_map *vm;
10061 size_t i;
10063 gcc_assert (fd->collapse == 1 && !broken_loop);
10065 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10066 remove arguments of the phi nodes in fin_bb. We need to create
10067 appropriate phi nodes in iter_part_bb instead. */
10068 se = find_edge (iter_part_bb, fin_bb);
10069 re = single_succ_edge (trip_update_bb);
10070 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10071 ene = single_succ_edge (entry_bb);
10073 psi = gsi_start_phis (fin_bb);
10074 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10075 gsi_next (&psi), ++i)
10077 gphi *nphi;
10078 source_location locus;
10080 phi = psi.phi ();
10081 t = gimple_phi_result (phi);
10082 gcc_assert (t == redirect_edge_var_map_result (vm));
10084 if (!single_pred_p (fin_bb))
10085 t = copy_ssa_name (t, phi);
10087 nphi = create_phi_node (t, iter_part_bb);
10089 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10090 locus = gimple_phi_arg_location_from_edge (phi, se);
10092 /* A special case -- fd->loop.v is not yet computed in
10093 iter_part_bb, we need to use vextra instead. */
10094 if (t == fd->loop.v)
10095 t = vextra;
10096 add_phi_arg (nphi, t, ene, locus);
10097 locus = redirect_edge_var_map_location (vm);
10098 tree back_arg = redirect_edge_var_map_def (vm);
10099 add_phi_arg (nphi, back_arg, re, locus);
10100 edge ce = find_edge (cont_bb, body_bb);
10101 if (ce == NULL)
10103 ce = BRANCH_EDGE (cont_bb);
10104 gcc_assert (single_succ (ce->dest) == body_bb);
10105 ce = single_succ_edge (ce->dest);
10107 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10108 gcc_assert (inner_loop_phi != NULL);
10109 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10110 find_edge (seq_start_bb, body_bb), locus);
10112 if (!single_pred_p (fin_bb))
10113 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10115 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10116 redirect_edge_var_map_clear (re);
10117 if (single_pred_p (fin_bb))
10118 while (1)
10120 psi = gsi_start_phis (fin_bb);
10121 if (gsi_end_p (psi))
10122 break;
10123 remove_phi_node (&psi, false);
10126 /* Make phi node for trip. */
10127 phi = create_phi_node (trip_main, iter_part_bb);
10128 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10129 UNKNOWN_LOCATION);
10130 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10131 UNKNOWN_LOCATION);
10134 if (!broken_loop)
10135 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10136 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10137 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10138 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10139 recompute_dominator (CDI_DOMINATORS, fin_bb));
10140 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10141 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10142 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10143 recompute_dominator (CDI_DOMINATORS, body_bb));
10145 if (!broken_loop)
10147 struct loop *loop = body_bb->loop_father;
10148 struct loop *trip_loop = alloc_loop ();
10149 trip_loop->header = iter_part_bb;
10150 trip_loop->latch = trip_update_bb;
10151 add_loop (trip_loop, iter_part_bb->loop_father);
10153 if (loop != entry_bb->loop_father)
10155 gcc_assert (loop->header == body_bb);
10156 gcc_assert (loop->latch == region->cont
10157 || single_pred (loop->latch) == region->cont);
10158 trip_loop->inner = loop;
10159 return;
10162 if (!gimple_omp_for_combined_p (fd->for_stmt))
10164 loop = alloc_loop ();
10165 loop->header = body_bb;
10166 if (collapse_bb == NULL)
10167 loop->latch = cont_bb;
10168 add_loop (loop, trip_loop);
10173 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10174 Given parameters:
10175 for (V = N1; V cond N2; V += STEP) BODY;
10177 where COND is "<" or ">" or "!=", we generate pseudocode
10179 for (ind_var = low; ind_var < high; ind_var++)
10181 V = n1 + (ind_var * STEP)
10183 <BODY>
10186 In the above pseudocode, low and high are function parameters of the
10187 child function. In the function below, we are inserting a temp.
10188 variable that will be making a call to two OMP functions that will not be
10189 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10190 with _Cilk_for). These functions are replaced with low and high
10191 by the function that handles taskreg. */
10194 static void
10195 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10197 bool broken_loop = region->cont == NULL;
10198 basic_block entry_bb = region->entry;
10199 basic_block cont_bb = region->cont;
10201 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10202 gcc_assert (broken_loop
10203 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10204 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10205 basic_block l1_bb, l2_bb;
10207 if (!broken_loop)
10209 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10210 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10211 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10212 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10214 else
10216 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10217 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10218 l2_bb = single_succ (l1_bb);
10220 basic_block exit_bb = region->exit;
10221 basic_block l2_dom_bb = NULL;
10223 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10225 /* Below statements until the "tree high_val = ..." are pseudo statements
10226 used to pass information to be used by expand_omp_taskreg.
10227 low_val and high_val will be replaced by the __low and __high
10228 parameter from the child function.
10230 The call_exprs part is a place-holder, it is mainly used
10231 to distinctly identify to the top-level part that this is
10232 where we should put low and high (reasoning given in header
10233 comment). */
10235 tree child_fndecl
10236 = gimple_omp_parallel_child_fn (
10237 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10238 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10239 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10241 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10242 high_val = t;
10243 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10244 low_val = t;
10246 gcc_assert (low_val && high_val);
10248 tree type = TREE_TYPE (low_val);
10249 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10250 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10252 /* Not needed in SSA form right now. */
10253 gcc_assert (!gimple_in_ssa_p (cfun));
10254 if (l2_dom_bb == NULL)
10255 l2_dom_bb = l1_bb;
10257 tree n1 = low_val;
10258 tree n2 = high_val;
10260 gimple *stmt = gimple_build_assign (ind_var, n1);
10262 /* Replace the GIMPLE_OMP_FOR statement. */
10263 gsi_replace (&gsi, stmt, true);
10265 if (!broken_loop)
10267 /* Code to control the increment goes in the CONT_BB. */
10268 gsi = gsi_last_bb (cont_bb);
10269 stmt = gsi_stmt (gsi);
10270 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10271 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10272 build_one_cst (type));
10274 /* Replace GIMPLE_OMP_CONTINUE. */
10275 gsi_replace (&gsi, stmt, true);
10278 /* Emit the condition in L1_BB. */
10279 gsi = gsi_after_labels (l1_bb);
10280 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10281 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10282 fd->loop.step);
10283 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10284 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10285 fd->loop.n1, fold_convert (sizetype, t));
10286 else
10287 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10288 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10289 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10290 expand_omp_build_assign (&gsi, fd->loop.v, t);
10292 /* The condition is always '<' since the runtime will fill in the low
10293 and high values. */
10294 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10295 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10297 /* Remove GIMPLE_OMP_RETURN. */
10298 gsi = gsi_last_bb (exit_bb);
10299 gsi_remove (&gsi, true);
10301 /* Connect the new blocks. */
10302 remove_edge (FALLTHRU_EDGE (entry_bb));
10304 edge e, ne;
10305 if (!broken_loop)
10307 remove_edge (BRANCH_EDGE (entry_bb));
10308 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10310 e = BRANCH_EDGE (l1_bb);
10311 ne = FALLTHRU_EDGE (l1_bb);
10312 e->flags = EDGE_TRUE_VALUE;
10314 else
10316 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10318 ne = single_succ_edge (l1_bb);
10319 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10322 ne->flags = EDGE_FALSE_VALUE;
10323 e->probability = REG_BR_PROB_BASE * 7 / 8;
10324 ne->probability = REG_BR_PROB_BASE / 8;
10326 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10327 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10328 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10330 if (!broken_loop)
10332 struct loop *loop = alloc_loop ();
10333 loop->header = l1_bb;
10334 loop->latch = cont_bb;
10335 add_loop (loop, l1_bb->loop_father);
10336 loop->safelen = INT_MAX;
10339 /* Pick the correct library function based on the precision of the
10340 induction variable type. */
10341 tree lib_fun = NULL_TREE;
10342 if (TYPE_PRECISION (type) == 32)
10343 lib_fun = cilk_for_32_fndecl;
10344 else if (TYPE_PRECISION (type) == 64)
10345 lib_fun = cilk_for_64_fndecl;
10346 else
10347 gcc_unreachable ();
10349 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10351 /* WS_ARGS contains the library function flavor to call:
10352 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10353 user-defined grain value. If the user does not define one, then zero
10354 is passed in by the parser. */
10355 vec_alloc (region->ws_args, 2);
10356 region->ws_args->quick_push (lib_fun);
10357 region->ws_args->quick_push (fd->chunk_size);
10360 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10361 loop. Given parameters:
10363 for (V = N1; V cond N2; V += STEP) BODY;
10365 where COND is "<" or ">", we generate pseudocode
10367 V = N1;
10368 goto L1;
10370 BODY;
10371 V += STEP;
10373 if (V cond N2) goto L0; else goto L2;
10376 For collapsed loops, given parameters:
10377 collapse(3)
10378 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10379 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10380 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10381 BODY;
10383 we generate pseudocode
10385 if (cond3 is <)
10386 adj = STEP3 - 1;
10387 else
10388 adj = STEP3 + 1;
10389 count3 = (adj + N32 - N31) / STEP3;
10390 if (cond2 is <)
10391 adj = STEP2 - 1;
10392 else
10393 adj = STEP2 + 1;
10394 count2 = (adj + N22 - N21) / STEP2;
10395 if (cond1 is <)
10396 adj = STEP1 - 1;
10397 else
10398 adj = STEP1 + 1;
10399 count1 = (adj + N12 - N11) / STEP1;
10400 count = count1 * count2 * count3;
10401 V = 0;
10402 V1 = N11;
10403 V2 = N21;
10404 V3 = N31;
10405 goto L1;
10407 BODY;
10408 V += 1;
10409 V3 += STEP3;
10410 V2 += (V3 cond3 N32) ? 0 : STEP2;
10411 V3 = (V3 cond3 N32) ? V3 : N31;
10412 V1 += (V2 cond2 N22) ? 0 : STEP1;
10413 V2 = (V2 cond2 N22) ? V2 : N21;
10415 if (V < count) goto L0; else goto L2;
10420 static void
10421 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10423 tree type, t;
10424 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10425 gimple_stmt_iterator gsi;
10426 gimple *stmt;
10427 gcond *cond_stmt;
10428 bool broken_loop = region->cont == NULL;
10429 edge e, ne;
10430 tree *counts = NULL;
10431 int i;
10432 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10433 OMP_CLAUSE_SAFELEN);
10434 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10435 OMP_CLAUSE__SIMDUID_);
10436 tree n1, n2;
10438 type = TREE_TYPE (fd->loop.v);
10439 entry_bb = region->entry;
10440 cont_bb = region->cont;
10441 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10442 gcc_assert (broken_loop
10443 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10444 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10445 if (!broken_loop)
10447 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10448 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10449 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10450 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10452 else
10454 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10455 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10456 l2_bb = single_succ (l1_bb);
10458 exit_bb = region->exit;
10459 l2_dom_bb = NULL;
10461 gsi = gsi_last_bb (entry_bb);
10463 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10464 /* Not needed in SSA form right now. */
10465 gcc_assert (!gimple_in_ssa_p (cfun));
10466 if (fd->collapse > 1)
10468 int first_zero_iter = -1, dummy = -1;
10469 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10471 counts = XALLOCAVEC (tree, fd->collapse);
10472 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10473 zero_iter_bb, first_zero_iter,
10474 dummy_bb, dummy, l2_dom_bb);
10476 if (l2_dom_bb == NULL)
10477 l2_dom_bb = l1_bb;
10479 n1 = fd->loop.n1;
10480 n2 = fd->loop.n2;
10481 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10483 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10484 OMP_CLAUSE__LOOPTEMP_);
10485 gcc_assert (innerc);
10486 n1 = OMP_CLAUSE_DECL (innerc);
10487 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10488 OMP_CLAUSE__LOOPTEMP_);
10489 gcc_assert (innerc);
10490 n2 = OMP_CLAUSE_DECL (innerc);
10491 expand_omp_build_assign (&gsi, fd->loop.v,
10492 fold_convert (type, n1));
10493 if (fd->collapse > 1)
10495 gsi_prev (&gsi);
10496 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10497 gsi_next (&gsi);
10500 else
10502 expand_omp_build_assign (&gsi, fd->loop.v,
10503 fold_convert (type, fd->loop.n1));
10504 if (fd->collapse > 1)
10505 for (i = 0; i < fd->collapse; i++)
10507 tree itype = TREE_TYPE (fd->loops[i].v);
10508 if (POINTER_TYPE_P (itype))
10509 itype = signed_type_for (itype);
10510 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10511 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10515 /* Remove the GIMPLE_OMP_FOR statement. */
10516 gsi_remove (&gsi, true);
10518 if (!broken_loop)
10520 /* Code to control the increment goes in the CONT_BB. */
10521 gsi = gsi_last_bb (cont_bb);
10522 stmt = gsi_stmt (gsi);
10523 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10525 if (POINTER_TYPE_P (type))
10526 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10527 else
10528 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10529 expand_omp_build_assign (&gsi, fd->loop.v, t);
10531 if (fd->collapse > 1)
10533 i = fd->collapse - 1;
10534 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10536 t = fold_convert (sizetype, fd->loops[i].step);
10537 t = fold_build_pointer_plus (fd->loops[i].v, t);
10539 else
10541 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10542 fd->loops[i].step);
10543 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10544 fd->loops[i].v, t);
10546 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10548 for (i = fd->collapse - 1; i > 0; i--)
10550 tree itype = TREE_TYPE (fd->loops[i].v);
10551 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10552 if (POINTER_TYPE_P (itype2))
10553 itype2 = signed_type_for (itype2);
10554 t = build3 (COND_EXPR, itype2,
10555 build2 (fd->loops[i].cond_code, boolean_type_node,
10556 fd->loops[i].v,
10557 fold_convert (itype, fd->loops[i].n2)),
10558 build_int_cst (itype2, 0),
10559 fold_convert (itype2, fd->loops[i - 1].step));
10560 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10561 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10562 else
10563 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10564 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10566 t = build3 (COND_EXPR, itype,
10567 build2 (fd->loops[i].cond_code, boolean_type_node,
10568 fd->loops[i].v,
10569 fold_convert (itype, fd->loops[i].n2)),
10570 fd->loops[i].v,
10571 fold_convert (itype, fd->loops[i].n1));
10572 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10576 /* Remove GIMPLE_OMP_CONTINUE. */
10577 gsi_remove (&gsi, true);
10580 /* Emit the condition in L1_BB. */
10581 gsi = gsi_start_bb (l1_bb);
10583 t = fold_convert (type, n2);
10584 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10585 false, GSI_CONTINUE_LINKING);
10586 tree v = fd->loop.v;
10587 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10588 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10589 false, GSI_CONTINUE_LINKING);
10590 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10591 cond_stmt = gimple_build_cond_empty (t);
10592 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10593 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10594 NULL, NULL)
10595 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10596 NULL, NULL))
10598 gsi = gsi_for_stmt (cond_stmt);
10599 gimple_regimplify_operands (cond_stmt, &gsi);
10602 /* Remove GIMPLE_OMP_RETURN. */
10603 gsi = gsi_last_bb (exit_bb);
10604 gsi_remove (&gsi, true);
10606 /* Connect the new blocks. */
10607 remove_edge (FALLTHRU_EDGE (entry_bb));
10609 if (!broken_loop)
10611 remove_edge (BRANCH_EDGE (entry_bb));
10612 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10614 e = BRANCH_EDGE (l1_bb);
10615 ne = FALLTHRU_EDGE (l1_bb);
10616 e->flags = EDGE_TRUE_VALUE;
10618 else
10620 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10622 ne = single_succ_edge (l1_bb);
10623 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10626 ne->flags = EDGE_FALSE_VALUE;
10627 e->probability = REG_BR_PROB_BASE * 7 / 8;
10628 ne->probability = REG_BR_PROB_BASE / 8;
10630 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10631 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10632 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10634 if (!broken_loop)
10636 struct loop *loop = alloc_loop ();
10637 loop->header = l1_bb;
10638 loop->latch = cont_bb;
10639 add_loop (loop, l1_bb->loop_father);
10640 if (safelen == NULL_TREE)
10641 loop->safelen = INT_MAX;
10642 else
10644 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10645 if (TREE_CODE (safelen) != INTEGER_CST)
10646 loop->safelen = 0;
10647 else if (!tree_fits_uhwi_p (safelen)
10648 || tree_to_uhwi (safelen) > INT_MAX)
10649 loop->safelen = INT_MAX;
10650 else
10651 loop->safelen = tree_to_uhwi (safelen);
10652 if (loop->safelen == 1)
10653 loop->safelen = 0;
10655 if (simduid)
10657 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10658 cfun->has_simduid_loops = true;
10660 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10661 the loop. */
10662 if ((flag_tree_loop_vectorize
10663 || (!global_options_set.x_flag_tree_loop_vectorize
10664 && !global_options_set.x_flag_tree_vectorize))
10665 && flag_tree_loop_optimize
10666 && loop->safelen > 1)
10668 loop->force_vectorize = true;
10669 cfun->has_force_vectorize_loops = true;
10672 else if (simduid)
10673 cfun->has_simduid_loops = true;
10676 /* Taskloop construct is represented after gimplification with
10677 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10678 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10679 which should just compute all the needed loop temporaries
10680 for GIMPLE_OMP_TASK. */
10682 static void
10683 expand_omp_taskloop_for_outer (struct omp_region *region,
10684 struct omp_for_data *fd,
10685 gimple *inner_stmt)
10687 tree type, bias = NULL_TREE;
10688 basic_block entry_bb, cont_bb, exit_bb;
10689 gimple_stmt_iterator gsi;
10690 gassign *assign_stmt;
10691 tree *counts = NULL;
10692 int i;
10694 gcc_assert (inner_stmt);
10695 gcc_assert (region->cont);
10696 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10697 && gimple_omp_task_taskloop_p (inner_stmt));
10698 type = TREE_TYPE (fd->loop.v);
10700 /* See if we need to bias by LLONG_MIN. */
10701 if (fd->iter_type == long_long_unsigned_type_node
10702 && TREE_CODE (type) == INTEGER_TYPE
10703 && !TYPE_UNSIGNED (type))
10705 tree n1, n2;
10707 if (fd->loop.cond_code == LT_EXPR)
10709 n1 = fd->loop.n1;
10710 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10712 else
10714 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10715 n2 = fd->loop.n1;
10717 if (TREE_CODE (n1) != INTEGER_CST
10718 || TREE_CODE (n2) != INTEGER_CST
10719 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10720 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10723 entry_bb = region->entry;
10724 cont_bb = region->cont;
10725 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10726 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10727 exit_bb = region->exit;
10729 gsi = gsi_last_bb (entry_bb);
10730 gimple *for_stmt = gsi_stmt (gsi);
10731 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10732 if (fd->collapse > 1)
10734 int first_zero_iter = -1, dummy = -1;
10735 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10737 counts = XALLOCAVEC (tree, fd->collapse);
10738 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10739 zero_iter_bb, first_zero_iter,
10740 dummy_bb, dummy, l2_dom_bb);
10742 if (zero_iter_bb)
10744 /* Some counts[i] vars might be uninitialized if
10745 some loop has zero iterations. But the body shouldn't
10746 be executed in that case, so just avoid uninit warnings. */
10747 for (i = first_zero_iter; i < fd->collapse; i++)
10748 if (SSA_VAR_P (counts[i]))
10749 TREE_NO_WARNING (counts[i]) = 1;
10750 gsi_prev (&gsi);
10751 edge e = split_block (entry_bb, gsi_stmt (gsi));
10752 entry_bb = e->dest;
10753 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10754 gsi = gsi_last_bb (entry_bb);
10755 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10756 get_immediate_dominator (CDI_DOMINATORS,
10757 zero_iter_bb));
10761 tree t0, t1;
10762 t1 = fd->loop.n2;
10763 t0 = fd->loop.n1;
10764 if (POINTER_TYPE_P (TREE_TYPE (t0))
10765 && TYPE_PRECISION (TREE_TYPE (t0))
10766 != TYPE_PRECISION (fd->iter_type))
10768 /* Avoid casting pointers to integer of a different size. */
10769 tree itype = signed_type_for (type);
10770 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10771 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10773 else
10775 t1 = fold_convert (fd->iter_type, t1);
10776 t0 = fold_convert (fd->iter_type, t0);
10778 if (bias)
10780 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10781 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10784 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10785 OMP_CLAUSE__LOOPTEMP_);
10786 gcc_assert (innerc);
10787 tree startvar = OMP_CLAUSE_DECL (innerc);
10788 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10789 gcc_assert (innerc);
10790 tree endvar = OMP_CLAUSE_DECL (innerc);
10791 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10793 gcc_assert (innerc);
10794 for (i = 1; i < fd->collapse; i++)
10796 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10797 OMP_CLAUSE__LOOPTEMP_);
10798 gcc_assert (innerc);
10800 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10801 OMP_CLAUSE__LOOPTEMP_);
10802 if (innerc)
10804 /* If needed (inner taskloop has lastprivate clause), propagate
10805 down the total number of iterations. */
10806 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10807 NULL_TREE, false,
10808 GSI_CONTINUE_LINKING);
10809 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10810 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10814 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10815 GSI_CONTINUE_LINKING);
10816 assign_stmt = gimple_build_assign (startvar, t0);
10817 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10819 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10820 GSI_CONTINUE_LINKING);
10821 assign_stmt = gimple_build_assign (endvar, t1);
10822 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10823 if (fd->collapse > 1)
10824 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10826 /* Remove the GIMPLE_OMP_FOR statement. */
10827 gsi = gsi_for_stmt (for_stmt);
10828 gsi_remove (&gsi, true);
10830 gsi = gsi_last_bb (cont_bb);
10831 gsi_remove (&gsi, true);
10833 gsi = gsi_last_bb (exit_bb);
10834 gsi_remove (&gsi, true);
10836 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10837 remove_edge (BRANCH_EDGE (entry_bb));
10838 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10839 remove_edge (BRANCH_EDGE (cont_bb));
10840 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10841 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10842 recompute_dominator (CDI_DOMINATORS, region->entry));
10845 /* Taskloop construct is represented after gimplification with
10846 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10847 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10848 GOMP_taskloop{,_ull} function arranges for each task to be given just
10849 a single range of iterations. */
10851 static void
10852 expand_omp_taskloop_for_inner (struct omp_region *region,
10853 struct omp_for_data *fd,
10854 gimple *inner_stmt)
10856 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10857 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10858 basic_block fin_bb;
10859 gimple_stmt_iterator gsi;
10860 edge ep;
10861 bool broken_loop = region->cont == NULL;
10862 tree *counts = NULL;
10863 tree n1, n2, step;
10865 itype = type = TREE_TYPE (fd->loop.v);
10866 if (POINTER_TYPE_P (type))
10867 itype = signed_type_for (type);
10869 /* See if we need to bias by LLONG_MIN. */
10870 if (fd->iter_type == long_long_unsigned_type_node
10871 && TREE_CODE (type) == INTEGER_TYPE
10872 && !TYPE_UNSIGNED (type))
10874 tree n1, n2;
10876 if (fd->loop.cond_code == LT_EXPR)
10878 n1 = fd->loop.n1;
10879 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10881 else
10883 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10884 n2 = fd->loop.n1;
10886 if (TREE_CODE (n1) != INTEGER_CST
10887 || TREE_CODE (n2) != INTEGER_CST
10888 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10889 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10892 entry_bb = region->entry;
10893 cont_bb = region->cont;
10894 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10895 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10896 gcc_assert (broken_loop
10897 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10898 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10899 if (!broken_loop)
10901 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10902 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10904 exit_bb = region->exit;
10906 /* Iteration space partitioning goes in ENTRY_BB. */
10907 gsi = gsi_last_bb (entry_bb);
10908 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10910 if (fd->collapse > 1)
10912 int first_zero_iter = -1, dummy = -1;
10913 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10915 counts = XALLOCAVEC (tree, fd->collapse);
10916 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10917 fin_bb, first_zero_iter,
10918 dummy_bb, dummy, l2_dom_bb);
10919 t = NULL_TREE;
10921 else
10922 t = integer_one_node;
10924 step = fd->loop.step;
10925 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10926 OMP_CLAUSE__LOOPTEMP_);
10927 gcc_assert (innerc);
10928 n1 = OMP_CLAUSE_DECL (innerc);
10929 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10930 gcc_assert (innerc);
10931 n2 = OMP_CLAUSE_DECL (innerc);
10932 if (bias)
10934 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10935 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10937 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10938 true, NULL_TREE, true, GSI_SAME_STMT);
10939 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10940 true, NULL_TREE, true, GSI_SAME_STMT);
10941 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10942 true, NULL_TREE, true, GSI_SAME_STMT);
10944 tree startvar = fd->loop.v;
10945 tree endvar = NULL_TREE;
10947 if (gimple_omp_for_combined_p (fd->for_stmt))
10949 tree clauses = gimple_omp_for_clauses (inner_stmt);
10950 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10951 gcc_assert (innerc);
10952 startvar = OMP_CLAUSE_DECL (innerc);
10953 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10954 OMP_CLAUSE__LOOPTEMP_);
10955 gcc_assert (innerc);
10956 endvar = OMP_CLAUSE_DECL (innerc);
10958 t = fold_convert (TREE_TYPE (startvar), n1);
10959 t = force_gimple_operand_gsi (&gsi, t,
10960 DECL_P (startvar)
10961 && TREE_ADDRESSABLE (startvar),
10962 NULL_TREE, false, GSI_CONTINUE_LINKING);
10963 gimple *assign_stmt = gimple_build_assign (startvar, t);
10964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10966 t = fold_convert (TREE_TYPE (startvar), n2);
10967 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10968 false, GSI_CONTINUE_LINKING);
10969 if (endvar)
10971 assign_stmt = gimple_build_assign (endvar, e);
10972 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10973 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10974 assign_stmt = gimple_build_assign (fd->loop.v, e);
10975 else
10976 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10977 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10979 if (fd->collapse > 1)
10980 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10982 if (!broken_loop)
10984 /* The code controlling the sequential loop replaces the
10985 GIMPLE_OMP_CONTINUE. */
10986 gsi = gsi_last_bb (cont_bb);
10987 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10988 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10989 vmain = gimple_omp_continue_control_use (cont_stmt);
10990 vback = gimple_omp_continue_control_def (cont_stmt);
10992 if (!gimple_omp_for_combined_p (fd->for_stmt))
10994 if (POINTER_TYPE_P (type))
10995 t = fold_build_pointer_plus (vmain, step);
10996 else
10997 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10998 t = force_gimple_operand_gsi (&gsi, t,
10999 DECL_P (vback)
11000 && TREE_ADDRESSABLE (vback),
11001 NULL_TREE, true, GSI_SAME_STMT);
11002 assign_stmt = gimple_build_assign (vback, t);
11003 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11005 t = build2 (fd->loop.cond_code, boolean_type_node,
11006 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11007 ? t : vback, e);
11008 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11011 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11012 gsi_remove (&gsi, true);
11014 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11015 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11018 /* Remove the GIMPLE_OMP_FOR statement. */
11019 gsi = gsi_for_stmt (fd->for_stmt);
11020 gsi_remove (&gsi, true);
11022 /* Remove the GIMPLE_OMP_RETURN statement. */
11023 gsi = gsi_last_bb (exit_bb);
11024 gsi_remove (&gsi, true);
11026 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11027 if (!broken_loop)
11028 remove_edge (BRANCH_EDGE (entry_bb));
11029 else
11031 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11032 region->outer->cont = NULL;
11035 /* Connect all the blocks. */
11036 if (!broken_loop)
11038 ep = find_edge (cont_bb, body_bb);
11039 if (gimple_omp_for_combined_p (fd->for_stmt))
11041 remove_edge (ep);
11042 ep = NULL;
11044 else if (fd->collapse > 1)
11046 remove_edge (ep);
11047 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11049 else
11050 ep->flags = EDGE_TRUE_VALUE;
11051 find_edge (cont_bb, fin_bb)->flags
11052 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11055 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11056 recompute_dominator (CDI_DOMINATORS, body_bb));
11057 if (!broken_loop)
11058 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11059 recompute_dominator (CDI_DOMINATORS, fin_bb));
11061 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11063 struct loop *loop = alloc_loop ();
11064 loop->header = body_bb;
11065 if (collapse_bb == NULL)
11066 loop->latch = cont_bb;
11067 add_loop (loop, body_bb->loop_father);
11071 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11072 partitioned loop. The lowering here is abstracted, in that the
11073 loop parameters are passed through internal functions, which are
11074 further lowered by oacc_device_lower, once we get to the target
11075 compiler. The loop is of the form:
11077 for (V = B; V LTGT E; V += S) {BODY}
11079 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11080 (constant 0 for no chunking) and we will have a GWV partitioning
11081 mask, specifying dimensions over which the loop is to be
11082 partitioned (see note below). We generate code that looks like:
11084 <entry_bb> [incoming FALL->body, BRANCH->exit]
11085 typedef signedintify (typeof (V)) T; // underlying signed integral type
11086 T range = E - B;
11087 T chunk_no = 0;
11088 T DIR = LTGT == '<' ? +1 : -1;
11089 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11090 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11092 <head_bb> [created by splitting end of entry_bb]
11093 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11094 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11095 if (!(offset LTGT bound)) goto bottom_bb;
11097 <body_bb> [incoming]
11098 V = B + offset;
11099 {BODY}
11101 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11102 offset += step;
11103 if (offset LTGT bound) goto body_bb; [*]
11105 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11106 chunk_no++;
11107 if (chunk < chunk_max) goto head_bb;
11109 <exit_bb> [incoming]
11110 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11112 [*] Needed if V live at end of loop
11114 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11115 transition, and will be specified by a more general mechanism shortly.
11118 static void
11119 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11121 tree v = fd->loop.v;
11122 enum tree_code cond_code = fd->loop.cond_code;
11123 enum tree_code plus_code = PLUS_EXPR;
11125 tree chunk_size = integer_minus_one_node;
11126 tree gwv = integer_zero_node;
11127 tree iter_type = TREE_TYPE (v);
11128 tree diff_type = iter_type;
11129 tree plus_type = iter_type;
11130 struct oacc_collapse *counts = NULL;
11132 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11133 == GF_OMP_FOR_KIND_OACC_LOOP);
11134 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11135 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11137 if (POINTER_TYPE_P (iter_type))
11139 plus_code = POINTER_PLUS_EXPR;
11140 plus_type = sizetype;
11142 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11143 diff_type = signed_type_for (diff_type);
11145 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11146 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11147 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11148 basic_block bottom_bb = NULL;
11150 /* entry_bb has two sucessors; the branch edge is to the exit
11151 block, fallthrough edge to body. */
11152 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11153 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11155 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11156 body_bb, or to a block whose only successor is the body_bb. Its
11157 fallthrough successor is the final block (same as the branch
11158 successor of the entry_bb). */
11159 if (cont_bb)
11161 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11162 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11164 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11165 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11167 else
11168 gcc_assert (!gimple_in_ssa_p (cfun));
11170 /* The exit block only has entry_bb and cont_bb as predecessors. */
11171 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11173 tree chunk_no;
11174 tree chunk_max = NULL_TREE;
11175 tree bound, offset;
11176 tree step = create_tmp_var (diff_type, ".step");
11177 bool up = cond_code == LT_EXPR;
11178 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11179 bool chunking = !gimple_in_ssa_p (cfun);;
11180 bool negating;
11182 /* SSA instances. */
11183 tree offset_incr = NULL_TREE;
11184 tree offset_init = NULL_TREE;
11186 gimple_stmt_iterator gsi;
11187 gassign *ass;
11188 gcall *call;
11189 gimple *stmt;
11190 tree expr;
11191 location_t loc;
11192 edge split, be, fte;
11194 /* Split the end of entry_bb to create head_bb. */
11195 split = split_block (entry_bb, last_stmt (entry_bb));
11196 basic_block head_bb = split->dest;
11197 entry_bb = split->src;
11199 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11200 gsi = gsi_last_bb (entry_bb);
11201 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11202 loc = gimple_location (for_stmt);
11204 if (gimple_in_ssa_p (cfun))
11206 offset_init = gimple_omp_for_index (for_stmt, 0);
11207 gcc_assert (integer_zerop (fd->loop.n1));
11208 /* The SSA parallelizer does gang parallelism. */
11209 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11212 if (fd->collapse > 1)
11214 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11215 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11216 TREE_TYPE (fd->loop.n2));
11218 if (SSA_VAR_P (fd->loop.n2))
11220 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11221 true, GSI_SAME_STMT);
11222 ass = gimple_build_assign (fd->loop.n2, total);
11223 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11228 tree b = fd->loop.n1;
11229 tree e = fd->loop.n2;
11230 tree s = fd->loop.step;
11232 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11233 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11235 /* Convert the step, avoiding possible unsigned->signed overflow. */
11236 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11237 if (negating)
11238 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11239 s = fold_convert (diff_type, s);
11240 if (negating)
11241 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11242 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11244 if (!chunking)
11245 chunk_size = integer_zero_node;
11246 expr = fold_convert (diff_type, chunk_size);
11247 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11248 NULL_TREE, true, GSI_SAME_STMT);
11249 /* Determine the range, avoiding possible unsigned->signed overflow. */
11250 negating = !up && TYPE_UNSIGNED (iter_type);
11251 expr = fold_build2 (MINUS_EXPR, plus_type,
11252 fold_convert (plus_type, negating ? b : e),
11253 fold_convert (plus_type, negating ? e : b));
11254 expr = fold_convert (diff_type, expr);
11255 if (negating)
11256 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11257 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11258 NULL_TREE, true, GSI_SAME_STMT);
11260 chunk_no = build_int_cst (diff_type, 0);
11261 if (chunking)
11263 gcc_assert (!gimple_in_ssa_p (cfun));
11265 expr = chunk_no;
11266 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11267 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11269 ass = gimple_build_assign (chunk_no, expr);
11270 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11272 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11273 build_int_cst (integer_type_node,
11274 IFN_GOACC_LOOP_CHUNKS),
11275 dir, range, s, chunk_size, gwv);
11276 gimple_call_set_lhs (call, chunk_max);
11277 gimple_set_location (call, loc);
11278 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11280 else
11281 chunk_size = chunk_no;
11283 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11284 build_int_cst (integer_type_node,
11285 IFN_GOACC_LOOP_STEP),
11286 dir, range, s, chunk_size, gwv);
11287 gimple_call_set_lhs (call, step);
11288 gimple_set_location (call, loc);
11289 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11291 /* Remove the GIMPLE_OMP_FOR. */
11292 gsi_remove (&gsi, true);
11294 /* Fixup edges from head_bb */
11295 be = BRANCH_EDGE (head_bb);
11296 fte = FALLTHRU_EDGE (head_bb);
11297 be->flags |= EDGE_FALSE_VALUE;
11298 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11300 basic_block body_bb = fte->dest;
11302 if (gimple_in_ssa_p (cfun))
11304 gsi = gsi_last_bb (cont_bb);
11305 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11307 offset = gimple_omp_continue_control_use (cont_stmt);
11308 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11310 else
11312 offset = create_tmp_var (diff_type, ".offset");
11313 offset_init = offset_incr = offset;
11315 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11317 /* Loop offset & bound go into head_bb. */
11318 gsi = gsi_start_bb (head_bb);
11320 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11321 build_int_cst (integer_type_node,
11322 IFN_GOACC_LOOP_OFFSET),
11323 dir, range, s,
11324 chunk_size, gwv, chunk_no);
11325 gimple_call_set_lhs (call, offset_init);
11326 gimple_set_location (call, loc);
11327 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11329 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11330 build_int_cst (integer_type_node,
11331 IFN_GOACC_LOOP_BOUND),
11332 dir, range, s,
11333 chunk_size, gwv, offset_init);
11334 gimple_call_set_lhs (call, bound);
11335 gimple_set_location (call, loc);
11336 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11338 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11339 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11340 GSI_CONTINUE_LINKING);
11342 /* V assignment goes into body_bb. */
11343 if (!gimple_in_ssa_p (cfun))
11345 gsi = gsi_start_bb (body_bb);
11347 expr = build2 (plus_code, iter_type, b,
11348 fold_convert (plus_type, offset));
11349 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11350 true, GSI_SAME_STMT);
11351 ass = gimple_build_assign (v, expr);
11352 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11353 if (fd->collapse > 1)
11354 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11357 /* Loop increment goes into cont_bb. If this is not a loop, we
11358 will have spawned threads as if it was, and each one will
11359 execute one iteration. The specification is not explicit about
11360 whether such constructs are ill-formed or not, and they can
11361 occur, especially when noreturn routines are involved. */
11362 if (cont_bb)
11364 gsi = gsi_last_bb (cont_bb);
11365 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11366 loc = gimple_location (cont_stmt);
11368 /* Increment offset. */
11369 if (gimple_in_ssa_p (cfun))
11370 expr= build2 (plus_code, iter_type, offset,
11371 fold_convert (plus_type, step));
11372 else
11373 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11374 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11375 true, GSI_SAME_STMT);
11376 ass = gimple_build_assign (offset_incr, expr);
11377 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11378 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11379 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11381 /* Remove the GIMPLE_OMP_CONTINUE. */
11382 gsi_remove (&gsi, true);
11384 /* Fixup edges from cont_bb */
11385 be = BRANCH_EDGE (cont_bb);
11386 fte = FALLTHRU_EDGE (cont_bb);
11387 be->flags |= EDGE_TRUE_VALUE;
11388 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11390 if (chunking)
11392 /* Split the beginning of exit_bb to make bottom_bb. We
11393 need to insert a nop at the start, because splitting is
11394 after a stmt, not before. */
11395 gsi = gsi_start_bb (exit_bb);
11396 stmt = gimple_build_nop ();
11397 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11398 split = split_block (exit_bb, stmt);
11399 bottom_bb = split->src;
11400 exit_bb = split->dest;
11401 gsi = gsi_last_bb (bottom_bb);
11403 /* Chunk increment and test goes into bottom_bb. */
11404 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11405 build_int_cst (diff_type, 1));
11406 ass = gimple_build_assign (chunk_no, expr);
11407 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11409 /* Chunk test at end of bottom_bb. */
11410 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11411 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11412 GSI_CONTINUE_LINKING);
11414 /* Fixup edges from bottom_bb. */
11415 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11416 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11420 gsi = gsi_last_bb (exit_bb);
11421 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11422 loc = gimple_location (gsi_stmt (gsi));
11424 if (!gimple_in_ssa_p (cfun))
11426 /* Insert the final value of V, in case it is live. This is the
11427 value for the only thread that survives past the join. */
11428 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11429 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11430 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11431 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11432 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11433 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11434 true, GSI_SAME_STMT);
11435 ass = gimple_build_assign (v, expr);
11436 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11439 /* Remove the OMP_RETURN. */
11440 gsi_remove (&gsi, true);
11442 if (cont_bb)
11444 /* We now have one or two nested loops. Update the loop
11445 structures. */
11446 struct loop *parent = entry_bb->loop_father;
11447 struct loop *body = body_bb->loop_father;
11449 if (chunking)
11451 struct loop *chunk_loop = alloc_loop ();
11452 chunk_loop->header = head_bb;
11453 chunk_loop->latch = bottom_bb;
11454 add_loop (chunk_loop, parent);
11455 parent = chunk_loop;
11457 else if (parent != body)
11459 gcc_assert (body->header == body_bb);
11460 gcc_assert (body->latch == cont_bb
11461 || single_pred (body->latch) == cont_bb);
11462 parent = NULL;
11465 if (parent)
11467 struct loop *body_loop = alloc_loop ();
11468 body_loop->header = body_bb;
11469 body_loop->latch = cont_bb;
11470 add_loop (body_loop, parent);
11475 /* Expand the OMP loop defined by REGION. */
11477 static void
11478 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11480 struct omp_for_data fd;
11481 struct omp_for_data_loop *loops;
11483 loops
11484 = (struct omp_for_data_loop *)
11485 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11486 * sizeof (struct omp_for_data_loop));
11487 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11488 &fd, loops);
11489 region->sched_kind = fd.sched_kind;
11490 region->sched_modifiers = fd.sched_modifiers;
11492 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11493 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11494 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11495 if (region->cont)
11497 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11498 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11499 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11501 else
11502 /* If there isn't a continue then this is a degerate case where
11503 the introduction of abnormal edges during lowering will prevent
11504 original loops from being detected. Fix that up. */
11505 loops_state_set (LOOPS_NEED_FIXUP);
11507 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11508 expand_omp_simd (region, &fd);
11509 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11510 expand_cilk_for (region, &fd);
11511 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11513 gcc_assert (!inner_stmt);
11514 expand_oacc_for (region, &fd);
11516 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11518 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11519 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11520 else
11521 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11523 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11524 && !fd.have_ordered)
11526 if (fd.chunk_size == NULL)
11527 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11528 else
11529 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11531 else
11533 int fn_index, start_ix, next_ix;
11535 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11536 == GF_OMP_FOR_KIND_FOR);
11537 if (fd.chunk_size == NULL
11538 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11539 fd.chunk_size = integer_zero_node;
11540 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11541 switch (fd.sched_kind)
11543 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11544 fn_index = 3;
11545 break;
11546 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11547 case OMP_CLAUSE_SCHEDULE_GUIDED:
11548 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11549 && !fd.ordered
11550 && !fd.have_ordered)
11552 fn_index = 3 + fd.sched_kind;
11553 break;
11555 /* FALLTHRU */
11556 default:
11557 fn_index = fd.sched_kind;
11558 break;
11560 if (!fd.ordered)
11561 fn_index += fd.have_ordered * 6;
11562 if (fd.ordered)
11563 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11564 else
11565 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11566 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11567 if (fd.iter_type == long_long_unsigned_type_node)
11569 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11570 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11571 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11572 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11574 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11575 (enum built_in_function) next_ix, inner_stmt);
11578 if (gimple_in_ssa_p (cfun))
11579 update_ssa (TODO_update_ssa_only_virtuals);
11583 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11585 v = GOMP_sections_start (n);
11587 switch (v)
11589 case 0:
11590 goto L2;
11591 case 1:
11592 section 1;
11593 goto L1;
11594 case 2:
11596 case n:
11598 default:
11599 abort ();
11602 v = GOMP_sections_next ();
11603 goto L0;
11605 reduction;
11607 If this is a combined parallel sections, replace the call to
11608 GOMP_sections_start with call to GOMP_sections_next. */
11610 static void
11611 expand_omp_sections (struct omp_region *region)
11613 tree t, u, vin = NULL, vmain, vnext, l2;
11614 unsigned len;
11615 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11616 gimple_stmt_iterator si, switch_si;
11617 gomp_sections *sections_stmt;
11618 gimple *stmt;
11619 gomp_continue *cont;
11620 edge_iterator ei;
11621 edge e;
11622 struct omp_region *inner;
11623 unsigned i, casei;
11624 bool exit_reachable = region->cont != NULL;
11626 gcc_assert (region->exit != NULL);
11627 entry_bb = region->entry;
11628 l0_bb = single_succ (entry_bb);
11629 l1_bb = region->cont;
11630 l2_bb = region->exit;
11631 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11632 l2 = gimple_block_label (l2_bb);
11633 else
11635 /* This can happen if there are reductions. */
11636 len = EDGE_COUNT (l0_bb->succs);
11637 gcc_assert (len > 0);
11638 e = EDGE_SUCC (l0_bb, len - 1);
11639 si = gsi_last_bb (e->dest);
11640 l2 = NULL_TREE;
11641 if (gsi_end_p (si)
11642 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11643 l2 = gimple_block_label (e->dest);
11644 else
11645 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11647 si = gsi_last_bb (e->dest);
11648 if (gsi_end_p (si)
11649 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11651 l2 = gimple_block_label (e->dest);
11652 break;
11656 if (exit_reachable)
11657 default_bb = create_empty_bb (l1_bb->prev_bb);
11658 else
11659 default_bb = create_empty_bb (l0_bb);
11661 /* We will build a switch() with enough cases for all the
11662 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11663 and a default case to abort if something goes wrong. */
11664 len = EDGE_COUNT (l0_bb->succs);
11666 /* Use vec::quick_push on label_vec throughout, since we know the size
11667 in advance. */
11668 auto_vec<tree> label_vec (len);
11670 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11671 GIMPLE_OMP_SECTIONS statement. */
11672 si = gsi_last_bb (entry_bb);
11673 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11674 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11675 vin = gimple_omp_sections_control (sections_stmt);
11676 if (!is_combined_parallel (region))
11678 /* If we are not inside a combined parallel+sections region,
11679 call GOMP_sections_start. */
11680 t = build_int_cst (unsigned_type_node, len - 1);
11681 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11682 stmt = gimple_build_call (u, 1, t);
11684 else
11686 /* Otherwise, call GOMP_sections_next. */
11687 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11688 stmt = gimple_build_call (u, 0);
11690 gimple_call_set_lhs (stmt, vin);
11691 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11692 gsi_remove (&si, true);
11694 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11695 L0_BB. */
11696 switch_si = gsi_last_bb (l0_bb);
11697 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11698 if (exit_reachable)
11700 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11701 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11702 vmain = gimple_omp_continue_control_use (cont);
11703 vnext = gimple_omp_continue_control_def (cont);
11705 else
11707 vmain = vin;
11708 vnext = NULL_TREE;
11711 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11712 label_vec.quick_push (t);
11713 i = 1;
11715 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11716 for (inner = region->inner, casei = 1;
11717 inner;
11718 inner = inner->next, i++, casei++)
11720 basic_block s_entry_bb, s_exit_bb;
11722 /* Skip optional reduction region. */
11723 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11725 --i;
11726 --casei;
11727 continue;
11730 s_entry_bb = inner->entry;
11731 s_exit_bb = inner->exit;
11733 t = gimple_block_label (s_entry_bb);
11734 u = build_int_cst (unsigned_type_node, casei);
11735 u = build_case_label (u, NULL, t);
11736 label_vec.quick_push (u);
11738 si = gsi_last_bb (s_entry_bb);
11739 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11740 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11741 gsi_remove (&si, true);
11742 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11744 if (s_exit_bb == NULL)
11745 continue;
11747 si = gsi_last_bb (s_exit_bb);
11748 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11749 gsi_remove (&si, true);
11751 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11754 /* Error handling code goes in DEFAULT_BB. */
11755 t = gimple_block_label (default_bb);
11756 u = build_case_label (NULL, NULL, t);
11757 make_edge (l0_bb, default_bb, 0);
11758 add_bb_to_loop (default_bb, current_loops->tree_root);
11760 stmt = gimple_build_switch (vmain, u, label_vec);
11761 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11762 gsi_remove (&switch_si, true);
11764 si = gsi_start_bb (default_bb);
11765 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11766 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11768 if (exit_reachable)
11770 tree bfn_decl;
11772 /* Code to get the next section goes in L1_BB. */
11773 si = gsi_last_bb (l1_bb);
11774 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11776 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11777 stmt = gimple_build_call (bfn_decl, 0);
11778 gimple_call_set_lhs (stmt, vnext);
11779 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11780 gsi_remove (&si, true);
11782 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11785 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11786 si = gsi_last_bb (l2_bb);
11787 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11788 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11789 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11790 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11791 else
11792 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11793 stmt = gimple_build_call (t, 0);
11794 if (gimple_omp_return_lhs (gsi_stmt (si)))
11795 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11796 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11797 gsi_remove (&si, true);
11799 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11803 /* Expand code for an OpenMP single directive. We've already expanded
11804 much of the code, here we simply place the GOMP_barrier call. */
11806 static void
11807 expand_omp_single (struct omp_region *region)
11809 basic_block entry_bb, exit_bb;
11810 gimple_stmt_iterator si;
11812 entry_bb = region->entry;
11813 exit_bb = region->exit;
11815 si = gsi_last_bb (entry_bb);
11816 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11817 gsi_remove (&si, true);
11818 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11820 si = gsi_last_bb (exit_bb);
11821 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11823 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11824 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11826 gsi_remove (&si, true);
11827 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11831 /* Generic expansion for OpenMP synchronization directives: master,
11832 ordered and critical. All we need to do here is remove the entry
11833 and exit markers for REGION. */
11835 static void
11836 expand_omp_synch (struct omp_region *region)
11838 basic_block entry_bb, exit_bb;
11839 gimple_stmt_iterator si;
11841 entry_bb = region->entry;
11842 exit_bb = region->exit;
11844 si = gsi_last_bb (entry_bb);
11845 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11846 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11847 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11848 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11849 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11850 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11851 gsi_remove (&si, true);
11852 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11854 if (exit_bb)
11856 si = gsi_last_bb (exit_bb);
11857 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11858 gsi_remove (&si, true);
11859 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11863 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11864 operation as a normal volatile load. */
11866 static bool
11867 expand_omp_atomic_load (basic_block load_bb, tree addr,
11868 tree loaded_val, int index)
11870 enum built_in_function tmpbase;
11871 gimple_stmt_iterator gsi;
11872 basic_block store_bb;
11873 location_t loc;
11874 gimple *stmt;
11875 tree decl, call, type, itype;
11877 gsi = gsi_last_bb (load_bb);
11878 stmt = gsi_stmt (gsi);
11879 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11880 loc = gimple_location (stmt);
11882 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11883 is smaller than word size, then expand_atomic_load assumes that the load
11884 is atomic. We could avoid the builtin entirely in this case. */
11886 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11887 decl = builtin_decl_explicit (tmpbase);
11888 if (decl == NULL_TREE)
11889 return false;
11891 type = TREE_TYPE (loaded_val);
11892 itype = TREE_TYPE (TREE_TYPE (decl));
11894 call = build_call_expr_loc (loc, decl, 2, addr,
11895 build_int_cst (NULL,
11896 gimple_omp_atomic_seq_cst_p (stmt)
11897 ? MEMMODEL_SEQ_CST
11898 : MEMMODEL_RELAXED));
11899 if (!useless_type_conversion_p (type, itype))
11900 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11901 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11903 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11904 gsi_remove (&gsi, true);
11906 store_bb = single_succ (load_bb);
11907 gsi = gsi_last_bb (store_bb);
11908 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11909 gsi_remove (&gsi, true);
11911 if (gimple_in_ssa_p (cfun))
11912 update_ssa (TODO_update_ssa_no_phi);
11914 return true;
11917 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11918 operation as a normal volatile store. */
11920 static bool
11921 expand_omp_atomic_store (basic_block load_bb, tree addr,
11922 tree loaded_val, tree stored_val, int index)
11924 enum built_in_function tmpbase;
11925 gimple_stmt_iterator gsi;
11926 basic_block store_bb = single_succ (load_bb);
11927 location_t loc;
11928 gimple *stmt;
11929 tree decl, call, type, itype;
11930 machine_mode imode;
11931 bool exchange;
11933 gsi = gsi_last_bb (load_bb);
11934 stmt = gsi_stmt (gsi);
11935 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11937 /* If the load value is needed, then this isn't a store but an exchange. */
11938 exchange = gimple_omp_atomic_need_value_p (stmt);
11940 gsi = gsi_last_bb (store_bb);
11941 stmt = gsi_stmt (gsi);
11942 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11943 loc = gimple_location (stmt);
11945 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11946 is smaller than word size, then expand_atomic_store assumes that the store
11947 is atomic. We could avoid the builtin entirely in this case. */
11949 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11950 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11951 decl = builtin_decl_explicit (tmpbase);
11952 if (decl == NULL_TREE)
11953 return false;
11955 type = TREE_TYPE (stored_val);
11957 /* Dig out the type of the function's second argument. */
11958 itype = TREE_TYPE (decl);
11959 itype = TYPE_ARG_TYPES (itype);
11960 itype = TREE_CHAIN (itype);
11961 itype = TREE_VALUE (itype);
11962 imode = TYPE_MODE (itype);
11964 if (exchange && !can_atomic_exchange_p (imode, true))
11965 return false;
11967 if (!useless_type_conversion_p (itype, type))
11968 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11969 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11970 build_int_cst (NULL,
11971 gimple_omp_atomic_seq_cst_p (stmt)
11972 ? MEMMODEL_SEQ_CST
11973 : MEMMODEL_RELAXED));
11974 if (exchange)
11976 if (!useless_type_conversion_p (type, itype))
11977 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11978 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11981 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11982 gsi_remove (&gsi, true);
11984 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11985 gsi = gsi_last_bb (load_bb);
11986 gsi_remove (&gsi, true);
11988 if (gimple_in_ssa_p (cfun))
11989 update_ssa (TODO_update_ssa_no_phi);
11991 return true;
11994 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11995 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11996 size of the data type, and thus usable to find the index of the builtin
11997 decl. Returns false if the expression is not of the proper form. */
11999 static bool
12000 expand_omp_atomic_fetch_op (basic_block load_bb,
12001 tree addr, tree loaded_val,
12002 tree stored_val, int index)
12004 enum built_in_function oldbase, newbase, tmpbase;
12005 tree decl, itype, call;
12006 tree lhs, rhs;
12007 basic_block store_bb = single_succ (load_bb);
12008 gimple_stmt_iterator gsi;
12009 gimple *stmt;
12010 location_t loc;
12011 enum tree_code code;
12012 bool need_old, need_new;
12013 machine_mode imode;
12014 bool seq_cst;
12016 /* We expect to find the following sequences:
12018 load_bb:
12019 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12021 store_bb:
12022 val = tmp OP something; (or: something OP tmp)
12023 GIMPLE_OMP_STORE (val)
12025 ???FIXME: Allow a more flexible sequence.
12026 Perhaps use data flow to pick the statements.
12030 gsi = gsi_after_labels (store_bb);
12031 stmt = gsi_stmt (gsi);
12032 loc = gimple_location (stmt);
12033 if (!is_gimple_assign (stmt))
12034 return false;
12035 gsi_next (&gsi);
12036 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12037 return false;
12038 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12039 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12040 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12041 gcc_checking_assert (!need_old || !need_new);
12043 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12044 return false;
12046 /* Check for one of the supported fetch-op operations. */
12047 code = gimple_assign_rhs_code (stmt);
12048 switch (code)
12050 case PLUS_EXPR:
12051 case POINTER_PLUS_EXPR:
12052 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12053 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12054 break;
12055 case MINUS_EXPR:
12056 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12057 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12058 break;
12059 case BIT_AND_EXPR:
12060 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12061 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12062 break;
12063 case BIT_IOR_EXPR:
12064 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12065 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12066 break;
12067 case BIT_XOR_EXPR:
12068 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12069 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12070 break;
12071 default:
12072 return false;
12075 /* Make sure the expression is of the proper form. */
12076 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12077 rhs = gimple_assign_rhs2 (stmt);
12078 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12079 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12080 rhs = gimple_assign_rhs1 (stmt);
12081 else
12082 return false;
12084 tmpbase = ((enum built_in_function)
12085 ((need_new ? newbase : oldbase) + index + 1));
12086 decl = builtin_decl_explicit (tmpbase);
12087 if (decl == NULL_TREE)
12088 return false;
12089 itype = TREE_TYPE (TREE_TYPE (decl));
12090 imode = TYPE_MODE (itype);
12092 /* We could test all of the various optabs involved, but the fact of the
12093 matter is that (with the exception of i486 vs i586 and xadd) all targets
12094 that support any atomic operaton optab also implements compare-and-swap.
12095 Let optabs.c take care of expanding any compare-and-swap loop. */
12096 if (!can_compare_and_swap_p (imode, true))
12097 return false;
12099 gsi = gsi_last_bb (load_bb);
12100 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12102 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12103 It only requires that the operation happen atomically. Thus we can
12104 use the RELAXED memory model. */
12105 call = build_call_expr_loc (loc, decl, 3, addr,
12106 fold_convert_loc (loc, itype, rhs),
12107 build_int_cst (NULL,
12108 seq_cst ? MEMMODEL_SEQ_CST
12109 : MEMMODEL_RELAXED));
12111 if (need_old || need_new)
12113 lhs = need_old ? loaded_val : stored_val;
12114 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12115 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12117 else
12118 call = fold_convert_loc (loc, void_type_node, call);
12119 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12120 gsi_remove (&gsi, true);
12122 gsi = gsi_last_bb (store_bb);
12123 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12124 gsi_remove (&gsi, true);
12125 gsi = gsi_last_bb (store_bb);
12126 stmt = gsi_stmt (gsi);
12127 gsi_remove (&gsi, true);
12129 if (gimple_in_ssa_p (cfun))
12131 release_defs (stmt);
12132 update_ssa (TODO_update_ssa_no_phi);
12135 return true;
12138 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12140 oldval = *addr;
12141 repeat:
12142 newval = rhs; // with oldval replacing *addr in rhs
12143 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12144 if (oldval != newval)
12145 goto repeat;
12147 INDEX is log2 of the size of the data type, and thus usable to find the
12148 index of the builtin decl. */
12150 static bool
12151 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12152 tree addr, tree loaded_val, tree stored_val,
12153 int index)
12155 tree loadedi, storedi, initial, new_storedi, old_vali;
12156 tree type, itype, cmpxchg, iaddr;
12157 gimple_stmt_iterator si;
12158 basic_block loop_header = single_succ (load_bb);
12159 gimple *phi, *stmt;
12160 edge e;
12161 enum built_in_function fncode;
12163 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12164 order to use the RELAXED memory model effectively. */
12165 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12166 + index + 1);
12167 cmpxchg = builtin_decl_explicit (fncode);
12168 if (cmpxchg == NULL_TREE)
12169 return false;
12170 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12171 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12173 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12174 return false;
12176 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12177 si = gsi_last_bb (load_bb);
12178 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12180 /* For floating-point values, we'll need to view-convert them to integers
12181 so that we can perform the atomic compare and swap. Simplify the
12182 following code by always setting up the "i"ntegral variables. */
12183 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12185 tree iaddr_val;
12187 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12188 true));
12189 iaddr_val
12190 = force_gimple_operand_gsi (&si,
12191 fold_convert (TREE_TYPE (iaddr), addr),
12192 false, NULL_TREE, true, GSI_SAME_STMT);
12193 stmt = gimple_build_assign (iaddr, iaddr_val);
12194 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12195 loadedi = create_tmp_var (itype);
12196 if (gimple_in_ssa_p (cfun))
12197 loadedi = make_ssa_name (loadedi);
12199 else
12201 iaddr = addr;
12202 loadedi = loaded_val;
12205 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12206 tree loaddecl = builtin_decl_explicit (fncode);
12207 if (loaddecl)
12208 initial
12209 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12210 build_call_expr (loaddecl, 2, iaddr,
12211 build_int_cst (NULL_TREE,
12212 MEMMODEL_RELAXED)));
12213 else
12214 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12215 build_int_cst (TREE_TYPE (iaddr), 0));
12217 initial
12218 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12219 GSI_SAME_STMT);
12221 /* Move the value to the LOADEDI temporary. */
12222 if (gimple_in_ssa_p (cfun))
12224 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12225 phi = create_phi_node (loadedi, loop_header);
12226 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12227 initial);
12229 else
12230 gsi_insert_before (&si,
12231 gimple_build_assign (loadedi, initial),
12232 GSI_SAME_STMT);
12233 if (loadedi != loaded_val)
12235 gimple_stmt_iterator gsi2;
12236 tree x;
12238 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12239 gsi2 = gsi_start_bb (loop_header);
12240 if (gimple_in_ssa_p (cfun))
12242 gassign *stmt;
12243 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12244 true, GSI_SAME_STMT);
12245 stmt = gimple_build_assign (loaded_val, x);
12246 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12248 else
12250 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12251 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12252 true, GSI_SAME_STMT);
12255 gsi_remove (&si, true);
12257 si = gsi_last_bb (store_bb);
12258 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12260 if (iaddr == addr)
12261 storedi = stored_val;
12262 else
12263 storedi =
12264 force_gimple_operand_gsi (&si,
12265 build1 (VIEW_CONVERT_EXPR, itype,
12266 stored_val), true, NULL_TREE, true,
12267 GSI_SAME_STMT);
12269 /* Build the compare&swap statement. */
12270 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12271 new_storedi = force_gimple_operand_gsi (&si,
12272 fold_convert (TREE_TYPE (loadedi),
12273 new_storedi),
12274 true, NULL_TREE,
12275 true, GSI_SAME_STMT);
12277 if (gimple_in_ssa_p (cfun))
12278 old_vali = loadedi;
12279 else
12281 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12282 stmt = gimple_build_assign (old_vali, loadedi);
12283 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12285 stmt = gimple_build_assign (loadedi, new_storedi);
12286 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12289 /* Note that we always perform the comparison as an integer, even for
12290 floating point. This allows the atomic operation to properly
12291 succeed even with NaNs and -0.0. */
12292 stmt = gimple_build_cond_empty
12293 (build2 (NE_EXPR, boolean_type_node,
12294 new_storedi, old_vali));
12295 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12297 /* Update cfg. */
12298 e = single_succ_edge (store_bb);
12299 e->flags &= ~EDGE_FALLTHRU;
12300 e->flags |= EDGE_FALSE_VALUE;
12302 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12304 /* Copy the new value to loadedi (we already did that before the condition
12305 if we are not in SSA). */
12306 if (gimple_in_ssa_p (cfun))
12308 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12309 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12312 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12313 gsi_remove (&si, true);
12315 struct loop *loop = alloc_loop ();
12316 loop->header = loop_header;
12317 loop->latch = store_bb;
12318 add_loop (loop, loop_header->loop_father);
12320 if (gimple_in_ssa_p (cfun))
12321 update_ssa (TODO_update_ssa_no_phi);
12323 return true;
12326 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12328 GOMP_atomic_start ();
12329 *addr = rhs;
12330 GOMP_atomic_end ();
12332 The result is not globally atomic, but works so long as all parallel
12333 references are within #pragma omp atomic directives. According to
12334 responses received from omp@openmp.org, appears to be within spec.
12335 Which makes sense, since that's how several other compilers handle
12336 this situation as well.
12337 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12338 expanding. STORED_VAL is the operand of the matching
12339 GIMPLE_OMP_ATOMIC_STORE.
12341 We replace
12342 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12343 loaded_val = *addr;
12345 and replace
12346 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12347 *addr = stored_val;
12350 static bool
12351 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12352 tree addr, tree loaded_val, tree stored_val)
12354 gimple_stmt_iterator si;
12355 gassign *stmt;
12356 tree t;
12358 si = gsi_last_bb (load_bb);
12359 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12361 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12362 t = build_call_expr (t, 0);
12363 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12365 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12366 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12367 gsi_remove (&si, true);
12369 si = gsi_last_bb (store_bb);
12370 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12372 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12373 stored_val);
12374 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12376 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12377 t = build_call_expr (t, 0);
12378 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12379 gsi_remove (&si, true);
12381 if (gimple_in_ssa_p (cfun))
12382 update_ssa (TODO_update_ssa_no_phi);
12383 return true;
12386 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12387 using expand_omp_atomic_fetch_op. If it failed, we try to
12388 call expand_omp_atomic_pipeline, and if it fails too, the
12389 ultimate fallback is wrapping the operation in a mutex
12390 (expand_omp_atomic_mutex). REGION is the atomic region built
12391 by build_omp_regions_1(). */
12393 static void
12394 expand_omp_atomic (struct omp_region *region)
12396 basic_block load_bb = region->entry, store_bb = region->exit;
12397 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12398 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12399 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12400 tree addr = gimple_omp_atomic_load_rhs (load);
12401 tree stored_val = gimple_omp_atomic_store_val (store);
12402 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12403 HOST_WIDE_INT index;
12405 /* Make sure the type is one of the supported sizes. */
12406 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12407 index = exact_log2 (index);
12408 if (index >= 0 && index <= 4)
12410 unsigned int align = TYPE_ALIGN_UNIT (type);
12412 /* __sync builtins require strict data alignment. */
12413 if (exact_log2 (align) >= index)
12415 /* Atomic load. */
12416 if (loaded_val == stored_val
12417 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12418 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12419 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12420 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12421 return;
12423 /* Atomic store. */
12424 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12425 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12426 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12427 && store_bb == single_succ (load_bb)
12428 && first_stmt (store_bb) == store
12429 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12430 stored_val, index))
12431 return;
12433 /* When possible, use specialized atomic update functions. */
12434 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12435 && store_bb == single_succ (load_bb)
12436 && expand_omp_atomic_fetch_op (load_bb, addr,
12437 loaded_val, stored_val, index))
12438 return;
12440 /* If we don't have specialized __sync builtins, try and implement
12441 as a compare and swap loop. */
12442 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12443 loaded_val, stored_val, index))
12444 return;
12448 /* The ultimate fallback is wrapping the operation in a mutex. */
12449 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12453 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12454 macro on gomp-constants.h. We do not check for overflow. */
12456 static tree
12457 oacc_launch_pack (unsigned code, tree device, unsigned op)
12459 tree res;
12461 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12462 if (device)
12464 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12465 device, build_int_cst (unsigned_type_node,
12466 GOMP_LAUNCH_DEVICE_SHIFT));
12467 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12469 return res;
12472 /* Look for compute grid dimension clauses and convert to an attribute
12473 attached to FN. This permits the target-side code to (a) massage
12474 the dimensions, (b) emit that data and (c) optimize. Non-constant
12475 dimensions are pushed onto ARGS.
12477 The attribute value is a TREE_LIST. A set of dimensions is
12478 represented as a list of INTEGER_CST. Those that are runtime
12479 exprs are represented as an INTEGER_CST of zero.
12481 TOOO. Normally the attribute will just contain a single such list. If
12482 however it contains a list of lists, this will represent the use of
12483 device_type. Each member of the outer list is an assoc list of
12484 dimensions, keyed by the device type. The first entry will be the
12485 default. Well, that's the plan. */
12487 #define OACC_FN_ATTRIB "oacc function"
12489 /* Replace any existing oacc fn attribute with updated dimensions. */
12491 void
12492 replace_oacc_fn_attrib (tree fn, tree dims)
12494 tree ident = get_identifier (OACC_FN_ATTRIB);
12495 tree attribs = DECL_ATTRIBUTES (fn);
12497 /* If we happen to be present as the first attrib, drop it. */
12498 if (attribs && TREE_PURPOSE (attribs) == ident)
12499 attribs = TREE_CHAIN (attribs);
12500 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12503 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12504 function attribute. Push any that are non-constant onto the ARGS
12505 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12506 true, if these are for a kernels region offload function. */
12508 void
12509 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12511 /* Must match GOMP_DIM ordering. */
12512 static const omp_clause_code ids[]
12513 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12514 OMP_CLAUSE_VECTOR_LENGTH };
12515 unsigned ix;
12516 tree dims[GOMP_DIM_MAX];
12517 tree attr = NULL_TREE;
12518 unsigned non_const = 0;
12520 for (ix = GOMP_DIM_MAX; ix--;)
12522 tree clause = find_omp_clause (clauses, ids[ix]);
12523 tree dim = NULL_TREE;
12525 if (clause)
12526 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12527 dims[ix] = dim;
12528 if (dim && TREE_CODE (dim) != INTEGER_CST)
12530 dim = integer_zero_node;
12531 non_const |= GOMP_DIM_MASK (ix);
12533 attr = tree_cons (NULL_TREE, dim, attr);
12534 /* Note kernelness with TREE_PUBLIC. */
12535 if (is_kernel)
12536 TREE_PUBLIC (attr) = 1;
12539 replace_oacc_fn_attrib (fn, attr);
12541 if (non_const)
12543 /* Push a dynamic argument set. */
12544 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12545 NULL_TREE, non_const));
12546 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12547 if (non_const & GOMP_DIM_MASK (ix))
12548 args->safe_push (dims[ix]);
12552 /* Process the routine's dimension clauess to generate an attribute
12553 value. Issue diagnostics as appropriate. We default to SEQ
12554 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12555 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12556 can have a loop partitioned on it. non-zero indicates
12557 yes, zero indicates no. By construction once a non-zero has been
12558 reached, further inner dimensions must also be non-zero. We set
12559 TREE_VALUE to zero for the dimensions that may be partitioned and
12560 1 for the other ones -- if a loop is (erroneously) spawned at
12561 an outer level, we don't want to try and partition it. */
12563 tree
12564 build_oacc_routine_dims (tree clauses)
12566 /* Must match GOMP_DIM ordering. */
12567 static const omp_clause_code ids[] =
12568 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12569 int ix;
12570 int level = -1;
12572 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12573 for (ix = GOMP_DIM_MAX + 1; ix--;)
12574 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12576 if (level >= 0)
12577 error_at (OMP_CLAUSE_LOCATION (clauses),
12578 "multiple loop axes specified for routine");
12579 level = ix;
12580 break;
12583 /* Default to SEQ. */
12584 if (level < 0)
12585 level = GOMP_DIM_MAX;
12587 tree dims = NULL_TREE;
12589 for (ix = GOMP_DIM_MAX; ix--;)
12590 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12591 build_int_cst (integer_type_node, ix < level), dims);
12593 return dims;
12596 /* Retrieve the oacc function attrib and return it. Non-oacc
12597 functions will return NULL. */
12599 tree
12600 get_oacc_fn_attrib (tree fn)
12602 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12605 /* Return true if this oacc fn attrib is for a kernels offload
12606 region. We use the TREE_PUBLIC flag of each dimension -- only
12607 need to check the first one. */
12609 bool
12610 oacc_fn_attrib_kernels_p (tree attr)
12612 return TREE_PUBLIC (TREE_VALUE (attr));
12615 /* Return level at which oacc routine may spawn a partitioned loop, or
12616 -1 if it is not a routine (i.e. is an offload fn). */
12618 static int
12619 oacc_fn_attrib_level (tree attr)
12621 tree pos = TREE_VALUE (attr);
12623 if (!TREE_PURPOSE (pos))
12624 return -1;
12626 int ix = 0;
12627 for (ix = 0; ix != GOMP_DIM_MAX;
12628 ix++, pos = TREE_CHAIN (pos))
12629 if (!integer_zerop (TREE_PURPOSE (pos)))
12630 break;
12632 return ix;
12635 /* Extract an oacc execution dimension from FN. FN must be an
12636 offloaded function or routine that has already had its execution
12637 dimensions lowered to the target-specific values. */
12640 get_oacc_fn_dim_size (tree fn, int axis)
12642 tree attrs = get_oacc_fn_attrib (fn);
12644 gcc_assert (axis < GOMP_DIM_MAX);
12646 tree dims = TREE_VALUE (attrs);
12647 while (axis--)
12648 dims = TREE_CHAIN (dims);
12650 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12652 return size;
12655 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12656 IFN_GOACC_DIM_SIZE call. */
12659 get_oacc_ifn_dim_arg (const gimple *stmt)
12661 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12662 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12663 tree arg = gimple_call_arg (stmt, 0);
12664 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12666 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12667 return (int) axis;
12670 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12671 at REGION_EXIT. */
12673 static void
12674 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12675 basic_block region_exit)
12677 struct loop *outer = region_entry->loop_father;
12678 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12680 /* Don't parallelize the kernels region if it contains more than one outer
12681 loop. */
12682 unsigned int nr_outer_loops = 0;
12683 struct loop *single_outer = NULL;
12684 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12686 gcc_assert (loop_outer (loop) == outer);
12688 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12689 continue;
12691 if (region_exit != NULL
12692 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12693 continue;
12695 nr_outer_loops++;
12696 single_outer = loop;
12698 if (nr_outer_loops != 1)
12699 return;
12701 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12702 if (loop->next)
12703 return;
12705 /* Mark the loops in the region. */
12706 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12707 loop->in_oacc_kernels_region = true;
12710 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12712 struct GTY(()) grid_launch_attributes_trees
12714 tree kernel_dim_array_type;
12715 tree kernel_lattrs_dimnum_decl;
12716 tree kernel_lattrs_grid_decl;
12717 tree kernel_lattrs_group_decl;
12718 tree kernel_launch_attributes_type;
12721 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12723 /* Create types used to pass kernel launch attributes to target. */
12725 static void
12726 grid_create_kernel_launch_attr_types (void)
12728 if (grid_attr_trees)
12729 return;
12730 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12732 tree dim_arr_index_type
12733 = build_index_type (build_int_cst (integer_type_node, 2));
12734 grid_attr_trees->kernel_dim_array_type
12735 = build_array_type (uint32_type_node, dim_arr_index_type);
12737 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12738 grid_attr_trees->kernel_lattrs_dimnum_decl
12739 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12740 uint32_type_node);
12741 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12743 grid_attr_trees->kernel_lattrs_grid_decl
12744 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12745 grid_attr_trees->kernel_dim_array_type);
12746 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12747 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12748 grid_attr_trees->kernel_lattrs_group_decl
12749 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12750 grid_attr_trees->kernel_dim_array_type);
12751 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12752 = grid_attr_trees->kernel_lattrs_grid_decl;
12753 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12754 "__gomp_kernel_launch_attributes",
12755 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12758 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12759 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12760 of type uint32_type_node. */
12762 static void
12763 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12764 tree fld_decl, int index, tree value)
12766 tree ref = build4 (ARRAY_REF, uint32_type_node,
12767 build3 (COMPONENT_REF,
12768 grid_attr_trees->kernel_dim_array_type,
12769 range_var, fld_decl, NULL_TREE),
12770 build_int_cst (integer_type_node, index),
12771 NULL_TREE, NULL_TREE);
12772 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12775 /* Return a tree representation of a pointer to a structure with grid and
12776 work-group size information. Statements filling that information will be
12777 inserted before GSI, TGT_STMT is the target statement which has the
12778 necessary information in it. */
12780 static tree
12781 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12782 gomp_target *tgt_stmt)
12784 grid_create_kernel_launch_attr_types ();
12785 tree u32_one = build_one_cst (uint32_type_node);
12786 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12787 "__kernel_launch_attrs");
12789 unsigned max_dim = 0;
12790 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12791 clause;
12792 clause = OMP_CLAUSE_CHAIN (clause))
12794 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12795 continue;
12797 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12798 max_dim = MAX (dim, max_dim);
12800 grid_insert_store_range_dim (gsi, lattrs,
12801 grid_attr_trees->kernel_lattrs_grid_decl,
12802 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12803 grid_insert_store_range_dim (gsi, lattrs,
12804 grid_attr_trees->kernel_lattrs_group_decl,
12805 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12808 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12809 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12810 /* At this moment we cannot gridify a loop with a collapse clause. */
12811 /* TODO: Adjust when we support bigger collapse. */
12812 gcc_assert (max_dim == 0);
12813 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12814 TREE_ADDRESSABLE (lattrs) = 1;
12815 return build_fold_addr_expr (lattrs);
12818 /* Build target argument identifier from the DEVICE identifier, value
12819 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12821 static tree
12822 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12824 tree t = build_int_cst (integer_type_node, device);
12825 if (subseqent_param)
12826 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12827 build_int_cst (integer_type_node,
12828 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12829 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12830 build_int_cst (integer_type_node, id));
12831 return t;
12834 /* Like above but return it in type that can be directly stored as an element
12835 of the argument array. */
12837 static tree
12838 get_target_argument_identifier (int device, bool subseqent_param, int id)
12840 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12841 return fold_convert (ptr_type_node, t);
12844 /* Return a target argument consisting of DEVICE identifier, value identifier
12845 ID, and the actual VALUE. */
12847 static tree
12848 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12849 tree value)
12851 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12852 fold_convert (integer_type_node, value),
12853 build_int_cst (unsigned_type_node,
12854 GOMP_TARGET_ARG_VALUE_SHIFT));
12855 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12856 get_target_argument_identifier_1 (device, false, id));
12857 t = fold_convert (ptr_type_node, t);
12858 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12861 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12862 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12863 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12864 arguments. */
12866 static void
12867 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12868 int id, tree value, vec <tree> *args)
12870 if (tree_fits_shwi_p (value)
12871 && tree_to_shwi (value) > -(1 << 15)
12872 && tree_to_shwi (value) < (1 << 15))
12873 args->quick_push (get_target_argument_value (gsi, device, id, value));
12874 else
12876 args->quick_push (get_target_argument_identifier (device, true, id));
12877 value = fold_convert (ptr_type_node, value);
12878 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12879 GSI_SAME_STMT);
12880 args->quick_push (value);
12884 /* Create an array of arguments that is then passed to GOMP_target. */
12886 static tree
12887 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12889 auto_vec <tree, 6> args;
12890 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12891 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12892 if (c)
12893 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12894 else
12895 t = integer_minus_one_node;
12896 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12897 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12899 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12900 if (c)
12901 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12902 else
12903 t = integer_minus_one_node;
12904 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12905 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12906 &args);
12908 /* Add HSA-specific grid sizes, if available. */
12909 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12910 OMP_CLAUSE__GRIDDIM_))
12912 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12913 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12914 args.quick_push (t);
12915 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12918 /* Produce more, perhaps device specific, arguments here. */
12920 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12921 args.length () + 1),
12922 ".omp_target_args");
12923 for (unsigned i = 0; i < args.length (); i++)
12925 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12926 build_int_cst (integer_type_node, i),
12927 NULL_TREE, NULL_TREE);
12928 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12929 GSI_SAME_STMT);
12931 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12932 build_int_cst (integer_type_node, args.length ()),
12933 NULL_TREE, NULL_TREE);
12934 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12935 GSI_SAME_STMT);
12936 TREE_ADDRESSABLE (argarray) = 1;
12937 return build_fold_addr_expr (argarray);
12940 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12942 static void
12943 expand_omp_target (struct omp_region *region)
12945 basic_block entry_bb, exit_bb, new_bb;
12946 struct function *child_cfun;
12947 tree child_fn, block, t;
12948 gimple_stmt_iterator gsi;
12949 gomp_target *entry_stmt;
12950 gimple *stmt;
12951 edge e;
12952 bool offloaded, data_region;
12954 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12955 new_bb = region->entry;
12957 offloaded = is_gimple_omp_offloaded (entry_stmt);
12958 switch (gimple_omp_target_kind (entry_stmt))
12960 case GF_OMP_TARGET_KIND_REGION:
12961 case GF_OMP_TARGET_KIND_UPDATE:
12962 case GF_OMP_TARGET_KIND_ENTER_DATA:
12963 case GF_OMP_TARGET_KIND_EXIT_DATA:
12964 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12965 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12966 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12967 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12968 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12969 data_region = false;
12970 break;
12971 case GF_OMP_TARGET_KIND_DATA:
12972 case GF_OMP_TARGET_KIND_OACC_DATA:
12973 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12974 data_region = true;
12975 break;
12976 default:
12977 gcc_unreachable ();
12980 child_fn = NULL_TREE;
12981 child_cfun = NULL;
12982 if (offloaded)
12984 child_fn = gimple_omp_target_child_fn (entry_stmt);
12985 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12988 /* Supported by expand_omp_taskreg, but not here. */
12989 if (child_cfun != NULL)
12990 gcc_checking_assert (!child_cfun->cfg);
12991 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12993 entry_bb = region->entry;
12994 exit_bb = region->exit;
12996 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12997 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12999 if (offloaded)
13001 unsigned srcidx, dstidx, num;
13003 /* If the offloading region needs data sent from the parent
13004 function, then the very first statement (except possible
13005 tree profile counter updates) of the offloading body
13006 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13007 &.OMP_DATA_O is passed as an argument to the child function,
13008 we need to replace it with the argument as seen by the child
13009 function.
13011 In most cases, this will end up being the identity assignment
13012 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13013 a function call that has been inlined, the original PARM_DECL
13014 .OMP_DATA_I may have been converted into a different local
13015 variable. In which case, we need to keep the assignment. */
13016 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13017 if (data_arg)
13019 basic_block entry_succ_bb = single_succ (entry_bb);
13020 gimple_stmt_iterator gsi;
13021 tree arg;
13022 gimple *tgtcopy_stmt = NULL;
13023 tree sender = TREE_VEC_ELT (data_arg, 0);
13025 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13027 gcc_assert (!gsi_end_p (gsi));
13028 stmt = gsi_stmt (gsi);
13029 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13030 continue;
13032 if (gimple_num_ops (stmt) == 2)
13034 tree arg = gimple_assign_rhs1 (stmt);
13036 /* We're ignoring the subcode because we're
13037 effectively doing a STRIP_NOPS. */
13039 if (TREE_CODE (arg) == ADDR_EXPR
13040 && TREE_OPERAND (arg, 0) == sender)
13042 tgtcopy_stmt = stmt;
13043 break;
13048 gcc_assert (tgtcopy_stmt != NULL);
13049 arg = DECL_ARGUMENTS (child_fn);
13051 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13052 gsi_remove (&gsi, true);
13055 /* Declare local variables needed in CHILD_CFUN. */
13056 block = DECL_INITIAL (child_fn);
13057 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13058 /* The gimplifier could record temporaries in the offloading block
13059 rather than in containing function's local_decls chain,
13060 which would mean cgraph missed finalizing them. Do it now. */
13061 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13062 if (TREE_CODE (t) == VAR_DECL
13063 && TREE_STATIC (t)
13064 && !DECL_EXTERNAL (t))
13065 varpool_node::finalize_decl (t);
13066 DECL_SAVED_TREE (child_fn) = NULL;
13067 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13068 gimple_set_body (child_fn, NULL);
13069 TREE_USED (block) = 1;
13071 /* Reset DECL_CONTEXT on function arguments. */
13072 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13073 DECL_CONTEXT (t) = child_fn;
13075 /* Split ENTRY_BB at GIMPLE_*,
13076 so that it can be moved to the child function. */
13077 gsi = gsi_last_bb (entry_bb);
13078 stmt = gsi_stmt (gsi);
13079 gcc_assert (stmt
13080 && gimple_code (stmt) == gimple_code (entry_stmt));
13081 e = split_block (entry_bb, stmt);
13082 gsi_remove (&gsi, true);
13083 entry_bb = e->dest;
13084 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13086 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13087 if (exit_bb)
13089 gsi = gsi_last_bb (exit_bb);
13090 gcc_assert (!gsi_end_p (gsi)
13091 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13092 stmt = gimple_build_return (NULL);
13093 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13094 gsi_remove (&gsi, true);
13097 /* Move the offloading region into CHILD_CFUN. */
13099 block = gimple_block (entry_stmt);
13101 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13102 if (exit_bb)
13103 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13104 /* When the OMP expansion process cannot guarantee an up-to-date
13105 loop tree arrange for the child function to fixup loops. */
13106 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13107 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13109 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13110 num = vec_safe_length (child_cfun->local_decls);
13111 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13113 t = (*child_cfun->local_decls)[srcidx];
13114 if (DECL_CONTEXT (t) == cfun->decl)
13115 continue;
13116 if (srcidx != dstidx)
13117 (*child_cfun->local_decls)[dstidx] = t;
13118 dstidx++;
13120 if (dstidx != num)
13121 vec_safe_truncate (child_cfun->local_decls, dstidx);
13123 /* Inform the callgraph about the new function. */
13124 child_cfun->curr_properties = cfun->curr_properties;
13125 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13126 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13127 cgraph_node *node = cgraph_node::get_create (child_fn);
13128 node->parallelized_function = 1;
13129 cgraph_node::add_new_function (child_fn, true);
13131 /* Add the new function to the offload table. */
13132 if (ENABLE_OFFLOADING)
13133 vec_safe_push (offload_funcs, child_fn);
13135 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13136 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13138 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13139 fixed in a following pass. */
13140 push_cfun (child_cfun);
13141 if (need_asm)
13142 assign_assembler_name_if_neeeded (child_fn);
13143 cgraph_edge::rebuild_edges ();
13145 /* Some EH regions might become dead, see PR34608. If
13146 pass_cleanup_cfg isn't the first pass to happen with the
13147 new child, these dead EH edges might cause problems.
13148 Clean them up now. */
13149 if (flag_exceptions)
13151 basic_block bb;
13152 bool changed = false;
13154 FOR_EACH_BB_FN (bb, cfun)
13155 changed |= gimple_purge_dead_eh_edges (bb);
13156 if (changed)
13157 cleanup_tree_cfg ();
13159 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13160 verify_loop_structure ();
13161 pop_cfun ();
13163 if (dump_file && !gimple_in_ssa_p (cfun))
13165 omp_any_child_fn_dumped = true;
13166 dump_function_header (dump_file, child_fn, dump_flags);
13167 dump_function_to_file (child_fn, dump_file, dump_flags);
13171 /* Emit a library call to launch the offloading region, or do data
13172 transfers. */
13173 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13174 enum built_in_function start_ix;
13175 location_t clause_loc;
13176 unsigned int flags_i = 0;
13177 bool oacc_kernels_p = false;
13179 switch (gimple_omp_target_kind (entry_stmt))
13181 case GF_OMP_TARGET_KIND_REGION:
13182 start_ix = BUILT_IN_GOMP_TARGET;
13183 break;
13184 case GF_OMP_TARGET_KIND_DATA:
13185 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13186 break;
13187 case GF_OMP_TARGET_KIND_UPDATE:
13188 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13189 break;
13190 case GF_OMP_TARGET_KIND_ENTER_DATA:
13191 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13192 break;
13193 case GF_OMP_TARGET_KIND_EXIT_DATA:
13194 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13195 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13196 break;
13197 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13198 oacc_kernels_p = true;
13199 /* FALLTHROUGH */
13200 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13201 start_ix = BUILT_IN_GOACC_PARALLEL;
13202 break;
13203 case GF_OMP_TARGET_KIND_OACC_DATA:
13204 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13205 start_ix = BUILT_IN_GOACC_DATA_START;
13206 break;
13207 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13208 start_ix = BUILT_IN_GOACC_UPDATE;
13209 break;
13210 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13211 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13212 break;
13213 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13214 start_ix = BUILT_IN_GOACC_DECLARE;
13215 break;
13216 default:
13217 gcc_unreachable ();
13220 clauses = gimple_omp_target_clauses (entry_stmt);
13222 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13223 library choose) and there is no conditional. */
13224 cond = NULL_TREE;
13225 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13227 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13228 if (c)
13229 cond = OMP_CLAUSE_IF_EXPR (c);
13231 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13232 if (c)
13234 /* Even if we pass it to all library function calls, it is currently only
13235 defined/used for the OpenMP target ones. */
13236 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13237 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13238 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13239 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13241 device = OMP_CLAUSE_DEVICE_ID (c);
13242 clause_loc = OMP_CLAUSE_LOCATION (c);
13244 else
13245 clause_loc = gimple_location (entry_stmt);
13247 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13248 if (c)
13249 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13251 /* Ensure 'device' is of the correct type. */
13252 device = fold_convert_loc (clause_loc, integer_type_node, device);
13254 /* If we found the clause 'if (cond)', build
13255 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13256 if (cond)
13258 cond = gimple_boolify (cond);
13260 basic_block cond_bb, then_bb, else_bb;
13261 edge e;
13262 tree tmp_var;
13264 tmp_var = create_tmp_var (TREE_TYPE (device));
13265 if (offloaded)
13266 e = split_block_after_labels (new_bb);
13267 else
13269 gsi = gsi_last_bb (new_bb);
13270 gsi_prev (&gsi);
13271 e = split_block (new_bb, gsi_stmt (gsi));
13273 cond_bb = e->src;
13274 new_bb = e->dest;
13275 remove_edge (e);
13277 then_bb = create_empty_bb (cond_bb);
13278 else_bb = create_empty_bb (then_bb);
13279 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13280 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13282 stmt = gimple_build_cond_empty (cond);
13283 gsi = gsi_last_bb (cond_bb);
13284 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13286 gsi = gsi_start_bb (then_bb);
13287 stmt = gimple_build_assign (tmp_var, device);
13288 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13290 gsi = gsi_start_bb (else_bb);
13291 stmt = gimple_build_assign (tmp_var,
13292 build_int_cst (integer_type_node,
13293 GOMP_DEVICE_HOST_FALLBACK));
13294 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13296 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13297 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13298 add_bb_to_loop (then_bb, cond_bb->loop_father);
13299 add_bb_to_loop (else_bb, cond_bb->loop_father);
13300 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13301 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13303 device = tmp_var;
13306 gsi = gsi_last_bb (new_bb);
13307 t = gimple_omp_target_data_arg (entry_stmt);
13308 if (t == NULL)
13310 t1 = size_zero_node;
13311 t2 = build_zero_cst (ptr_type_node);
13312 t3 = t2;
13313 t4 = t2;
13315 else
13317 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13318 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13319 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13320 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13321 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13324 gimple *g;
13325 bool tagging = false;
13326 /* The maximum number used by any start_ix, without varargs. */
13327 auto_vec<tree, 11> args;
13328 args.quick_push (device);
13329 if (offloaded)
13330 args.quick_push (build_fold_addr_expr (child_fn));
13331 args.quick_push (t1);
13332 args.quick_push (t2);
13333 args.quick_push (t3);
13334 args.quick_push (t4);
13335 switch (start_ix)
13337 case BUILT_IN_GOACC_DATA_START:
13338 case BUILT_IN_GOACC_DECLARE:
13339 case BUILT_IN_GOMP_TARGET_DATA:
13340 break;
13341 case BUILT_IN_GOMP_TARGET:
13342 case BUILT_IN_GOMP_TARGET_UPDATE:
13343 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13344 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13345 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13346 if (c)
13347 depend = OMP_CLAUSE_DECL (c);
13348 else
13349 depend = build_int_cst (ptr_type_node, 0);
13350 args.quick_push (depend);
13351 if (start_ix == BUILT_IN_GOMP_TARGET)
13352 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13353 break;
13354 case BUILT_IN_GOACC_PARALLEL:
13356 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13357 tagging = true;
13359 /* FALLTHRU */
13360 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13361 case BUILT_IN_GOACC_UPDATE:
13363 tree t_async = NULL_TREE;
13365 /* If present, use the value specified by the respective
13366 clause, making sure that is of the correct type. */
13367 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13368 if (c)
13369 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13370 integer_type_node,
13371 OMP_CLAUSE_ASYNC_EXPR (c));
13372 else if (!tagging)
13373 /* Default values for t_async. */
13374 t_async = fold_convert_loc (gimple_location (entry_stmt),
13375 integer_type_node,
13376 build_int_cst (integer_type_node,
13377 GOMP_ASYNC_SYNC));
13378 if (tagging && t_async)
13380 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13382 if (TREE_CODE (t_async) == INTEGER_CST)
13384 /* See if we can pack the async arg in to the tag's
13385 operand. */
13386 i_async = TREE_INT_CST_LOW (t_async);
13387 if (i_async < GOMP_LAUNCH_OP_MAX)
13388 t_async = NULL_TREE;
13389 else
13390 i_async = GOMP_LAUNCH_OP_MAX;
13392 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13393 i_async));
13395 if (t_async)
13396 args.safe_push (t_async);
13398 /* Save the argument index, and ... */
13399 unsigned t_wait_idx = args.length ();
13400 unsigned num_waits = 0;
13401 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13402 if (!tagging || c)
13403 /* ... push a placeholder. */
13404 args.safe_push (integer_zero_node);
13406 for (; c; c = OMP_CLAUSE_CHAIN (c))
13407 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13409 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13410 integer_type_node,
13411 OMP_CLAUSE_WAIT_EXPR (c)));
13412 num_waits++;
13415 if (!tagging || num_waits)
13417 tree len;
13419 /* Now that we know the number, update the placeholder. */
13420 if (tagging)
13421 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13422 else
13423 len = build_int_cst (integer_type_node, num_waits);
13424 len = fold_convert_loc (gimple_location (entry_stmt),
13425 unsigned_type_node, len);
13426 args[t_wait_idx] = len;
13429 break;
13430 default:
13431 gcc_unreachable ();
13433 if (tagging)
13434 /* Push terminal marker - zero. */
13435 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13437 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13438 gimple_set_location (g, gimple_location (entry_stmt));
13439 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13440 if (!offloaded)
13442 g = gsi_stmt (gsi);
13443 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13444 gsi_remove (&gsi, true);
13446 if (data_region && region->exit)
13448 gsi = gsi_last_bb (region->exit);
13449 g = gsi_stmt (gsi);
13450 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13451 gsi_remove (&gsi, true);
13455 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13456 variable derived from the thread number. */
13458 static void
13459 grid_expand_omp_for_loop (struct omp_region *kfor)
13461 tree t, threadid;
13462 tree type, itype;
13463 gimple_stmt_iterator gsi;
13464 tree n1, step;
13465 struct omp_for_data fd;
13467 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13468 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13469 == GF_OMP_FOR_KIND_GRID_LOOP);
13470 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13472 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13473 gcc_assert (kfor->cont);
13474 extract_omp_for_data (for_stmt, &fd, NULL);
13476 itype = type = TREE_TYPE (fd.loop.v);
13477 if (POINTER_TYPE_P (type))
13478 itype = signed_type_for (type);
13480 gsi = gsi_start_bb (body_bb);
13482 n1 = fd.loop.n1;
13483 step = fd.loop.step;
13484 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13485 true, NULL_TREE, true, GSI_SAME_STMT);
13486 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13487 true, NULL_TREE, true, GSI_SAME_STMT);
13488 threadid = build_call_expr (builtin_decl_explicit
13489 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13490 threadid = fold_convert (itype, threadid);
13491 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13492 true, GSI_SAME_STMT);
13494 tree startvar = fd.loop.v;
13495 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13496 if (POINTER_TYPE_P (type))
13497 t = fold_build_pointer_plus (n1, t);
13498 else
13499 t = fold_build2 (PLUS_EXPR, type, t, n1);
13500 t = fold_convert (type, t);
13501 t = force_gimple_operand_gsi (&gsi, t,
13502 DECL_P (startvar)
13503 && TREE_ADDRESSABLE (startvar),
13504 NULL_TREE, true, GSI_SAME_STMT);
13505 gassign *assign_stmt = gimple_build_assign (startvar, t);
13506 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13508 /* Remove the omp for statement */
13509 gsi = gsi_last_bb (kfor->entry);
13510 gsi_remove (&gsi, true);
13512 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13513 gsi = gsi_last_bb (kfor->cont);
13514 gcc_assert (!gsi_end_p (gsi)
13515 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13516 gsi_remove (&gsi, true);
13518 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13519 gsi = gsi_last_bb (kfor->exit);
13520 gcc_assert (!gsi_end_p (gsi)
13521 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13522 gsi_remove (&gsi, true);
13524 /* Fixup the much simpler CFG. */
13525 remove_edge (find_edge (kfor->cont, body_bb));
13527 if (kfor->cont != body_bb)
13528 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13529 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13532 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13533 argument_decls. */
13535 struct grid_arg_decl_map
13537 tree old_arg;
13538 tree new_arg;
13541 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13542 pertaining to kernel function. */
13544 static tree
13545 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13547 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13548 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13549 tree t = *tp;
13551 if (t == adm->old_arg)
13552 *tp = adm->new_arg;
13553 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13554 return NULL_TREE;
13557 static void expand_omp (struct omp_region *region);
13559 /* If TARGET region contains a kernel body for loop, remove its region from the
13560 TARGET and expand it in GPGPU kernel fashion. */
13562 static void
13563 grid_expand_target_grid_body (struct omp_region *target)
13565 if (!hsa_gen_requested_p ())
13566 return;
13568 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13569 struct omp_region **pp;
13571 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13572 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13573 break;
13575 struct omp_region *gpukernel = *pp;
13577 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13578 if (!gpukernel)
13580 /* HSA cannot handle OACC stuff. */
13581 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13582 return;
13583 gcc_checking_assert (orig_child_fndecl);
13584 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13585 OMP_CLAUSE__GRIDDIM_));
13586 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13588 hsa_register_kernel (n);
13589 return;
13592 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13593 OMP_CLAUSE__GRIDDIM_));
13594 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13595 *pp = gpukernel->next;
13596 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13597 if ((*pp)->type == GIMPLE_OMP_FOR)
13598 break;
13600 struct omp_region *kfor = *pp;
13601 gcc_assert (kfor);
13602 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13603 == GF_OMP_FOR_KIND_GRID_LOOP);
13604 *pp = kfor->next;
13605 if (kfor->inner)
13606 expand_omp (kfor->inner);
13607 if (gpukernel->inner)
13608 expand_omp (gpukernel->inner);
13610 tree kern_fndecl = copy_node (orig_child_fndecl);
13611 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13612 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13613 tree tgtblock = gimple_block (tgt_stmt);
13614 tree fniniblock = make_node (BLOCK);
13615 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13616 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13617 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13618 DECL_INITIAL (kern_fndecl) = fniniblock;
13619 push_struct_function (kern_fndecl);
13620 cfun->function_end_locus = gimple_location (tgt_stmt);
13621 pop_cfun ();
13623 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13624 gcc_assert (!DECL_CHAIN (old_parm_decl));
13625 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13626 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13627 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13628 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13629 kern_cfun->curr_properties = cfun->curr_properties;
13631 remove_edge (BRANCH_EDGE (kfor->entry));
13632 grid_expand_omp_for_loop (kfor);
13634 /* Remove the omp for statement */
13635 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13636 gsi_remove (&gsi, true);
13637 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13638 return. */
13639 gsi = gsi_last_bb (gpukernel->exit);
13640 gcc_assert (!gsi_end_p (gsi)
13641 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13642 gimple *ret_stmt = gimple_build_return (NULL);
13643 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13644 gsi_remove (&gsi, true);
13646 /* Statements in the first BB in the target construct have been produced by
13647 target lowering and must be copied inside the GPUKERNEL, with the two
13648 exceptions of the first OMP statement and the OMP_DATA assignment
13649 statement. */
13650 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13651 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13652 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13653 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13654 !gsi_end_p (tsi); gsi_next (&tsi))
13656 gimple *stmt = gsi_stmt (tsi);
13657 if (is_gimple_omp (stmt))
13658 break;
13659 if (sender
13660 && is_gimple_assign (stmt)
13661 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13662 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13663 continue;
13664 gimple *copy = gimple_copy (stmt);
13665 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13666 gimple_set_block (copy, fniniblock);
13669 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13670 gpukernel->exit, inside_block);
13672 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13673 kcn->mark_force_output ();
13674 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13676 hsa_register_kernel (kcn, orig_child);
13678 cgraph_node::add_new_function (kern_fndecl, true);
13679 push_cfun (kern_cfun);
13680 cgraph_edge::rebuild_edges ();
13682 /* Re-map any mention of the PARM_DECL of the original function to the
13683 PARM_DECL of the new one.
13685 TODO: It would be great if lowering produced references into the GPU
13686 kernel decl straight away and we did not have to do this. */
13687 struct grid_arg_decl_map adm;
13688 adm.old_arg = old_parm_decl;
13689 adm.new_arg = new_parm_decl;
13690 basic_block bb;
13691 FOR_EACH_BB_FN (bb, kern_cfun)
13693 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13695 gimple *stmt = gsi_stmt (gsi);
13696 struct walk_stmt_info wi;
13697 memset (&wi, 0, sizeof (wi));
13698 wi.info = &adm;
13699 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13702 pop_cfun ();
13704 return;
13707 /* Expand the parallel region tree rooted at REGION. Expansion
13708 proceeds in depth-first order. Innermost regions are expanded
13709 first. This way, parallel regions that require a new function to
13710 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13711 internal dependencies in their body. */
13713 static void
13714 expand_omp (struct omp_region *region)
13716 omp_any_child_fn_dumped = false;
13717 while (region)
13719 location_t saved_location;
13720 gimple *inner_stmt = NULL;
13722 /* First, determine whether this is a combined parallel+workshare
13723 region. */
13724 if (region->type == GIMPLE_OMP_PARALLEL)
13725 determine_parallel_type (region);
13726 else if (region->type == GIMPLE_OMP_TARGET)
13727 grid_expand_target_grid_body (region);
13729 if (region->type == GIMPLE_OMP_FOR
13730 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13731 inner_stmt = last_stmt (region->inner->entry);
13733 if (region->inner)
13734 expand_omp (region->inner);
13736 saved_location = input_location;
13737 if (gimple_has_location (last_stmt (region->entry)))
13738 input_location = gimple_location (last_stmt (region->entry));
13740 switch (region->type)
13742 case GIMPLE_OMP_PARALLEL:
13743 case GIMPLE_OMP_TASK:
13744 expand_omp_taskreg (region);
13745 break;
13747 case GIMPLE_OMP_FOR:
13748 expand_omp_for (region, inner_stmt);
13749 break;
13751 case GIMPLE_OMP_SECTIONS:
13752 expand_omp_sections (region);
13753 break;
13755 case GIMPLE_OMP_SECTION:
13756 /* Individual omp sections are handled together with their
13757 parent GIMPLE_OMP_SECTIONS region. */
13758 break;
13760 case GIMPLE_OMP_SINGLE:
13761 expand_omp_single (region);
13762 break;
13764 case GIMPLE_OMP_ORDERED:
13766 gomp_ordered *ord_stmt
13767 = as_a <gomp_ordered *> (last_stmt (region->entry));
13768 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13769 OMP_CLAUSE_DEPEND))
13771 /* We'll expand these when expanding corresponding
13772 worksharing region with ordered(n) clause. */
13773 gcc_assert (region->outer
13774 && region->outer->type == GIMPLE_OMP_FOR);
13775 region->ord_stmt = ord_stmt;
13776 break;
13779 /* FALLTHRU */
13780 case GIMPLE_OMP_MASTER:
13781 case GIMPLE_OMP_TASKGROUP:
13782 case GIMPLE_OMP_CRITICAL:
13783 case GIMPLE_OMP_TEAMS:
13784 expand_omp_synch (region);
13785 break;
13787 case GIMPLE_OMP_ATOMIC_LOAD:
13788 expand_omp_atomic (region);
13789 break;
13791 case GIMPLE_OMP_TARGET:
13792 expand_omp_target (region);
13793 break;
13795 default:
13796 gcc_unreachable ();
13799 input_location = saved_location;
13800 region = region->next;
13802 if (omp_any_child_fn_dumped)
13804 if (dump_file)
13805 dump_function_header (dump_file, current_function_decl, dump_flags);
13806 omp_any_child_fn_dumped = false;
13811 /* Helper for build_omp_regions. Scan the dominator tree starting at
13812 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13813 true, the function ends once a single tree is built (otherwise, whole
13814 forest of OMP constructs may be built). */
13816 static void
13817 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13818 bool single_tree)
13820 gimple_stmt_iterator gsi;
13821 gimple *stmt;
13822 basic_block son;
13824 gsi = gsi_last_bb (bb);
13825 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13827 struct omp_region *region;
13828 enum gimple_code code;
13830 stmt = gsi_stmt (gsi);
13831 code = gimple_code (stmt);
13832 if (code == GIMPLE_OMP_RETURN)
13834 /* STMT is the return point out of region PARENT. Mark it
13835 as the exit point and make PARENT the immediately
13836 enclosing region. */
13837 gcc_assert (parent);
13838 region = parent;
13839 region->exit = bb;
13840 parent = parent->outer;
13842 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13844 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13845 GIMPLE_OMP_RETURN, but matches with
13846 GIMPLE_OMP_ATOMIC_LOAD. */
13847 gcc_assert (parent);
13848 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13849 region = parent;
13850 region->exit = bb;
13851 parent = parent->outer;
13853 else if (code == GIMPLE_OMP_CONTINUE)
13855 gcc_assert (parent);
13856 parent->cont = bb;
13858 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13860 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13861 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13863 else
13865 region = new_omp_region (bb, code, parent);
13866 /* Otherwise... */
13867 if (code == GIMPLE_OMP_TARGET)
13869 switch (gimple_omp_target_kind (stmt))
13871 case GF_OMP_TARGET_KIND_REGION:
13872 case GF_OMP_TARGET_KIND_DATA:
13873 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13874 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13875 case GF_OMP_TARGET_KIND_OACC_DATA:
13876 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13877 break;
13878 case GF_OMP_TARGET_KIND_UPDATE:
13879 case GF_OMP_TARGET_KIND_ENTER_DATA:
13880 case GF_OMP_TARGET_KIND_EXIT_DATA:
13881 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13882 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13883 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13884 /* ..., other than for those stand-alone directives... */
13885 region = NULL;
13886 break;
13887 default:
13888 gcc_unreachable ();
13891 else if (code == GIMPLE_OMP_ORDERED
13892 && find_omp_clause (gimple_omp_ordered_clauses
13893 (as_a <gomp_ordered *> (stmt)),
13894 OMP_CLAUSE_DEPEND))
13895 /* #pragma omp ordered depend is also just a stand-alone
13896 directive. */
13897 region = NULL;
13898 /* ..., this directive becomes the parent for a new region. */
13899 if (region)
13900 parent = region;
13904 if (single_tree && !parent)
13905 return;
13907 for (son = first_dom_son (CDI_DOMINATORS, bb);
13908 son;
13909 son = next_dom_son (CDI_DOMINATORS, son))
13910 build_omp_regions_1 (son, parent, single_tree);
13913 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13914 root_omp_region. */
13916 static void
13917 build_omp_regions_root (basic_block root)
13919 gcc_assert (root_omp_region == NULL);
13920 build_omp_regions_1 (root, NULL, true);
13921 gcc_assert (root_omp_region != NULL);
13924 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13926 void
13927 omp_expand_local (basic_block head)
13929 build_omp_regions_root (head);
13930 if (dump_file && (dump_flags & TDF_DETAILS))
13932 fprintf (dump_file, "\nOMP region tree\n\n");
13933 dump_omp_region (dump_file, root_omp_region, 0);
13934 fprintf (dump_file, "\n");
13937 remove_exit_barriers (root_omp_region);
13938 expand_omp (root_omp_region);
13940 free_omp_regions ();
13943 /* Scan the CFG and build a tree of OMP regions. Return the root of
13944 the OMP region tree. */
13946 static void
13947 build_omp_regions (void)
13949 gcc_assert (root_omp_region == NULL);
13950 calculate_dominance_info (CDI_DOMINATORS);
13951 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
13954 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13956 static unsigned int
13957 execute_expand_omp (void)
13959 build_omp_regions ();
13961 if (!root_omp_region)
13962 return 0;
13964 if (dump_file)
13966 fprintf (dump_file, "\nOMP region tree\n\n");
13967 dump_omp_region (dump_file, root_omp_region, 0);
13968 fprintf (dump_file, "\n");
13971 remove_exit_barriers (root_omp_region);
13973 expand_omp (root_omp_region);
13975 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13976 verify_loop_structure ();
13977 cleanup_tree_cfg ();
13979 free_omp_regions ();
13981 return 0;
13984 /* OMP expansion -- the default pass, run before creation of SSA form. */
13986 namespace {
13988 const pass_data pass_data_expand_omp =
13990 GIMPLE_PASS, /* type */
13991 "ompexp", /* name */
13992 OPTGROUP_NONE, /* optinfo_flags */
13993 TV_NONE, /* tv_id */
13994 PROP_gimple_any, /* properties_required */
13995 PROP_gimple_eomp, /* properties_provided */
13996 0, /* properties_destroyed */
13997 0, /* todo_flags_start */
13998 0, /* todo_flags_finish */
14001 class pass_expand_omp : public gimple_opt_pass
14003 public:
14004 pass_expand_omp (gcc::context *ctxt)
14005 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14008 /* opt_pass methods: */
14009 virtual unsigned int execute (function *)
14011 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14012 || flag_openmp_simd != 0)
14013 && !seen_error ());
14015 /* This pass always runs, to provide PROP_gimple_eomp.
14016 But often, there is nothing to do. */
14017 if (!gate)
14018 return 0;
14020 return execute_expand_omp ();
14023 }; // class pass_expand_omp
14025 } // anon namespace
14027 gimple_opt_pass *
14028 make_pass_expand_omp (gcc::context *ctxt)
14030 return new pass_expand_omp (ctxt);
14033 namespace {
14035 const pass_data pass_data_expand_omp_ssa =
14037 GIMPLE_PASS, /* type */
14038 "ompexpssa", /* name */
14039 OPTGROUP_NONE, /* optinfo_flags */
14040 TV_NONE, /* tv_id */
14041 PROP_cfg | PROP_ssa, /* properties_required */
14042 PROP_gimple_eomp, /* properties_provided */
14043 0, /* properties_destroyed */
14044 0, /* todo_flags_start */
14045 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14048 class pass_expand_omp_ssa : public gimple_opt_pass
14050 public:
14051 pass_expand_omp_ssa (gcc::context *ctxt)
14052 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14055 /* opt_pass methods: */
14056 virtual bool gate (function *fun)
14058 return !(fun->curr_properties & PROP_gimple_eomp);
14060 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14061 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14063 }; // class pass_expand_omp_ssa
14065 } // anon namespace
14067 gimple_opt_pass *
14068 make_pass_expand_omp_ssa (gcc::context *ctxt)
14070 return new pass_expand_omp_ssa (ctxt);
14073 /* Routines to lower OMP directives into OMP-GIMPLE. */
14075 /* If ctx is a worksharing context inside of a cancellable parallel
14076 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14077 and conditional branch to parallel's cancel_label to handle
14078 cancellation in the implicit barrier. */
14080 static void
14081 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14083 gimple *omp_return = gimple_seq_last_stmt (*body);
14084 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14085 if (gimple_omp_return_nowait_p (omp_return))
14086 return;
14087 if (ctx->outer
14088 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14089 && ctx->outer->cancellable)
14091 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14092 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14093 tree lhs = create_tmp_var (c_bool_type);
14094 gimple_omp_return_set_lhs (omp_return, lhs);
14095 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14096 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14097 fold_convert (c_bool_type,
14098 boolean_false_node),
14099 ctx->outer->cancel_label, fallthru_label);
14100 gimple_seq_add_stmt (body, g);
14101 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14105 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14106 CTX is the enclosing OMP context for the current statement. */
14108 static void
14109 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14111 tree block, control;
14112 gimple_stmt_iterator tgsi;
14113 gomp_sections *stmt;
14114 gimple *t;
14115 gbind *new_stmt, *bind;
14116 gimple_seq ilist, dlist, olist, new_body;
14118 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14120 push_gimplify_context ();
14122 dlist = NULL;
14123 ilist = NULL;
14124 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14125 &ilist, &dlist, ctx, NULL);
14127 new_body = gimple_omp_body (stmt);
14128 gimple_omp_set_body (stmt, NULL);
14129 tgsi = gsi_start (new_body);
14130 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14132 omp_context *sctx;
14133 gimple *sec_start;
14135 sec_start = gsi_stmt (tgsi);
14136 sctx = maybe_lookup_ctx (sec_start);
14137 gcc_assert (sctx);
14139 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14140 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14141 GSI_CONTINUE_LINKING);
14142 gimple_omp_set_body (sec_start, NULL);
14144 if (gsi_one_before_end_p (tgsi))
14146 gimple_seq l = NULL;
14147 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14148 &l, ctx);
14149 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14150 gimple_omp_section_set_last (sec_start);
14153 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14154 GSI_CONTINUE_LINKING);
14157 block = make_node (BLOCK);
14158 bind = gimple_build_bind (NULL, new_body, block);
14160 olist = NULL;
14161 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14163 block = make_node (BLOCK);
14164 new_stmt = gimple_build_bind (NULL, NULL, block);
14165 gsi_replace (gsi_p, new_stmt, true);
14167 pop_gimplify_context (new_stmt);
14168 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14169 BLOCK_VARS (block) = gimple_bind_vars (bind);
14170 if (BLOCK_VARS (block))
14171 TREE_USED (block) = 1;
14173 new_body = NULL;
14174 gimple_seq_add_seq (&new_body, ilist);
14175 gimple_seq_add_stmt (&new_body, stmt);
14176 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14177 gimple_seq_add_stmt (&new_body, bind);
14179 control = create_tmp_var (unsigned_type_node, ".section");
14180 t = gimple_build_omp_continue (control, control);
14181 gimple_omp_sections_set_control (stmt, control);
14182 gimple_seq_add_stmt (&new_body, t);
14184 gimple_seq_add_seq (&new_body, olist);
14185 if (ctx->cancellable)
14186 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14187 gimple_seq_add_seq (&new_body, dlist);
14189 new_body = maybe_catch_exception (new_body);
14191 t = gimple_build_omp_return
14192 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14193 OMP_CLAUSE_NOWAIT));
14194 gimple_seq_add_stmt (&new_body, t);
14195 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14197 gimple_bind_set_body (new_stmt, new_body);
14201 /* A subroutine of lower_omp_single. Expand the simple form of
14202 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14204 if (GOMP_single_start ())
14205 BODY;
14206 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14208 FIXME. It may be better to delay expanding the logic of this until
14209 pass_expand_omp. The expanded logic may make the job more difficult
14210 to a synchronization analysis pass. */
14212 static void
14213 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14215 location_t loc = gimple_location (single_stmt);
14216 tree tlabel = create_artificial_label (loc);
14217 tree flabel = create_artificial_label (loc);
14218 gimple *call, *cond;
14219 tree lhs, decl;
14221 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14222 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14223 call = gimple_build_call (decl, 0);
14224 gimple_call_set_lhs (call, lhs);
14225 gimple_seq_add_stmt (pre_p, call);
14227 cond = gimple_build_cond (EQ_EXPR, lhs,
14228 fold_convert_loc (loc, TREE_TYPE (lhs),
14229 boolean_true_node),
14230 tlabel, flabel);
14231 gimple_seq_add_stmt (pre_p, cond);
14232 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14233 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14234 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14238 /* A subroutine of lower_omp_single. Expand the simple form of
14239 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14241 #pragma omp single copyprivate (a, b, c)
14243 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14246 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14248 BODY;
14249 copyout.a = a;
14250 copyout.b = b;
14251 copyout.c = c;
14252 GOMP_single_copy_end (&copyout);
14254 else
14256 a = copyout_p->a;
14257 b = copyout_p->b;
14258 c = copyout_p->c;
14260 GOMP_barrier ();
14263 FIXME. It may be better to delay expanding the logic of this until
14264 pass_expand_omp. The expanded logic may make the job more difficult
14265 to a synchronization analysis pass. */
14267 static void
14268 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14269 omp_context *ctx)
14271 tree ptr_type, t, l0, l1, l2, bfn_decl;
14272 gimple_seq copyin_seq;
14273 location_t loc = gimple_location (single_stmt);
14275 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14277 ptr_type = build_pointer_type (ctx->record_type);
14278 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14280 l0 = create_artificial_label (loc);
14281 l1 = create_artificial_label (loc);
14282 l2 = create_artificial_label (loc);
14284 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14285 t = build_call_expr_loc (loc, bfn_decl, 0);
14286 t = fold_convert_loc (loc, ptr_type, t);
14287 gimplify_assign (ctx->receiver_decl, t, pre_p);
14289 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14290 build_int_cst (ptr_type, 0));
14291 t = build3 (COND_EXPR, void_type_node, t,
14292 build_and_jump (&l0), build_and_jump (&l1));
14293 gimplify_and_add (t, pre_p);
14295 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14297 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14299 copyin_seq = NULL;
14300 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14301 &copyin_seq, ctx);
14303 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14304 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14305 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14306 gimplify_and_add (t, pre_p);
14308 t = build_and_jump (&l2);
14309 gimplify_and_add (t, pre_p);
14311 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14313 gimple_seq_add_seq (pre_p, copyin_seq);
14315 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14319 /* Expand code for an OpenMP single directive. */
14321 static void
14322 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14324 tree block;
14325 gimple *t;
14326 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14327 gbind *bind;
14328 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14330 push_gimplify_context ();
14332 block = make_node (BLOCK);
14333 bind = gimple_build_bind (NULL, NULL, block);
14334 gsi_replace (gsi_p, bind, true);
14335 bind_body = NULL;
14336 dlist = NULL;
14337 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14338 &bind_body, &dlist, ctx, NULL);
14339 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14341 gimple_seq_add_stmt (&bind_body, single_stmt);
14343 if (ctx->record_type)
14344 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14345 else
14346 lower_omp_single_simple (single_stmt, &bind_body);
14348 gimple_omp_set_body (single_stmt, NULL);
14350 gimple_seq_add_seq (&bind_body, dlist);
14352 bind_body = maybe_catch_exception (bind_body);
14354 t = gimple_build_omp_return
14355 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14356 OMP_CLAUSE_NOWAIT));
14357 gimple_seq_add_stmt (&bind_body_tail, t);
14358 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14359 if (ctx->record_type)
14361 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14362 tree clobber = build_constructor (ctx->record_type, NULL);
14363 TREE_THIS_VOLATILE (clobber) = 1;
14364 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14365 clobber), GSI_SAME_STMT);
14367 gimple_seq_add_seq (&bind_body, bind_body_tail);
14368 gimple_bind_set_body (bind, bind_body);
14370 pop_gimplify_context (bind);
14372 gimple_bind_append_vars (bind, ctx->block_vars);
14373 BLOCK_VARS (block) = ctx->block_vars;
14374 if (BLOCK_VARS (block))
14375 TREE_USED (block) = 1;
14379 /* Expand code for an OpenMP master directive. */
14381 static void
14382 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14384 tree block, lab = NULL, x, bfn_decl;
14385 gimple *stmt = gsi_stmt (*gsi_p);
14386 gbind *bind;
14387 location_t loc = gimple_location (stmt);
14388 gimple_seq tseq;
14390 push_gimplify_context ();
14392 block = make_node (BLOCK);
14393 bind = gimple_build_bind (NULL, NULL, block);
14394 gsi_replace (gsi_p, bind, true);
14395 gimple_bind_add_stmt (bind, stmt);
14397 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14398 x = build_call_expr_loc (loc, bfn_decl, 0);
14399 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14400 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14401 tseq = NULL;
14402 gimplify_and_add (x, &tseq);
14403 gimple_bind_add_seq (bind, tseq);
14405 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14406 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14407 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14408 gimple_omp_set_body (stmt, NULL);
14410 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14412 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14414 pop_gimplify_context (bind);
14416 gimple_bind_append_vars (bind, ctx->block_vars);
14417 BLOCK_VARS (block) = ctx->block_vars;
14421 /* Expand code for an OpenMP taskgroup directive. */
14423 static void
14424 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14426 gimple *stmt = gsi_stmt (*gsi_p);
14427 gcall *x;
14428 gbind *bind;
14429 tree block = make_node (BLOCK);
14431 bind = gimple_build_bind (NULL, NULL, block);
14432 gsi_replace (gsi_p, bind, true);
14433 gimple_bind_add_stmt (bind, stmt);
14435 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14437 gimple_bind_add_stmt (bind, x);
14439 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14440 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14441 gimple_omp_set_body (stmt, NULL);
14443 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14445 gimple_bind_append_vars (bind, ctx->block_vars);
14446 BLOCK_VARS (block) = ctx->block_vars;
14450 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14452 static void
14453 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14454 omp_context *ctx)
14456 struct omp_for_data fd;
14457 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14458 return;
14460 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14461 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14462 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14463 if (!fd.ordered)
14464 return;
14466 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14467 tree c = gimple_omp_ordered_clauses (ord_stmt);
14468 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14469 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14471 /* Merge depend clauses from multiple adjacent
14472 #pragma omp ordered depend(sink:...) constructs
14473 into one #pragma omp ordered depend(sink:...), so that
14474 we can optimize them together. */
14475 gimple_stmt_iterator gsi = *gsi_p;
14476 gsi_next (&gsi);
14477 while (!gsi_end_p (gsi))
14479 gimple *stmt = gsi_stmt (gsi);
14480 if (is_gimple_debug (stmt)
14481 || gimple_code (stmt) == GIMPLE_NOP)
14483 gsi_next (&gsi);
14484 continue;
14486 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14487 break;
14488 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14489 c = gimple_omp_ordered_clauses (ord_stmt2);
14490 if (c == NULL_TREE
14491 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14492 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14493 break;
14494 while (*list_p)
14495 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14496 *list_p = c;
14497 gsi_remove (&gsi, true);
14501 /* Canonicalize sink dependence clauses into one folded clause if
14502 possible.
14504 The basic algorithm is to create a sink vector whose first
14505 element is the GCD of all the first elements, and whose remaining
14506 elements are the minimum of the subsequent columns.
14508 We ignore dependence vectors whose first element is zero because
14509 such dependencies are known to be executed by the same thread.
14511 We take into account the direction of the loop, so a minimum
14512 becomes a maximum if the loop is iterating forwards. We also
14513 ignore sink clauses where the loop direction is unknown, or where
14514 the offsets are clearly invalid because they are not a multiple
14515 of the loop increment.
14517 For example:
14519 #pragma omp for ordered(2)
14520 for (i=0; i < N; ++i)
14521 for (j=0; j < M; ++j)
14523 #pragma omp ordered \
14524 depend(sink:i-8,j-2) \
14525 depend(sink:i,j-1) \ // Completely ignored because i+0.
14526 depend(sink:i-4,j-3) \
14527 depend(sink:i-6,j-4)
14528 #pragma omp ordered depend(source)
14531 Folded clause is:
14533 depend(sink:-gcd(8,4,6),-min(2,3,4))
14534 -or-
14535 depend(sink:-2,-2)
14538 /* FIXME: Computing GCD's where the first element is zero is
14539 non-trivial in the presence of collapsed loops. Do this later. */
14540 if (fd.collapse > 1)
14541 return;
14543 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14544 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14545 tree folded_dep = NULL_TREE;
14546 /* TRUE if the first dimension's offset is negative. */
14547 bool neg_offset_p = false;
14549 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14550 unsigned int i;
14551 while ((c = *list_p) != NULL)
14553 bool remove = false;
14555 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14556 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14557 goto next_ordered_clause;
14559 tree vec;
14560 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14561 vec && TREE_CODE (vec) == TREE_LIST;
14562 vec = TREE_CHAIN (vec), ++i)
14564 gcc_assert (i < len);
14566 /* extract_omp_for_data has canonicalized the condition. */
14567 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14568 || fd.loops[i].cond_code == GT_EXPR);
14569 bool forward = fd.loops[i].cond_code == LT_EXPR;
14570 bool maybe_lexically_later = true;
14572 /* While the committee makes up its mind, bail if we have any
14573 non-constant steps. */
14574 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14575 goto lower_omp_ordered_ret;
14577 tree itype = TREE_TYPE (TREE_VALUE (vec));
14578 if (POINTER_TYPE_P (itype))
14579 itype = sizetype;
14580 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14581 TYPE_PRECISION (itype),
14582 TYPE_SIGN (itype));
14584 /* Ignore invalid offsets that are not multiples of the step. */
14585 if (!wi::multiple_of_p
14586 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14587 UNSIGNED))
14589 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14590 "ignoring sink clause with offset that is not "
14591 "a multiple of the loop step");
14592 remove = true;
14593 goto next_ordered_clause;
14596 /* Calculate the first dimension. The first dimension of
14597 the folded dependency vector is the GCD of the first
14598 elements, while ignoring any first elements whose offset
14599 is 0. */
14600 if (i == 0)
14602 /* Ignore dependence vectors whose first dimension is 0. */
14603 if (offset == 0)
14605 remove = true;
14606 goto next_ordered_clause;
14608 else
14610 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14612 error_at (OMP_CLAUSE_LOCATION (c),
14613 "first offset must be in opposite direction "
14614 "of loop iterations");
14615 goto lower_omp_ordered_ret;
14617 if (forward)
14618 offset = -offset;
14619 neg_offset_p = forward;
14620 /* Initialize the first time around. */
14621 if (folded_dep == NULL_TREE)
14623 folded_dep = c;
14624 folded_deps[0] = offset;
14626 else
14627 folded_deps[0] = wi::gcd (folded_deps[0],
14628 offset, UNSIGNED);
14631 /* Calculate minimum for the remaining dimensions. */
14632 else
14634 folded_deps[len + i - 1] = offset;
14635 if (folded_dep == c)
14636 folded_deps[i] = offset;
14637 else if (maybe_lexically_later
14638 && !wi::eq_p (folded_deps[i], offset))
14640 if (forward ^ wi::gts_p (folded_deps[i], offset))
14642 unsigned int j;
14643 folded_dep = c;
14644 for (j = 1; j <= i; j++)
14645 folded_deps[j] = folded_deps[len + j - 1];
14647 else
14648 maybe_lexically_later = false;
14652 gcc_assert (i == len);
14654 remove = true;
14656 next_ordered_clause:
14657 if (remove)
14658 *list_p = OMP_CLAUSE_CHAIN (c);
14659 else
14660 list_p = &OMP_CLAUSE_CHAIN (c);
14663 if (folded_dep)
14665 if (neg_offset_p)
14666 folded_deps[0] = -folded_deps[0];
14668 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14669 if (POINTER_TYPE_P (itype))
14670 itype = sizetype;
14672 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14673 = wide_int_to_tree (itype, folded_deps[0]);
14674 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14675 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14678 lower_omp_ordered_ret:
14680 /* Ordered without clauses is #pragma omp threads, while we want
14681 a nop instead if we remove all clauses. */
14682 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14683 gsi_replace (gsi_p, gimple_build_nop (), true);
14687 /* Expand code for an OpenMP ordered directive. */
14689 static void
14690 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14692 tree block;
14693 gimple *stmt = gsi_stmt (*gsi_p);
14694 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14695 gcall *x;
14696 gbind *bind;
14697 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14698 OMP_CLAUSE_SIMD);
14699 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14700 OMP_CLAUSE_THREADS);
14702 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14703 OMP_CLAUSE_DEPEND))
14705 /* FIXME: This is needs to be moved to the expansion to verify various
14706 conditions only testable on cfg with dominators computed, and also
14707 all the depend clauses to be merged still might need to be available
14708 for the runtime checks. */
14709 if (0)
14710 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14711 return;
14714 push_gimplify_context ();
14716 block = make_node (BLOCK);
14717 bind = gimple_build_bind (NULL, NULL, block);
14718 gsi_replace (gsi_p, bind, true);
14719 gimple_bind_add_stmt (bind, stmt);
14721 if (simd)
14723 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14724 build_int_cst (NULL_TREE, threads));
14725 cfun->has_simduid_loops = true;
14727 else
14728 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14730 gimple_bind_add_stmt (bind, x);
14732 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14733 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14734 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14735 gimple_omp_set_body (stmt, NULL);
14737 if (simd)
14738 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14739 build_int_cst (NULL_TREE, threads));
14740 else
14741 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14743 gimple_bind_add_stmt (bind, x);
14745 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14747 pop_gimplify_context (bind);
14749 gimple_bind_append_vars (bind, ctx->block_vars);
14750 BLOCK_VARS (block) = gimple_bind_vars (bind);
14754 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14755 substitution of a couple of function calls. But in the NAMED case,
14756 requires that languages coordinate a symbol name. It is therefore
14757 best put here in common code. */
14759 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14761 static void
14762 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14764 tree block;
14765 tree name, lock, unlock;
14766 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14767 gbind *bind;
14768 location_t loc = gimple_location (stmt);
14769 gimple_seq tbody;
14771 name = gimple_omp_critical_name (stmt);
14772 if (name)
14774 tree decl;
14776 if (!critical_name_mutexes)
14777 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14779 tree *n = critical_name_mutexes->get (name);
14780 if (n == NULL)
14782 char *new_str;
14784 decl = create_tmp_var_raw (ptr_type_node);
14786 new_str = ACONCAT ((".gomp_critical_user_",
14787 IDENTIFIER_POINTER (name), NULL));
14788 DECL_NAME (decl) = get_identifier (new_str);
14789 TREE_PUBLIC (decl) = 1;
14790 TREE_STATIC (decl) = 1;
14791 DECL_COMMON (decl) = 1;
14792 DECL_ARTIFICIAL (decl) = 1;
14793 DECL_IGNORED_P (decl) = 1;
14795 varpool_node::finalize_decl (decl);
14797 critical_name_mutexes->put (name, decl);
14799 else
14800 decl = *n;
14802 /* If '#pragma omp critical' is inside offloaded region or
14803 inside function marked as offloadable, the symbol must be
14804 marked as offloadable too. */
14805 omp_context *octx;
14806 if (cgraph_node::get (current_function_decl)->offloadable)
14807 varpool_node::get_create (decl)->offloadable = 1;
14808 else
14809 for (octx = ctx->outer; octx; octx = octx->outer)
14810 if (is_gimple_omp_offloaded (octx->stmt))
14812 varpool_node::get_create (decl)->offloadable = 1;
14813 break;
14816 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14817 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14819 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14820 unlock = build_call_expr_loc (loc, unlock, 1,
14821 build_fold_addr_expr_loc (loc, decl));
14823 else
14825 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14826 lock = build_call_expr_loc (loc, lock, 0);
14828 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14829 unlock = build_call_expr_loc (loc, unlock, 0);
14832 push_gimplify_context ();
14834 block = make_node (BLOCK);
14835 bind = gimple_build_bind (NULL, NULL, block);
14836 gsi_replace (gsi_p, bind, true);
14837 gimple_bind_add_stmt (bind, stmt);
14839 tbody = gimple_bind_body (bind);
14840 gimplify_and_add (lock, &tbody);
14841 gimple_bind_set_body (bind, tbody);
14843 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14844 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14845 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14846 gimple_omp_set_body (stmt, NULL);
14848 tbody = gimple_bind_body (bind);
14849 gimplify_and_add (unlock, &tbody);
14850 gimple_bind_set_body (bind, tbody);
14852 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14854 pop_gimplify_context (bind);
14855 gimple_bind_append_vars (bind, ctx->block_vars);
14856 BLOCK_VARS (block) = gimple_bind_vars (bind);
14860 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14861 for a lastprivate clause. Given a loop control predicate of (V
14862 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14863 is appended to *DLIST, iterator initialization is appended to
14864 *BODY_P. */
14866 static void
14867 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14868 gimple_seq *dlist, struct omp_context *ctx)
14870 tree clauses, cond, vinit;
14871 enum tree_code cond_code;
14872 gimple_seq stmts;
14874 cond_code = fd->loop.cond_code;
14875 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14877 /* When possible, use a strict equality expression. This can let VRP
14878 type optimizations deduce the value and remove a copy. */
14879 if (tree_fits_shwi_p (fd->loop.step))
14881 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14882 if (step == 1 || step == -1)
14883 cond_code = EQ_EXPR;
14886 tree n2 = fd->loop.n2;
14887 if (fd->collapse > 1
14888 && TREE_CODE (n2) != INTEGER_CST
14889 && gimple_omp_for_combined_into_p (fd->for_stmt))
14891 struct omp_context *taskreg_ctx = NULL;
14892 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14894 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14895 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14896 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14898 if (gimple_omp_for_combined_into_p (gfor))
14900 gcc_assert (ctx->outer->outer
14901 && is_parallel_ctx (ctx->outer->outer));
14902 taskreg_ctx = ctx->outer->outer;
14904 else
14906 struct omp_for_data outer_fd;
14907 extract_omp_for_data (gfor, &outer_fd, NULL);
14908 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14911 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14912 taskreg_ctx = ctx->outer->outer;
14914 else if (is_taskreg_ctx (ctx->outer))
14915 taskreg_ctx = ctx->outer;
14916 if (taskreg_ctx)
14918 int i;
14919 tree innerc
14920 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14921 OMP_CLAUSE__LOOPTEMP_);
14922 gcc_assert (innerc);
14923 for (i = 0; i < fd->collapse; i++)
14925 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14926 OMP_CLAUSE__LOOPTEMP_);
14927 gcc_assert (innerc);
14929 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14930 OMP_CLAUSE__LOOPTEMP_);
14931 if (innerc)
14932 n2 = fold_convert (TREE_TYPE (n2),
14933 lookup_decl (OMP_CLAUSE_DECL (innerc),
14934 taskreg_ctx));
14937 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14939 clauses = gimple_omp_for_clauses (fd->for_stmt);
14940 stmts = NULL;
14941 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14942 if (!gimple_seq_empty_p (stmts))
14944 gimple_seq_add_seq (&stmts, *dlist);
14945 *dlist = stmts;
14947 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14948 vinit = fd->loop.n1;
14949 if (cond_code == EQ_EXPR
14950 && tree_fits_shwi_p (fd->loop.n2)
14951 && ! integer_zerop (fd->loop.n2))
14952 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14953 else
14954 vinit = unshare_expr (vinit);
14956 /* Initialize the iterator variable, so that threads that don't execute
14957 any iterations don't execute the lastprivate clauses by accident. */
14958 gimplify_assign (fd->loop.v, vinit, body_p);
14963 /* Lower code for an OMP loop directive. */
14965 static void
14966 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14968 tree *rhs_p, block;
14969 struct omp_for_data fd, *fdp = NULL;
14970 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14971 gbind *new_stmt;
14972 gimple_seq omp_for_body, body, dlist;
14973 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14974 size_t i;
14976 push_gimplify_context ();
14978 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14980 block = make_node (BLOCK);
14981 new_stmt = gimple_build_bind (NULL, NULL, block);
14982 /* Replace at gsi right away, so that 'stmt' is no member
14983 of a sequence anymore as we're going to add to a different
14984 one below. */
14985 gsi_replace (gsi_p, new_stmt, true);
14987 /* Move declaration of temporaries in the loop body before we make
14988 it go away. */
14989 omp_for_body = gimple_omp_body (stmt);
14990 if (!gimple_seq_empty_p (omp_for_body)
14991 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14993 gbind *inner_bind
14994 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14995 tree vars = gimple_bind_vars (inner_bind);
14996 gimple_bind_append_vars (new_stmt, vars);
14997 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14998 keep them on the inner_bind and it's block. */
14999 gimple_bind_set_vars (inner_bind, NULL_TREE);
15000 if (gimple_bind_block (inner_bind))
15001 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15004 if (gimple_omp_for_combined_into_p (stmt))
15006 extract_omp_for_data (stmt, &fd, NULL);
15007 fdp = &fd;
15009 /* We need two temporaries with fd.loop.v type (istart/iend)
15010 and then (fd.collapse - 1) temporaries with the same
15011 type for count2 ... countN-1 vars if not constant. */
15012 size_t count = 2;
15013 tree type = fd.iter_type;
15014 if (fd.collapse > 1
15015 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15016 count += fd.collapse - 1;
15017 bool taskreg_for
15018 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15019 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15020 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15021 tree clauses = *pc;
15022 if (taskreg_for)
15023 outerc
15024 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15025 OMP_CLAUSE__LOOPTEMP_);
15026 for (i = 0; i < count; i++)
15028 tree temp;
15029 if (taskreg_for)
15031 gcc_assert (outerc);
15032 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15033 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15034 OMP_CLAUSE__LOOPTEMP_);
15036 else
15038 temp = create_tmp_var (type);
15039 insert_decl_map (&ctx->outer->cb, temp, temp);
15041 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15042 OMP_CLAUSE_DECL (*pc) = temp;
15043 pc = &OMP_CLAUSE_CHAIN (*pc);
15045 *pc = clauses;
15048 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15049 dlist = NULL;
15050 body = NULL;
15051 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15052 fdp);
15053 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15055 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15057 /* Lower the header expressions. At this point, we can assume that
15058 the header is of the form:
15060 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15062 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15063 using the .omp_data_s mapping, if needed. */
15064 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15066 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15067 if (!is_gimple_min_invariant (*rhs_p))
15068 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15070 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15071 if (!is_gimple_min_invariant (*rhs_p))
15072 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15074 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15075 if (!is_gimple_min_invariant (*rhs_p))
15076 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15079 /* Once lowered, extract the bounds and clauses. */
15080 extract_omp_for_data (stmt, &fd, NULL);
15082 if (is_gimple_omp_oacc (ctx->stmt)
15083 && !ctx_in_oacc_kernels_region (ctx))
15084 lower_oacc_head_tail (gimple_location (stmt),
15085 gimple_omp_for_clauses (stmt),
15086 &oacc_head, &oacc_tail, ctx);
15088 /* Add OpenACC partitioning and reduction markers just before the loop */
15089 if (oacc_head)
15090 gimple_seq_add_seq (&body, oacc_head);
15092 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15094 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15095 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15096 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15097 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15099 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15100 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15101 OMP_CLAUSE_LINEAR_STEP (c)
15102 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15103 ctx);
15106 if (!gimple_omp_for_grid_phony (stmt))
15107 gimple_seq_add_stmt (&body, stmt);
15108 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15110 if (!gimple_omp_for_grid_phony (stmt))
15111 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15112 fd.loop.v));
15114 /* After the loop, add exit clauses. */
15115 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15117 if (ctx->cancellable)
15118 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15120 gimple_seq_add_seq (&body, dlist);
15122 body = maybe_catch_exception (body);
15124 if (!gimple_omp_for_grid_phony (stmt))
15126 /* Region exit marker goes at the end of the loop body. */
15127 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15128 maybe_add_implicit_barrier_cancel (ctx, &body);
15131 /* Add OpenACC joining and reduction markers just after the loop. */
15132 if (oacc_tail)
15133 gimple_seq_add_seq (&body, oacc_tail);
15135 pop_gimplify_context (new_stmt);
15137 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15138 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15139 if (BLOCK_VARS (block))
15140 TREE_USED (block) = 1;
15142 gimple_bind_set_body (new_stmt, body);
15143 gimple_omp_set_body (stmt, NULL);
15144 gimple_omp_for_set_pre_body (stmt, NULL);
15147 /* Callback for walk_stmts. Check if the current statement only contains
15148 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15150 static tree
15151 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15152 bool *handled_ops_p,
15153 struct walk_stmt_info *wi)
15155 int *info = (int *) wi->info;
15156 gimple *stmt = gsi_stmt (*gsi_p);
15158 *handled_ops_p = true;
15159 switch (gimple_code (stmt))
15161 WALK_SUBSTMTS;
15163 case GIMPLE_OMP_FOR:
15164 case GIMPLE_OMP_SECTIONS:
15165 *info = *info == 0 ? 1 : -1;
15166 break;
15167 default:
15168 *info = -1;
15169 break;
15171 return NULL;
15174 struct omp_taskcopy_context
15176 /* This field must be at the beginning, as we do "inheritance": Some
15177 callback functions for tree-inline.c (e.g., omp_copy_decl)
15178 receive a copy_body_data pointer that is up-casted to an
15179 omp_context pointer. */
15180 copy_body_data cb;
15181 omp_context *ctx;
15184 static tree
15185 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15187 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15189 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15190 return create_tmp_var (TREE_TYPE (var));
15192 return var;
15195 static tree
15196 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15198 tree name, new_fields = NULL, type, f;
15200 type = lang_hooks.types.make_type (RECORD_TYPE);
15201 name = DECL_NAME (TYPE_NAME (orig_type));
15202 name = build_decl (gimple_location (tcctx->ctx->stmt),
15203 TYPE_DECL, name, type);
15204 TYPE_NAME (type) = name;
15206 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15208 tree new_f = copy_node (f);
15209 DECL_CONTEXT (new_f) = type;
15210 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15211 TREE_CHAIN (new_f) = new_fields;
15212 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15213 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15214 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15215 &tcctx->cb, NULL);
15216 new_fields = new_f;
15217 tcctx->cb.decl_map->put (f, new_f);
15219 TYPE_FIELDS (type) = nreverse (new_fields);
15220 layout_type (type);
15221 return type;
15224 /* Create task copyfn. */
15226 static void
15227 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15229 struct function *child_cfun;
15230 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15231 tree record_type, srecord_type, bind, list;
15232 bool record_needs_remap = false, srecord_needs_remap = false;
15233 splay_tree_node n;
15234 struct omp_taskcopy_context tcctx;
15235 location_t loc = gimple_location (task_stmt);
15237 child_fn = gimple_omp_task_copy_fn (task_stmt);
15238 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15239 gcc_assert (child_cfun->cfg == NULL);
15240 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15242 /* Reset DECL_CONTEXT on function arguments. */
15243 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15244 DECL_CONTEXT (t) = child_fn;
15246 /* Populate the function. */
15247 push_gimplify_context ();
15248 push_cfun (child_cfun);
15250 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15251 TREE_SIDE_EFFECTS (bind) = 1;
15252 list = NULL;
15253 DECL_SAVED_TREE (child_fn) = bind;
15254 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15256 /* Remap src and dst argument types if needed. */
15257 record_type = ctx->record_type;
15258 srecord_type = ctx->srecord_type;
15259 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15260 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15262 record_needs_remap = true;
15263 break;
15265 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15266 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15268 srecord_needs_remap = true;
15269 break;
15272 if (record_needs_remap || srecord_needs_remap)
15274 memset (&tcctx, '\0', sizeof (tcctx));
15275 tcctx.cb.src_fn = ctx->cb.src_fn;
15276 tcctx.cb.dst_fn = child_fn;
15277 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15278 gcc_checking_assert (tcctx.cb.src_node);
15279 tcctx.cb.dst_node = tcctx.cb.src_node;
15280 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15281 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15282 tcctx.cb.eh_lp_nr = 0;
15283 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15284 tcctx.cb.decl_map = new hash_map<tree, tree>;
15285 tcctx.ctx = ctx;
15287 if (record_needs_remap)
15288 record_type = task_copyfn_remap_type (&tcctx, record_type);
15289 if (srecord_needs_remap)
15290 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15292 else
15293 tcctx.cb.decl_map = NULL;
15295 arg = DECL_ARGUMENTS (child_fn);
15296 TREE_TYPE (arg) = build_pointer_type (record_type);
15297 sarg = DECL_CHAIN (arg);
15298 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15300 /* First pass: initialize temporaries used in record_type and srecord_type
15301 sizes and field offsets. */
15302 if (tcctx.cb.decl_map)
15303 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15304 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15306 tree *p;
15308 decl = OMP_CLAUSE_DECL (c);
15309 p = tcctx.cb.decl_map->get (decl);
15310 if (p == NULL)
15311 continue;
15312 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15313 sf = (tree) n->value;
15314 sf = *tcctx.cb.decl_map->get (sf);
15315 src = build_simple_mem_ref_loc (loc, sarg);
15316 src = omp_build_component_ref (src, sf);
15317 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15318 append_to_statement_list (t, &list);
15321 /* Second pass: copy shared var pointers and copy construct non-VLA
15322 firstprivate vars. */
15323 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15324 switch (OMP_CLAUSE_CODE (c))
15326 splay_tree_key key;
15327 case OMP_CLAUSE_SHARED:
15328 decl = OMP_CLAUSE_DECL (c);
15329 key = (splay_tree_key) decl;
15330 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15331 key = (splay_tree_key) &DECL_UID (decl);
15332 n = splay_tree_lookup (ctx->field_map, key);
15333 if (n == NULL)
15334 break;
15335 f = (tree) n->value;
15336 if (tcctx.cb.decl_map)
15337 f = *tcctx.cb.decl_map->get (f);
15338 n = splay_tree_lookup (ctx->sfield_map, key);
15339 sf = (tree) n->value;
15340 if (tcctx.cb.decl_map)
15341 sf = *tcctx.cb.decl_map->get (sf);
15342 src = build_simple_mem_ref_loc (loc, sarg);
15343 src = omp_build_component_ref (src, sf);
15344 dst = build_simple_mem_ref_loc (loc, arg);
15345 dst = omp_build_component_ref (dst, f);
15346 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15347 append_to_statement_list (t, &list);
15348 break;
15349 case OMP_CLAUSE_FIRSTPRIVATE:
15350 decl = OMP_CLAUSE_DECL (c);
15351 if (is_variable_sized (decl))
15352 break;
15353 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15354 if (n == NULL)
15355 break;
15356 f = (tree) n->value;
15357 if (tcctx.cb.decl_map)
15358 f = *tcctx.cb.decl_map->get (f);
15359 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15360 if (n != NULL)
15362 sf = (tree) n->value;
15363 if (tcctx.cb.decl_map)
15364 sf = *tcctx.cb.decl_map->get (sf);
15365 src = build_simple_mem_ref_loc (loc, sarg);
15366 src = omp_build_component_ref (src, sf);
15367 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15368 src = build_simple_mem_ref_loc (loc, src);
15370 else
15371 src = decl;
15372 dst = build_simple_mem_ref_loc (loc, arg);
15373 dst = omp_build_component_ref (dst, f);
15374 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15375 append_to_statement_list (t, &list);
15376 break;
15377 case OMP_CLAUSE_PRIVATE:
15378 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15379 break;
15380 decl = OMP_CLAUSE_DECL (c);
15381 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15382 f = (tree) n->value;
15383 if (tcctx.cb.decl_map)
15384 f = *tcctx.cb.decl_map->get (f);
15385 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15386 if (n != NULL)
15388 sf = (tree) n->value;
15389 if (tcctx.cb.decl_map)
15390 sf = *tcctx.cb.decl_map->get (sf);
15391 src = build_simple_mem_ref_loc (loc, sarg);
15392 src = omp_build_component_ref (src, sf);
15393 if (use_pointer_for_field (decl, NULL))
15394 src = build_simple_mem_ref_loc (loc, src);
15396 else
15397 src = decl;
15398 dst = build_simple_mem_ref_loc (loc, arg);
15399 dst = omp_build_component_ref (dst, f);
15400 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15401 append_to_statement_list (t, &list);
15402 break;
15403 default:
15404 break;
15407 /* Last pass: handle VLA firstprivates. */
15408 if (tcctx.cb.decl_map)
15409 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15410 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15412 tree ind, ptr, df;
15414 decl = OMP_CLAUSE_DECL (c);
15415 if (!is_variable_sized (decl))
15416 continue;
15417 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15418 if (n == NULL)
15419 continue;
15420 f = (tree) n->value;
15421 f = *tcctx.cb.decl_map->get (f);
15422 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15423 ind = DECL_VALUE_EXPR (decl);
15424 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15425 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15426 n = splay_tree_lookup (ctx->sfield_map,
15427 (splay_tree_key) TREE_OPERAND (ind, 0));
15428 sf = (tree) n->value;
15429 sf = *tcctx.cb.decl_map->get (sf);
15430 src = build_simple_mem_ref_loc (loc, sarg);
15431 src = omp_build_component_ref (src, sf);
15432 src = build_simple_mem_ref_loc (loc, src);
15433 dst = build_simple_mem_ref_loc (loc, arg);
15434 dst = omp_build_component_ref (dst, f);
15435 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15436 append_to_statement_list (t, &list);
15437 n = splay_tree_lookup (ctx->field_map,
15438 (splay_tree_key) TREE_OPERAND (ind, 0));
15439 df = (tree) n->value;
15440 df = *tcctx.cb.decl_map->get (df);
15441 ptr = build_simple_mem_ref_loc (loc, arg);
15442 ptr = omp_build_component_ref (ptr, df);
15443 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15444 build_fold_addr_expr_loc (loc, dst));
15445 append_to_statement_list (t, &list);
15448 t = build1 (RETURN_EXPR, void_type_node, NULL);
15449 append_to_statement_list (t, &list);
15451 if (tcctx.cb.decl_map)
15452 delete tcctx.cb.decl_map;
15453 pop_gimplify_context (NULL);
15454 BIND_EXPR_BODY (bind) = list;
15455 pop_cfun ();
15458 static void
15459 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15461 tree c, clauses;
15462 gimple *g;
15463 size_t n_in = 0, n_out = 0, idx = 2, i;
15465 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15466 gcc_assert (clauses);
15467 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15468 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15469 switch (OMP_CLAUSE_DEPEND_KIND (c))
15471 case OMP_CLAUSE_DEPEND_IN:
15472 n_in++;
15473 break;
15474 case OMP_CLAUSE_DEPEND_OUT:
15475 case OMP_CLAUSE_DEPEND_INOUT:
15476 n_out++;
15477 break;
15478 case OMP_CLAUSE_DEPEND_SOURCE:
15479 case OMP_CLAUSE_DEPEND_SINK:
15480 /* FALLTHRU */
15481 default:
15482 gcc_unreachable ();
15484 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15485 tree array = create_tmp_var (type);
15486 TREE_ADDRESSABLE (array) = 1;
15487 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15488 NULL_TREE);
15489 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15490 gimple_seq_add_stmt (iseq, g);
15491 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15492 NULL_TREE);
15493 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15494 gimple_seq_add_stmt (iseq, g);
15495 for (i = 0; i < 2; i++)
15497 if ((i ? n_in : n_out) == 0)
15498 continue;
15499 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15501 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15503 tree t = OMP_CLAUSE_DECL (c);
15504 t = fold_convert (ptr_type_node, t);
15505 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15506 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15507 NULL_TREE, NULL_TREE);
15508 g = gimple_build_assign (r, t);
15509 gimple_seq_add_stmt (iseq, g);
15512 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15513 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15514 OMP_CLAUSE_CHAIN (c) = *pclauses;
15515 *pclauses = c;
15516 tree clobber = build_constructor (type, NULL);
15517 TREE_THIS_VOLATILE (clobber) = 1;
15518 g = gimple_build_assign (array, clobber);
15519 gimple_seq_add_stmt (oseq, g);
15522 /* Lower the OpenMP parallel or task directive in the current statement
15523 in GSI_P. CTX holds context information for the directive. */
15525 static void
15526 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15528 tree clauses;
15529 tree child_fn, t;
15530 gimple *stmt = gsi_stmt (*gsi_p);
15531 gbind *par_bind, *bind, *dep_bind = NULL;
15532 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15533 location_t loc = gimple_location (stmt);
15535 clauses = gimple_omp_taskreg_clauses (stmt);
15536 par_bind
15537 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15538 par_body = gimple_bind_body (par_bind);
15539 child_fn = ctx->cb.dst_fn;
15540 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15541 && !gimple_omp_parallel_combined_p (stmt))
15543 struct walk_stmt_info wi;
15544 int ws_num = 0;
15546 memset (&wi, 0, sizeof (wi));
15547 wi.info = &ws_num;
15548 wi.val_only = true;
15549 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15550 if (ws_num == 1)
15551 gimple_omp_parallel_set_combined_p (stmt, true);
15553 gimple_seq dep_ilist = NULL;
15554 gimple_seq dep_olist = NULL;
15555 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15556 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15558 push_gimplify_context ();
15559 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15560 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15561 &dep_ilist, &dep_olist);
15564 if (ctx->srecord_type)
15565 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15567 push_gimplify_context ();
15569 par_olist = NULL;
15570 par_ilist = NULL;
15571 par_rlist = NULL;
15572 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15573 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15574 if (phony_construct && ctx->record_type)
15576 gcc_checking_assert (!ctx->receiver_decl);
15577 ctx->receiver_decl = create_tmp_var
15578 (build_reference_type (ctx->record_type), ".omp_rec");
15580 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15581 lower_omp (&par_body, ctx);
15582 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15583 lower_reduction_clauses (clauses, &par_rlist, ctx);
15585 /* Declare all the variables created by mapping and the variables
15586 declared in the scope of the parallel body. */
15587 record_vars_into (ctx->block_vars, child_fn);
15588 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15590 if (ctx->record_type)
15592 ctx->sender_decl
15593 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15594 : ctx->record_type, ".omp_data_o");
15595 DECL_NAMELESS (ctx->sender_decl) = 1;
15596 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15597 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15600 olist = NULL;
15601 ilist = NULL;
15602 lower_send_clauses (clauses, &ilist, &olist, ctx);
15603 lower_send_shared_vars (&ilist, &olist, ctx);
15605 if (ctx->record_type)
15607 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15608 TREE_THIS_VOLATILE (clobber) = 1;
15609 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15610 clobber));
15613 /* Once all the expansions are done, sequence all the different
15614 fragments inside gimple_omp_body. */
15616 new_body = NULL;
15618 if (ctx->record_type)
15620 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15621 /* fixup_child_record_type might have changed receiver_decl's type. */
15622 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15623 gimple_seq_add_stmt (&new_body,
15624 gimple_build_assign (ctx->receiver_decl, t));
15627 gimple_seq_add_seq (&new_body, par_ilist);
15628 gimple_seq_add_seq (&new_body, par_body);
15629 gimple_seq_add_seq (&new_body, par_rlist);
15630 if (ctx->cancellable)
15631 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15632 gimple_seq_add_seq (&new_body, par_olist);
15633 new_body = maybe_catch_exception (new_body);
15634 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15635 gimple_seq_add_stmt (&new_body,
15636 gimple_build_omp_continue (integer_zero_node,
15637 integer_zero_node));
15638 if (!phony_construct)
15640 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15641 gimple_omp_set_body (stmt, new_body);
15644 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15645 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15646 gimple_bind_add_seq (bind, ilist);
15647 if (!phony_construct)
15648 gimple_bind_add_stmt (bind, stmt);
15649 else
15650 gimple_bind_add_seq (bind, new_body);
15651 gimple_bind_add_seq (bind, olist);
15653 pop_gimplify_context (NULL);
15655 if (dep_bind)
15657 gimple_bind_add_seq (dep_bind, dep_ilist);
15658 gimple_bind_add_stmt (dep_bind, bind);
15659 gimple_bind_add_seq (dep_bind, dep_olist);
15660 pop_gimplify_context (dep_bind);
15664 /* Lower the GIMPLE_OMP_TARGET in the current statement
15665 in GSI_P. CTX holds context information for the directive. */
15667 static void
15668 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15670 tree clauses;
15671 tree child_fn, t, c;
15672 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15673 gbind *tgt_bind, *bind, *dep_bind = NULL;
15674 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15675 location_t loc = gimple_location (stmt);
15676 bool offloaded, data_region;
15677 unsigned int map_cnt = 0;
15678 bool has_depend = false;
15680 offloaded = is_gimple_omp_offloaded (stmt);
15681 switch (gimple_omp_target_kind (stmt))
15683 case GF_OMP_TARGET_KIND_REGION:
15684 case GF_OMP_TARGET_KIND_UPDATE:
15685 case GF_OMP_TARGET_KIND_ENTER_DATA:
15686 case GF_OMP_TARGET_KIND_EXIT_DATA:
15687 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15688 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15689 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15690 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15691 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15692 data_region = false;
15693 break;
15694 case GF_OMP_TARGET_KIND_DATA:
15695 case GF_OMP_TARGET_KIND_OACC_DATA:
15696 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15697 data_region = true;
15698 break;
15699 default:
15700 gcc_unreachable ();
15703 clauses = gimple_omp_target_clauses (stmt);
15705 gimple_seq dep_ilist = NULL;
15706 gimple_seq dep_olist = NULL;
15707 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15709 push_gimplify_context ();
15710 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15711 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15712 &dep_ilist, &dep_olist);
15713 has_depend = true;
15716 tgt_bind = NULL;
15717 tgt_body = NULL;
15718 if (offloaded)
15720 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15721 tgt_body = gimple_bind_body (tgt_bind);
15723 else if (data_region)
15724 tgt_body = gimple_omp_body (stmt);
15725 child_fn = ctx->cb.dst_fn;
15727 push_gimplify_context ();
15728 fplist = NULL;
15730 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15731 switch (OMP_CLAUSE_CODE (c))
15733 tree var, x;
15735 default:
15736 break;
15737 case OMP_CLAUSE_MAP:
15738 #if CHECKING_P
15739 /* First check what we're prepared to handle in the following. */
15740 switch (OMP_CLAUSE_MAP_KIND (c))
15742 case GOMP_MAP_ALLOC:
15743 case GOMP_MAP_TO:
15744 case GOMP_MAP_FROM:
15745 case GOMP_MAP_TOFROM:
15746 case GOMP_MAP_POINTER:
15747 case GOMP_MAP_TO_PSET:
15748 case GOMP_MAP_FORCE_DEALLOC:
15749 case GOMP_MAP_RELEASE:
15750 case GOMP_MAP_ALWAYS_TO:
15751 case GOMP_MAP_ALWAYS_FROM:
15752 case GOMP_MAP_ALWAYS_TOFROM:
15753 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15754 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15755 case GOMP_MAP_STRUCT:
15756 case GOMP_MAP_ALWAYS_POINTER:
15757 break;
15758 case GOMP_MAP_FORCE_ALLOC:
15759 case GOMP_MAP_FORCE_TO:
15760 case GOMP_MAP_FORCE_FROM:
15761 case GOMP_MAP_FORCE_TOFROM:
15762 case GOMP_MAP_FORCE_PRESENT:
15763 case GOMP_MAP_FORCE_DEVICEPTR:
15764 case GOMP_MAP_DEVICE_RESIDENT:
15765 case GOMP_MAP_LINK:
15766 gcc_assert (is_gimple_omp_oacc (stmt));
15767 break;
15768 default:
15769 gcc_unreachable ();
15771 #endif
15772 /* FALLTHRU */
15773 case OMP_CLAUSE_TO:
15774 case OMP_CLAUSE_FROM:
15775 oacc_firstprivate:
15776 var = OMP_CLAUSE_DECL (c);
15777 if (!DECL_P (var))
15779 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15780 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15781 && (OMP_CLAUSE_MAP_KIND (c)
15782 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15783 map_cnt++;
15784 continue;
15787 if (DECL_SIZE (var)
15788 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15790 tree var2 = DECL_VALUE_EXPR (var);
15791 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15792 var2 = TREE_OPERAND (var2, 0);
15793 gcc_assert (DECL_P (var2));
15794 var = var2;
15797 if (offloaded
15798 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15799 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15800 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15802 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15804 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15805 && varpool_node::get_create (var)->offloadable)
15806 continue;
15808 tree type = build_pointer_type (TREE_TYPE (var));
15809 tree new_var = lookup_decl (var, ctx);
15810 x = create_tmp_var_raw (type, get_name (new_var));
15811 gimple_add_tmp_var (x);
15812 x = build_simple_mem_ref (x);
15813 SET_DECL_VALUE_EXPR (new_var, x);
15814 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15816 continue;
15819 if (!maybe_lookup_field (var, ctx))
15820 continue;
15822 if (offloaded)
15824 x = build_receiver_ref (var, true, ctx);
15825 tree new_var = lookup_decl (var, ctx);
15827 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15828 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15829 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15830 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15831 x = build_simple_mem_ref (x);
15832 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15834 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15835 if (is_reference (new_var))
15837 /* Create a local object to hold the instance
15838 value. */
15839 tree type = TREE_TYPE (TREE_TYPE (new_var));
15840 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15841 tree inst = create_tmp_var (type, id);
15842 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15843 x = build_fold_addr_expr (inst);
15845 gimplify_assign (new_var, x, &fplist);
15847 else if (DECL_P (new_var))
15849 SET_DECL_VALUE_EXPR (new_var, x);
15850 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15852 else
15853 gcc_unreachable ();
15855 map_cnt++;
15856 break;
15858 case OMP_CLAUSE_FIRSTPRIVATE:
15859 if (is_oacc_parallel (ctx))
15860 goto oacc_firstprivate;
15861 map_cnt++;
15862 var = OMP_CLAUSE_DECL (c);
15863 if (!is_reference (var)
15864 && !is_gimple_reg_type (TREE_TYPE (var)))
15866 tree new_var = lookup_decl (var, ctx);
15867 if (is_variable_sized (var))
15869 tree pvar = DECL_VALUE_EXPR (var);
15870 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15871 pvar = TREE_OPERAND (pvar, 0);
15872 gcc_assert (DECL_P (pvar));
15873 tree new_pvar = lookup_decl (pvar, ctx);
15874 x = build_fold_indirect_ref (new_pvar);
15875 TREE_THIS_NOTRAP (x) = 1;
15877 else
15878 x = build_receiver_ref (var, true, ctx);
15879 SET_DECL_VALUE_EXPR (new_var, x);
15880 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15882 break;
15884 case OMP_CLAUSE_PRIVATE:
15885 if (is_gimple_omp_oacc (ctx->stmt))
15886 break;
15887 var = OMP_CLAUSE_DECL (c);
15888 if (is_variable_sized (var))
15890 tree new_var = lookup_decl (var, ctx);
15891 tree pvar = DECL_VALUE_EXPR (var);
15892 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15893 pvar = TREE_OPERAND (pvar, 0);
15894 gcc_assert (DECL_P (pvar));
15895 tree new_pvar = lookup_decl (pvar, ctx);
15896 x = build_fold_indirect_ref (new_pvar);
15897 TREE_THIS_NOTRAP (x) = 1;
15898 SET_DECL_VALUE_EXPR (new_var, x);
15899 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15901 break;
15903 case OMP_CLAUSE_USE_DEVICE_PTR:
15904 case OMP_CLAUSE_IS_DEVICE_PTR:
15905 var = OMP_CLAUSE_DECL (c);
15906 map_cnt++;
15907 if (is_variable_sized (var))
15909 tree new_var = lookup_decl (var, ctx);
15910 tree pvar = DECL_VALUE_EXPR (var);
15911 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15912 pvar = TREE_OPERAND (pvar, 0);
15913 gcc_assert (DECL_P (pvar));
15914 tree new_pvar = lookup_decl (pvar, ctx);
15915 x = build_fold_indirect_ref (new_pvar);
15916 TREE_THIS_NOTRAP (x) = 1;
15917 SET_DECL_VALUE_EXPR (new_var, x);
15918 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15920 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15922 tree new_var = lookup_decl (var, ctx);
15923 tree type = build_pointer_type (TREE_TYPE (var));
15924 x = create_tmp_var_raw (type, get_name (new_var));
15925 gimple_add_tmp_var (x);
15926 x = build_simple_mem_ref (x);
15927 SET_DECL_VALUE_EXPR (new_var, x);
15928 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15930 else
15932 tree new_var = lookup_decl (var, ctx);
15933 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15934 gimple_add_tmp_var (x);
15935 SET_DECL_VALUE_EXPR (new_var, x);
15936 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15938 break;
15941 if (offloaded)
15943 target_nesting_level++;
15944 lower_omp (&tgt_body, ctx);
15945 target_nesting_level--;
15947 else if (data_region)
15948 lower_omp (&tgt_body, ctx);
15950 if (offloaded)
15952 /* Declare all the variables created by mapping and the variables
15953 declared in the scope of the target body. */
15954 record_vars_into (ctx->block_vars, child_fn);
15955 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15958 olist = NULL;
15959 ilist = NULL;
15960 if (ctx->record_type)
15962 ctx->sender_decl
15963 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15964 DECL_NAMELESS (ctx->sender_decl) = 1;
15965 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15966 t = make_tree_vec (3);
15967 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15968 TREE_VEC_ELT (t, 1)
15969 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15970 ".omp_data_sizes");
15971 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15972 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15973 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15974 tree tkind_type = short_unsigned_type_node;
15975 int talign_shift = 8;
15976 TREE_VEC_ELT (t, 2)
15977 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15978 ".omp_data_kinds");
15979 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15980 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15981 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15982 gimple_omp_target_set_data_arg (stmt, t);
15984 vec<constructor_elt, va_gc> *vsize;
15985 vec<constructor_elt, va_gc> *vkind;
15986 vec_alloc (vsize, map_cnt);
15987 vec_alloc (vkind, map_cnt);
15988 unsigned int map_idx = 0;
15990 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15991 switch (OMP_CLAUSE_CODE (c))
15993 tree ovar, nc, s, purpose, var, x, type;
15994 unsigned int talign;
15996 default:
15997 break;
15999 case OMP_CLAUSE_MAP:
16000 case OMP_CLAUSE_TO:
16001 case OMP_CLAUSE_FROM:
16002 oacc_firstprivate_map:
16003 nc = c;
16004 ovar = OMP_CLAUSE_DECL (c);
16005 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16006 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16007 || (OMP_CLAUSE_MAP_KIND (c)
16008 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16009 break;
16010 if (!DECL_P (ovar))
16012 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16013 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16015 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16016 == get_base_address (ovar));
16017 nc = OMP_CLAUSE_CHAIN (c);
16018 ovar = OMP_CLAUSE_DECL (nc);
16020 else
16022 tree x = build_sender_ref (ovar, ctx);
16023 tree v
16024 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16025 gimplify_assign (x, v, &ilist);
16026 nc = NULL_TREE;
16029 else
16031 if (DECL_SIZE (ovar)
16032 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16034 tree ovar2 = DECL_VALUE_EXPR (ovar);
16035 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16036 ovar2 = TREE_OPERAND (ovar2, 0);
16037 gcc_assert (DECL_P (ovar2));
16038 ovar = ovar2;
16040 if (!maybe_lookup_field (ovar, ctx))
16041 continue;
16044 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16045 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16046 talign = DECL_ALIGN_UNIT (ovar);
16047 if (nc)
16049 var = lookup_decl_in_outer_ctx (ovar, ctx);
16050 x = build_sender_ref (ovar, ctx);
16052 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16053 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16054 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16055 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16057 gcc_assert (offloaded);
16058 tree avar
16059 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16060 mark_addressable (avar);
16061 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16062 talign = DECL_ALIGN_UNIT (avar);
16063 avar = build_fold_addr_expr (avar);
16064 gimplify_assign (x, avar, &ilist);
16066 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16068 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16069 if (!is_reference (var))
16070 var = build_fold_addr_expr (var);
16071 else
16072 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16073 gimplify_assign (x, var, &ilist);
16075 else if (is_gimple_reg (var))
16077 gcc_assert (offloaded);
16078 tree avar = create_tmp_var (TREE_TYPE (var));
16079 mark_addressable (avar);
16080 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16081 if (GOMP_MAP_COPY_TO_P (map_kind)
16082 || map_kind == GOMP_MAP_POINTER
16083 || map_kind == GOMP_MAP_TO_PSET
16084 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16085 gimplify_assign (avar, var, &ilist);
16086 avar = build_fold_addr_expr (avar);
16087 gimplify_assign (x, avar, &ilist);
16088 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16089 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16090 && !TYPE_READONLY (TREE_TYPE (var)))
16092 x = unshare_expr (x);
16093 x = build_simple_mem_ref (x);
16094 gimplify_assign (var, x, &olist);
16097 else
16099 var = build_fold_addr_expr (var);
16100 gimplify_assign (x, var, &ilist);
16103 s = NULL_TREE;
16104 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16106 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16107 s = TREE_TYPE (ovar);
16108 if (TREE_CODE (s) == REFERENCE_TYPE)
16109 s = TREE_TYPE (s);
16110 s = TYPE_SIZE_UNIT (s);
16112 else
16113 s = OMP_CLAUSE_SIZE (c);
16114 if (s == NULL_TREE)
16115 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16116 s = fold_convert (size_type_node, s);
16117 purpose = size_int (map_idx++);
16118 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16119 if (TREE_CODE (s) != INTEGER_CST)
16120 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16122 unsigned HOST_WIDE_INT tkind, tkind_zero;
16123 switch (OMP_CLAUSE_CODE (c))
16125 case OMP_CLAUSE_MAP:
16126 tkind = OMP_CLAUSE_MAP_KIND (c);
16127 tkind_zero = tkind;
16128 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16129 switch (tkind)
16131 case GOMP_MAP_ALLOC:
16132 case GOMP_MAP_TO:
16133 case GOMP_MAP_FROM:
16134 case GOMP_MAP_TOFROM:
16135 case GOMP_MAP_ALWAYS_TO:
16136 case GOMP_MAP_ALWAYS_FROM:
16137 case GOMP_MAP_ALWAYS_TOFROM:
16138 case GOMP_MAP_RELEASE:
16139 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16140 break;
16141 case GOMP_MAP_DELETE:
16142 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16143 default:
16144 break;
16146 if (tkind_zero != tkind)
16148 if (integer_zerop (s))
16149 tkind = tkind_zero;
16150 else if (integer_nonzerop (s))
16151 tkind_zero = tkind;
16153 break;
16154 case OMP_CLAUSE_FIRSTPRIVATE:
16155 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16156 tkind = GOMP_MAP_TO;
16157 tkind_zero = tkind;
16158 break;
16159 case OMP_CLAUSE_TO:
16160 tkind = GOMP_MAP_TO;
16161 tkind_zero = tkind;
16162 break;
16163 case OMP_CLAUSE_FROM:
16164 tkind = GOMP_MAP_FROM;
16165 tkind_zero = tkind;
16166 break;
16167 default:
16168 gcc_unreachable ();
16170 gcc_checking_assert (tkind
16171 < (HOST_WIDE_INT_C (1U) << talign_shift));
16172 gcc_checking_assert (tkind_zero
16173 < (HOST_WIDE_INT_C (1U) << talign_shift));
16174 talign = ceil_log2 (talign);
16175 tkind |= talign << talign_shift;
16176 tkind_zero |= talign << talign_shift;
16177 gcc_checking_assert (tkind
16178 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16179 gcc_checking_assert (tkind_zero
16180 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16181 if (tkind == tkind_zero)
16182 x = build_int_cstu (tkind_type, tkind);
16183 else
16185 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16186 x = build3 (COND_EXPR, tkind_type,
16187 fold_build2 (EQ_EXPR, boolean_type_node,
16188 unshare_expr (s), size_zero_node),
16189 build_int_cstu (tkind_type, tkind_zero),
16190 build_int_cstu (tkind_type, tkind));
16192 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16193 if (nc && nc != c)
16194 c = nc;
16195 break;
16197 case OMP_CLAUSE_FIRSTPRIVATE:
16198 if (is_oacc_parallel (ctx))
16199 goto oacc_firstprivate_map;
16200 ovar = OMP_CLAUSE_DECL (c);
16201 if (is_reference (ovar))
16202 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16203 else
16204 talign = DECL_ALIGN_UNIT (ovar);
16205 var = lookup_decl_in_outer_ctx (ovar, ctx);
16206 x = build_sender_ref (ovar, ctx);
16207 tkind = GOMP_MAP_FIRSTPRIVATE;
16208 type = TREE_TYPE (ovar);
16209 if (is_reference (ovar))
16210 type = TREE_TYPE (type);
16211 bool use_firstprivate_int, force_addr;
16212 use_firstprivate_int = false;
16213 force_addr = false;
16214 if ((INTEGRAL_TYPE_P (type)
16215 && TYPE_PRECISION (type) <= POINTER_SIZE)
16216 || TREE_CODE (type) == POINTER_TYPE)
16217 use_firstprivate_int = true;
16218 if (has_depend)
16220 if (is_reference (var))
16221 use_firstprivate_int = false;
16222 else if (is_gimple_reg (var))
16224 if (DECL_HAS_VALUE_EXPR_P (var))
16226 tree v = get_base_address (var);
16227 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16229 use_firstprivate_int = false;
16230 force_addr = true;
16232 else
16233 switch (TREE_CODE (v))
16235 case INDIRECT_REF:
16236 case MEM_REF:
16237 use_firstprivate_int = false;
16238 force_addr = true;
16239 break;
16240 default:
16241 break;
16245 else
16246 use_firstprivate_int = false;
16248 if (use_firstprivate_int)
16250 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16251 tree t = var;
16252 if (is_reference (var))
16253 t = build_simple_mem_ref (var);
16254 if (TREE_CODE (type) != POINTER_TYPE)
16255 t = fold_convert (pointer_sized_int_node, t);
16256 t = fold_convert (TREE_TYPE (x), t);
16257 gimplify_assign (x, t, &ilist);
16259 else if (is_reference (var))
16260 gimplify_assign (x, var, &ilist);
16261 else if (!force_addr && is_gimple_reg (var))
16263 tree avar = create_tmp_var (TREE_TYPE (var));
16264 mark_addressable (avar);
16265 gimplify_assign (avar, var, &ilist);
16266 avar = build_fold_addr_expr (avar);
16267 gimplify_assign (x, avar, &ilist);
16269 else
16271 var = build_fold_addr_expr (var);
16272 gimplify_assign (x, var, &ilist);
16274 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16275 s = size_int (0);
16276 else if (is_reference (var))
16277 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16278 else
16279 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16280 s = fold_convert (size_type_node, s);
16281 purpose = size_int (map_idx++);
16282 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16283 if (TREE_CODE (s) != INTEGER_CST)
16284 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16286 gcc_checking_assert (tkind
16287 < (HOST_WIDE_INT_C (1U) << talign_shift));
16288 talign = ceil_log2 (talign);
16289 tkind |= talign << talign_shift;
16290 gcc_checking_assert (tkind
16291 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16292 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16293 build_int_cstu (tkind_type, tkind));
16294 break;
16296 case OMP_CLAUSE_USE_DEVICE_PTR:
16297 case OMP_CLAUSE_IS_DEVICE_PTR:
16298 ovar = OMP_CLAUSE_DECL (c);
16299 var = lookup_decl_in_outer_ctx (ovar, ctx);
16300 x = build_sender_ref (ovar, ctx);
16301 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16302 tkind = GOMP_MAP_USE_DEVICE_PTR;
16303 else
16304 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16305 type = TREE_TYPE (ovar);
16306 if (TREE_CODE (type) == ARRAY_TYPE)
16307 var = build_fold_addr_expr (var);
16308 else
16310 if (is_reference (ovar))
16312 type = TREE_TYPE (type);
16313 if (TREE_CODE (type) != ARRAY_TYPE)
16314 var = build_simple_mem_ref (var);
16315 var = fold_convert (TREE_TYPE (x), var);
16318 gimplify_assign (x, var, &ilist);
16319 s = size_int (0);
16320 purpose = size_int (map_idx++);
16321 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16322 gcc_checking_assert (tkind
16323 < (HOST_WIDE_INT_C (1U) << talign_shift));
16324 gcc_checking_assert (tkind
16325 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16326 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16327 build_int_cstu (tkind_type, tkind));
16328 break;
16331 gcc_assert (map_idx == map_cnt);
16333 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16334 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16335 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16336 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16337 for (int i = 1; i <= 2; i++)
16338 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16340 gimple_seq initlist = NULL;
16341 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16342 TREE_VEC_ELT (t, i)),
16343 &initlist, true, NULL_TREE);
16344 gimple_seq_add_seq (&ilist, initlist);
16346 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16347 NULL);
16348 TREE_THIS_VOLATILE (clobber) = 1;
16349 gimple_seq_add_stmt (&olist,
16350 gimple_build_assign (TREE_VEC_ELT (t, i),
16351 clobber));
16354 tree clobber = build_constructor (ctx->record_type, NULL);
16355 TREE_THIS_VOLATILE (clobber) = 1;
16356 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16357 clobber));
16360 /* Once all the expansions are done, sequence all the different
16361 fragments inside gimple_omp_body. */
16363 new_body = NULL;
16365 if (offloaded
16366 && ctx->record_type)
16368 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16369 /* fixup_child_record_type might have changed receiver_decl's type. */
16370 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16371 gimple_seq_add_stmt (&new_body,
16372 gimple_build_assign (ctx->receiver_decl, t));
16374 gimple_seq_add_seq (&new_body, fplist);
16376 if (offloaded || data_region)
16378 tree prev = NULL_TREE;
16379 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16380 switch (OMP_CLAUSE_CODE (c))
16382 tree var, x;
16383 default:
16384 break;
16385 case OMP_CLAUSE_FIRSTPRIVATE:
16386 if (is_gimple_omp_oacc (ctx->stmt))
16387 break;
16388 var = OMP_CLAUSE_DECL (c);
16389 if (is_reference (var)
16390 || is_gimple_reg_type (TREE_TYPE (var)))
16392 tree new_var = lookup_decl (var, ctx);
16393 tree type;
16394 type = TREE_TYPE (var);
16395 if (is_reference (var))
16396 type = TREE_TYPE (type);
16397 bool use_firstprivate_int;
16398 use_firstprivate_int = false;
16399 if ((INTEGRAL_TYPE_P (type)
16400 && TYPE_PRECISION (type) <= POINTER_SIZE)
16401 || TREE_CODE (type) == POINTER_TYPE)
16402 use_firstprivate_int = true;
16403 if (has_depend)
16405 tree v = lookup_decl_in_outer_ctx (var, ctx);
16406 if (is_reference (v))
16407 use_firstprivate_int = false;
16408 else if (is_gimple_reg (v))
16410 if (DECL_HAS_VALUE_EXPR_P (v))
16412 v = get_base_address (v);
16413 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16414 use_firstprivate_int = false;
16415 else
16416 switch (TREE_CODE (v))
16418 case INDIRECT_REF:
16419 case MEM_REF:
16420 use_firstprivate_int = false;
16421 break;
16422 default:
16423 break;
16427 else
16428 use_firstprivate_int = false;
16430 if (use_firstprivate_int)
16432 x = build_receiver_ref (var, false, ctx);
16433 if (TREE_CODE (type) != POINTER_TYPE)
16434 x = fold_convert (pointer_sized_int_node, x);
16435 x = fold_convert (type, x);
16436 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16437 fb_rvalue);
16438 if (is_reference (var))
16440 tree v = create_tmp_var_raw (type, get_name (var));
16441 gimple_add_tmp_var (v);
16442 TREE_ADDRESSABLE (v) = 1;
16443 gimple_seq_add_stmt (&new_body,
16444 gimple_build_assign (v, x));
16445 x = build_fold_addr_expr (v);
16447 gimple_seq_add_stmt (&new_body,
16448 gimple_build_assign (new_var, x));
16450 else
16452 x = build_receiver_ref (var, !is_reference (var), ctx);
16453 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16454 fb_rvalue);
16455 gimple_seq_add_stmt (&new_body,
16456 gimple_build_assign (new_var, x));
16459 else if (is_variable_sized (var))
16461 tree pvar = DECL_VALUE_EXPR (var);
16462 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16463 pvar = TREE_OPERAND (pvar, 0);
16464 gcc_assert (DECL_P (pvar));
16465 tree new_var = lookup_decl (pvar, ctx);
16466 x = build_receiver_ref (var, false, ctx);
16467 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16468 gimple_seq_add_stmt (&new_body,
16469 gimple_build_assign (new_var, x));
16471 break;
16472 case OMP_CLAUSE_PRIVATE:
16473 if (is_gimple_omp_oacc (ctx->stmt))
16474 break;
16475 var = OMP_CLAUSE_DECL (c);
16476 if (is_reference (var))
16478 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16479 tree new_var = lookup_decl (var, ctx);
16480 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16481 if (TREE_CONSTANT (x))
16483 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16484 get_name (var));
16485 gimple_add_tmp_var (x);
16486 TREE_ADDRESSABLE (x) = 1;
16487 x = build_fold_addr_expr_loc (clause_loc, x);
16489 else
16490 break;
16492 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16493 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16494 gimple_seq_add_stmt (&new_body,
16495 gimple_build_assign (new_var, x));
16497 break;
16498 case OMP_CLAUSE_USE_DEVICE_PTR:
16499 case OMP_CLAUSE_IS_DEVICE_PTR:
16500 var = OMP_CLAUSE_DECL (c);
16501 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16502 x = build_sender_ref (var, ctx);
16503 else
16504 x = build_receiver_ref (var, false, ctx);
16505 if (is_variable_sized (var))
16507 tree pvar = DECL_VALUE_EXPR (var);
16508 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16509 pvar = TREE_OPERAND (pvar, 0);
16510 gcc_assert (DECL_P (pvar));
16511 tree new_var = lookup_decl (pvar, ctx);
16512 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16513 gimple_seq_add_stmt (&new_body,
16514 gimple_build_assign (new_var, x));
16516 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16518 tree new_var = lookup_decl (var, ctx);
16519 new_var = DECL_VALUE_EXPR (new_var);
16520 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16521 new_var = TREE_OPERAND (new_var, 0);
16522 gcc_assert (DECL_P (new_var));
16523 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16524 gimple_seq_add_stmt (&new_body,
16525 gimple_build_assign (new_var, x));
16527 else
16529 tree type = TREE_TYPE (var);
16530 tree new_var = lookup_decl (var, ctx);
16531 if (is_reference (var))
16533 type = TREE_TYPE (type);
16534 if (TREE_CODE (type) != ARRAY_TYPE)
16536 tree v = create_tmp_var_raw (type, get_name (var));
16537 gimple_add_tmp_var (v);
16538 TREE_ADDRESSABLE (v) = 1;
16539 x = fold_convert (type, x);
16540 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16541 fb_rvalue);
16542 gimple_seq_add_stmt (&new_body,
16543 gimple_build_assign (v, x));
16544 x = build_fold_addr_expr (v);
16547 new_var = DECL_VALUE_EXPR (new_var);
16548 x = fold_convert (TREE_TYPE (new_var), x);
16549 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16550 gimple_seq_add_stmt (&new_body,
16551 gimple_build_assign (new_var, x));
16553 break;
16555 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16556 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16557 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16558 or references to VLAs. */
16559 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16560 switch (OMP_CLAUSE_CODE (c))
16562 tree var;
16563 default:
16564 break;
16565 case OMP_CLAUSE_MAP:
16566 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16567 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16569 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16570 HOST_WIDE_INT offset = 0;
16571 gcc_assert (prev);
16572 var = OMP_CLAUSE_DECL (c);
16573 if (DECL_P (var)
16574 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16575 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16576 ctx))
16577 && varpool_node::get_create (var)->offloadable)
16578 break;
16579 if (TREE_CODE (var) == INDIRECT_REF
16580 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16581 var = TREE_OPERAND (var, 0);
16582 if (TREE_CODE (var) == COMPONENT_REF)
16584 var = get_addr_base_and_unit_offset (var, &offset);
16585 gcc_assert (var != NULL_TREE && DECL_P (var));
16587 else if (DECL_SIZE (var)
16588 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16590 tree var2 = DECL_VALUE_EXPR (var);
16591 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16592 var2 = TREE_OPERAND (var2, 0);
16593 gcc_assert (DECL_P (var2));
16594 var = var2;
16596 tree new_var = lookup_decl (var, ctx), x;
16597 tree type = TREE_TYPE (new_var);
16598 bool is_ref;
16599 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16600 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16601 == COMPONENT_REF))
16603 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16604 is_ref = true;
16605 new_var = build2 (MEM_REF, type,
16606 build_fold_addr_expr (new_var),
16607 build_int_cst (build_pointer_type (type),
16608 offset));
16610 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16612 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16613 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
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
16620 is_ref = is_reference (var);
16621 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16622 is_ref = false;
16623 bool ref_to_array = false;
16624 if (is_ref)
16626 type = TREE_TYPE (type);
16627 if (TREE_CODE (type) == ARRAY_TYPE)
16629 type = build_pointer_type (type);
16630 ref_to_array = true;
16633 else if (TREE_CODE (type) == ARRAY_TYPE)
16635 tree decl2 = DECL_VALUE_EXPR (new_var);
16636 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16637 decl2 = TREE_OPERAND (decl2, 0);
16638 gcc_assert (DECL_P (decl2));
16639 new_var = decl2;
16640 type = TREE_TYPE (new_var);
16642 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16643 x = fold_convert_loc (clause_loc, type, x);
16644 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16646 tree bias = OMP_CLAUSE_SIZE (c);
16647 if (DECL_P (bias))
16648 bias = lookup_decl (bias, ctx);
16649 bias = fold_convert_loc (clause_loc, sizetype, bias);
16650 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16651 bias);
16652 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16653 TREE_TYPE (x), x, bias);
16655 if (ref_to_array)
16656 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16657 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16658 if (is_ref && !ref_to_array)
16660 tree t = create_tmp_var_raw (type, get_name (var));
16661 gimple_add_tmp_var (t);
16662 TREE_ADDRESSABLE (t) = 1;
16663 gimple_seq_add_stmt (&new_body,
16664 gimple_build_assign (t, x));
16665 x = build_fold_addr_expr_loc (clause_loc, t);
16667 gimple_seq_add_stmt (&new_body,
16668 gimple_build_assign (new_var, x));
16669 prev = NULL_TREE;
16671 else if (OMP_CLAUSE_CHAIN (c)
16672 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16673 == OMP_CLAUSE_MAP
16674 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16675 == GOMP_MAP_FIRSTPRIVATE_POINTER
16676 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16677 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16678 prev = c;
16679 break;
16680 case OMP_CLAUSE_PRIVATE:
16681 var = OMP_CLAUSE_DECL (c);
16682 if (is_variable_sized (var))
16684 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16685 tree new_var = lookup_decl (var, ctx);
16686 tree pvar = DECL_VALUE_EXPR (var);
16687 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16688 pvar = TREE_OPERAND (pvar, 0);
16689 gcc_assert (DECL_P (pvar));
16690 tree new_pvar = lookup_decl (pvar, ctx);
16691 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16692 tree al = size_int (DECL_ALIGN (var));
16693 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16694 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16695 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16696 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16697 gimple_seq_add_stmt (&new_body,
16698 gimple_build_assign (new_pvar, x));
16700 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16702 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16703 tree new_var = lookup_decl (var, ctx);
16704 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16705 if (TREE_CONSTANT (x))
16706 break;
16707 else
16709 tree atmp
16710 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16711 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16712 tree al = size_int (TYPE_ALIGN (rtype));
16713 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16716 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16717 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16718 gimple_seq_add_stmt (&new_body,
16719 gimple_build_assign (new_var, x));
16721 break;
16724 gimple_seq fork_seq = NULL;
16725 gimple_seq join_seq = NULL;
16727 if (is_oacc_parallel (ctx))
16729 /* If there are reductions on the offloaded region itself, treat
16730 them as a dummy GANG loop. */
16731 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16733 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16734 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16737 gimple_seq_add_seq (&new_body, fork_seq);
16738 gimple_seq_add_seq (&new_body, tgt_body);
16739 gimple_seq_add_seq (&new_body, join_seq);
16741 if (offloaded)
16742 new_body = maybe_catch_exception (new_body);
16744 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16745 gimple_omp_set_body (stmt, new_body);
16748 bind = gimple_build_bind (NULL, NULL,
16749 tgt_bind ? gimple_bind_block (tgt_bind)
16750 : NULL_TREE);
16751 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16752 gimple_bind_add_seq (bind, ilist);
16753 gimple_bind_add_stmt (bind, stmt);
16754 gimple_bind_add_seq (bind, olist);
16756 pop_gimplify_context (NULL);
16758 if (dep_bind)
16760 gimple_bind_add_seq (dep_bind, dep_ilist);
16761 gimple_bind_add_stmt (dep_bind, bind);
16762 gimple_bind_add_seq (dep_bind, dep_olist);
16763 pop_gimplify_context (dep_bind);
16767 /* Expand code for an OpenMP teams directive. */
16769 static void
16770 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16772 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16773 push_gimplify_context ();
16775 tree block = make_node (BLOCK);
16776 gbind *bind = gimple_build_bind (NULL, NULL, block);
16777 gsi_replace (gsi_p, bind, true);
16778 gimple_seq bind_body = NULL;
16779 gimple_seq dlist = NULL;
16780 gimple_seq olist = NULL;
16782 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16783 OMP_CLAUSE_NUM_TEAMS);
16784 if (num_teams == NULL_TREE)
16785 num_teams = build_int_cst (unsigned_type_node, 0);
16786 else
16788 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16789 num_teams = fold_convert (unsigned_type_node, num_teams);
16790 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16792 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16793 OMP_CLAUSE_THREAD_LIMIT);
16794 if (thread_limit == NULL_TREE)
16795 thread_limit = build_int_cst (unsigned_type_node, 0);
16796 else
16798 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16799 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16800 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16801 fb_rvalue);
16804 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16805 &bind_body, &dlist, ctx, NULL);
16806 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16807 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16808 if (!gimple_omp_teams_grid_phony (teams_stmt))
16810 gimple_seq_add_stmt (&bind_body, teams_stmt);
16811 location_t loc = gimple_location (teams_stmt);
16812 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16813 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16814 gimple_set_location (call, loc);
16815 gimple_seq_add_stmt (&bind_body, call);
16818 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16819 gimple_omp_set_body (teams_stmt, NULL);
16820 gimple_seq_add_seq (&bind_body, olist);
16821 gimple_seq_add_seq (&bind_body, dlist);
16822 if (!gimple_omp_teams_grid_phony (teams_stmt))
16823 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16824 gimple_bind_set_body (bind, bind_body);
16826 pop_gimplify_context (bind);
16828 gimple_bind_append_vars (bind, ctx->block_vars);
16829 BLOCK_VARS (block) = ctx->block_vars;
16830 if (BLOCK_VARS (block))
16831 TREE_USED (block) = 1;
16834 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16836 static void
16837 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16839 gimple *stmt = gsi_stmt (*gsi_p);
16840 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16841 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16842 gimple_build_omp_return (false));
16846 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16847 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16848 of OMP context, but with task_shared_vars set. */
16850 static tree
16851 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16852 void *data)
16854 tree t = *tp;
16856 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16857 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16858 return t;
16860 if (task_shared_vars
16861 && DECL_P (t)
16862 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16863 return t;
16865 /* If a global variable has been privatized, TREE_CONSTANT on
16866 ADDR_EXPR might be wrong. */
16867 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16868 recompute_tree_invariant_for_addr_expr (t);
16870 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16871 return NULL_TREE;
16874 /* Data to be communicated between lower_omp_regimplify_operands and
16875 lower_omp_regimplify_operands_p. */
16877 struct lower_omp_regimplify_operands_data
16879 omp_context *ctx;
16880 vec<tree> *decls;
16883 /* Helper function for lower_omp_regimplify_operands. Find
16884 omp_member_access_dummy_var vars and adjust temporarily their
16885 DECL_VALUE_EXPRs if needed. */
16887 static tree
16888 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16889 void *data)
16891 tree t = omp_member_access_dummy_var (*tp);
16892 if (t)
16894 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16895 lower_omp_regimplify_operands_data *ldata
16896 = (lower_omp_regimplify_operands_data *) wi->info;
16897 tree o = maybe_lookup_decl (t, ldata->ctx);
16898 if (o != t)
16900 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16901 ldata->decls->safe_push (*tp);
16902 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16903 SET_DECL_VALUE_EXPR (*tp, v);
16906 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16907 return NULL_TREE;
16910 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16911 of omp_member_access_dummy_var vars during regimplification. */
16913 static void
16914 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16915 gimple_stmt_iterator *gsi_p)
16917 auto_vec<tree, 10> decls;
16918 if (ctx)
16920 struct walk_stmt_info wi;
16921 memset (&wi, '\0', sizeof (wi));
16922 struct lower_omp_regimplify_operands_data data;
16923 data.ctx = ctx;
16924 data.decls = &decls;
16925 wi.info = &data;
16926 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16928 gimple_regimplify_operands (stmt, gsi_p);
16929 while (!decls.is_empty ())
16931 tree t = decls.pop ();
16932 tree v = decls.pop ();
16933 SET_DECL_VALUE_EXPR (t, v);
16937 static void
16938 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16940 gimple *stmt = gsi_stmt (*gsi_p);
16941 struct walk_stmt_info wi;
16942 gcall *call_stmt;
16944 if (gimple_has_location (stmt))
16945 input_location = gimple_location (stmt);
16947 if (task_shared_vars)
16948 memset (&wi, '\0', sizeof (wi));
16950 /* If we have issued syntax errors, avoid doing any heavy lifting.
16951 Just replace the OMP directives with a NOP to avoid
16952 confusing RTL expansion. */
16953 if (seen_error () && is_gimple_omp (stmt))
16955 gsi_replace (gsi_p, gimple_build_nop (), true);
16956 return;
16959 switch (gimple_code (stmt))
16961 case GIMPLE_COND:
16963 gcond *cond_stmt = as_a <gcond *> (stmt);
16964 if ((ctx || task_shared_vars)
16965 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16966 lower_omp_regimplify_p,
16967 ctx ? NULL : &wi, NULL)
16968 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16969 lower_omp_regimplify_p,
16970 ctx ? NULL : &wi, NULL)))
16971 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16973 break;
16974 case GIMPLE_CATCH:
16975 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16976 break;
16977 case GIMPLE_EH_FILTER:
16978 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16979 break;
16980 case GIMPLE_TRY:
16981 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16982 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16983 break;
16984 case GIMPLE_TRANSACTION:
16985 lower_omp (gimple_transaction_body_ptr (
16986 as_a <gtransaction *> (stmt)),
16987 ctx);
16988 break;
16989 case GIMPLE_BIND:
16990 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16991 break;
16992 case GIMPLE_OMP_PARALLEL:
16993 case GIMPLE_OMP_TASK:
16994 ctx = maybe_lookup_ctx (stmt);
16995 gcc_assert (ctx);
16996 if (ctx->cancellable)
16997 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16998 lower_omp_taskreg (gsi_p, ctx);
16999 break;
17000 case GIMPLE_OMP_FOR:
17001 ctx = maybe_lookup_ctx (stmt);
17002 gcc_assert (ctx);
17003 if (ctx->cancellable)
17004 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17005 lower_omp_for (gsi_p, ctx);
17006 break;
17007 case GIMPLE_OMP_SECTIONS:
17008 ctx = maybe_lookup_ctx (stmt);
17009 gcc_assert (ctx);
17010 if (ctx->cancellable)
17011 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17012 lower_omp_sections (gsi_p, ctx);
17013 break;
17014 case GIMPLE_OMP_SINGLE:
17015 ctx = maybe_lookup_ctx (stmt);
17016 gcc_assert (ctx);
17017 lower_omp_single (gsi_p, ctx);
17018 break;
17019 case GIMPLE_OMP_MASTER:
17020 ctx = maybe_lookup_ctx (stmt);
17021 gcc_assert (ctx);
17022 lower_omp_master (gsi_p, ctx);
17023 break;
17024 case GIMPLE_OMP_TASKGROUP:
17025 ctx = maybe_lookup_ctx (stmt);
17026 gcc_assert (ctx);
17027 lower_omp_taskgroup (gsi_p, ctx);
17028 break;
17029 case GIMPLE_OMP_ORDERED:
17030 ctx = maybe_lookup_ctx (stmt);
17031 gcc_assert (ctx);
17032 lower_omp_ordered (gsi_p, ctx);
17033 break;
17034 case GIMPLE_OMP_CRITICAL:
17035 ctx = maybe_lookup_ctx (stmt);
17036 gcc_assert (ctx);
17037 lower_omp_critical (gsi_p, ctx);
17038 break;
17039 case GIMPLE_OMP_ATOMIC_LOAD:
17040 if ((ctx || task_shared_vars)
17041 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17042 as_a <gomp_atomic_load *> (stmt)),
17043 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17044 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17045 break;
17046 case GIMPLE_OMP_TARGET:
17047 ctx = maybe_lookup_ctx (stmt);
17048 gcc_assert (ctx);
17049 lower_omp_target (gsi_p, ctx);
17050 break;
17051 case GIMPLE_OMP_TEAMS:
17052 ctx = maybe_lookup_ctx (stmt);
17053 gcc_assert (ctx);
17054 lower_omp_teams (gsi_p, ctx);
17055 break;
17056 case GIMPLE_OMP_GRID_BODY:
17057 ctx = maybe_lookup_ctx (stmt);
17058 gcc_assert (ctx);
17059 lower_omp_grid_body (gsi_p, ctx);
17060 break;
17061 case GIMPLE_CALL:
17062 tree fndecl;
17063 call_stmt = as_a <gcall *> (stmt);
17064 fndecl = gimple_call_fndecl (call_stmt);
17065 if (fndecl
17066 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17067 switch (DECL_FUNCTION_CODE (fndecl))
17069 case BUILT_IN_GOMP_BARRIER:
17070 if (ctx == NULL)
17071 break;
17072 /* FALLTHRU */
17073 case BUILT_IN_GOMP_CANCEL:
17074 case BUILT_IN_GOMP_CANCELLATION_POINT:
17075 omp_context *cctx;
17076 cctx = ctx;
17077 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17078 cctx = cctx->outer;
17079 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17080 if (!cctx->cancellable)
17082 if (DECL_FUNCTION_CODE (fndecl)
17083 == BUILT_IN_GOMP_CANCELLATION_POINT)
17085 stmt = gimple_build_nop ();
17086 gsi_replace (gsi_p, stmt, false);
17088 break;
17090 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17092 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17093 gimple_call_set_fndecl (call_stmt, fndecl);
17094 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17096 tree lhs;
17097 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17098 gimple_call_set_lhs (call_stmt, lhs);
17099 tree fallthru_label;
17100 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17101 gimple *g;
17102 g = gimple_build_label (fallthru_label);
17103 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17104 g = gimple_build_cond (NE_EXPR, lhs,
17105 fold_convert (TREE_TYPE (lhs),
17106 boolean_false_node),
17107 cctx->cancel_label, fallthru_label);
17108 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17109 break;
17110 default:
17111 break;
17113 /* FALLTHRU */
17114 default:
17115 if ((ctx || task_shared_vars)
17116 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17117 ctx ? NULL : &wi))
17119 /* Just remove clobbers, this should happen only if we have
17120 "privatized" local addressable variables in SIMD regions,
17121 the clobber isn't needed in that case and gimplifying address
17122 of the ARRAY_REF into a pointer and creating MEM_REF based
17123 clobber would create worse code than we get with the clobber
17124 dropped. */
17125 if (gimple_clobber_p (stmt))
17127 gsi_replace (gsi_p, gimple_build_nop (), true);
17128 break;
17130 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17132 break;
17136 static void
17137 lower_omp (gimple_seq *body, omp_context *ctx)
17139 location_t saved_location = input_location;
17140 gimple_stmt_iterator gsi;
17141 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17142 lower_omp_1 (&gsi, ctx);
17143 /* During gimplification, we haven't folded statments inside offloading
17144 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17145 if (target_nesting_level || taskreg_nesting_level)
17146 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17147 fold_stmt (&gsi);
17148 input_location = saved_location;
17151 /* Returen true if STMT is an assignment of a register-type into a local
17152 VAR_DECL. */
17154 static bool
17155 grid_reg_assignment_to_local_var_p (gimple *stmt)
17157 gassign *assign = dyn_cast <gassign *> (stmt);
17158 if (!assign)
17159 return false;
17160 tree lhs = gimple_assign_lhs (assign);
17161 if (TREE_CODE (lhs) != VAR_DECL
17162 || !is_gimple_reg_type (TREE_TYPE (lhs))
17163 || is_global_var (lhs))
17164 return false;
17165 return true;
17168 /* Return true if all statements in SEQ are assignments to local register-type
17169 variables. */
17171 static bool
17172 grid_seq_only_contains_local_assignments (gimple_seq seq)
17174 if (!seq)
17175 return true;
17177 gimple_stmt_iterator gsi;
17178 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17179 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17180 return false;
17181 return true;
17184 /* Scan statements in SEQ and call itself recursively on any bind. If during
17185 whole search only assignments to register-type local variables and one
17186 single OMP statement is encountered, return true, otherwise return false.
17187 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17188 are used for dumping a note about a failure. */
17190 static bool
17191 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17192 const char *name, gimple **ret)
17194 gimple_stmt_iterator gsi;
17195 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17197 gimple *stmt = gsi_stmt (gsi);
17199 if (grid_reg_assignment_to_local_var_p (stmt))
17200 continue;
17201 if (gbind *bind = dyn_cast <gbind *> (stmt))
17203 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17204 target_loc, name, ret))
17205 return false;
17207 else if (is_gimple_omp (stmt))
17209 if (*ret)
17211 if (dump_enabled_p ())
17212 dump_printf_loc (MSG_NOTE, target_loc,
17213 "Will not turn target construct into a simple "
17214 "GPGPU kernel because %s construct contains "
17215 "multiple OpenMP constructs\n", name);
17216 return false;
17218 *ret = stmt;
17220 else
17222 if (dump_enabled_p ())
17223 dump_printf_loc (MSG_NOTE, target_loc,
17224 "Will not turn target construct into a simple "
17225 "GPGPU kernel because %s construct contains "
17226 "a complex statement\n", name);
17227 return false;
17230 return true;
17233 /* Scan statements in SEQ and make sure that it and any binds in it contain
17234 only assignments to local register-type variables and one OMP construct. If
17235 so, return that construct, otherwise return NULL. If dumping is enabled and
17236 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17237 failure. */
17239 static gimple *
17240 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17241 const char *name)
17243 if (!seq)
17245 if (dump_enabled_p ())
17246 dump_printf_loc (MSG_NOTE, target_loc,
17247 "Will not turn target construct into a simple "
17248 "GPGPU kernel because %s construct has empty "
17249 "body\n",
17250 name);
17251 return NULL;
17254 gimple *ret = NULL;
17255 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17257 if (!ret && dump_enabled_p ())
17258 dump_printf_loc (MSG_NOTE, target_loc,
17259 "Will not turn target construct into a simple "
17260 "GPGPU kernel because %s construct does not contain"
17261 "any other OpenMP construct\n", name);
17262 return ret;
17264 else
17265 return NULL;
17268 /* Walker function looking for statements there is no point gridifying (and for
17269 noreturn function calls which we cannot do). Return non-NULL if such a
17270 function is found. */
17272 static tree
17273 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17274 bool *handled_ops_p,
17275 struct walk_stmt_info *wi)
17277 *handled_ops_p = false;
17278 gimple *stmt = gsi_stmt (*gsi);
17279 switch (gimple_code (stmt))
17281 case GIMPLE_CALL:
17282 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17284 *handled_ops_p = true;
17285 wi->info = stmt;
17286 return error_mark_node;
17288 break;
17290 /* We may reduce the following list if we find a way to implement the
17291 clauses, but now there is no point trying further. */
17292 case GIMPLE_OMP_CRITICAL:
17293 case GIMPLE_OMP_TASKGROUP:
17294 case GIMPLE_OMP_TASK:
17295 case GIMPLE_OMP_SECTION:
17296 case GIMPLE_OMP_SECTIONS:
17297 case GIMPLE_OMP_SECTIONS_SWITCH:
17298 case GIMPLE_OMP_TARGET:
17299 case GIMPLE_OMP_ORDERED:
17300 *handled_ops_p = true;
17301 wi->info = stmt;
17302 return error_mark_node;
17304 case GIMPLE_OMP_FOR:
17305 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17306 && gimple_omp_for_combined_into_p (stmt))
17308 *handled_ops_p = true;
17309 wi->info = stmt;
17310 return error_mark_node;
17312 break;
17314 default:
17315 break;
17317 return NULL;
17321 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17322 kernel, return true, otherwise return false. In the case of success, also
17323 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17324 none. */
17326 static bool
17327 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17329 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17330 return false;
17332 location_t tloc = gimple_location (target);
17333 gimple *stmt
17334 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17335 tloc, "target");
17336 if (!stmt)
17337 return false;
17338 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17339 tree group_size = NULL;
17340 if (!teams)
17342 dump_printf_loc (MSG_NOTE, tloc,
17343 "Will not turn target construct into a simple "
17344 "GPGPU kernel because it does not have a sole teams "
17345 "construct in it.\n");
17346 return false;
17349 tree clauses = gimple_omp_teams_clauses (teams);
17350 while (clauses)
17352 switch (OMP_CLAUSE_CODE (clauses))
17354 case OMP_CLAUSE_NUM_TEAMS:
17355 if (dump_enabled_p ())
17356 dump_printf_loc (MSG_NOTE, tloc,
17357 "Will not turn target construct into a "
17358 "gridified GPGPU kernel because we cannot "
17359 "handle num_teams clause of teams "
17360 "construct\n ");
17361 return false;
17363 case OMP_CLAUSE_REDUCTION:
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 a reduction "
17368 "clause is present\n ");
17369 return false;
17371 case OMP_CLAUSE_LASTPRIVATE:
17372 if (dump_enabled_p ())
17373 dump_printf_loc (MSG_NOTE, tloc,
17374 "Will not turn target construct into a "
17375 "gridified GPGPU kernel because a lastprivate "
17376 "clause is present\n ");
17377 return false;
17379 case OMP_CLAUSE_THREAD_LIMIT:
17380 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17381 break;
17383 default:
17384 break;
17386 clauses = OMP_CLAUSE_CHAIN (clauses);
17389 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17390 "teams");
17391 if (!stmt)
17392 return false;
17393 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17394 if (!dist)
17396 dump_printf_loc (MSG_NOTE, tloc,
17397 "Will not turn target construct into a simple "
17398 "GPGPU kernel because the teams construct does not have "
17399 "a sole distribute construct in it.\n");
17400 return false;
17403 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17404 if (!gimple_omp_for_combined_p (dist))
17406 if (dump_enabled_p ())
17407 dump_printf_loc (MSG_NOTE, tloc,
17408 "Will not turn target construct into a gridified GPGPU "
17409 "kernel because we cannot handle a standalone "
17410 "distribute construct\n ");
17411 return false;
17413 if (dist->collapse > 1)
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 the distribute construct contains "
17419 "collapse clause\n");
17420 return false;
17422 struct omp_for_data fd;
17423 extract_omp_for_data (dist, &fd, NULL);
17424 if (fd.chunk_size)
17426 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17428 if (dump_enabled_p ())
17429 dump_printf_loc (MSG_NOTE, tloc,
17430 "Will not turn target construct into a "
17431 "gridified GPGPU kernel because the teams "
17432 "thread limit is different from distribute "
17433 "schedule chunk\n");
17434 return false;
17436 group_size = fd.chunk_size;
17438 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17439 "distribute");
17440 gomp_parallel *par;
17441 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17442 return false;
17444 clauses = gimple_omp_parallel_clauses (par);
17445 while (clauses)
17447 switch (OMP_CLAUSE_CODE (clauses))
17449 case OMP_CLAUSE_NUM_THREADS:
17450 if (dump_enabled_p ())
17451 dump_printf_loc (MSG_NOTE, tloc,
17452 "Will not turn target construct into a gridified"
17453 "GPGPU kernel because there is a num_threads "
17454 "clause of the parallel construct\n");
17455 return false;
17457 case OMP_CLAUSE_REDUCTION:
17458 if (dump_enabled_p ())
17459 dump_printf_loc (MSG_NOTE, tloc,
17460 "Will not turn target construct into a "
17461 "gridified GPGPU kernel because a reduction "
17462 "clause is present\n ");
17463 return false;
17465 case OMP_CLAUSE_LASTPRIVATE:
17466 if (dump_enabled_p ())
17467 dump_printf_loc (MSG_NOTE, tloc,
17468 "Will not turn target construct into a "
17469 "gridified GPGPU kernel because a lastprivate "
17470 "clause is present\n ");
17471 return false;
17473 default:
17474 break;
17476 clauses = OMP_CLAUSE_CHAIN (clauses);
17479 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17480 "parallel");
17481 gomp_for *gfor;
17482 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17483 return false;
17485 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17487 if (dump_enabled_p ())
17488 dump_printf_loc (MSG_NOTE, tloc,
17489 "Will not turn target construct into a gridified GPGPU "
17490 "kernel because the inner loop is not a simple for "
17491 "loop\n");
17492 return false;
17494 if (gfor->collapse > 1)
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 contains collapse "
17500 "clause\n");
17501 return false;
17504 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17506 if (dump_enabled_p ())
17507 dump_printf_loc (MSG_NOTE, tloc,
17508 "Will not turn target construct into a gridified GPGPU "
17509 "kernel because the inner loop pre_body contains"
17510 "a complex instruction\n");
17511 return false;
17514 clauses = gimple_omp_for_clauses (gfor);
17515 while (clauses)
17517 switch (OMP_CLAUSE_CODE (clauses))
17519 case OMP_CLAUSE_SCHEDULE:
17520 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17522 if (dump_enabled_p ())
17523 dump_printf_loc (MSG_NOTE, tloc,
17524 "Will not turn target construct into a "
17525 "gridified GPGPU kernel because the inner "
17526 "loop has a non-automatic scheduling clause\n");
17527 return false;
17529 break;
17531 case OMP_CLAUSE_REDUCTION:
17532 if (dump_enabled_p ())
17533 dump_printf_loc (MSG_NOTE, tloc,
17534 "Will not turn target construct into a "
17535 "gridified GPGPU kernel because a reduction "
17536 "clause is present\n ");
17537 return false;
17539 case OMP_CLAUSE_LASTPRIVATE:
17540 if (dump_enabled_p ())
17541 dump_printf_loc (MSG_NOTE, tloc,
17542 "Will not turn target construct into a "
17543 "gridified GPGPU kernel because a lastprivate "
17544 "clause is present\n ");
17545 return false;
17547 default:
17548 break;
17550 clauses = OMP_CLAUSE_CHAIN (clauses);
17553 struct walk_stmt_info wi;
17554 memset (&wi, 0, sizeof (wi));
17555 if (walk_gimple_seq (gimple_omp_body (gfor),
17556 grid_find_ungridifiable_statement,
17557 NULL, &wi))
17559 gimple *bad = (gimple *) wi.info;
17560 if (dump_enabled_p ())
17562 if (is_gimple_call (bad))
17563 dump_printf_loc (MSG_NOTE, tloc,
17564 "Will not turn target construct into a gridified "
17565 " GPGPU kernel because the inner loop contains "
17566 "call to a noreturn function\n");
17567 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17568 dump_printf_loc (MSG_NOTE, tloc,
17569 "Will not turn target construct into a gridified "
17570 " GPGPU kernel because the inner loop contains "
17571 "a simd construct\n");
17572 else
17573 dump_printf_loc (MSG_NOTE, tloc,
17574 "Will not turn target construct into a gridified "
17575 "GPGPU kernel because the inner loop contains "
17576 "statement %s which cannot be transformed\n",
17577 gimple_code_name[(int) gimple_code (bad)]);
17579 return false;
17582 *group_size_p = group_size;
17583 return true;
17586 /* Operand walker, used to remap pre-body declarations according to a hash map
17587 provided in DATA. */
17589 static tree
17590 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17592 tree t = *tp;
17594 if (DECL_P (t) || TYPE_P (t))
17595 *walk_subtrees = 0;
17596 else
17597 *walk_subtrees = 1;
17599 if (TREE_CODE (t) == VAR_DECL)
17601 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17602 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17603 tree *repl = declmap->get (t);
17604 if (repl)
17605 *tp = *repl;
17607 return NULL_TREE;
17610 /* Copy leading register-type assignments to local variables in SRC to just
17611 before DST, Creating temporaries, adjusting mapping of operands in WI and
17612 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17613 Return the first statement that does not conform to
17614 grid_reg_assignment_to_local_var_p or NULL. */
17616 static gimple *
17617 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17618 gbind *tgt_bind, struct walk_stmt_info *wi)
17620 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17621 gimple_stmt_iterator gsi;
17622 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17624 gimple *stmt = gsi_stmt (gsi);
17625 if (gbind *bind = dyn_cast <gbind *> (stmt))
17627 gimple *r = grid_copy_leading_local_assignments
17628 (gimple_bind_body (bind), dst, tgt_bind, wi);
17629 if (r)
17630 return r;
17631 else
17632 continue;
17634 if (!grid_reg_assignment_to_local_var_p (stmt))
17635 return stmt;
17636 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17637 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17638 TREE_TYPE (lhs));
17639 DECL_CONTEXT (repl) = current_function_decl;
17640 gimple_bind_append_vars (tgt_bind, repl);
17642 declmap->put (lhs, repl);
17643 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17644 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17645 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17647 return NULL;
17650 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17651 components, mark them as part of kernel and return the inner loop, and copy
17652 assignment leading to them just before DST, remapping them using WI and
17653 adding new temporaries to TGT_BIND. */
17655 static gomp_for *
17656 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17657 gbind *tgt_bind, struct walk_stmt_info *wi)
17659 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17660 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17661 gcc_assert (teams);
17662 gimple_omp_teams_set_grid_phony (teams, true);
17663 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17664 tgt_bind, wi);
17665 gcc_checking_assert (stmt);
17666 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17667 gcc_assert (dist);
17668 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17669 if (prebody)
17670 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17671 gimple_omp_for_set_grid_phony (dist, true);
17672 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17673 tgt_bind, wi);
17674 gcc_checking_assert (stmt);
17676 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17677 gimple_omp_parallel_set_grid_phony (parallel, true);
17678 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17679 tgt_bind, wi);
17680 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17681 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17682 prebody = gimple_omp_for_pre_body (inner_loop);
17683 if (prebody)
17684 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17686 return inner_loop;
17689 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17690 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17691 is the bind into which temporaries inserted before TARGET should be
17692 added. */
17694 static void
17695 grid_attempt_target_gridification (gomp_target *target,
17696 gimple_stmt_iterator *gsi,
17697 gbind *tgt_bind)
17699 tree group_size;
17700 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17701 return;
17703 location_t loc = gimple_location (target);
17704 if (dump_enabled_p ())
17705 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17706 "Target construct will be turned into a gridified GPGPU "
17707 "kernel\n");
17709 /* Copy target body to a GPUKERNEL construct: */
17710 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17711 (gimple_omp_body (target));
17713 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17714 struct walk_stmt_info wi;
17715 memset (&wi, 0, sizeof (struct walk_stmt_info));
17716 wi.info = declmap;
17718 /* Copy assignments in between OMP statements before target, mark OMP
17719 statements within copy appropriatly. */
17720 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17721 tgt_bind, &wi);
17723 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17724 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17725 tree new_block = gimple_bind_block (new_bind);
17726 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17727 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17728 BLOCK_SUBBLOCKS (enc_block) = new_block;
17729 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17730 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17731 gimple_seq_add_stmt
17732 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17733 gpukernel);
17735 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17736 push_gimplify_context ();
17737 size_t collapse = gimple_omp_for_collapse (inner_loop);
17738 for (size_t i = 0; i < collapse; i++)
17740 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17741 if (POINTER_TYPE_P (type))
17742 itype = signed_type_for (type);
17743 else
17744 itype = type;
17746 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17747 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17748 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17749 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17750 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17751 adjust_for_condition (loc, &cond_code, &n2);
17752 tree step;
17753 step = get_omp_for_step_from_incr (loc,
17754 gimple_omp_for_incr (inner_loop, i));
17755 gimple_seq tmpseq = NULL;
17756 n1 = fold_convert (itype, n1);
17757 n2 = fold_convert (itype, n2);
17758 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17759 t = fold_build2 (PLUS_EXPR, itype, step, t);
17760 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17761 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17762 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17763 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17764 fold_build1 (NEGATE_EXPR, itype, t),
17765 fold_build1 (NEGATE_EXPR, itype, step));
17766 else
17767 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17768 tree gs = fold_convert (uint32_type_node, t);
17769 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17770 if (!gimple_seq_empty_p (tmpseq))
17771 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17773 tree ws;
17774 if (i == 0 && group_size)
17776 ws = fold_convert (uint32_type_node, group_size);
17777 tmpseq = NULL;
17778 gimplify_expr (&ws, &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 else
17783 ws = build_zero_cst (uint32_type_node);
17785 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17786 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17787 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17788 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17789 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17790 gimple_omp_target_set_clauses (target, c);
17792 pop_gimplify_context (tgt_bind);
17793 delete declmap;
17794 return;
17797 /* Walker function doing all the work for create_target_kernels. */
17799 static tree
17800 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17801 bool *handled_ops_p,
17802 struct walk_stmt_info *incoming)
17804 *handled_ops_p = false;
17806 gimple *stmt = gsi_stmt (*gsi);
17807 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17808 if (target)
17810 gbind *tgt_bind = (gbind *) incoming->info;
17811 gcc_checking_assert (tgt_bind);
17812 grid_attempt_target_gridification (target, gsi, tgt_bind);
17813 return NULL_TREE;
17815 gbind *bind = dyn_cast <gbind *> (stmt);
17816 if (bind)
17818 *handled_ops_p = true;
17819 struct walk_stmt_info wi;
17820 memset (&wi, 0, sizeof (wi));
17821 wi.info = bind;
17822 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17823 grid_gridify_all_targets_stmt, NULL, &wi);
17825 return NULL_TREE;
17828 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17829 have their bodies duplicated, with the new copy being put into a
17830 gimple_omp_grid_body statement. All kernel-related construct within the
17831 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17832 re-structuring is often needed, such as copying pre-bodies before the target
17833 construct so that kernel grid sizes can be computed. */
17835 static void
17836 grid_gridify_all_targets (gimple_seq *body_p)
17838 struct walk_stmt_info wi;
17839 memset (&wi, 0, sizeof (wi));
17840 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17844 /* Main entry point. */
17846 static unsigned int
17847 execute_lower_omp (void)
17849 gimple_seq body;
17850 int i;
17851 omp_context *ctx;
17853 /* This pass always runs, to provide PROP_gimple_lomp.
17854 But often, there is nothing to do. */
17855 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17856 && flag_openmp_simd == 0)
17857 return 0;
17859 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17860 delete_omp_context);
17862 body = gimple_body (current_function_decl);
17864 if (hsa_gen_requested_p ())
17865 grid_gridify_all_targets (&body);
17867 scan_omp (&body, NULL);
17868 gcc_assert (taskreg_nesting_level == 0);
17869 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17870 finish_taskreg_scan (ctx);
17871 taskreg_contexts.release ();
17873 if (all_contexts->root)
17875 if (task_shared_vars)
17876 push_gimplify_context ();
17877 lower_omp (&body, NULL);
17878 if (task_shared_vars)
17879 pop_gimplify_context (NULL);
17882 if (all_contexts)
17884 splay_tree_delete (all_contexts);
17885 all_contexts = NULL;
17887 BITMAP_FREE (task_shared_vars);
17888 return 0;
17891 namespace {
17893 const pass_data pass_data_lower_omp =
17895 GIMPLE_PASS, /* type */
17896 "omplower", /* name */
17897 OPTGROUP_NONE, /* optinfo_flags */
17898 TV_NONE, /* tv_id */
17899 PROP_gimple_any, /* properties_required */
17900 PROP_gimple_lomp, /* properties_provided */
17901 0, /* properties_destroyed */
17902 0, /* todo_flags_start */
17903 0, /* todo_flags_finish */
17906 class pass_lower_omp : public gimple_opt_pass
17908 public:
17909 pass_lower_omp (gcc::context *ctxt)
17910 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17913 /* opt_pass methods: */
17914 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17916 }; // class pass_lower_omp
17918 } // anon namespace
17920 gimple_opt_pass *
17921 make_pass_lower_omp (gcc::context *ctxt)
17923 return new pass_lower_omp (ctxt);
17926 /* The following is a utility to diagnose structured block violations.
17927 It is not part of the "omplower" pass, as that's invoked too late. It
17928 should be invoked by the respective front ends after gimplification. */
17930 static splay_tree all_labels;
17932 /* Check for mismatched contexts and generate an error if needed. Return
17933 true if an error is detected. */
17935 static bool
17936 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17937 gimple *branch_ctx, gimple *label_ctx)
17939 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17940 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17942 if (label_ctx == branch_ctx)
17943 return false;
17945 const char* kind = NULL;
17947 if (flag_cilkplus)
17949 if ((branch_ctx
17950 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17951 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17952 || (label_ctx
17953 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17954 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17955 kind = "Cilk Plus";
17957 if (flag_openacc)
17959 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17960 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17962 gcc_checking_assert (kind == NULL);
17963 kind = "OpenACC";
17966 if (kind == NULL)
17968 gcc_checking_assert (flag_openmp);
17969 kind = "OpenMP";
17973 Previously we kept track of the label's entire context in diagnose_sb_[12]
17974 so we could traverse it and issue a correct "exit" or "enter" error
17975 message upon a structured block violation.
17977 We built the context by building a list with tree_cons'ing, but there is
17978 no easy counterpart in gimple tuples. It seems like far too much work
17979 for issuing exit/enter error messages. If someone really misses the
17980 distinct error message... patches welcome.
17983 #if 0
17984 /* Try to avoid confusing the user by producing and error message
17985 with correct "exit" or "enter" verbiage. We prefer "exit"
17986 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17987 if (branch_ctx == NULL)
17988 exit_p = false;
17989 else
17991 while (label_ctx)
17993 if (TREE_VALUE (label_ctx) == branch_ctx)
17995 exit_p = false;
17996 break;
17998 label_ctx = TREE_CHAIN (label_ctx);
18002 if (exit_p)
18003 error ("invalid exit from %s structured block", kind);
18004 else
18005 error ("invalid entry to %s structured block", kind);
18006 #endif
18008 /* If it's obvious we have an invalid entry, be specific about the error. */
18009 if (branch_ctx == NULL)
18010 error ("invalid entry to %s structured block", kind);
18011 else
18013 /* Otherwise, be vague and lazy, but efficient. */
18014 error ("invalid branch to/from %s structured block", kind);
18017 gsi_replace (gsi_p, gimple_build_nop (), false);
18018 return true;
18021 /* Pass 1: Create a minimal tree of structured blocks, and record
18022 where each label is found. */
18024 static tree
18025 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18026 struct walk_stmt_info *wi)
18028 gimple *context = (gimple *) wi->info;
18029 gimple *inner_context;
18030 gimple *stmt = gsi_stmt (*gsi_p);
18032 *handled_ops_p = true;
18034 switch (gimple_code (stmt))
18036 WALK_SUBSTMTS;
18038 case GIMPLE_OMP_PARALLEL:
18039 case GIMPLE_OMP_TASK:
18040 case GIMPLE_OMP_SECTIONS:
18041 case GIMPLE_OMP_SINGLE:
18042 case GIMPLE_OMP_SECTION:
18043 case GIMPLE_OMP_MASTER:
18044 case GIMPLE_OMP_ORDERED:
18045 case GIMPLE_OMP_CRITICAL:
18046 case GIMPLE_OMP_TARGET:
18047 case GIMPLE_OMP_TEAMS:
18048 case GIMPLE_OMP_TASKGROUP:
18049 /* The minimal context here is just the current OMP construct. */
18050 inner_context = stmt;
18051 wi->info = inner_context;
18052 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18053 wi->info = context;
18054 break;
18056 case GIMPLE_OMP_FOR:
18057 inner_context = stmt;
18058 wi->info = inner_context;
18059 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18060 walk them. */
18061 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18062 diagnose_sb_1, NULL, wi);
18063 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18064 wi->info = context;
18065 break;
18067 case GIMPLE_LABEL:
18068 splay_tree_insert (all_labels,
18069 (splay_tree_key) gimple_label_label (
18070 as_a <glabel *> (stmt)),
18071 (splay_tree_value) context);
18072 break;
18074 default:
18075 break;
18078 return NULL_TREE;
18081 /* Pass 2: Check each branch and see if its context differs from that of
18082 the destination label's context. */
18084 static tree
18085 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18086 struct walk_stmt_info *wi)
18088 gimple *context = (gimple *) wi->info;
18089 splay_tree_node n;
18090 gimple *stmt = gsi_stmt (*gsi_p);
18092 *handled_ops_p = true;
18094 switch (gimple_code (stmt))
18096 WALK_SUBSTMTS;
18098 case GIMPLE_OMP_PARALLEL:
18099 case GIMPLE_OMP_TASK:
18100 case GIMPLE_OMP_SECTIONS:
18101 case GIMPLE_OMP_SINGLE:
18102 case GIMPLE_OMP_SECTION:
18103 case GIMPLE_OMP_MASTER:
18104 case GIMPLE_OMP_ORDERED:
18105 case GIMPLE_OMP_CRITICAL:
18106 case GIMPLE_OMP_TARGET:
18107 case GIMPLE_OMP_TEAMS:
18108 case GIMPLE_OMP_TASKGROUP:
18109 wi->info = stmt;
18110 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18111 wi->info = context;
18112 break;
18114 case GIMPLE_OMP_FOR:
18115 wi->info = stmt;
18116 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18117 walk them. */
18118 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18119 diagnose_sb_2, NULL, wi);
18120 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18121 wi->info = context;
18122 break;
18124 case GIMPLE_COND:
18126 gcond *cond_stmt = as_a <gcond *> (stmt);
18127 tree lab = gimple_cond_true_label (cond_stmt);
18128 if (lab)
18130 n = splay_tree_lookup (all_labels,
18131 (splay_tree_key) lab);
18132 diagnose_sb_0 (gsi_p, context,
18133 n ? (gimple *) n->value : NULL);
18135 lab = gimple_cond_false_label (cond_stmt);
18136 if (lab)
18138 n = splay_tree_lookup (all_labels,
18139 (splay_tree_key) lab);
18140 diagnose_sb_0 (gsi_p, context,
18141 n ? (gimple *) n->value : NULL);
18144 break;
18146 case GIMPLE_GOTO:
18148 tree lab = gimple_goto_dest (stmt);
18149 if (TREE_CODE (lab) != LABEL_DECL)
18150 break;
18152 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18153 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18155 break;
18157 case GIMPLE_SWITCH:
18159 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18160 unsigned int i;
18161 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18163 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18164 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18165 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18166 break;
18169 break;
18171 case GIMPLE_RETURN:
18172 diagnose_sb_0 (gsi_p, context, NULL);
18173 break;
18175 default:
18176 break;
18179 return NULL_TREE;
18182 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18183 GIMPLE_* codes. */
18184 bool
18185 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18186 int *region_idx)
18188 gimple *last = last_stmt (bb);
18189 enum gimple_code code = gimple_code (last);
18190 struct omp_region *cur_region = *region;
18191 bool fallthru = false;
18193 switch (code)
18195 case GIMPLE_OMP_PARALLEL:
18196 case GIMPLE_OMP_TASK:
18197 case GIMPLE_OMP_FOR:
18198 case GIMPLE_OMP_SINGLE:
18199 case GIMPLE_OMP_TEAMS:
18200 case GIMPLE_OMP_MASTER:
18201 case GIMPLE_OMP_TASKGROUP:
18202 case GIMPLE_OMP_CRITICAL:
18203 case GIMPLE_OMP_SECTION:
18204 case GIMPLE_OMP_GRID_BODY:
18205 cur_region = new_omp_region (bb, code, cur_region);
18206 fallthru = true;
18207 break;
18209 case GIMPLE_OMP_ORDERED:
18210 cur_region = new_omp_region (bb, code, cur_region);
18211 fallthru = true;
18212 if (find_omp_clause (gimple_omp_ordered_clauses
18213 (as_a <gomp_ordered *> (last)),
18214 OMP_CLAUSE_DEPEND))
18215 cur_region = cur_region->outer;
18216 break;
18218 case GIMPLE_OMP_TARGET:
18219 cur_region = new_omp_region (bb, code, cur_region);
18220 fallthru = true;
18221 switch (gimple_omp_target_kind (last))
18223 case GF_OMP_TARGET_KIND_REGION:
18224 case GF_OMP_TARGET_KIND_DATA:
18225 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18226 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18227 case GF_OMP_TARGET_KIND_OACC_DATA:
18228 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18229 break;
18230 case GF_OMP_TARGET_KIND_UPDATE:
18231 case GF_OMP_TARGET_KIND_ENTER_DATA:
18232 case GF_OMP_TARGET_KIND_EXIT_DATA:
18233 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18234 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18235 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18236 cur_region = cur_region->outer;
18237 break;
18238 default:
18239 gcc_unreachable ();
18241 break;
18243 case GIMPLE_OMP_SECTIONS:
18244 cur_region = new_omp_region (bb, code, cur_region);
18245 fallthru = true;
18246 break;
18248 case GIMPLE_OMP_SECTIONS_SWITCH:
18249 fallthru = false;
18250 break;
18252 case GIMPLE_OMP_ATOMIC_LOAD:
18253 case GIMPLE_OMP_ATOMIC_STORE:
18254 fallthru = true;
18255 break;
18257 case GIMPLE_OMP_RETURN:
18258 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18259 somewhere other than the next block. This will be
18260 created later. */
18261 cur_region->exit = bb;
18262 if (cur_region->type == GIMPLE_OMP_TASK)
18263 /* Add an edge corresponding to not scheduling the task
18264 immediately. */
18265 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18266 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18267 cur_region = cur_region->outer;
18268 break;
18270 case GIMPLE_OMP_CONTINUE:
18271 cur_region->cont = bb;
18272 switch (cur_region->type)
18274 case GIMPLE_OMP_FOR:
18275 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18276 succs edges as abnormal to prevent splitting
18277 them. */
18278 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18279 /* Make the loopback edge. */
18280 make_edge (bb, single_succ (cur_region->entry),
18281 EDGE_ABNORMAL);
18283 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18284 corresponds to the case that the body of the loop
18285 is not executed at all. */
18286 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18287 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18288 fallthru = false;
18289 break;
18291 case GIMPLE_OMP_SECTIONS:
18292 /* Wire up the edges into and out of the nested sections. */
18294 basic_block switch_bb = single_succ (cur_region->entry);
18296 struct omp_region *i;
18297 for (i = cur_region->inner; i ; i = i->next)
18299 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18300 make_edge (switch_bb, i->entry, 0);
18301 make_edge (i->exit, bb, EDGE_FALLTHRU);
18304 /* Make the loopback edge to the block with
18305 GIMPLE_OMP_SECTIONS_SWITCH. */
18306 make_edge (bb, switch_bb, 0);
18308 /* Make the edge from the switch to exit. */
18309 make_edge (switch_bb, bb->next_bb, 0);
18310 fallthru = false;
18312 break;
18314 case GIMPLE_OMP_TASK:
18315 fallthru = true;
18316 break;
18318 default:
18319 gcc_unreachable ();
18321 break;
18323 default:
18324 gcc_unreachable ();
18327 if (*region != cur_region)
18329 *region = cur_region;
18330 if (cur_region)
18331 *region_idx = cur_region->entry->index;
18332 else
18333 *region_idx = 0;
18336 return fallthru;
18339 static unsigned int
18340 diagnose_omp_structured_block_errors (void)
18342 struct walk_stmt_info wi;
18343 gimple_seq body = gimple_body (current_function_decl);
18345 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18347 memset (&wi, 0, sizeof (wi));
18348 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18350 memset (&wi, 0, sizeof (wi));
18351 wi.want_locations = true;
18352 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18354 gimple_set_body (current_function_decl, body);
18356 splay_tree_delete (all_labels);
18357 all_labels = NULL;
18359 return 0;
18362 namespace {
18364 const pass_data pass_data_diagnose_omp_blocks =
18366 GIMPLE_PASS, /* type */
18367 "*diagnose_omp_blocks", /* name */
18368 OPTGROUP_NONE, /* optinfo_flags */
18369 TV_NONE, /* tv_id */
18370 PROP_gimple_any, /* properties_required */
18371 0, /* properties_provided */
18372 0, /* properties_destroyed */
18373 0, /* todo_flags_start */
18374 0, /* todo_flags_finish */
18377 class pass_diagnose_omp_blocks : public gimple_opt_pass
18379 public:
18380 pass_diagnose_omp_blocks (gcc::context *ctxt)
18381 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18384 /* opt_pass methods: */
18385 virtual bool gate (function *)
18387 return flag_cilkplus || flag_openacc || flag_openmp;
18389 virtual unsigned int execute (function *)
18391 return diagnose_omp_structured_block_errors ();
18394 }; // class pass_diagnose_omp_blocks
18396 } // anon namespace
18398 gimple_opt_pass *
18399 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18401 return new pass_diagnose_omp_blocks (ctxt);
18404 /* SIMD clone supporting code. */
18406 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
18407 of arguments to reserve space for. */
18409 static struct cgraph_simd_clone *
18410 simd_clone_struct_alloc (int nargs)
18412 struct cgraph_simd_clone *clone_info;
18413 size_t len = (sizeof (struct cgraph_simd_clone)
18414 + nargs * sizeof (struct cgraph_simd_clone_arg));
18415 clone_info = (struct cgraph_simd_clone *)
18416 ggc_internal_cleared_alloc (len);
18417 return clone_info;
18420 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
18422 static inline void
18423 simd_clone_struct_copy (struct cgraph_simd_clone *to,
18424 struct cgraph_simd_clone *from)
18426 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
18427 + ((from->nargs - from->inbranch)
18428 * sizeof (struct cgraph_simd_clone_arg))));
18431 /* Return vector of parameter types of function FNDECL. This uses
18432 TYPE_ARG_TYPES if available, otherwise falls back to types of
18433 DECL_ARGUMENTS types. */
18435 vec<tree>
18436 simd_clone_vector_of_formal_parm_types (tree fndecl)
18438 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
18439 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
18440 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
18441 unsigned int i;
18442 tree arg;
18443 FOR_EACH_VEC_ELT (args, i, arg)
18444 args[i] = TREE_TYPE (args[i]);
18445 return args;
18448 /* Given a simd function in NODE, extract the simd specific
18449 information from the OMP clauses passed in CLAUSES, and return
18450 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
18451 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
18452 otherwise set to FALSE. */
18454 static struct cgraph_simd_clone *
18455 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
18456 bool *inbranch_specified)
18458 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
18459 tree t;
18460 int n;
18461 *inbranch_specified = false;
18463 n = args.length ();
18464 if (n > 0 && args.last () == void_type_node)
18465 n--;
18467 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
18468 be cloned have a distinctive artificial label in addition to "omp
18469 declare simd". */
18470 bool cilk_clone
18471 = (flag_cilkplus
18472 && lookup_attribute ("cilk simd function",
18473 DECL_ATTRIBUTES (node->decl)));
18475 /* Allocate one more than needed just in case this is an in-branch
18476 clone which will require a mask argument. */
18477 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
18478 clone_info->nargs = n;
18479 clone_info->cilk_elemental = cilk_clone;
18481 if (!clauses)
18483 args.release ();
18484 return clone_info;
18486 clauses = TREE_VALUE (clauses);
18487 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
18488 return clone_info;
18490 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
18492 switch (OMP_CLAUSE_CODE (t))
18494 case OMP_CLAUSE_INBRANCH:
18495 clone_info->inbranch = 1;
18496 *inbranch_specified = true;
18497 break;
18498 case OMP_CLAUSE_NOTINBRANCH:
18499 clone_info->inbranch = 0;
18500 *inbranch_specified = true;
18501 break;
18502 case OMP_CLAUSE_SIMDLEN:
18503 clone_info->simdlen
18504 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
18505 break;
18506 case OMP_CLAUSE_LINEAR:
18508 tree decl = OMP_CLAUSE_DECL (t);
18509 tree step = OMP_CLAUSE_LINEAR_STEP (t);
18510 int argno = TREE_INT_CST_LOW (decl);
18511 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
18513 enum cgraph_simd_clone_arg_type arg_type;
18514 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18515 switch (OMP_CLAUSE_LINEAR_KIND (t))
18517 case OMP_CLAUSE_LINEAR_REF:
18518 arg_type
18519 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
18520 break;
18521 case OMP_CLAUSE_LINEAR_UVAL:
18522 arg_type
18523 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
18524 break;
18525 case OMP_CLAUSE_LINEAR_VAL:
18526 case OMP_CLAUSE_LINEAR_DEFAULT:
18527 arg_type
18528 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
18529 break;
18530 default:
18531 gcc_unreachable ();
18533 else
18534 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
18535 clone_info->args[argno].arg_type = arg_type;
18536 clone_info->args[argno].linear_step = tree_to_shwi (step);
18537 gcc_assert (clone_info->args[argno].linear_step >= 0
18538 && clone_info->args[argno].linear_step < n);
18540 else
18542 if (POINTER_TYPE_P (args[argno]))
18543 step = fold_convert (ssizetype, step);
18544 if (!tree_fits_shwi_p (step))
18546 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18547 "ignoring large linear step");
18548 args.release ();
18549 return NULL;
18551 else if (integer_zerop (step))
18553 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18554 "ignoring zero linear step");
18555 args.release ();
18556 return NULL;
18558 else
18560 enum cgraph_simd_clone_arg_type arg_type;
18561 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18562 switch (OMP_CLAUSE_LINEAR_KIND (t))
18564 case OMP_CLAUSE_LINEAR_REF:
18565 arg_type
18566 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
18567 break;
18568 case OMP_CLAUSE_LINEAR_UVAL:
18569 arg_type
18570 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
18571 break;
18572 case OMP_CLAUSE_LINEAR_VAL:
18573 case OMP_CLAUSE_LINEAR_DEFAULT:
18574 arg_type
18575 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
18576 break;
18577 default:
18578 gcc_unreachable ();
18580 else
18581 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
18582 clone_info->args[argno].arg_type = arg_type;
18583 clone_info->args[argno].linear_step = tree_to_shwi (step);
18586 break;
18588 case OMP_CLAUSE_UNIFORM:
18590 tree decl = OMP_CLAUSE_DECL (t);
18591 int argno = tree_to_uhwi (decl);
18592 clone_info->args[argno].arg_type
18593 = SIMD_CLONE_ARG_TYPE_UNIFORM;
18594 break;
18596 case OMP_CLAUSE_ALIGNED:
18598 tree decl = OMP_CLAUSE_DECL (t);
18599 int argno = tree_to_uhwi (decl);
18600 clone_info->args[argno].alignment
18601 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
18602 break;
18604 default:
18605 break;
18608 args.release ();
18609 return clone_info;
18612 /* Given a SIMD clone in NODE, calculate the characteristic data
18613 type and return the coresponding type. The characteristic data
18614 type is computed as described in the Intel Vector ABI. */
18616 static tree
18617 simd_clone_compute_base_data_type (struct cgraph_node *node,
18618 struct cgraph_simd_clone *clone_info)
18620 tree type = integer_type_node;
18621 tree fndecl = node->decl;
18623 /* a) For non-void function, the characteristic data type is the
18624 return type. */
18625 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
18626 type = TREE_TYPE (TREE_TYPE (fndecl));
18628 /* b) If the function has any non-uniform, non-linear parameters,
18629 then the characteristic data type is the type of the first
18630 such parameter. */
18631 else
18633 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
18634 for (unsigned int i = 0; i < clone_info->nargs; ++i)
18635 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
18637 type = map[i];
18638 break;
18640 map.release ();
18643 /* c) If the characteristic data type determined by a) or b) above
18644 is struct, union, or class type which is pass-by-value (except
18645 for the type that maps to the built-in complex data type), the
18646 characteristic data type is int. */
18647 if (RECORD_OR_UNION_TYPE_P (type)
18648 && !aggregate_value_p (type, NULL)
18649 && TREE_CODE (type) != COMPLEX_TYPE)
18650 return integer_type_node;
18652 /* d) If none of the above three classes is applicable, the
18653 characteristic data type is int. */
18655 return type;
18657 /* e) For Intel Xeon Phi native and offload compilation, if the
18658 resulting characteristic data type is 8-bit or 16-bit integer
18659 data type, the characteristic data type is int. */
18660 /* Well, we don't handle Xeon Phi yet. */
18663 static tree
18664 simd_clone_mangle (struct cgraph_node *node,
18665 struct cgraph_simd_clone *clone_info)
18667 char vecsize_mangle = clone_info->vecsize_mangle;
18668 char mask = clone_info->inbranch ? 'M' : 'N';
18669 unsigned int simdlen = clone_info->simdlen;
18670 unsigned int n;
18671 pretty_printer pp;
18673 gcc_assert (vecsize_mangle && simdlen);
18675 pp_string (&pp, "_ZGV");
18676 pp_character (&pp, vecsize_mangle);
18677 pp_character (&pp, mask);
18678 pp_decimal_int (&pp, simdlen);
18680 for (n = 0; n < clone_info->nargs; ++n)
18682 struct cgraph_simd_clone_arg arg = clone_info->args[n];
18684 switch (arg.arg_type)
18686 case SIMD_CLONE_ARG_TYPE_UNIFORM:
18687 pp_character (&pp, 'u');
18688 break;
18689 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
18690 pp_character (&pp, 'l');
18691 goto mangle_linear;
18692 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
18693 pp_character (&pp, 'R');
18694 goto mangle_linear;
18695 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
18696 pp_character (&pp, 'L');
18697 goto mangle_linear;
18698 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
18699 pp_character (&pp, 'U');
18700 goto mangle_linear;
18701 mangle_linear:
18702 gcc_assert (arg.linear_step != 0);
18703 if (arg.linear_step > 1)
18704 pp_unsigned_wide_integer (&pp, arg.linear_step);
18705 else if (arg.linear_step < 0)
18707 pp_character (&pp, 'n');
18708 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
18709 arg.linear_step));
18711 break;
18712 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
18713 pp_string (&pp, "ls");
18714 pp_unsigned_wide_integer (&pp, arg.linear_step);
18715 break;
18716 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
18717 pp_string (&pp, "Rs");
18718 pp_unsigned_wide_integer (&pp, arg.linear_step);
18719 break;
18720 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
18721 pp_string (&pp, "Ls");
18722 pp_unsigned_wide_integer (&pp, arg.linear_step);
18723 break;
18724 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
18725 pp_string (&pp, "Us");
18726 pp_unsigned_wide_integer (&pp, arg.linear_step);
18727 break;
18728 default:
18729 pp_character (&pp, 'v');
18731 if (arg.alignment)
18733 pp_character (&pp, 'a');
18734 pp_decimal_int (&pp, arg.alignment);
18738 pp_underscore (&pp);
18739 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
18740 if (*str == '*')
18741 ++str;
18742 pp_string (&pp, str);
18743 str = pp_formatted_text (&pp);
18745 /* If there already is a SIMD clone with the same mangled name, don't
18746 add another one. This can happen e.g. for
18747 #pragma omp declare simd
18748 #pragma omp declare simd simdlen(8)
18749 int foo (int, int);
18750 if the simdlen is assumed to be 8 for the first one, etc. */
18751 for (struct cgraph_node *clone = node->simd_clones; clone;
18752 clone = clone->simdclone->next_clone)
18753 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
18754 str) == 0)
18755 return NULL_TREE;
18757 return get_identifier (str);
18760 /* Create a simd clone of OLD_NODE and return it. */
18762 static struct cgraph_node *
18763 simd_clone_create (struct cgraph_node *old_node)
18765 struct cgraph_node *new_node;
18766 if (old_node->definition)
18768 if (!old_node->has_gimple_body_p ())
18769 return NULL;
18770 old_node->get_body ();
18771 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
18772 false, NULL, NULL,
18773 "simdclone");
18775 else
18777 tree old_decl = old_node->decl;
18778 tree new_decl = copy_node (old_node->decl);
18779 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
18780 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
18781 SET_DECL_RTL (new_decl, NULL);
18782 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
18783 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
18784 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
18785 if (old_node->in_other_partition)
18786 new_node->in_other_partition = 1;
18788 if (new_node == NULL)
18789 return new_node;
18791 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
18793 /* The function cgraph_function_versioning () will force the new
18794 symbol local. Undo this, and inherit external visability from
18795 the old node. */
18796 new_node->local.local = old_node->local.local;
18797 new_node->externally_visible = old_node->externally_visible;
18799 return new_node;
18802 /* Adjust the return type of the given function to its appropriate
18803 vector counterpart. Returns a simd array to be used throughout the
18804 function as a return value. */
18806 static tree
18807 simd_clone_adjust_return_type (struct cgraph_node *node)
18809 tree fndecl = node->decl;
18810 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
18811 unsigned int veclen;
18812 tree t;
18814 /* Adjust the function return type. */
18815 if (orig_rettype == void_type_node)
18816 return NULL_TREE;
18817 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
18818 t = TREE_TYPE (TREE_TYPE (fndecl));
18819 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
18820 veclen = node->simdclone->vecsize_int;
18821 else
18822 veclen = node->simdclone->vecsize_float;
18823 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
18824 if (veclen > node->simdclone->simdlen)
18825 veclen = node->simdclone->simdlen;
18826 if (POINTER_TYPE_P (t))
18827 t = pointer_sized_int_node;
18828 if (veclen == node->simdclone->simdlen)
18829 t = build_vector_type (t, node->simdclone->simdlen);
18830 else
18832 t = build_vector_type (t, veclen);
18833 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
18835 TREE_TYPE (TREE_TYPE (fndecl)) = t;
18836 if (!node->definition)
18837 return NULL_TREE;
18839 t = DECL_RESULT (fndecl);
18840 /* Adjust the DECL_RESULT. */
18841 gcc_assert (TREE_TYPE (t) != void_type_node);
18842 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
18843 relayout_decl (t);
18845 tree atype = build_array_type_nelts (orig_rettype,
18846 node->simdclone->simdlen);
18847 if (veclen != node->simdclone->simdlen)
18848 return build1 (VIEW_CONVERT_EXPR, atype, t);
18850 /* Set up a SIMD array to use as the return value. */
18851 tree retval = create_tmp_var_raw (atype, "retval");
18852 gimple_add_tmp_var (retval);
18853 return retval;
18856 /* Each vector argument has a corresponding array to be used locally
18857 as part of the eventual loop. Create such temporary array and
18858 return it.
18860 PREFIX is the prefix to be used for the temporary.
18862 TYPE is the inner element type.
18864 SIMDLEN is the number of elements. */
18866 static tree
18867 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
18869 tree atype = build_array_type_nelts (type, simdlen);
18870 tree avar = create_tmp_var_raw (atype, prefix);
18871 gimple_add_tmp_var (avar);
18872 return avar;
18875 /* Modify the function argument types to their corresponding vector
18876 counterparts if appropriate. Also, create one array for each simd
18877 argument to be used locally when using the function arguments as
18878 part of the loop.
18880 NODE is the function whose arguments are to be adjusted.
18882 Returns an adjustment vector that will be filled describing how the
18883 argument types will be adjusted. */
18885 static ipa_parm_adjustment_vec
18886 simd_clone_adjust_argument_types (struct cgraph_node *node)
18888 vec<tree> args;
18889 ipa_parm_adjustment_vec adjustments;
18891 if (node->definition)
18892 args = ipa_get_vector_of_formal_parms (node->decl);
18893 else
18894 args = simd_clone_vector_of_formal_parm_types (node->decl);
18895 adjustments.create (args.length ());
18896 unsigned i, j, veclen;
18897 struct ipa_parm_adjustment adj;
18898 for (i = 0; i < node->simdclone->nargs; ++i)
18900 memset (&adj, 0, sizeof (adj));
18901 tree parm = args[i];
18902 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
18903 adj.base_index = i;
18904 adj.base = parm;
18906 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
18907 node->simdclone->args[i].orig_type = parm_type;
18909 switch (node->simdclone->args[i].arg_type)
18911 default:
18912 /* No adjustment necessary for scalar arguments. */
18913 adj.op = IPA_PARM_OP_COPY;
18914 break;
18915 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
18916 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
18917 if (node->definition)
18918 node->simdclone->args[i].simd_array
18919 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18920 TREE_TYPE (parm_type),
18921 node->simdclone->simdlen);
18922 adj.op = IPA_PARM_OP_COPY;
18923 break;
18924 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
18925 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
18926 case SIMD_CLONE_ARG_TYPE_VECTOR:
18927 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
18928 veclen = node->simdclone->vecsize_int;
18929 else
18930 veclen = node->simdclone->vecsize_float;
18931 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
18932 if (veclen > node->simdclone->simdlen)
18933 veclen = node->simdclone->simdlen;
18934 adj.arg_prefix = "simd";
18935 if (POINTER_TYPE_P (parm_type))
18936 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18937 else
18938 adj.type = build_vector_type (parm_type, veclen);
18939 node->simdclone->args[i].vector_type = adj.type;
18940 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18942 adjustments.safe_push (adj);
18943 if (j == veclen)
18945 memset (&adj, 0, sizeof (adj));
18946 adj.op = IPA_PARM_OP_NEW;
18947 adj.arg_prefix = "simd";
18948 adj.base_index = i;
18949 adj.type = node->simdclone->args[i].vector_type;
18953 if (node->definition)
18954 node->simdclone->args[i].simd_array
18955 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18956 parm_type, node->simdclone->simdlen);
18958 adjustments.safe_push (adj);
18961 if (node->simdclone->inbranch)
18963 tree base_type
18964 = simd_clone_compute_base_data_type (node->simdclone->origin,
18965 node->simdclone);
18967 memset (&adj, 0, sizeof (adj));
18968 adj.op = IPA_PARM_OP_NEW;
18969 adj.arg_prefix = "mask";
18971 adj.base_index = i;
18972 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
18973 veclen = node->simdclone->vecsize_int;
18974 else
18975 veclen = node->simdclone->vecsize_float;
18976 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
18977 if (veclen > node->simdclone->simdlen)
18978 veclen = node->simdclone->simdlen;
18979 if (POINTER_TYPE_P (base_type))
18980 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18981 else
18982 adj.type = build_vector_type (base_type, veclen);
18983 adjustments.safe_push (adj);
18985 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18986 adjustments.safe_push (adj);
18988 /* We have previously allocated one extra entry for the mask. Use
18989 it and fill it. */
18990 struct cgraph_simd_clone *sc = node->simdclone;
18991 sc->nargs++;
18992 if (node->definition)
18994 sc->args[i].orig_arg
18995 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
18996 sc->args[i].simd_array
18997 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
18999 sc->args[i].orig_type = base_type;
19000 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
19003 if (node->definition)
19004 ipa_modify_formal_parameters (node->decl, adjustments);
19005 else
19007 tree new_arg_types = NULL_TREE, new_reversed;
19008 bool last_parm_void = false;
19009 if (args.length () > 0 && args.last () == void_type_node)
19010 last_parm_void = true;
19012 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
19013 j = adjustments.length ();
19014 for (i = 0; i < j; i++)
19016 struct ipa_parm_adjustment *adj = &adjustments[i];
19017 tree ptype;
19018 if (adj->op == IPA_PARM_OP_COPY)
19019 ptype = args[adj->base_index];
19020 else
19021 ptype = adj->type;
19022 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
19024 new_reversed = nreverse (new_arg_types);
19025 if (last_parm_void)
19027 if (new_reversed)
19028 TREE_CHAIN (new_arg_types) = void_list_node;
19029 else
19030 new_reversed = void_list_node;
19033 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
19034 TYPE_ARG_TYPES (new_type) = new_reversed;
19035 TREE_TYPE (node->decl) = new_type;
19037 adjustments.release ();
19039 args.release ();
19040 return adjustments;
19043 /* Initialize and copy the function arguments in NODE to their
19044 corresponding local simd arrays. Returns a fresh gimple_seq with
19045 the instruction sequence generated. */
19047 static gimple_seq
19048 simd_clone_init_simd_arrays (struct cgraph_node *node,
19049 ipa_parm_adjustment_vec adjustments)
19051 gimple_seq seq = NULL;
19052 unsigned i = 0, j = 0, k;
19054 for (tree arg = DECL_ARGUMENTS (node->decl);
19055 arg;
19056 arg = DECL_CHAIN (arg), i++, j++)
19058 if (adjustments[j].op == IPA_PARM_OP_COPY
19059 || POINTER_TYPE_P (TREE_TYPE (arg)))
19060 continue;
19062 node->simdclone->args[i].vector_arg = arg;
19064 tree array = node->simdclone->args[i].simd_array;
19065 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
19067 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19068 tree ptr = build_fold_addr_expr (array);
19069 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19070 build_int_cst (ptype, 0));
19071 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19072 gimplify_and_add (t, &seq);
19074 else
19076 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
19077 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19078 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
19080 tree ptr = build_fold_addr_expr (array);
19081 int elemsize;
19082 if (k)
19084 arg = DECL_CHAIN (arg);
19085 j++;
19087 elemsize
19088 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
19089 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19090 build_int_cst (ptype, k * elemsize));
19091 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19092 gimplify_and_add (t, &seq);
19096 return seq;
19099 /* Callback info for ipa_simd_modify_stmt_ops below. */
19101 struct modify_stmt_info {
19102 ipa_parm_adjustment_vec adjustments;
19103 gimple *stmt;
19104 /* True if the parent statement was modified by
19105 ipa_simd_modify_stmt_ops. */
19106 bool modified;
19109 /* Callback for walk_gimple_op.
19111 Adjust operands from a given statement as specified in the
19112 adjustments vector in the callback data. */
19114 static tree
19115 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
19117 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
19118 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
19119 tree *orig_tp = tp;
19120 if (TREE_CODE (*tp) == ADDR_EXPR)
19121 tp = &TREE_OPERAND (*tp, 0);
19122 struct ipa_parm_adjustment *cand = NULL;
19123 if (TREE_CODE (*tp) == PARM_DECL)
19124 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
19125 else
19127 if (TYPE_P (*tp))
19128 *walk_subtrees = 0;
19131 tree repl = NULL_TREE;
19132 if (cand)
19133 repl = unshare_expr (cand->new_decl);
19134 else
19136 if (tp != orig_tp)
19138 *walk_subtrees = 0;
19139 bool modified = info->modified;
19140 info->modified = false;
19141 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
19142 if (!info->modified)
19144 info->modified = modified;
19145 return NULL_TREE;
19147 info->modified = modified;
19148 repl = *tp;
19150 else
19151 return NULL_TREE;
19154 if (tp != orig_tp)
19156 repl = build_fold_addr_expr (repl);
19157 gimple *stmt;
19158 if (is_gimple_debug (info->stmt))
19160 tree vexpr = make_node (DEBUG_EXPR_DECL);
19161 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
19162 DECL_ARTIFICIAL (vexpr) = 1;
19163 TREE_TYPE (vexpr) = TREE_TYPE (repl);
19164 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
19165 repl = vexpr;
19167 else
19169 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
19170 repl = gimple_assign_lhs (stmt);
19172 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
19173 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
19174 *orig_tp = repl;
19176 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
19178 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
19179 *tp = vce;
19181 else
19182 *tp = repl;
19184 info->modified = true;
19185 return NULL_TREE;
19188 /* Traverse the function body and perform all modifications as
19189 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
19190 modified such that the replacement/reduction value will now be an
19191 offset into the corresponding simd_array.
19193 This function will replace all function argument uses with their
19194 corresponding simd array elements, and ajust the return values
19195 accordingly. */
19197 static void
19198 ipa_simd_modify_function_body (struct cgraph_node *node,
19199 ipa_parm_adjustment_vec adjustments,
19200 tree retval_array, tree iter)
19202 basic_block bb;
19203 unsigned int i, j, l;
19205 /* Re-use the adjustments array, but this time use it to replace
19206 every function argument use to an offset into the corresponding
19207 simd_array. */
19208 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
19210 if (!node->simdclone->args[i].vector_arg)
19211 continue;
19213 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19214 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
19215 adjustments[j].new_decl
19216 = build4 (ARRAY_REF,
19217 basetype,
19218 node->simdclone->args[i].simd_array,
19219 iter,
19220 NULL_TREE, NULL_TREE);
19221 if (adjustments[j].op == IPA_PARM_OP_NONE
19222 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
19223 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
19226 l = adjustments.length ();
19227 for (i = 1; i < num_ssa_names; i++)
19229 tree name = ssa_name (i);
19230 if (name
19231 && SSA_NAME_VAR (name)
19232 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
19234 for (j = 0; j < l; j++)
19235 if (SSA_NAME_VAR (name) == adjustments[j].base
19236 && adjustments[j].new_decl)
19238 tree base_var;
19239 if (adjustments[j].new_ssa_base == NULL_TREE)
19241 base_var
19242 = copy_var_decl (adjustments[j].base,
19243 DECL_NAME (adjustments[j].base),
19244 TREE_TYPE (adjustments[j].base));
19245 adjustments[j].new_ssa_base = base_var;
19247 else
19248 base_var = adjustments[j].new_ssa_base;
19249 if (SSA_NAME_IS_DEFAULT_DEF (name))
19251 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19252 gimple_stmt_iterator gsi = gsi_after_labels (bb);
19253 tree new_decl = unshare_expr (adjustments[j].new_decl);
19254 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
19255 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19256 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
19257 gimple *stmt = gimple_build_assign (name, new_decl);
19258 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
19260 else
19261 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19266 struct modify_stmt_info info;
19267 info.adjustments = adjustments;
19269 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
19271 gimple_stmt_iterator gsi;
19273 gsi = gsi_start_bb (bb);
19274 while (!gsi_end_p (gsi))
19276 gimple *stmt = gsi_stmt (gsi);
19277 info.stmt = stmt;
19278 struct walk_stmt_info wi;
19280 memset (&wi, 0, sizeof (wi));
19281 info.modified = false;
19282 wi.info = &info;
19283 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
19285 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
19287 tree retval = gimple_return_retval (return_stmt);
19288 if (!retval)
19290 gsi_remove (&gsi, true);
19291 continue;
19294 /* Replace `return foo' with `retval_array[iter] = foo'. */
19295 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
19296 retval_array, iter, NULL, NULL);
19297 stmt = gimple_build_assign (ref, retval);
19298 gsi_replace (&gsi, stmt, true);
19299 info.modified = true;
19302 if (info.modified)
19304 update_stmt (stmt);
19305 if (maybe_clean_eh_stmt (stmt))
19306 gimple_purge_dead_eh_edges (gimple_bb (stmt));
19308 gsi_next (&gsi);
19313 /* Helper function of simd_clone_adjust, return linear step addend
19314 of Ith argument. */
19316 static tree
19317 simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
19318 tree addtype, basic_block entry_bb)
19320 tree ptype = NULL_TREE;
19321 switch (node->simdclone->args[i].arg_type)
19323 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
19324 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
19325 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
19326 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
19327 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
19328 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
19329 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
19330 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19331 break;
19332 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
19333 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
19334 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
19335 break;
19336 default:
19337 gcc_unreachable ();
19340 unsigned int idx = node->simdclone->args[i].linear_step;
19341 tree arg = node->simdclone->args[idx].orig_arg;
19342 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
19343 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19344 gimple *g;
19345 tree ret;
19346 if (is_gimple_reg (arg))
19347 ret = get_or_create_ssa_default_def (cfun, arg);
19348 else
19350 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
19351 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19352 ret = gimple_assign_lhs (g);
19354 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
19356 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
19357 build_simple_mem_ref (ret));
19358 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19359 ret = gimple_assign_lhs (g);
19361 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
19363 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
19364 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19365 ret = gimple_assign_lhs (g);
19367 if (POINTER_TYPE_P (ptype))
19369 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
19370 if (size && TREE_CODE (size) == INTEGER_CST)
19372 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
19373 ret, fold_convert (addtype, size));
19374 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19375 ret = gimple_assign_lhs (g);
19378 return ret;
19381 /* Adjust the argument types in NODE to their appropriate vector
19382 counterparts. */
19384 static void
19385 simd_clone_adjust (struct cgraph_node *node)
19387 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
19389 targetm.simd_clone.adjust (node);
19391 tree retval = simd_clone_adjust_return_type (node);
19392 ipa_parm_adjustment_vec adjustments
19393 = simd_clone_adjust_argument_types (node);
19395 push_gimplify_context ();
19397 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
19399 /* Adjust all uses of vector arguments accordingly. Adjust all
19400 return values accordingly. */
19401 tree iter = create_tmp_var (unsigned_type_node, "iter");
19402 tree iter1 = make_ssa_name (iter);
19403 tree iter2 = make_ssa_name (iter);
19404 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
19406 /* Initialize the iteration variable. */
19407 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19408 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
19409 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19410 /* Insert the SIMD array and iv initialization at function
19411 entry. */
19412 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
19414 pop_gimplify_context (NULL);
19416 /* Create a new BB right before the original exit BB, to hold the
19417 iteration increment and the condition/branch. */
19418 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
19419 basic_block incr_bb = create_empty_bb (orig_exit);
19420 add_bb_to_loop (incr_bb, body_bb->loop_father);
19421 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
19422 flag. Set it now to be a FALLTHRU_EDGE. */
19423 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
19424 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
19425 for (unsigned i = 0;
19426 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
19428 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
19429 redirect_edge_succ (e, incr_bb);
19431 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
19432 e->probability = REG_BR_PROB_BASE;
19433 gsi = gsi_last_bb (incr_bb);
19434 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
19435 build_int_cst (unsigned_type_node, 1));
19436 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19438 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
19439 struct loop *loop = alloc_loop ();
19440 cfun->has_force_vectorize_loops = true;
19441 loop->safelen = node->simdclone->simdlen;
19442 loop->force_vectorize = true;
19443 loop->header = body_bb;
19445 /* Branch around the body if the mask applies. */
19446 if (node->simdclone->inbranch)
19448 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
19449 tree mask_array
19450 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
19451 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
19452 tree aref = build4 (ARRAY_REF,
19453 TREE_TYPE (TREE_TYPE (mask_array)),
19454 mask_array, iter1,
19455 NULL, NULL);
19456 g = gimple_build_assign (mask, aref);
19457 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19458 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
19459 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
19461 aref = build1 (VIEW_CONVERT_EXPR,
19462 build_nonstandard_integer_type (bitsize, 0), mask);
19463 mask = make_ssa_name (TREE_TYPE (aref));
19464 g = gimple_build_assign (mask, aref);
19465 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19468 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
19469 NULL, NULL);
19470 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19471 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
19472 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
19475 /* Generate the condition. */
19476 g = gimple_build_cond (LT_EXPR,
19477 iter2,
19478 build_int_cst (unsigned_type_node,
19479 node->simdclone->simdlen),
19480 NULL, NULL);
19481 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19482 e = split_block (incr_bb, gsi_stmt (gsi));
19483 basic_block latch_bb = e->dest;
19484 basic_block new_exit_bb;
19485 new_exit_bb = split_block_after_labels (latch_bb)->dest;
19486 loop->latch = latch_bb;
19488 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
19490 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
19491 /* The successor of incr_bb is already pointing to latch_bb; just
19492 change the flags.
19493 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
19494 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
19496 gphi *phi = create_phi_node (iter1, body_bb);
19497 edge preheader_edge = find_edge (entry_bb, body_bb);
19498 edge latch_edge = single_succ_edge (latch_bb);
19499 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
19500 UNKNOWN_LOCATION);
19501 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19503 /* Generate the new return. */
19504 gsi = gsi_last_bb (new_exit_bb);
19505 if (retval
19506 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
19507 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
19508 retval = TREE_OPERAND (retval, 0);
19509 else if (retval)
19511 retval = build1 (VIEW_CONVERT_EXPR,
19512 TREE_TYPE (TREE_TYPE (node->decl)),
19513 retval);
19514 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
19515 false, GSI_CONTINUE_LINKING);
19517 g = gimple_build_return (retval);
19518 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19520 /* Handle aligned clauses by replacing default defs of the aligned
19521 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
19522 lhs. Handle linear by adding PHIs. */
19523 for (unsigned i = 0; i < node->simdclone->nargs; i++)
19524 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19525 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
19526 || !is_gimple_reg_type
19527 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19529 tree orig_arg = node->simdclone->args[i].orig_arg;
19530 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
19531 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19532 else
19534 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
19535 gimple_add_tmp_var (iter1);
19537 gsi = gsi_after_labels (entry_bb);
19538 g = gimple_build_assign (iter1, orig_arg);
19539 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19540 gsi = gsi_after_labels (body_bb);
19541 g = gimple_build_assign (orig_arg, iter1);
19542 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19544 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19545 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
19546 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19547 == REFERENCE_TYPE
19548 && TREE_ADDRESSABLE
19549 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19551 tree orig_arg = node->simdclone->args[i].orig_arg;
19552 tree def = ssa_default_def (cfun, orig_arg);
19553 if (def && !has_zero_uses (def))
19555 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
19556 gimple_add_tmp_var (iter1);
19557 gsi = gsi_after_labels (entry_bb);
19558 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
19559 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19560 gsi = gsi_after_labels (body_bb);
19561 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
19562 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19565 else if (node->simdclone->args[i].alignment
19566 && node->simdclone->args[i].arg_type
19567 == SIMD_CLONE_ARG_TYPE_UNIFORM
19568 && (node->simdclone->args[i].alignment
19569 & (node->simdclone->args[i].alignment - 1)) == 0
19570 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19571 == POINTER_TYPE)
19573 unsigned int alignment = node->simdclone->args[i].alignment;
19574 tree orig_arg = node->simdclone->args[i].orig_arg;
19575 tree def = ssa_default_def (cfun, orig_arg);
19576 if (def && !has_zero_uses (def))
19578 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
19579 gimple_seq seq = NULL;
19580 bool need_cvt = false;
19581 gcall *call
19582 = gimple_build_call (fn, 2, def, size_int (alignment));
19583 g = call;
19584 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
19585 ptr_type_node))
19586 need_cvt = true;
19587 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
19588 gimple_call_set_lhs (g, t);
19589 gimple_seq_add_stmt_without_update (&seq, g);
19590 if (need_cvt)
19592 t = make_ssa_name (orig_arg);
19593 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
19594 gimple_seq_add_stmt_without_update (&seq, g);
19596 gsi_insert_seq_on_edge_immediate
19597 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
19599 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19600 int freq = compute_call_stmt_bb_frequency (current_function_decl,
19601 entry_bb);
19602 node->create_edge (cgraph_node::get_create (fn),
19603 call, entry_bb->count, freq);
19605 imm_use_iterator iter;
19606 use_operand_p use_p;
19607 gimple *use_stmt;
19608 tree repl = gimple_get_lhs (g);
19609 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19610 if (is_gimple_debug (use_stmt) || use_stmt == call)
19611 continue;
19612 else
19613 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19614 SET_USE (use_p, repl);
19617 else if ((node->simdclone->args[i].arg_type
19618 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
19619 || (node->simdclone->args[i].arg_type
19620 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
19621 || (node->simdclone->args[i].arg_type
19622 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
19623 || (node->simdclone->args[i].arg_type
19624 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
19626 tree orig_arg = node->simdclone->args[i].orig_arg;
19627 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19628 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
19629 tree def = NULL_TREE;
19630 if (TREE_ADDRESSABLE (orig_arg))
19632 def = make_ssa_name (TREE_TYPE (orig_arg));
19633 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19634 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
19635 gsi = gsi_after_labels (entry_bb);
19636 g = gimple_build_assign (def, orig_arg);
19637 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19639 else
19641 def = ssa_default_def (cfun, orig_arg);
19642 if (!def || has_zero_uses (def))
19643 def = NULL_TREE;
19644 else
19646 iter1 = make_ssa_name (orig_arg);
19647 iter2 = make_ssa_name (orig_arg);
19650 if (def)
19652 phi = create_phi_node (iter1, body_bb);
19653 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
19654 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19655 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19656 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19657 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19658 ? TREE_TYPE (orig_arg) : sizetype;
19659 tree addcst = simd_clone_linear_addend (node, i, addtype,
19660 entry_bb);
19661 gsi = gsi_last_bb (incr_bb);
19662 g = gimple_build_assign (iter2, code, iter1, addcst);
19663 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19665 imm_use_iterator iter;
19666 use_operand_p use_p;
19667 gimple *use_stmt;
19668 if (TREE_ADDRESSABLE (orig_arg))
19670 gsi = gsi_after_labels (body_bb);
19671 g = gimple_build_assign (orig_arg, iter1);
19672 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19674 else
19675 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19676 if (use_stmt == phi)
19677 continue;
19678 else
19679 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19680 SET_USE (use_p, iter1);
19683 else if (node->simdclone->args[i].arg_type
19684 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
19685 || (node->simdclone->args[i].arg_type
19686 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
19688 tree orig_arg = node->simdclone->args[i].orig_arg;
19689 tree def = ssa_default_def (cfun, orig_arg);
19690 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
19691 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
19692 if (def && !has_zero_uses (def))
19694 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
19695 iter1 = make_ssa_name (orig_arg);
19696 iter2 = make_ssa_name (orig_arg);
19697 tree iter3 = make_ssa_name (rtype);
19698 tree iter4 = make_ssa_name (rtype);
19699 tree iter5 = make_ssa_name (rtype);
19700 gsi = gsi_after_labels (entry_bb);
19701 gimple *load
19702 = gimple_build_assign (iter3, build_simple_mem_ref (def));
19703 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
19705 tree array = node->simdclone->args[i].simd_array;
19706 TREE_ADDRESSABLE (array) = 1;
19707 tree ptr = build_fold_addr_expr (array);
19708 phi = create_phi_node (iter1, body_bb);
19709 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
19710 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19711 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
19712 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
19713 gsi = gsi_last_bb (incr_bb);
19714 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19716 phi = create_phi_node (iter4, body_bb);
19717 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
19718 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
19719 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19720 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19721 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19722 ? TREE_TYPE (iter3) : sizetype;
19723 tree addcst = simd_clone_linear_addend (node, i, addtype,
19724 entry_bb);
19725 g = gimple_build_assign (iter5, code, iter4, addcst);
19726 gsi = gsi_last_bb (incr_bb);
19727 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19729 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
19730 gsi = gsi_after_labels (body_bb);
19731 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19733 imm_use_iterator iter;
19734 use_operand_p use_p;
19735 gimple *use_stmt;
19736 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19737 if (use_stmt == load)
19738 continue;
19739 else
19740 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19741 SET_USE (use_p, iter1);
19743 if (!TYPE_READONLY (rtype))
19745 tree v = make_ssa_name (rtype);
19746 tree aref = build4 (ARRAY_REF, rtype, array,
19747 size_zero_node, NULL_TREE,
19748 NULL_TREE);
19749 gsi = gsi_after_labels (new_exit_bb);
19750 g = gimple_build_assign (v, aref);
19751 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19752 g = gimple_build_assign (build_simple_mem_ref (def), v);
19753 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19758 calculate_dominance_info (CDI_DOMINATORS);
19759 add_loop (loop, loop->header->loop_father);
19760 update_ssa (TODO_update_ssa);
19762 pop_cfun ();
19765 /* If the function in NODE is tagged as an elemental SIMD function,
19766 create the appropriate SIMD clones. */
19768 static void
19769 expand_simd_clones (struct cgraph_node *node)
19771 tree attr = lookup_attribute ("omp declare simd",
19772 DECL_ATTRIBUTES (node->decl));
19773 if (attr == NULL_TREE
19774 || node->global.inlined_to
19775 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
19776 return;
19778 /* Ignore
19779 #pragma omp declare simd
19780 extern int foo ();
19781 in C, there we don't know the argument types at all. */
19782 if (!node->definition
19783 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
19784 return;
19786 /* Call this before creating clone_info, as it might ggc_collect. */
19787 if (node->definition && node->has_gimple_body_p ())
19788 node->get_body ();
19792 /* Start with parsing the "omp declare simd" attribute(s). */
19793 bool inbranch_clause_specified;
19794 struct cgraph_simd_clone *clone_info
19795 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
19796 &inbranch_clause_specified);
19797 if (clone_info == NULL)
19798 continue;
19800 int orig_simdlen = clone_info->simdlen;
19801 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
19802 /* The target can return 0 (no simd clones should be created),
19803 1 (just one ISA of simd clones should be created) or higher
19804 count of ISA variants. In that case, clone_info is initialized
19805 for the first ISA variant. */
19806 int count
19807 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
19808 base_type, 0);
19809 if (count == 0)
19810 continue;
19812 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
19813 also create one inbranch and one !inbranch clone of it. */
19814 for (int i = 0; i < count * 2; i++)
19816 struct cgraph_simd_clone *clone = clone_info;
19817 if (inbranch_clause_specified && (i & 1) != 0)
19818 continue;
19820 if (i != 0)
19822 clone = simd_clone_struct_alloc (clone_info->nargs
19823 + ((i & 1) != 0));
19824 simd_clone_struct_copy (clone, clone_info);
19825 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
19826 and simd_clone_adjust_argument_types did to the first
19827 clone's info. */
19828 clone->nargs -= clone_info->inbranch;
19829 clone->simdlen = orig_simdlen;
19830 /* And call the target hook again to get the right ISA. */
19831 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
19832 base_type,
19833 i / 2);
19834 if ((i & 1) != 0)
19835 clone->inbranch = 1;
19838 /* simd_clone_mangle might fail if such a clone has been created
19839 already. */
19840 tree id = simd_clone_mangle (node, clone);
19841 if (id == NULL_TREE)
19842 continue;
19844 /* Only when we are sure we want to create the clone actually
19845 clone the function (or definitions) or create another
19846 extern FUNCTION_DECL (for prototypes without definitions). */
19847 struct cgraph_node *n = simd_clone_create (node);
19848 if (n == NULL)
19849 continue;
19851 n->simdclone = clone;
19852 clone->origin = node;
19853 clone->next_clone = NULL;
19854 if (node->simd_clones == NULL)
19856 clone->prev_clone = n;
19857 node->simd_clones = n;
19859 else
19861 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
19862 clone->prev_clone->simdclone->next_clone = n;
19863 node->simd_clones->simdclone->prev_clone = n;
19865 symtab->change_decl_assembler_name (n->decl, id);
19866 /* And finally adjust the return type, parameters and for
19867 definitions also function body. */
19868 if (node->definition)
19869 simd_clone_adjust (n);
19870 else
19872 simd_clone_adjust_return_type (n);
19873 simd_clone_adjust_argument_types (n);
19877 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
19880 /* Entry point for IPA simd clone creation pass. */
19882 static unsigned int
19883 ipa_omp_simd_clone (void)
19885 struct cgraph_node *node;
19886 FOR_EACH_FUNCTION (node)
19887 expand_simd_clones (node);
19888 return 0;
19891 namespace {
19893 const pass_data pass_data_omp_simd_clone =
19895 SIMPLE_IPA_PASS, /* type */
19896 "simdclone", /* name */
19897 OPTGROUP_NONE, /* optinfo_flags */
19898 TV_NONE, /* tv_id */
19899 ( PROP_ssa | PROP_cfg ), /* properties_required */
19900 0, /* properties_provided */
19901 0, /* properties_destroyed */
19902 0, /* todo_flags_start */
19903 0, /* todo_flags_finish */
19906 class pass_omp_simd_clone : public simple_ipa_opt_pass
19908 public:
19909 pass_omp_simd_clone(gcc::context *ctxt)
19910 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
19913 /* opt_pass methods: */
19914 virtual bool gate (function *);
19915 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
19918 bool
19919 pass_omp_simd_clone::gate (function *)
19921 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
19924 } // anon namespace
19926 simple_ipa_opt_pass *
19927 make_pass_omp_simd_clone (gcc::context *ctxt)
19929 return new pass_omp_simd_clone (ctxt);
19932 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
19933 adds their addresses and sizes to constructor-vector V_CTOR. */
19934 static void
19935 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
19936 vec<constructor_elt, va_gc> *v_ctor)
19938 unsigned len = vec_safe_length (v_decls);
19939 for (unsigned i = 0; i < len; i++)
19941 tree it = (*v_decls)[i];
19942 bool is_var = TREE_CODE (it) == VAR_DECL;
19943 bool is_link_var
19944 = is_var
19945 #ifdef ACCEL_COMPILER
19946 && DECL_HAS_VALUE_EXPR_P (it)
19947 #endif
19948 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
19950 tree size = NULL_TREE;
19951 if (is_var)
19952 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
19954 tree addr;
19955 if (!is_link_var)
19956 addr = build_fold_addr_expr (it);
19957 else
19959 #ifdef ACCEL_COMPILER
19960 /* For "omp declare target link" vars add address of the pointer to
19961 the target table, instead of address of the var. */
19962 tree value_expr = DECL_VALUE_EXPR (it);
19963 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
19964 varpool_node::finalize_decl (link_ptr_decl);
19965 addr = build_fold_addr_expr (link_ptr_decl);
19966 #else
19967 addr = build_fold_addr_expr (it);
19968 #endif
19970 /* Most significant bit of the size marks "omp declare target link"
19971 vars in host and target tables. */
19972 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
19973 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
19974 * BITS_PER_UNIT - 1);
19975 size = wide_int_to_tree (const_ptr_type_node, isize);
19978 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
19979 if (is_var)
19980 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
19984 /* Create new symbols containing (address, size) pairs for global variables,
19985 marked with "omp declare target" attribute, as well as addresses for the
19986 functions, which are outlined offloading regions. */
19987 void
19988 omp_finish_file (void)
19990 unsigned num_funcs = vec_safe_length (offload_funcs);
19991 unsigned num_vars = vec_safe_length (offload_vars);
19993 if (num_funcs == 0 && num_vars == 0)
19994 return;
19996 if (targetm_common.have_named_sections)
19998 vec<constructor_elt, va_gc> *v_f, *v_v;
19999 vec_alloc (v_f, num_funcs);
20000 vec_alloc (v_v, num_vars * 2);
20002 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
20003 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
20005 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
20006 num_vars * 2);
20007 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
20008 num_funcs);
20009 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20010 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20011 tree ctor_v = build_constructor (vars_decl_type, v_v);
20012 tree ctor_f = build_constructor (funcs_decl_type, v_f);
20013 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
20014 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
20015 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20016 get_identifier (".offload_func_table"),
20017 funcs_decl_type);
20018 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20019 get_identifier (".offload_var_table"),
20020 vars_decl_type);
20021 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
20022 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
20023 otherwise a joint table in a binary will contain padding between
20024 tables from multiple object files. */
20025 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
20026 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
20027 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
20028 DECL_INITIAL (funcs_decl) = ctor_f;
20029 DECL_INITIAL (vars_decl) = ctor_v;
20030 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
20031 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
20033 varpool_node::finalize_decl (vars_decl);
20034 varpool_node::finalize_decl (funcs_decl);
20036 else
20038 for (unsigned i = 0; i < num_funcs; i++)
20040 tree it = (*offload_funcs)[i];
20041 targetm.record_offload_symbol (it);
20043 for (unsigned i = 0; i < num_vars; i++)
20045 tree it = (*offload_vars)[i];
20046 targetm.record_offload_symbol (it);
20051 /* Find the number of threads (POS = false), or thread number (POS =
20052 true) for an OpenACC region partitioned as MASK. Setup code
20053 required for the calculation is added to SEQ. */
20055 static tree
20056 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
20058 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
20059 unsigned ix;
20061 /* Start at gang level, and examine relevant dimension indices. */
20062 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20063 if (GOMP_DIM_MASK (ix) & mask)
20065 tree arg = build_int_cst (unsigned_type_node, ix);
20067 if (res)
20069 /* We had an outer index, so scale that by the size of
20070 this dimension. */
20071 tree n = create_tmp_var (integer_type_node);
20072 gimple *call
20073 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
20075 gimple_call_set_lhs (call, n);
20076 gimple_seq_add_stmt (seq, call);
20077 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
20079 if (pos)
20081 /* Determine index in this dimension. */
20082 tree id = create_tmp_var (integer_type_node);
20083 gimple *call = gimple_build_call_internal
20084 (IFN_GOACC_DIM_POS, 1, arg);
20086 gimple_call_set_lhs (call, id);
20087 gimple_seq_add_stmt (seq, call);
20088 if (res)
20089 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
20090 else
20091 res = id;
20095 if (res == NULL_TREE)
20096 res = integer_zero_node;
20098 return res;
20101 /* Transform IFN_GOACC_LOOP calls to actual code. See
20102 expand_oacc_for for where these are generated. At the vector
20103 level, we stride loops, such that each member of a warp will
20104 operate on adjacent iterations. At the worker and gang level,
20105 each gang/warp executes a set of contiguous iterations. Chunking
20106 can override this such that each iteration engine executes a
20107 contiguous chunk, and then moves on to stride to the next chunk. */
20109 static void
20110 oacc_xform_loop (gcall *call)
20112 gimple_stmt_iterator gsi = gsi_for_stmt (call);
20113 enum ifn_goacc_loop_kind code
20114 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
20115 tree dir = gimple_call_arg (call, 1);
20116 tree range = gimple_call_arg (call, 2);
20117 tree step = gimple_call_arg (call, 3);
20118 tree chunk_size = NULL_TREE;
20119 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
20120 tree lhs = gimple_call_lhs (call);
20121 tree type = TREE_TYPE (lhs);
20122 tree diff_type = TREE_TYPE (range);
20123 tree r = NULL_TREE;
20124 gimple_seq seq = NULL;
20125 bool chunking = false, striding = true;
20126 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
20127 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
20129 #ifdef ACCEL_COMPILER
20130 chunk_size = gimple_call_arg (call, 4);
20131 if (integer_minus_onep (chunk_size) /* Force static allocation. */
20132 || integer_zerop (chunk_size)) /* Default (also static). */
20134 /* If we're at the gang level, we want each to execute a
20135 contiguous run of iterations. Otherwise we want each element
20136 to stride. */
20137 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
20138 chunking = false;
20140 else
20142 /* Chunk of size 1 is striding. */
20143 striding = integer_onep (chunk_size);
20144 chunking = !striding;
20146 #endif
20148 /* striding=true, chunking=true
20149 -> invalid.
20150 striding=true, chunking=false
20151 -> chunks=1
20152 striding=false,chunking=true
20153 -> chunks=ceil (range/(chunksize*threads*step))
20154 striding=false,chunking=false
20155 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
20156 push_gimplify_context (true);
20158 switch (code)
20160 default: gcc_unreachable ();
20162 case IFN_GOACC_LOOP_CHUNKS:
20163 if (!chunking)
20164 r = build_int_cst (type, 1);
20165 else
20167 /* chunk_max
20168 = (range - dir) / (chunks * step * num_threads) + dir */
20169 tree per = oacc_thread_numbers (false, mask, &seq);
20170 per = fold_convert (type, per);
20171 chunk_size = fold_convert (type, chunk_size);
20172 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
20173 per = fold_build2 (MULT_EXPR, type, per, step);
20174 r = build2 (MINUS_EXPR, type, range, dir);
20175 r = build2 (PLUS_EXPR, type, r, per);
20176 r = build2 (TRUNC_DIV_EXPR, type, r, per);
20178 break;
20180 case IFN_GOACC_LOOP_STEP:
20182 /* If striding, step by the entire compute volume, otherwise
20183 step by the inner volume. */
20184 unsigned volume = striding ? mask : inner_mask;
20186 r = oacc_thread_numbers (false, volume, &seq);
20187 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
20189 break;
20191 case IFN_GOACC_LOOP_OFFSET:
20192 if (striding)
20194 r = oacc_thread_numbers (true, mask, &seq);
20195 r = fold_convert (diff_type, r);
20197 else
20199 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20200 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20201 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20202 inner_size, outer_size);
20204 volume = fold_convert (diff_type, volume);
20205 if (chunking)
20206 chunk_size = fold_convert (diff_type, chunk_size);
20207 else
20209 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20211 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20212 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20213 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20216 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20217 fold_convert (diff_type, inner_size));
20218 r = oacc_thread_numbers (true, outer_mask, &seq);
20219 r = fold_convert (diff_type, r);
20220 r = build2 (MULT_EXPR, diff_type, r, span);
20222 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
20223 inner = fold_convert (diff_type, inner);
20224 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
20226 if (chunking)
20228 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
20229 tree per
20230 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
20231 per = build2 (MULT_EXPR, diff_type, per, chunk);
20233 r = build2 (PLUS_EXPR, diff_type, r, per);
20236 r = fold_build2 (MULT_EXPR, diff_type, r, step);
20237 if (type != diff_type)
20238 r = fold_convert (type, r);
20239 break;
20241 case IFN_GOACC_LOOP_BOUND:
20242 if (striding)
20243 r = range;
20244 else
20246 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20247 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20248 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20249 inner_size, outer_size);
20251 volume = fold_convert (diff_type, volume);
20252 if (chunking)
20253 chunk_size = fold_convert (diff_type, chunk_size);
20254 else
20256 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20258 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20259 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20260 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20263 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20264 fold_convert (diff_type, inner_size));
20266 r = fold_build2 (MULT_EXPR, diff_type, span, step);
20268 tree offset = gimple_call_arg (call, 6);
20269 r = build2 (PLUS_EXPR, diff_type, r,
20270 fold_convert (diff_type, offset));
20271 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
20272 diff_type, r, range);
20274 if (diff_type != type)
20275 r = fold_convert (type, r);
20276 break;
20279 gimplify_assign (lhs, r, &seq);
20281 pop_gimplify_context (NULL);
20283 gsi_replace_with_seq (&gsi, seq, true);
20286 /* Default partitioned and minimum partitioned dimensions. */
20288 static int oacc_default_dims[GOMP_DIM_MAX];
20289 static int oacc_min_dims[GOMP_DIM_MAX];
20291 /* Parse the default dimension parameter. This is a set of
20292 :-separated optional compute dimensions. Each specified dimension
20293 is a positive integer. When device type support is added, it is
20294 planned to be a comma separated list of such compute dimensions,
20295 with all but the first prefixed by the colon-terminated device
20296 type. */
20298 static void
20299 oacc_parse_default_dims (const char *dims)
20301 int ix;
20303 for (ix = GOMP_DIM_MAX; ix--;)
20305 oacc_default_dims[ix] = -1;
20306 oacc_min_dims[ix] = 1;
20309 #ifndef ACCEL_COMPILER
20310 /* Cannot be overridden on the host. */
20311 dims = NULL;
20312 #endif
20313 if (dims)
20315 const char *pos = dims;
20317 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
20319 if (ix)
20321 if (*pos != ':')
20322 goto malformed;
20323 pos++;
20326 if (*pos != ':')
20328 long val;
20329 const char *eptr;
20331 errno = 0;
20332 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
20333 if (errno || val <= 0 || (int) val != val)
20334 goto malformed;
20335 pos = eptr;
20336 oacc_default_dims[ix] = (int) val;
20339 if (*pos)
20341 malformed:
20342 error_at (UNKNOWN_LOCATION,
20343 "-fopenacc-dim operand is malformed at '%s'", pos);
20347 /* Allow the backend to validate the dimensions. */
20348 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
20349 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
20352 /* Validate and update the dimensions for offloaded FN. ATTRS is the
20353 raw attribute. DIMS is an array of dimensions, which is filled in.
20354 LEVEL is the partitioning level of a routine, or -1 for an offload
20355 region itself. USED is the mask of partitioned execution in the
20356 function. */
20358 static void
20359 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
20361 tree purpose[GOMP_DIM_MAX];
20362 unsigned ix;
20363 tree pos = TREE_VALUE (attrs);
20364 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
20366 /* Make sure the attribute creator attached the dimension
20367 information. */
20368 gcc_assert (pos);
20370 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20372 purpose[ix] = TREE_PURPOSE (pos);
20373 tree val = TREE_VALUE (pos);
20374 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
20375 pos = TREE_CHAIN (pos);
20378 bool changed = targetm.goacc.validate_dims (fn, dims, level);
20380 /* Default anything left to 1 or a partitioned default. */
20381 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20382 if (dims[ix] < 0)
20384 /* The OpenACC spec says 'If the [num_gangs] clause is not
20385 specified, an implementation-defined default will be used;
20386 the default may depend on the code within the construct.'
20387 (2.5.6). Thus an implementation is free to choose
20388 non-unity default for a parallel region that doesn't have
20389 any gang-partitioned loops. However, it appears that there
20390 is a sufficient body of user code that expects non-gang
20391 partitioned regions to not execute in gang-redundant mode.
20392 So we (a) don't warn about the non-portability and (b) pick
20393 the minimum permissible dimension size when there is no
20394 partitioned execution. Otherwise we pick the global
20395 default for the dimension, which the user can control. The
20396 same wording and logic applies to num_workers and
20397 vector_length, however the worker- or vector- single
20398 execution doesn't have the same impact as gang-redundant
20399 execution. (If the minimum gang-level partioning is not 1,
20400 the target is probably too confusing.) */
20401 dims[ix] = (used & GOMP_DIM_MASK (ix)
20402 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
20403 changed = true;
20406 if (changed)
20408 /* Replace the attribute with new values. */
20409 pos = NULL_TREE;
20410 for (ix = GOMP_DIM_MAX; ix--;)
20412 pos = tree_cons (purpose[ix],
20413 build_int_cst (integer_type_node, dims[ix]),
20414 pos);
20415 if (is_kernel)
20416 TREE_PUBLIC (pos) = 1;
20418 replace_oacc_fn_attrib (fn, pos);
20422 /* Create an empty OpenACC loop structure at LOC. */
20424 static oacc_loop *
20425 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
20427 oacc_loop *loop = XCNEW (oacc_loop);
20429 loop->parent = parent;
20430 loop->child = loop->sibling = NULL;
20432 if (parent)
20434 loop->sibling = parent->child;
20435 parent->child = loop;
20438 loop->loc = loc;
20439 loop->marker = NULL;
20440 memset (loop->heads, 0, sizeof (loop->heads));
20441 memset (loop->tails, 0, sizeof (loop->tails));
20442 loop->routine = NULL_TREE;
20444 loop->mask = loop->flags = 0;
20445 loop->chunk_size = 0;
20446 loop->head_end = NULL;
20448 return loop;
20451 /* Create an outermost, dummy OpenACC loop for offloaded function
20452 DECL. */
20454 static oacc_loop *
20455 new_oacc_loop_outer (tree decl)
20457 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
20460 /* Start a new OpenACC loop structure beginning at head marker HEAD.
20461 Link into PARENT loop. Return the new loop. */
20463 static oacc_loop *
20464 new_oacc_loop (oacc_loop *parent, gcall *marker)
20466 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
20468 loop->marker = marker;
20470 /* TODO: This is where device_type flattening would occur for the loop
20471 flags. */
20473 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
20475 tree chunk_size = integer_zero_node;
20476 if (loop->flags & OLF_GANG_STATIC)
20477 chunk_size = gimple_call_arg (marker, 4);
20478 loop->chunk_size = chunk_size;
20480 return loop;
20483 /* Create a dummy loop encompassing a call to a openACC routine.
20484 Extract the routine's partitioning requirements. */
20486 static void
20487 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
20489 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
20490 int level = oacc_fn_attrib_level (attrs);
20492 gcc_assert (level >= 0);
20494 loop->marker = call;
20495 loop->routine = decl;
20496 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
20497 ^ (GOMP_DIM_MASK (level) - 1));
20500 /* Finish off the current OpenACC loop ending at tail marker TAIL.
20501 Return the parent loop. */
20503 static oacc_loop *
20504 finish_oacc_loop (oacc_loop *loop)
20506 return loop->parent;
20509 /* Free all OpenACC loop structures within LOOP (inclusive). */
20511 static void
20512 free_oacc_loop (oacc_loop *loop)
20514 if (loop->sibling)
20515 free_oacc_loop (loop->sibling);
20516 if (loop->child)
20517 free_oacc_loop (loop->child);
20519 free (loop);
20522 /* Dump out the OpenACC loop head or tail beginning at FROM. */
20524 static void
20525 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
20526 const char *title, int level)
20528 enum ifn_unique_kind kind
20529 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20531 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
20532 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20534 gimple *stmt = gsi_stmt (gsi);
20536 if (is_gimple_call (stmt)
20537 && gimple_call_internal_p (stmt)
20538 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20540 enum ifn_unique_kind k
20541 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
20542 (gimple_call_arg (stmt, 0)));
20544 if (k == kind && stmt != from)
20545 break;
20547 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
20549 gsi_next (&gsi);
20550 while (gsi_end_p (gsi))
20551 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20555 /* Dump OpenACC loops LOOP, its siblings and its children. */
20557 static void
20558 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
20560 int ix;
20562 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
20563 loop->flags, loop->mask,
20564 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
20566 if (loop->marker)
20567 print_gimple_stmt (file, loop->marker, depth * 2, 0);
20569 if (loop->routine)
20570 fprintf (file, "%*sRoutine %s:%u:%s\n",
20571 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
20572 DECL_SOURCE_LINE (loop->routine),
20573 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
20575 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20576 if (loop->heads[ix])
20577 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
20578 for (ix = GOMP_DIM_MAX; ix--;)
20579 if (loop->tails[ix])
20580 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
20582 if (loop->child)
20583 dump_oacc_loop (file, loop->child, depth + 1);
20584 if (loop->sibling)
20585 dump_oacc_loop (file, loop->sibling, depth);
20588 void debug_oacc_loop (oacc_loop *);
20590 /* Dump loops to stderr. */
20592 DEBUG_FUNCTION void
20593 debug_oacc_loop (oacc_loop *loop)
20595 dump_oacc_loop (stderr, loop, 0);
20598 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
20599 structures as we go. By construction these loops are properly
20600 nested. */
20602 static void
20603 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
20605 int marker = 0;
20606 int remaining = 0;
20608 if (bb->flags & BB_VISITED)
20609 return;
20611 follow:
20612 bb->flags |= BB_VISITED;
20614 /* Scan for loop markers. */
20615 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
20616 gsi_next (&gsi))
20618 gimple *stmt = gsi_stmt (gsi);
20620 if (!is_gimple_call (stmt))
20621 continue;
20623 gcall *call = as_a <gcall *> (stmt);
20625 /* If this is a routine, make a dummy loop for it. */
20626 if (tree decl = gimple_call_fndecl (call))
20627 if (tree attrs = get_oacc_fn_attrib (decl))
20629 gcc_assert (!marker);
20630 new_oacc_loop_routine (loop, call, decl, attrs);
20633 if (!gimple_call_internal_p (call))
20634 continue;
20636 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
20637 continue;
20639 enum ifn_unique_kind kind
20640 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
20641 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
20642 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
20644 if (gimple_call_num_args (call) == 2)
20646 gcc_assert (marker && !remaining);
20647 marker = 0;
20648 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
20649 loop = finish_oacc_loop (loop);
20650 else
20651 loop->head_end = call;
20653 else
20655 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
20657 if (!marker)
20659 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20660 loop = new_oacc_loop (loop, call);
20661 remaining = count;
20663 gcc_assert (count == remaining);
20664 if (remaining)
20666 remaining--;
20667 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20668 loop->heads[marker] = call;
20669 else
20670 loop->tails[remaining] = call;
20672 marker++;
20676 if (remaining || marker)
20678 bb = single_succ (bb);
20679 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
20680 goto follow;
20683 /* Walk successor blocks. */
20684 edge e;
20685 edge_iterator ei;
20687 FOR_EACH_EDGE (e, ei, bb->succs)
20688 oacc_loop_discover_walk (loop, e->dest);
20691 /* LOOP is the first sibling. Reverse the order in place and return
20692 the new first sibling. Recurse to child loops. */
20694 static oacc_loop *
20695 oacc_loop_sibling_nreverse (oacc_loop *loop)
20697 oacc_loop *last = NULL;
20700 if (loop->child)
20701 loop->child = oacc_loop_sibling_nreverse (loop->child);
20703 oacc_loop *next = loop->sibling;
20704 loop->sibling = last;
20705 last = loop;
20706 loop = next;
20708 while (loop);
20710 return last;
20713 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
20714 the current function. */
20716 static oacc_loop *
20717 oacc_loop_discovery ()
20719 basic_block bb;
20721 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
20722 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
20724 /* The siblings were constructed in reverse order, reverse them so
20725 that diagnostics come out in an unsurprising order. */
20726 top = oacc_loop_sibling_nreverse (top);
20728 /* Reset the visited flags. */
20729 FOR_ALL_BB_FN (bb, cfun)
20730 bb->flags &= ~BB_VISITED;
20732 return top;
20735 /* Transform the abstract internal function markers starting at FROM
20736 to be for partitioning level LEVEL. Stop when we meet another HEAD
20737 or TAIL marker. */
20739 static void
20740 oacc_loop_xform_head_tail (gcall *from, int level)
20742 enum ifn_unique_kind kind
20743 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20744 tree replacement = build_int_cst (unsigned_type_node, level);
20746 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20748 gimple *stmt = gsi_stmt (gsi);
20750 if (is_gimple_call (stmt)
20751 && gimple_call_internal_p (stmt)
20752 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20754 enum ifn_unique_kind k
20755 = ((enum ifn_unique_kind)
20756 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
20758 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
20759 *gimple_call_arg_ptr (stmt, 2) = replacement;
20760 else if (k == kind && stmt != from)
20761 break;
20763 else if (is_gimple_call (stmt)
20764 && gimple_call_internal_p (stmt)
20765 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
20766 *gimple_call_arg_ptr (stmt, 3) = replacement;
20768 gsi_next (&gsi);
20769 while (gsi_end_p (gsi))
20770 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20774 /* Transform the IFN_GOACC_LOOP internal functions by providing the
20775 determined partitioning mask and chunking argument. */
20777 static void
20778 oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
20780 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
20782 for (;;)
20784 for (; !gsi_end_p (gsi); gsi_next (&gsi))
20786 gimple *stmt = gsi_stmt (gsi);
20788 if (!is_gimple_call (stmt))
20789 continue;
20791 gcall *call = as_a <gcall *> (stmt);
20793 if (!gimple_call_internal_p (call))
20794 continue;
20796 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
20797 continue;
20799 *gimple_call_arg_ptr (call, 5) = mask_arg;
20800 *gimple_call_arg_ptr (call, 4) = chunk_arg;
20801 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
20802 == IFN_GOACC_LOOP_BOUND)
20803 return;
20806 /* If we didn't see LOOP_BOUND, it should be in the single
20807 successor block. */
20808 basic_block bb = single_succ (gsi_bb (gsi));
20809 gsi = gsi_start_bb (bb);
20813 /* Process the discovered OpenACC loops, setting the correct
20814 partitioning level etc. */
20816 static void
20817 oacc_loop_process (oacc_loop *loop)
20819 if (loop->child)
20820 oacc_loop_process (loop->child);
20822 if (loop->mask && !loop->routine)
20824 int ix;
20825 unsigned mask = loop->mask;
20826 unsigned dim = GOMP_DIM_GANG;
20827 tree mask_arg = build_int_cst (unsigned_type_node, mask);
20828 tree chunk_arg = loop->chunk_size;
20830 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
20832 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
20834 gcc_assert (mask);
20836 while (!(GOMP_DIM_MASK (dim) & mask))
20837 dim++;
20839 oacc_loop_xform_head_tail (loop->heads[ix], dim);
20840 oacc_loop_xform_head_tail (loop->tails[ix], dim);
20842 mask ^= GOMP_DIM_MASK (dim);
20846 if (loop->sibling)
20847 oacc_loop_process (loop->sibling);
20850 /* Walk the OpenACC loop heirarchy checking and assigning the
20851 programmer-specified partitionings. OUTER_MASK is the partitioning
20852 this loop is contained within. Return mask of partitioning
20853 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
20854 bit. */
20856 static unsigned
20857 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
20859 unsigned this_mask = loop->mask;
20860 unsigned mask_all = 0;
20861 bool noisy = true;
20863 #ifdef ACCEL_COMPILER
20864 /* When device_type is supported, we want the device compiler to be
20865 noisy, if the loop parameters are device_type-specific. */
20866 noisy = false;
20867 #endif
20869 if (!loop->routine)
20871 bool auto_par = (loop->flags & OLF_AUTO) != 0;
20872 bool seq_par = (loop->flags & OLF_SEQ) != 0;
20874 this_mask = ((loop->flags >> OLF_DIM_BASE)
20875 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
20877 if ((this_mask != 0) + auto_par + seq_par > 1)
20879 if (noisy)
20880 error_at (loop->loc,
20881 seq_par
20882 ? "%<seq%> overrides other OpenACC loop specifiers"
20883 : "%<auto%> conflicts with other OpenACC loop specifiers");
20884 auto_par = false;
20885 loop->flags &= ~OLF_AUTO;
20886 if (seq_par)
20888 loop->flags &=
20889 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
20890 this_mask = 0;
20893 if (auto_par && (loop->flags & OLF_INDEPENDENT))
20894 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
20897 if (this_mask & outer_mask)
20899 const oacc_loop *outer;
20900 for (outer = loop->parent; outer; outer = outer->parent)
20901 if (outer->mask & this_mask)
20902 break;
20904 if (noisy)
20906 if (outer)
20908 error_at (loop->loc,
20909 "%s uses same OpenACC parallelism as containing loop",
20910 loop->routine ? "routine call" : "inner loop");
20911 inform (outer->loc, "containing loop here");
20913 else
20914 error_at (loop->loc,
20915 "%s uses OpenACC parallelism disallowed by containing routine",
20916 loop->routine ? "routine call" : "loop");
20918 if (loop->routine)
20919 inform (DECL_SOURCE_LOCATION (loop->routine),
20920 "routine %qD declared here", loop->routine);
20922 this_mask &= ~outer_mask;
20924 else
20926 unsigned outermost = this_mask & -this_mask;
20928 if (outermost && outermost <= outer_mask)
20930 if (noisy)
20932 error_at (loop->loc,
20933 "incorrectly nested OpenACC loop parallelism");
20935 const oacc_loop *outer;
20936 for (outer = loop->parent;
20937 outer->flags && outer->flags < outermost;
20938 outer = outer->parent)
20939 continue;
20940 inform (outer->loc, "containing loop here");
20943 this_mask &= ~outermost;
20947 loop->mask = this_mask;
20948 mask_all |= this_mask;
20950 if (loop->child)
20951 mask_all |= oacc_loop_fixed_partitions (loop->child,
20952 outer_mask | this_mask);
20954 if (loop->sibling)
20955 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
20957 return mask_all;
20960 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
20961 OUTER_MASK is the partitioning this loop is contained within.
20962 Return the cumulative partitioning used by this loop, siblings and
20963 children. */
20965 static unsigned
20966 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
20968 unsigned inner_mask = 0;
20969 bool noisy = true;
20971 #ifdef ACCEL_COMPILER
20972 /* When device_type is supported, we want the device compiler to be
20973 noisy, if the loop parameters are device_type-specific. */
20974 noisy = false;
20975 #endif
20977 if (loop->child)
20978 inner_mask |= oacc_loop_auto_partitions (loop->child,
20979 outer_mask | loop->mask);
20981 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
20983 unsigned this_mask = 0;
20985 /* Determine the outermost partitioning used within this loop. */
20986 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
20987 this_mask = (this_mask & -this_mask);
20989 /* Pick the partitioning just inside that one. */
20990 this_mask >>= 1;
20992 /* And avoid picking one use by an outer loop. */
20993 this_mask &= ~outer_mask;
20995 if (!this_mask && noisy)
20996 warning_at (loop->loc, 0,
20997 "insufficient partitioning available to parallelize loop");
20999 if (dump_file)
21000 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
21001 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
21002 this_mask);
21004 loop->mask = this_mask;
21006 inner_mask |= loop->mask;
21008 if (loop->sibling)
21009 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
21011 return inner_mask;
21014 /* Walk the OpenACC loop heirarchy to check and assign partitioning
21015 axes. Return mask of partitioning. */
21017 static unsigned
21018 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
21020 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
21022 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
21024 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
21025 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
21027 return mask_all;
21030 /* Default fork/join early expander. Delete the function calls if
21031 there is no RTL expander. */
21033 bool
21034 default_goacc_fork_join (gcall *ARG_UNUSED (call),
21035 const int *ARG_UNUSED (dims), bool is_fork)
21037 if (is_fork)
21038 return targetm.have_oacc_fork ();
21039 else
21040 return targetm.have_oacc_join ();
21043 /* Default goacc.reduction early expander.
21045 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
21046 If RES_PTR is not integer-zerop:
21047 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
21048 TEARDOWN - emit '*RES_PTR = VAR'
21049 If LHS is not NULL
21050 emit 'LHS = VAR' */
21052 void
21053 default_goacc_reduction (gcall *call)
21055 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
21056 gimple_stmt_iterator gsi = gsi_for_stmt (call);
21057 tree lhs = gimple_call_lhs (call);
21058 tree var = gimple_call_arg (call, 2);
21059 gimple_seq seq = NULL;
21061 if (code == IFN_GOACC_REDUCTION_SETUP
21062 || code == IFN_GOACC_REDUCTION_TEARDOWN)
21064 /* Setup and Teardown need to copy from/to the receiver object,
21065 if there is one. */
21066 tree ref_to_res = gimple_call_arg (call, 1);
21068 if (!integer_zerop (ref_to_res))
21070 tree dst = build_simple_mem_ref (ref_to_res);
21071 tree src = var;
21073 if (code == IFN_GOACC_REDUCTION_SETUP)
21075 src = dst;
21076 dst = lhs;
21077 lhs = NULL;
21079 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
21083 /* Copy VAR to LHS, if there is an LHS. */
21084 if (lhs)
21085 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
21087 gsi_replace_with_seq (&gsi, seq, true);
21090 /* Main entry point for oacc transformations which run on the device
21091 compiler after LTO, so we know what the target device is at this
21092 point (including the host fallback). */
21094 static unsigned int
21095 execute_oacc_device_lower ()
21097 tree attrs = get_oacc_fn_attrib (current_function_decl);
21099 if (!attrs)
21100 /* Not an offloaded function. */
21101 return 0;
21103 /* Parse the default dim argument exactly once. */
21104 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
21106 oacc_parse_default_dims (flag_openacc_dims);
21107 flag_openacc_dims = (char *)&flag_openacc_dims;
21110 /* Discover, partition and process the loops. */
21111 oacc_loop *loops = oacc_loop_discovery ();
21112 int fn_level = oacc_fn_attrib_level (attrs);
21114 if (dump_file)
21115 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
21116 ? "Function is kernels offload\n"
21117 : fn_level < 0 ? "Function is parallel offload\n"
21118 : "Function is routine level %d\n", fn_level);
21120 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
21121 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
21122 int dims[GOMP_DIM_MAX];
21124 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
21126 if (dump_file)
21128 const char *comma = "Compute dimensions [";
21129 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
21130 fprintf (dump_file, "%s%d", comma, dims[ix]);
21131 fprintf (dump_file, "]\n");
21134 oacc_loop_process (loops);
21135 if (dump_file)
21137 fprintf (dump_file, "OpenACC loops\n");
21138 dump_oacc_loop (dump_file, loops, 0);
21139 fprintf (dump_file, "\n");
21142 /* Offloaded targets may introduce new basic blocks, which require
21143 dominance information to update SSA. */
21144 calculate_dominance_info (CDI_DOMINATORS);
21146 /* Now lower internal loop functions to target-specific code
21147 sequences. */
21148 basic_block bb;
21149 FOR_ALL_BB_FN (bb, cfun)
21150 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
21152 gimple *stmt = gsi_stmt (gsi);
21153 if (!is_gimple_call (stmt))
21155 gsi_next (&gsi);
21156 continue;
21159 gcall *call = as_a <gcall *> (stmt);
21160 if (!gimple_call_internal_p (call))
21162 gsi_next (&gsi);
21163 continue;
21166 /* Rewind to allow rescan. */
21167 gsi_prev (&gsi);
21168 bool rescan = false, remove = false;
21169 enum internal_fn ifn_code = gimple_call_internal_fn (call);
21171 switch (ifn_code)
21173 default: break;
21175 case IFN_GOACC_LOOP:
21176 oacc_xform_loop (call);
21177 rescan = true;
21178 break;
21180 case IFN_GOACC_REDUCTION:
21181 /* Mark the function for SSA renaming. */
21182 mark_virtual_operands_for_renaming (cfun);
21184 /* If the level is -1, this ended up being an unused
21185 axis. Handle as a default. */
21186 if (integer_minus_onep (gimple_call_arg (call, 3)))
21187 default_goacc_reduction (call);
21188 else
21189 targetm.goacc.reduction (call);
21190 rescan = true;
21191 break;
21193 case IFN_UNIQUE:
21195 enum ifn_unique_kind kind
21196 = ((enum ifn_unique_kind)
21197 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
21199 switch (kind)
21201 default:
21202 gcc_unreachable ();
21204 case IFN_UNIQUE_OACC_FORK:
21205 case IFN_UNIQUE_OACC_JOIN:
21206 if (integer_minus_onep (gimple_call_arg (call, 2)))
21207 remove = true;
21208 else if (!targetm.goacc.fork_join
21209 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
21210 remove = true;
21211 break;
21213 case IFN_UNIQUE_OACC_HEAD_MARK:
21214 case IFN_UNIQUE_OACC_TAIL_MARK:
21215 remove = true;
21216 break;
21218 break;
21222 if (gsi_end_p (gsi))
21223 /* We rewound past the beginning of the BB. */
21224 gsi = gsi_start_bb (bb);
21225 else
21226 /* Undo the rewind. */
21227 gsi_next (&gsi);
21229 if (remove)
21231 if (gimple_vdef (call))
21232 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
21233 if (gimple_call_lhs (call))
21235 /* Propagate the data dependency var. */
21236 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
21237 gimple_call_arg (call, 1));
21238 gsi_replace (&gsi, ass, false);
21240 else
21241 gsi_remove (&gsi, true);
21243 else if (!rescan)
21244 /* If not rescanning, advance over the call. */
21245 gsi_next (&gsi);
21248 free_oacc_loop (loops);
21250 return 0;
21253 /* Default launch dimension validator. Force everything to 1. A
21254 backend that wants to provide larger dimensions must override this
21255 hook. */
21257 bool
21258 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
21259 int ARG_UNUSED (fn_level))
21261 bool changed = false;
21263 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
21265 if (dims[ix] != 1)
21267 dims[ix] = 1;
21268 changed = true;
21272 return changed;
21275 /* Default dimension bound is unknown on accelerator and 1 on host. */
21278 default_goacc_dim_limit (int ARG_UNUSED (axis))
21280 #ifdef ACCEL_COMPILER
21281 return 0;
21282 #else
21283 return 1;
21284 #endif
21287 namespace {
21289 const pass_data pass_data_oacc_device_lower =
21291 GIMPLE_PASS, /* type */
21292 "oaccdevlow", /* name */
21293 OPTGROUP_NONE, /* optinfo_flags */
21294 TV_NONE, /* tv_id */
21295 PROP_cfg, /* properties_required */
21296 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
21297 0, /* properties_destroyed */
21298 0, /* todo_flags_start */
21299 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
21302 class pass_oacc_device_lower : public gimple_opt_pass
21304 public:
21305 pass_oacc_device_lower (gcc::context *ctxt)
21306 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
21309 /* opt_pass methods: */
21310 virtual unsigned int execute (function *)
21312 bool gate = flag_openacc != 0;
21314 if (!gate)
21315 return 0;
21317 return execute_oacc_device_lower ();
21320 }; // class pass_oacc_device_lower
21322 } // anon namespace
21324 gimple_opt_pass *
21325 make_pass_oacc_device_lower (gcc::context *ctxt)
21327 return new pass_oacc_device_lower (ctxt);
21330 /* "omp declare target link" handling pass. */
21332 namespace {
21334 const pass_data pass_data_omp_target_link =
21336 GIMPLE_PASS, /* type */
21337 "omptargetlink", /* name */
21338 OPTGROUP_NONE, /* optinfo_flags */
21339 TV_NONE, /* tv_id */
21340 PROP_ssa, /* properties_required */
21341 0, /* properties_provided */
21342 0, /* properties_destroyed */
21343 0, /* todo_flags_start */
21344 TODO_update_ssa, /* todo_flags_finish */
21347 class pass_omp_target_link : public gimple_opt_pass
21349 public:
21350 pass_omp_target_link (gcc::context *ctxt)
21351 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
21354 /* opt_pass methods: */
21355 virtual bool gate (function *fun)
21357 #ifdef ACCEL_COMPILER
21358 tree attrs = DECL_ATTRIBUTES (fun->decl);
21359 return lookup_attribute ("omp declare target", attrs)
21360 || lookup_attribute ("omp target entrypoint", attrs);
21361 #else
21362 (void) fun;
21363 return false;
21364 #endif
21367 virtual unsigned execute (function *);
21370 /* Callback for walk_gimple_stmt used to scan for link var operands. */
21372 static tree
21373 find_link_var_op (tree *tp, int *walk_subtrees, void *)
21375 tree t = *tp;
21377 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
21378 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
21380 *walk_subtrees = 0;
21381 return t;
21384 return NULL_TREE;
21387 unsigned
21388 pass_omp_target_link::execute (function *fun)
21390 basic_block bb;
21391 FOR_EACH_BB_FN (bb, fun)
21393 gimple_stmt_iterator gsi;
21394 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
21395 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
21396 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
21399 return 0;
21402 } // anon namespace
21404 gimple_opt_pass *
21405 make_pass_omp_target_link (gcc::context *ctxt)
21407 return new pass_omp_target_link (ctxt);
21410 #include "gt-omp-low.h"