* omp-low.c (lower_omp_target): Remove unreachable code & merge
[official-gcc.git] / gcc / omp-low.c
blobd0264e9ce67b67cc36b9010f196a90ac80f8b278
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-2015 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"
84 /* Lowering of OMP parallel and workshare constructs proceeds in two
85 phases. The first phase scans the function looking for OMP statements
86 and then for variables that must be replaced to satisfy data sharing
87 clauses. The second phase expands code for the constructs, as well as
88 re-gimplifying things when variables have been replaced with complex
89 expressions.
91 Final code generation is done by pass_expand_omp. The flowgraph is
92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
95 /* OMP region information. Every parallel and workshare
96 directive is enclosed between two markers, the OMP_* directive
97 and a corresponding GIMPLE_OMP_RETURN statement. */
99 struct omp_region
101 /* The enclosing region. */
102 struct omp_region *outer;
104 /* First child region. */
105 struct omp_region *inner;
107 /* Next peer region. */
108 struct omp_region *next;
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
114 basic_block exit;
116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
117 basic_block cont;
119 /* If this is a combined parallel+workshare region, this is a list
120 of additional arguments needed by the combined parallel+workshare
121 library call. */
122 vec<tree, va_gc> *ws_args;
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
128 enum omp_clause_schedule_kind sched_kind;
130 /* True if this is a combined parallel+workshare region. */
131 bool is_combined_parallel;
133 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
134 a depend clause. */
135 gomp_ordered *ord_stmt;
138 /* Context structure. Used to store information about each parallel
139 directive in the code. */
141 struct omp_context
143 /* This field must be at the beginning, as we do "inheritance": Some
144 callback functions for tree-inline.c (e.g., omp_copy_decl)
145 receive a copy_body_data pointer that is up-casted to an
146 omp_context pointer. */
147 copy_body_data cb;
149 /* The tree of contexts corresponding to the encountered constructs. */
150 struct omp_context *outer;
151 gimple *stmt;
153 /* Map variables to fields in a structure that allows communication
154 between sending and receiving threads. */
155 splay_tree field_map;
156 tree record_type;
157 tree sender_decl;
158 tree receiver_decl;
160 /* These are used just by task contexts, if task firstprivate fn is
161 needed. srecord_type is used to communicate from the thread
162 that encountered the task construct to task firstprivate fn,
163 record_type is allocated by GOMP_task, initialized by task firstprivate
164 fn and passed to the task body fn. */
165 splay_tree sfield_map;
166 tree srecord_type;
168 /* A chain of variables to add to the top-level block surrounding the
169 construct. In the case of a parallel, this is in the child function. */
170 tree block_vars;
172 /* A map of reduction pointer variables. For accelerators, each
173 reduction variable is replaced with an array. Each thread, in turn,
174 is assigned to a slot on that array. */
175 splay_tree reduction_map;
177 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
178 barriers should jump to during omplower pass. */
179 tree cancel_label;
181 /* What to do with variables with implicitly determined sharing
182 attributes. */
183 enum omp_clause_default_kind default_kind;
185 /* Nesting depth of this context. Used to beautify error messages re
186 invalid gotos. The outermost ctx is depth 1, with depth 0 being
187 reserved for the main body of the function. */
188 int depth;
190 /* True if this parallel directive is nested within another. */
191 bool is_nested;
193 /* True if this construct can be cancelled. */
194 bool cancellable;
197 /* A structure holding the elements of:
198 for (V = N1; V cond N2; V += STEP) [...] */
200 struct omp_for_data_loop
202 tree v, n1, n2, step;
203 enum tree_code cond_code;
206 /* A structure describing the main elements of a parallel loop. */
208 struct omp_for_data
210 struct omp_for_data_loop loop;
211 tree chunk_size;
212 gomp_for *for_stmt;
213 tree pre, iter_type;
214 int collapse;
215 int ordered;
216 bool have_nowait, have_ordered, simd_schedule;
217 enum omp_clause_schedule_kind sched_kind;
218 struct omp_for_data_loop *loops;
221 /* Describe the OpenACC looping structure of a function. The entire
222 function is held in a 'NULL' loop. */
224 struct oacc_loop
226 oacc_loop *parent; /* Containing loop. */
228 oacc_loop *child; /* First inner loop. */
230 oacc_loop *sibling; /* Next loop within same parent. */
232 location_t loc; /* Location of the loop start. */
234 gcall *marker; /* Initial head marker. */
236 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
237 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
239 tree routine; /* Pseudo-loop enclosing a routine. */
241 unsigned mask; /* Partitioning mask. */
242 unsigned flags; /* Partitioning flags. */
243 tree chunk_size; /* Chunk size. */
244 gcall *head_end; /* Final marker of head sequence. */
247 /* Flags for an OpenACC loop. */
249 enum oacc_loop_flags {
250 OLF_SEQ = 1u << 0, /* Explicitly sequential */
251 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
252 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
253 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
255 /* Explicitly specified loop axes. */
256 OLF_DIM_BASE = 4,
257 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
258 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
259 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
261 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
265 static splay_tree all_contexts;
266 static int taskreg_nesting_level;
267 static int target_nesting_level;
268 static struct omp_region *root_omp_region;
269 static bitmap task_shared_vars;
270 static vec<omp_context *> taskreg_contexts;
272 static void scan_omp (gimple_seq *, omp_context *);
273 static tree scan_omp_1_op (tree *, int *, void *);
274 static gphi *find_phi_with_arg_on_edge (tree, edge);
276 #define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
281 case GIMPLE_TRANSACTION: \
282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
286 /* Return true if CTX corresponds to an oacc parallel region. */
288 static bool
289 is_oacc_parallel (omp_context *ctx)
291 enum gimple_code outer_type = gimple_code (ctx->stmt);
292 return ((outer_type == GIMPLE_OMP_TARGET)
293 && (gimple_omp_target_kind (ctx->stmt)
294 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
297 /* Return true if CTX corresponds to an oacc kernels region. */
299 static bool
300 is_oacc_kernels (omp_context *ctx)
302 enum gimple_code outer_type = gimple_code (ctx->stmt);
303 return ((outer_type == GIMPLE_OMP_TARGET)
304 && (gimple_omp_target_kind (ctx->stmt)
305 == GF_OMP_TARGET_KIND_OACC_KERNELS));
308 /* Helper function to get the name of the array containing the partial
309 reductions for OpenACC reductions. */
310 static const char *
311 oacc_get_reduction_array_id (tree node)
313 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
314 int len = strlen ("OACC") + strlen (id);
315 char *temp_name = XALLOCAVEC (char, len + 1);
316 snprintf (temp_name, len + 1, "OACC%s", id);
317 return IDENTIFIER_POINTER (get_identifier (temp_name));
320 /* Determine the number of threads OpenACC threads used to determine the
321 size of the array of partial reductions. Currently, this is num_gangs
322 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
323 because it is independed of the device used. */
325 static tree
326 oacc_max_threads (omp_context *ctx)
328 tree nthreads, vector_length, gangs, clauses;
330 gangs = fold_convert (sizetype, integer_one_node);
331 vector_length = gangs;
333 /* The reduction clause may be nested inside a loop directive.
334 Scan for the innermost vector_length clause. */
335 for (omp_context *oc = ctx; oc; oc = oc->outer)
337 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
338 || (gimple_omp_target_kind (oc->stmt)
339 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
340 continue;
342 clauses = gimple_omp_target_clauses (oc->stmt);
344 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
345 if (vector_length)
346 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
347 sizetype,
348 OMP_CLAUSE_VECTOR_LENGTH_EXPR
349 (vector_length));
350 else
351 vector_length = fold_convert (sizetype, integer_one_node);
353 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
354 if (gangs)
355 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
356 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
357 else
358 gangs = fold_convert (sizetype, integer_one_node);
360 break;
363 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
365 return nthreads;
368 /* If DECL is the artificial dummy VAR_DECL created for non-static
369 data member privatization, return the underlying "this" parameter,
370 otherwise return NULL. */
372 tree
373 omp_member_access_dummy_var (tree decl)
375 if (!VAR_P (decl)
376 || !DECL_ARTIFICIAL (decl)
377 || !DECL_IGNORED_P (decl)
378 || !DECL_HAS_VALUE_EXPR_P (decl)
379 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
380 return NULL_TREE;
382 tree v = DECL_VALUE_EXPR (decl);
383 if (TREE_CODE (v) != COMPONENT_REF)
384 return NULL_TREE;
386 while (1)
387 switch (TREE_CODE (v))
389 case COMPONENT_REF:
390 case MEM_REF:
391 case INDIRECT_REF:
392 CASE_CONVERT:
393 case POINTER_PLUS_EXPR:
394 v = TREE_OPERAND (v, 0);
395 continue;
396 case PARM_DECL:
397 if (DECL_CONTEXT (v) == current_function_decl
398 && DECL_ARTIFICIAL (v)
399 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
400 return v;
401 return NULL_TREE;
402 default:
403 return NULL_TREE;
407 /* Helper for unshare_and_remap, called through walk_tree. */
409 static tree
410 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
412 tree *pair = (tree *) data;
413 if (*tp == pair[0])
415 *tp = unshare_expr (pair[1]);
416 *walk_subtrees = 0;
418 else if (IS_TYPE_OR_DECL_P (*tp))
419 *walk_subtrees = 0;
420 return NULL_TREE;
423 /* Return unshare_expr (X) with all occurrences of FROM
424 replaced with TO. */
426 static tree
427 unshare_and_remap (tree x, tree from, tree to)
429 tree pair[2] = { from, to };
430 x = unshare_expr (x);
431 walk_tree (&x, unshare_and_remap_1, pair, NULL);
432 return x;
435 /* Holds offload tables with decls. */
436 vec<tree, va_gc> *offload_funcs, *offload_vars;
438 /* Convenience function for calling scan_omp_1_op on tree operands. */
440 static inline tree
441 scan_omp_op (tree *tp, omp_context *ctx)
443 struct walk_stmt_info wi;
445 memset (&wi, 0, sizeof (wi));
446 wi.info = ctx;
447 wi.want_locations = true;
449 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
452 static void lower_omp (gimple_seq *, omp_context *);
453 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
454 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
456 /* Find an OMP clause of type KIND within CLAUSES. */
458 tree
459 find_omp_clause (tree clauses, enum omp_clause_code kind)
461 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
462 if (OMP_CLAUSE_CODE (clauses) == kind)
463 return clauses;
465 return NULL_TREE;
468 /* Return true if CTX is for an omp parallel. */
470 static inline bool
471 is_parallel_ctx (omp_context *ctx)
473 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
477 /* Return true if CTX is for an omp task. */
479 static inline bool
480 is_task_ctx (omp_context *ctx)
482 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
486 /* Return true if CTX is for an omp taskloop. */
488 static inline bool
489 is_taskloop_ctx (omp_context *ctx)
491 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
492 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
496 /* Return true if CTX is for an omp parallel or omp task. */
498 static inline bool
499 is_taskreg_ctx (omp_context *ctx)
501 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
505 /* Return true if REGION is a combined parallel+workshare region. */
507 static inline bool
508 is_combined_parallel (struct omp_region *region)
510 return region->is_combined_parallel;
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->chunk_size = NULL_TREE;
547 fd->simd_schedule = false;
548 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
549 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
550 collapse_iter = NULL;
551 collapse_count = NULL;
553 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
554 switch (OMP_CLAUSE_CODE (t))
556 case OMP_CLAUSE_NOWAIT:
557 fd->have_nowait = true;
558 break;
559 case OMP_CLAUSE_ORDERED:
560 fd->have_ordered = true;
561 if (OMP_CLAUSE_ORDERED_EXPR (t))
562 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
563 break;
564 case OMP_CLAUSE_SCHEDULE:
565 gcc_assert (!distribute && !taskloop);
566 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
567 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
568 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
569 break;
570 case OMP_CLAUSE_DIST_SCHEDULE:
571 gcc_assert (distribute);
572 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
573 break;
574 case OMP_CLAUSE_COLLAPSE:
575 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
576 if (fd->collapse > 1)
578 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
579 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
581 break;
582 default:
583 break;
585 if (fd->ordered && fd->collapse == 1 && loops != NULL)
587 fd->loops = loops;
588 iterv = NULL_TREE;
589 countv = NULL_TREE;
590 collapse_iter = &iterv;
591 collapse_count = &countv;
594 /* FIXME: for now map schedule(auto) to schedule(static).
595 There should be analysis to determine whether all iterations
596 are approximately the same amount of work (then schedule(static)
597 is best) or if it varies (then schedule(dynamic,N) is better). */
598 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
600 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
601 gcc_assert (fd->chunk_size == NULL);
603 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
604 if (taskloop)
605 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
606 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
607 gcc_assert (fd->chunk_size == NULL);
608 else if (fd->chunk_size == NULL)
610 /* We only need to compute a default chunk size for ordered
611 static loops and dynamic loops. */
612 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
613 || fd->have_ordered)
614 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
615 ? integer_zero_node : integer_one_node;
618 int cnt = fd->ordered ? fd->ordered : fd->collapse;
619 for (i = 0; i < cnt; i++)
621 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
622 loop = &fd->loop;
623 else if (loops != NULL)
624 loop = loops + i;
625 else
626 loop = &dummy_loop;
628 loop->v = gimple_omp_for_index (for_stmt, i);
629 gcc_assert (SSA_VAR_P (loop->v));
630 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
631 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
632 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
633 loop->n1 = gimple_omp_for_initial (for_stmt, i);
635 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
636 loop->n2 = gimple_omp_for_final (for_stmt, i);
637 switch (loop->cond_code)
639 case LT_EXPR:
640 case GT_EXPR:
641 break;
642 case NE_EXPR:
643 gcc_assert (gimple_omp_for_kind (for_stmt)
644 == GF_OMP_FOR_KIND_CILKSIMD
645 || (gimple_omp_for_kind (for_stmt)
646 == GF_OMP_FOR_KIND_CILKFOR));
647 break;
648 case LE_EXPR:
649 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
650 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
651 else
652 loop->n2 = fold_build2_loc (loc,
653 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
654 build_int_cst (TREE_TYPE (loop->n2), 1));
655 loop->cond_code = LT_EXPR;
656 break;
657 case GE_EXPR:
658 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
659 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
660 else
661 loop->n2 = fold_build2_loc (loc,
662 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
663 build_int_cst (TREE_TYPE (loop->n2), 1));
664 loop->cond_code = GT_EXPR;
665 break;
666 default:
667 gcc_unreachable ();
670 t = gimple_omp_for_incr (for_stmt, i);
671 gcc_assert (TREE_OPERAND (t, 0) == var);
672 switch (TREE_CODE (t))
674 case PLUS_EXPR:
675 loop->step = TREE_OPERAND (t, 1);
676 break;
677 case POINTER_PLUS_EXPR:
678 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
679 break;
680 case MINUS_EXPR:
681 loop->step = TREE_OPERAND (t, 1);
682 loop->step = fold_build1_loc (loc,
683 NEGATE_EXPR, TREE_TYPE (loop->step),
684 loop->step);
685 break;
686 default:
687 gcc_unreachable ();
690 if (simd
691 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
692 && !fd->have_ordered))
694 if (fd->collapse == 1)
695 iter_type = TREE_TYPE (loop->v);
696 else if (i == 0
697 || TYPE_PRECISION (iter_type)
698 < TYPE_PRECISION (TREE_TYPE (loop->v)))
699 iter_type
700 = build_nonstandard_integer_type
701 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
703 else if (iter_type != long_long_unsigned_type_node)
705 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
706 iter_type = long_long_unsigned_type_node;
707 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
708 && TYPE_PRECISION (TREE_TYPE (loop->v))
709 >= TYPE_PRECISION (iter_type))
711 tree n;
713 if (loop->cond_code == LT_EXPR)
714 n = fold_build2_loc (loc,
715 PLUS_EXPR, TREE_TYPE (loop->v),
716 loop->n2, loop->step);
717 else
718 n = loop->n1;
719 if (TREE_CODE (n) != INTEGER_CST
720 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
721 iter_type = long_long_unsigned_type_node;
723 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
724 > TYPE_PRECISION (iter_type))
726 tree n1, n2;
728 if (loop->cond_code == LT_EXPR)
730 n1 = loop->n1;
731 n2 = fold_build2_loc (loc,
732 PLUS_EXPR, TREE_TYPE (loop->v),
733 loop->n2, loop->step);
735 else
737 n1 = fold_build2_loc (loc,
738 MINUS_EXPR, TREE_TYPE (loop->v),
739 loop->n2, loop->step);
740 n2 = loop->n1;
742 if (TREE_CODE (n1) != INTEGER_CST
743 || TREE_CODE (n2) != INTEGER_CST
744 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
745 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
746 iter_type = long_long_unsigned_type_node;
750 if (i >= fd->collapse)
751 continue;
753 if (collapse_count && *collapse_count == NULL)
755 t = fold_binary (loop->cond_code, boolean_type_node,
756 fold_convert (TREE_TYPE (loop->v), loop->n1),
757 fold_convert (TREE_TYPE (loop->v), loop->n2));
758 if (t && integer_zerop (t))
759 count = build_zero_cst (long_long_unsigned_type_node);
760 else if ((i == 0 || count != NULL_TREE)
761 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
762 && TREE_CONSTANT (loop->n1)
763 && TREE_CONSTANT (loop->n2)
764 && TREE_CODE (loop->step) == INTEGER_CST)
766 tree itype = TREE_TYPE (loop->v);
768 if (POINTER_TYPE_P (itype))
769 itype = signed_type_for (itype);
770 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
771 t = fold_build2_loc (loc,
772 PLUS_EXPR, itype,
773 fold_convert_loc (loc, itype, loop->step), t);
774 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
775 fold_convert_loc (loc, itype, loop->n2));
776 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
777 fold_convert_loc (loc, itype, loop->n1));
778 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
779 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
780 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
781 fold_build1_loc (loc, NEGATE_EXPR, itype,
782 fold_convert_loc (loc, itype,
783 loop->step)));
784 else
785 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
786 fold_convert_loc (loc, itype, loop->step));
787 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
788 if (count != NULL_TREE)
789 count = fold_build2_loc (loc,
790 MULT_EXPR, long_long_unsigned_type_node,
791 count, t);
792 else
793 count = t;
794 if (TREE_CODE (count) != INTEGER_CST)
795 count = NULL_TREE;
797 else if (count && !integer_zerop (count))
798 count = NULL_TREE;
802 if (count
803 && !simd
804 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
805 || fd->have_ordered))
807 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
808 iter_type = long_long_unsigned_type_node;
809 else
810 iter_type = long_integer_type_node;
812 else if (collapse_iter && *collapse_iter != NULL)
813 iter_type = TREE_TYPE (*collapse_iter);
814 fd->iter_type = iter_type;
815 if (collapse_iter && *collapse_iter == NULL)
816 *collapse_iter = create_tmp_var (iter_type, ".iter");
817 if (collapse_count && *collapse_count == NULL)
819 if (count)
820 *collapse_count = fold_convert_loc (loc, iter_type, count);
821 else
822 *collapse_count = create_tmp_var (iter_type, ".count");
825 if (fd->collapse > 1 || (fd->ordered && loops))
827 fd->loop.v = *collapse_iter;
828 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
829 fd->loop.n2 = *collapse_count;
830 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
831 fd->loop.cond_code = LT_EXPR;
833 else if (loops)
834 loops[0] = fd->loop;
838 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
839 is the immediate dominator of PAR_ENTRY_BB, return true if there
840 are no data dependencies that would prevent expanding the parallel
841 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
843 When expanding a combined parallel+workshare region, the call to
844 the child function may need additional arguments in the case of
845 GIMPLE_OMP_FOR regions. In some cases, these arguments are
846 computed out of variables passed in from the parent to the child
847 via 'struct .omp_data_s'. For instance:
849 #pragma omp parallel for schedule (guided, i * 4)
850 for (j ...)
852 Is lowered into:
854 # BLOCK 2 (PAR_ENTRY_BB)
855 .omp_data_o.i = i;
856 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
858 # BLOCK 3 (WS_ENTRY_BB)
859 .omp_data_i = &.omp_data_o;
860 D.1667 = .omp_data_i->i;
861 D.1598 = D.1667 * 4;
862 #pragma omp for schedule (guided, D.1598)
864 When we outline the parallel region, the call to the child function
865 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
866 that value is computed *after* the call site. So, in principle we
867 cannot do the transformation.
869 To see whether the code in WS_ENTRY_BB blocks the combined
870 parallel+workshare call, we collect all the variables used in the
871 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
872 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
873 call.
875 FIXME. If we had the SSA form built at this point, we could merely
876 hoist the code in block 3 into block 2 and be done with it. But at
877 this point we don't have dataflow information and though we could
878 hack something up here, it is really not worth the aggravation. */
880 static bool
881 workshare_safe_to_combine_p (basic_block ws_entry_bb)
883 struct omp_for_data fd;
884 gimple *ws_stmt = last_stmt (ws_entry_bb);
886 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
887 return true;
889 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
891 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
893 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
894 return false;
895 if (fd.iter_type != long_integer_type_node)
896 return false;
898 /* FIXME. We give up too easily here. If any of these arguments
899 are not constants, they will likely involve variables that have
900 been mapped into fields of .omp_data_s for sharing with the child
901 function. With appropriate data flow, it would be possible to
902 see through this. */
903 if (!is_gimple_min_invariant (fd.loop.n1)
904 || !is_gimple_min_invariant (fd.loop.n2)
905 || !is_gimple_min_invariant (fd.loop.step)
906 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
907 return false;
909 return true;
913 static int omp_max_vf (void);
915 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
916 presence (SIMD_SCHEDULE). */
918 static tree
919 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
921 if (!simd_schedule)
922 return chunk_size;
924 int vf = omp_max_vf ();
925 if (vf == 1)
926 return chunk_size;
928 tree type = TREE_TYPE (chunk_size);
929 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
930 build_int_cst (type, vf - 1));
931 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
932 build_int_cst (type, -vf));
936 /* Collect additional arguments needed to emit a combined
937 parallel+workshare call. WS_STMT is the workshare directive being
938 expanded. */
940 static vec<tree, va_gc> *
941 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
943 tree t;
944 location_t loc = gimple_location (ws_stmt);
945 vec<tree, va_gc> *ws_args;
947 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
949 struct omp_for_data fd;
950 tree n1, n2;
952 extract_omp_for_data (for_stmt, &fd, NULL);
953 n1 = fd.loop.n1;
954 n2 = fd.loop.n2;
956 if (gimple_omp_for_combined_into_p (for_stmt))
958 tree innerc
959 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
960 OMP_CLAUSE__LOOPTEMP_);
961 gcc_assert (innerc);
962 n1 = OMP_CLAUSE_DECL (innerc);
963 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
964 OMP_CLAUSE__LOOPTEMP_);
965 gcc_assert (innerc);
966 n2 = OMP_CLAUSE_DECL (innerc);
969 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
971 t = fold_convert_loc (loc, long_integer_type_node, n1);
972 ws_args->quick_push (t);
974 t = fold_convert_loc (loc, long_integer_type_node, n2);
975 ws_args->quick_push (t);
977 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
978 ws_args->quick_push (t);
980 if (fd.chunk_size)
982 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
983 t = omp_adjust_chunk_size (t, fd.simd_schedule);
984 ws_args->quick_push (t);
987 return ws_args;
989 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
991 /* Number of sections is equal to the number of edges from the
992 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
993 the exit of the sections region. */
994 basic_block bb = single_succ (gimple_bb (ws_stmt));
995 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
996 vec_alloc (ws_args, 1);
997 ws_args->quick_push (t);
998 return ws_args;
1001 gcc_unreachable ();
1005 /* Discover whether REGION is a combined parallel+workshare region. */
1007 static void
1008 determine_parallel_type (struct omp_region *region)
1010 basic_block par_entry_bb, par_exit_bb;
1011 basic_block ws_entry_bb, ws_exit_bb;
1013 if (region == NULL || region->inner == NULL
1014 || region->exit == NULL || region->inner->exit == NULL
1015 || region->inner->cont == NULL)
1016 return;
1018 /* We only support parallel+for and parallel+sections. */
1019 if (region->type != GIMPLE_OMP_PARALLEL
1020 || (region->inner->type != GIMPLE_OMP_FOR
1021 && region->inner->type != GIMPLE_OMP_SECTIONS))
1022 return;
1024 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
1025 WS_EXIT_BB -> PAR_EXIT_BB. */
1026 par_entry_bb = region->entry;
1027 par_exit_bb = region->exit;
1028 ws_entry_bb = region->inner->entry;
1029 ws_exit_bb = region->inner->exit;
1031 if (single_succ (par_entry_bb) == ws_entry_bb
1032 && single_succ (ws_exit_bb) == par_exit_bb
1033 && workshare_safe_to_combine_p (ws_entry_bb)
1034 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
1035 || (last_and_only_stmt (ws_entry_bb)
1036 && last_and_only_stmt (par_exit_bb))))
1038 gimple *par_stmt = last_stmt (par_entry_bb);
1039 gimple *ws_stmt = last_stmt (ws_entry_bb);
1041 if (region->inner->type == GIMPLE_OMP_FOR)
1043 /* If this is a combined parallel loop, we need to determine
1044 whether or not to use the combined library calls. There
1045 are two cases where we do not apply the transformation:
1046 static loops and any kind of ordered loop. In the first
1047 case, we already open code the loop so there is no need
1048 to do anything else. In the latter case, the combined
1049 parallel loop call would still need extra synchronization
1050 to implement ordered semantics, so there would not be any
1051 gain in using the combined call. */
1052 tree clauses = gimple_omp_for_clauses (ws_stmt);
1053 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1054 if (c == NULL
1055 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
1056 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1058 region->is_combined_parallel = false;
1059 region->inner->is_combined_parallel = false;
1060 return;
1064 region->is_combined_parallel = true;
1065 region->inner->is_combined_parallel = true;
1066 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1071 /* Return true if EXPR is variable sized. */
1073 static inline bool
1074 is_variable_sized (const_tree expr)
1076 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1079 /* Return true if DECL is a reference type. */
1081 static inline bool
1082 is_reference (tree decl)
1084 return lang_hooks.decls.omp_privatize_by_reference (decl);
1087 /* Return the type of a decl. If the decl is reference type,
1088 return its base type. */
1089 static inline tree
1090 get_base_type (tree decl)
1092 tree type = TREE_TYPE (decl);
1093 if (is_reference (decl))
1094 type = TREE_TYPE (type);
1095 return type;
1098 /* Lookup variables. The "maybe" form
1099 allows for the variable form to not have been entered, otherwise we
1100 assert that the variable must have been entered. */
1102 static inline tree
1103 lookup_decl (tree var, omp_context *ctx)
1105 tree *n = ctx->cb.decl_map->get (var);
1106 return *n;
1109 static inline tree
1110 maybe_lookup_decl (const_tree var, omp_context *ctx)
1112 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1113 return n ? *n : NULL_TREE;
1116 static inline tree
1117 lookup_field (tree var, omp_context *ctx)
1119 splay_tree_node n;
1120 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1121 return (tree) n->value;
1124 static inline tree
1125 lookup_sfield (splay_tree_key key, omp_context *ctx)
1127 splay_tree_node n;
1128 n = splay_tree_lookup (ctx->sfield_map
1129 ? ctx->sfield_map : ctx->field_map, key);
1130 return (tree) n->value;
1133 static inline tree
1134 lookup_sfield (tree var, omp_context *ctx)
1136 return lookup_sfield ((splay_tree_key) var, ctx);
1139 static inline tree
1140 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1142 splay_tree_node n;
1143 n = splay_tree_lookup (ctx->field_map, key);
1144 return n ? (tree) n->value : NULL_TREE;
1147 static inline tree
1148 maybe_lookup_field (tree var, omp_context *ctx)
1150 return maybe_lookup_field ((splay_tree_key) var, ctx);
1153 static inline tree
1154 lookup_oacc_reduction (const char *id, omp_context *ctx)
1156 splay_tree_node n;
1157 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1158 return (tree) n->value;
1161 static inline tree
1162 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1164 splay_tree_node n = NULL;
1165 if (ctx->reduction_map)
1166 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1167 return n ? (tree) n->value : NULL_TREE;
1170 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1171 the parallel context if DECL is to be shared. */
1173 static bool
1174 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1176 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1177 return true;
1179 /* We can only use copy-in/copy-out semantics for shared variables
1180 when we know the value is not accessible from an outer scope. */
1181 if (shared_ctx)
1183 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1185 /* ??? Trivially accessible from anywhere. But why would we even
1186 be passing an address in this case? Should we simply assert
1187 this to be false, or should we have a cleanup pass that removes
1188 these from the list of mappings? */
1189 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1190 return true;
1192 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1193 without analyzing the expression whether or not its location
1194 is accessible to anyone else. In the case of nested parallel
1195 regions it certainly may be. */
1196 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1197 return true;
1199 /* Do not use copy-in/copy-out for variables that have their
1200 address taken. */
1201 if (TREE_ADDRESSABLE (decl))
1202 return true;
1204 /* lower_send_shared_vars only uses copy-in, but not copy-out
1205 for these. */
1206 if (TREE_READONLY (decl)
1207 || ((TREE_CODE (decl) == RESULT_DECL
1208 || TREE_CODE (decl) == PARM_DECL)
1209 && DECL_BY_REFERENCE (decl)))
1210 return false;
1212 /* Disallow copy-in/out in nested parallel if
1213 decl is shared in outer parallel, otherwise
1214 each thread could store the shared variable
1215 in its own copy-in location, making the
1216 variable no longer really shared. */
1217 if (shared_ctx->is_nested)
1219 omp_context *up;
1221 for (up = shared_ctx->outer; up; up = up->outer)
1222 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1223 break;
1225 if (up)
1227 tree c;
1229 for (c = gimple_omp_taskreg_clauses (up->stmt);
1230 c; c = OMP_CLAUSE_CHAIN (c))
1231 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1232 && OMP_CLAUSE_DECL (c) == decl)
1233 break;
1235 if (c)
1236 goto maybe_mark_addressable_and_ret;
1240 /* For tasks avoid using copy-in/out. As tasks can be
1241 deferred or executed in different thread, when GOMP_task
1242 returns, the task hasn't necessarily terminated. */
1243 if (is_task_ctx (shared_ctx))
1245 tree outer;
1246 maybe_mark_addressable_and_ret:
1247 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1248 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1250 /* Taking address of OUTER in lower_send_shared_vars
1251 might need regimplification of everything that uses the
1252 variable. */
1253 if (!task_shared_vars)
1254 task_shared_vars = BITMAP_ALLOC (NULL);
1255 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1256 TREE_ADDRESSABLE (outer) = 1;
1258 return true;
1262 return false;
1265 /* Construct a new automatic decl similar to VAR. */
1267 static tree
1268 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1270 tree copy = copy_var_decl (var, name, type);
1272 DECL_CONTEXT (copy) = current_function_decl;
1273 DECL_CHAIN (copy) = ctx->block_vars;
1274 /* If VAR is listed in task_shared_vars, it means it wasn't
1275 originally addressable and is just because task needs to take
1276 it's address. But we don't need to take address of privatizations
1277 from that var. */
1278 if (TREE_ADDRESSABLE (var)
1279 && task_shared_vars
1280 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1281 TREE_ADDRESSABLE (copy) = 0;
1282 ctx->block_vars = copy;
1284 return copy;
1287 static tree
1288 omp_copy_decl_1 (tree var, omp_context *ctx)
1290 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1293 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1294 as appropriate. */
1295 static tree
1296 omp_build_component_ref (tree obj, tree field)
1298 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1299 if (TREE_THIS_VOLATILE (field))
1300 TREE_THIS_VOLATILE (ret) |= 1;
1301 if (TREE_READONLY (field))
1302 TREE_READONLY (ret) |= 1;
1303 return ret;
1306 /* Build tree nodes to access the field for VAR on the receiver side. */
1308 static tree
1309 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1311 tree x, field = lookup_field (var, ctx);
1313 /* If the receiver record type was remapped in the child function,
1314 remap the field into the new record type. */
1315 x = maybe_lookup_field (field, ctx);
1316 if (x != NULL)
1317 field = x;
1319 x = build_simple_mem_ref (ctx->receiver_decl);
1320 TREE_THIS_NOTRAP (x) = 1;
1321 x = omp_build_component_ref (x, field);
1322 if (by_ref)
1323 x = build_simple_mem_ref (x);
1325 return x;
1328 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1329 of a parallel, this is a component reference; for workshare constructs
1330 this is some variable. */
1332 static tree
1333 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1335 tree x;
1337 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1338 x = var;
1339 else if (is_variable_sized (var))
1341 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1342 x = build_outer_var_ref (x, ctx, lastprivate);
1343 x = build_simple_mem_ref (x);
1345 else if (is_taskreg_ctx (ctx))
1347 bool by_ref = use_pointer_for_field (var, NULL);
1348 x = build_receiver_ref (var, by_ref, ctx);
1350 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1351 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1353 /* #pragma omp simd isn't a worksharing construct, and can reference even
1354 private vars in its linear etc. clauses. */
1355 x = NULL_TREE;
1356 if (ctx->outer && is_taskreg_ctx (ctx))
1357 x = lookup_decl (var, ctx->outer);
1358 else if (ctx->outer)
1359 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1360 if (x == NULL_TREE)
1361 x = var;
1363 else if (lastprivate && is_taskloop_ctx (ctx))
1365 gcc_assert (ctx->outer);
1366 splay_tree_node n
1367 = splay_tree_lookup (ctx->outer->field_map,
1368 (splay_tree_key) &DECL_UID (var));
1369 if (n == NULL)
1371 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1372 x = var;
1373 else
1374 x = lookup_decl (var, ctx->outer);
1376 else
1378 tree field = (tree) n->value;
1379 /* If the receiver record type was remapped in the child function,
1380 remap the field into the new record type. */
1381 x = maybe_lookup_field (field, ctx->outer);
1382 if (x != NULL)
1383 field = x;
1385 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1386 x = omp_build_component_ref (x, field);
1387 if (use_pointer_for_field (var, ctx->outer))
1388 x = build_simple_mem_ref (x);
1391 else if (ctx->outer)
1392 x = lookup_decl (var, ctx->outer);
1393 else if (is_reference (var))
1394 /* This can happen with orphaned constructs. If var is reference, it is
1395 possible it is shared and as such valid. */
1396 x = var;
1397 else if (omp_member_access_dummy_var (var))
1398 x = var;
1399 else
1400 gcc_unreachable ();
1402 if (x == var)
1404 tree t = omp_member_access_dummy_var (var);
1405 if (t)
1407 x = DECL_VALUE_EXPR (var);
1408 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1409 if (o != t)
1410 x = unshare_and_remap (x, t, o);
1411 else
1412 x = unshare_expr (x);
1416 if (is_reference (var))
1417 x = build_simple_mem_ref (x);
1419 return x;
1422 /* Build tree nodes to access the field for VAR on the sender side. */
1424 static tree
1425 build_sender_ref (splay_tree_key key, omp_context *ctx)
1427 tree field = lookup_sfield (key, ctx);
1428 return omp_build_component_ref (ctx->sender_decl, field);
1431 static tree
1432 build_sender_ref (tree var, omp_context *ctx)
1434 return build_sender_ref ((splay_tree_key) var, ctx);
1437 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1439 static void
1440 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1442 tree field, type, sfield = NULL_TREE;
1443 splay_tree_key key = (splay_tree_key) var;
1445 if ((mask & 8) != 0)
1447 key = (splay_tree_key) &DECL_UID (var);
1448 gcc_checking_assert (key != (splay_tree_key) var);
1450 gcc_assert ((mask & 1) == 0
1451 || !splay_tree_lookup (ctx->field_map, key));
1452 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1453 || !splay_tree_lookup (ctx->sfield_map, key));
1454 gcc_assert ((mask & 3) == 3
1455 || !is_gimple_omp_oacc (ctx->stmt));
1457 type = TREE_TYPE (var);
1458 if (mask & 4)
1460 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1461 type = build_pointer_type (build_pointer_type (type));
1463 else if (by_ref)
1464 type = build_pointer_type (type);
1465 else if ((mask & 3) == 1 && is_reference (var))
1466 type = TREE_TYPE (type);
1468 field = build_decl (DECL_SOURCE_LOCATION (var),
1469 FIELD_DECL, DECL_NAME (var), type);
1471 /* Remember what variable this field was created for. This does have a
1472 side effect of making dwarf2out ignore this member, so for helpful
1473 debugging we clear it later in delete_omp_context. */
1474 DECL_ABSTRACT_ORIGIN (field) = var;
1475 if (type == TREE_TYPE (var))
1477 DECL_ALIGN (field) = DECL_ALIGN (var);
1478 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1479 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1481 else
1482 DECL_ALIGN (field) = TYPE_ALIGN (type);
1484 if ((mask & 3) == 3)
1486 insert_field_into_struct (ctx->record_type, field);
1487 if (ctx->srecord_type)
1489 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1490 FIELD_DECL, DECL_NAME (var), type);
1491 DECL_ABSTRACT_ORIGIN (sfield) = var;
1492 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1493 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1494 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1495 insert_field_into_struct (ctx->srecord_type, sfield);
1498 else
1500 if (ctx->srecord_type == NULL_TREE)
1502 tree t;
1504 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1505 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1506 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1508 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1509 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1510 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1511 insert_field_into_struct (ctx->srecord_type, sfield);
1512 splay_tree_insert (ctx->sfield_map,
1513 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1514 (splay_tree_value) sfield);
1517 sfield = field;
1518 insert_field_into_struct ((mask & 1) ? ctx->record_type
1519 : ctx->srecord_type, field);
1522 if (mask & 1)
1523 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1524 if ((mask & 2) && ctx->sfield_map)
1525 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1528 static tree
1529 install_var_local (tree var, omp_context *ctx)
1531 tree new_var = omp_copy_decl_1 (var, ctx);
1532 insert_decl_map (&ctx->cb, var, new_var);
1533 return new_var;
1536 /* Adjust the replacement for DECL in CTX for the new context. This means
1537 copying the DECL_VALUE_EXPR, and fixing up the type. */
1539 static void
1540 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1542 tree new_decl, size;
1544 new_decl = lookup_decl (decl, ctx);
1546 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1548 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1549 && DECL_HAS_VALUE_EXPR_P (decl))
1551 tree ve = DECL_VALUE_EXPR (decl);
1552 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1553 SET_DECL_VALUE_EXPR (new_decl, ve);
1554 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1557 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1559 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1560 if (size == error_mark_node)
1561 size = TYPE_SIZE (TREE_TYPE (new_decl));
1562 DECL_SIZE (new_decl) = size;
1564 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1565 if (size == error_mark_node)
1566 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1567 DECL_SIZE_UNIT (new_decl) = size;
1571 /* The callback for remap_decl. Search all containing contexts for a
1572 mapping of the variable; this avoids having to duplicate the splay
1573 tree ahead of time. We know a mapping doesn't already exist in the
1574 given context. Create new mappings to implement default semantics. */
1576 static tree
1577 omp_copy_decl (tree var, copy_body_data *cb)
1579 omp_context *ctx = (omp_context *) cb;
1580 tree new_var;
1582 if (TREE_CODE (var) == LABEL_DECL)
1584 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1585 DECL_CONTEXT (new_var) = current_function_decl;
1586 insert_decl_map (&ctx->cb, var, new_var);
1587 return new_var;
1590 while (!is_taskreg_ctx (ctx))
1592 ctx = ctx->outer;
1593 if (ctx == NULL)
1594 return var;
1595 new_var = maybe_lookup_decl (var, ctx);
1596 if (new_var)
1597 return new_var;
1600 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1601 return var;
1603 return error_mark_node;
1607 /* Debugging dumps for parallel regions. */
1608 void dump_omp_region (FILE *, struct omp_region *, int);
1609 void debug_omp_region (struct omp_region *);
1610 void debug_all_omp_regions (void);
1612 /* Dump the parallel region tree rooted at REGION. */
1614 void
1615 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1617 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1618 gimple_code_name[region->type]);
1620 if (region->inner)
1621 dump_omp_region (file, region->inner, indent + 4);
1623 if (region->cont)
1625 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1626 region->cont->index);
1629 if (region->exit)
1630 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1631 region->exit->index);
1632 else
1633 fprintf (file, "%*s[no exit marker]\n", indent, "");
1635 if (region->next)
1636 dump_omp_region (file, region->next, indent);
1639 DEBUG_FUNCTION void
1640 debug_omp_region (struct omp_region *region)
1642 dump_omp_region (stderr, region, 0);
1645 DEBUG_FUNCTION void
1646 debug_all_omp_regions (void)
1648 dump_omp_region (stderr, root_omp_region, 0);
1652 /* Create a new parallel region starting at STMT inside region PARENT. */
1654 static struct omp_region *
1655 new_omp_region (basic_block bb, enum gimple_code type,
1656 struct omp_region *parent)
1658 struct omp_region *region = XCNEW (struct omp_region);
1660 region->outer = parent;
1661 region->entry = bb;
1662 region->type = type;
1664 if (parent)
1666 /* This is a nested region. Add it to the list of inner
1667 regions in PARENT. */
1668 region->next = parent->inner;
1669 parent->inner = region;
1671 else
1673 /* This is a toplevel region. Add it to the list of toplevel
1674 regions in ROOT_OMP_REGION. */
1675 region->next = root_omp_region;
1676 root_omp_region = region;
1679 return region;
1682 /* Release the memory associated with the region tree rooted at REGION. */
1684 static void
1685 free_omp_region_1 (struct omp_region *region)
1687 struct omp_region *i, *n;
1689 for (i = region->inner; i ; i = n)
1691 n = i->next;
1692 free_omp_region_1 (i);
1695 free (region);
1698 /* Release the memory for the entire omp region tree. */
1700 void
1701 free_omp_regions (void)
1703 struct omp_region *r, *n;
1704 for (r = root_omp_region; r ; r = n)
1706 n = r->next;
1707 free_omp_region_1 (r);
1709 root_omp_region = NULL;
1713 /* Create a new context, with OUTER_CTX being the surrounding context. */
1715 static omp_context *
1716 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1718 omp_context *ctx = XCNEW (omp_context);
1720 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1721 (splay_tree_value) ctx);
1722 ctx->stmt = stmt;
1724 if (outer_ctx)
1726 ctx->outer = outer_ctx;
1727 ctx->cb = outer_ctx->cb;
1728 ctx->cb.block = NULL;
1729 ctx->depth = outer_ctx->depth + 1;
1730 ctx->reduction_map = outer_ctx->reduction_map;
1732 else
1734 ctx->cb.src_fn = current_function_decl;
1735 ctx->cb.dst_fn = current_function_decl;
1736 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1737 gcc_checking_assert (ctx->cb.src_node);
1738 ctx->cb.dst_node = ctx->cb.src_node;
1739 ctx->cb.src_cfun = cfun;
1740 ctx->cb.copy_decl = omp_copy_decl;
1741 ctx->cb.eh_lp_nr = 0;
1742 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1743 ctx->depth = 1;
1746 ctx->cb.decl_map = new hash_map<tree, tree>;
1748 return ctx;
1751 static gimple_seq maybe_catch_exception (gimple_seq);
1753 /* Finalize task copyfn. */
1755 static void
1756 finalize_task_copyfn (gomp_task *task_stmt)
1758 struct function *child_cfun;
1759 tree child_fn;
1760 gimple_seq seq = NULL, new_seq;
1761 gbind *bind;
1763 child_fn = gimple_omp_task_copy_fn (task_stmt);
1764 if (child_fn == NULL_TREE)
1765 return;
1767 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1768 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1770 push_cfun (child_cfun);
1771 bind = gimplify_body (child_fn, false);
1772 gimple_seq_add_stmt (&seq, bind);
1773 new_seq = maybe_catch_exception (seq);
1774 if (new_seq != seq)
1776 bind = gimple_build_bind (NULL, new_seq, NULL);
1777 seq = NULL;
1778 gimple_seq_add_stmt (&seq, bind);
1780 gimple_set_body (child_fn, seq);
1781 pop_cfun ();
1783 /* Inform the callgraph about the new function. */
1784 cgraph_node *node = cgraph_node::get_create (child_fn);
1785 node->parallelized_function = 1;
1786 cgraph_node::add_new_function (child_fn, false);
1789 /* Destroy a omp_context data structures. Called through the splay tree
1790 value delete callback. */
1792 static void
1793 delete_omp_context (splay_tree_value value)
1795 omp_context *ctx = (omp_context *) value;
1797 delete ctx->cb.decl_map;
1799 if (ctx->field_map)
1800 splay_tree_delete (ctx->field_map);
1801 if (ctx->sfield_map)
1802 splay_tree_delete (ctx->sfield_map);
1803 /* Reduction map is copied to nested contexts, so only delete it in the
1804 owner. */
1805 if (ctx->reduction_map
1806 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1807 && is_gimple_omp_offloaded (ctx->stmt)
1808 && is_gimple_omp_oacc (ctx->stmt))
1809 splay_tree_delete (ctx->reduction_map);
1811 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1812 it produces corrupt debug information. */
1813 if (ctx->record_type)
1815 tree t;
1816 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1817 DECL_ABSTRACT_ORIGIN (t) = NULL;
1819 if (ctx->srecord_type)
1821 tree t;
1822 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1823 DECL_ABSTRACT_ORIGIN (t) = NULL;
1826 if (is_task_ctx (ctx))
1827 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1829 XDELETE (ctx);
1832 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1833 context. */
1835 static void
1836 fixup_child_record_type (omp_context *ctx)
1838 tree f, type = ctx->record_type;
1840 /* ??? It isn't sufficient to just call remap_type here, because
1841 variably_modified_type_p doesn't work the way we expect for
1842 record types. Testing each field for whether it needs remapping
1843 and creating a new record by hand works, however. */
1844 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1845 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1846 break;
1847 if (f)
1849 tree name, new_fields = NULL;
1851 type = lang_hooks.types.make_type (RECORD_TYPE);
1852 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1853 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1854 TYPE_DECL, name, type);
1855 TYPE_NAME (type) = name;
1857 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1859 tree new_f = copy_node (f);
1860 DECL_CONTEXT (new_f) = type;
1861 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1862 DECL_CHAIN (new_f) = new_fields;
1863 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1864 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1865 &ctx->cb, NULL);
1866 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1867 &ctx->cb, NULL);
1868 new_fields = new_f;
1870 /* Arrange to be able to look up the receiver field
1871 given the sender field. */
1872 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1873 (splay_tree_value) new_f);
1875 TYPE_FIELDS (type) = nreverse (new_fields);
1876 layout_type (type);
1879 /* In a target region we never modify any of the pointers in *.omp_data_i,
1880 so attempt to help the optimizers. */
1881 if (is_gimple_omp_offloaded (ctx->stmt))
1882 type = build_qualified_type (type, TYPE_QUAL_CONST);
1884 TREE_TYPE (ctx->receiver_decl)
1885 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1888 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1889 specified by CLAUSES. */
1891 static void
1892 scan_sharing_clauses (tree clauses, omp_context *ctx)
1894 tree c, decl;
1895 bool scan_array_reductions = false;
1897 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1899 bool by_ref;
1901 switch (OMP_CLAUSE_CODE (c))
1903 case OMP_CLAUSE_PRIVATE:
1904 decl = OMP_CLAUSE_DECL (c);
1905 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1906 goto do_private;
1907 else if (!is_variable_sized (decl))
1908 install_var_local (decl, ctx);
1909 break;
1911 case OMP_CLAUSE_SHARED:
1912 decl = OMP_CLAUSE_DECL (c);
1913 /* Ignore shared directives in teams construct. */
1914 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1916 /* Global variables don't need to be copied,
1917 the receiver side will use them directly. */
1918 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1919 if (is_global_var (odecl))
1920 break;
1921 insert_decl_map (&ctx->cb, decl, odecl);
1922 break;
1924 gcc_assert (is_taskreg_ctx (ctx));
1925 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1926 || !is_variable_sized (decl));
1927 /* Global variables don't need to be copied,
1928 the receiver side will use them directly. */
1929 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1930 break;
1931 by_ref = use_pointer_for_field (decl, ctx);
1932 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1933 break;
1934 if (! TREE_READONLY (decl)
1935 || TREE_ADDRESSABLE (decl)
1936 || by_ref
1937 || is_reference (decl))
1939 install_var_field (decl, by_ref, 3, ctx);
1940 install_var_local (decl, ctx);
1941 break;
1943 /* We don't need to copy const scalar vars back. */
1944 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1945 goto do_private;
1947 case OMP_CLAUSE_REDUCTION:
1948 decl = OMP_CLAUSE_DECL (c);
1949 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1950 && TREE_CODE (decl) == MEM_REF)
1952 tree t = TREE_OPERAND (decl, 0);
1953 if (TREE_CODE (t) == INDIRECT_REF
1954 || TREE_CODE (t) == ADDR_EXPR)
1955 t = TREE_OPERAND (t, 0);
1956 install_var_local (t, ctx);
1957 if (is_taskreg_ctx (ctx)
1958 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1959 && !is_variable_sized (t))
1961 by_ref = use_pointer_for_field (t, ctx);
1962 install_var_field (t, by_ref, 3, ctx);
1964 break;
1966 goto do_private;
1968 case OMP_CLAUSE_LASTPRIVATE:
1969 /* Let the corresponding firstprivate clause create
1970 the variable. */
1971 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1972 break;
1973 /* FALLTHRU */
1975 case OMP_CLAUSE_FIRSTPRIVATE:
1976 if (is_gimple_omp_oacc (ctx->stmt))
1978 sorry ("clause not supported yet");
1979 break;
1981 /* FALLTHRU */
1982 case OMP_CLAUSE_LINEAR:
1983 decl = OMP_CLAUSE_DECL (c);
1984 do_private:
1985 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1986 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1987 && is_gimple_omp_offloaded (ctx->stmt))
1989 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1990 install_var_field (decl, !is_reference (decl), 3, ctx);
1991 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1996 if (is_variable_sized (decl))
1998 if (is_task_ctx (ctx))
1999 install_var_field (decl, false, 1, ctx);
2000 break;
2002 else if (is_taskreg_ctx (ctx))
2004 bool global
2005 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
2006 by_ref = use_pointer_for_field (decl, NULL);
2008 if (is_task_ctx (ctx)
2009 && (global || by_ref || is_reference (decl)))
2011 install_var_field (decl, false, 1, ctx);
2012 if (!global)
2013 install_var_field (decl, by_ref, 2, ctx);
2015 else if (!global)
2016 install_var_field (decl, by_ref, 3, ctx);
2018 install_var_local (decl, ctx);
2019 if (is_gimple_omp_oacc (ctx->stmt)
2020 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2022 /* Create a decl for the reduction array. */
2023 tree var = OMP_CLAUSE_DECL (c);
2024 tree type = get_base_type (var);
2025 tree ptype = build_pointer_type (type);
2026 tree array = create_tmp_var (ptype,
2027 oacc_get_reduction_array_id (var));
2028 omp_context *octx = (ctx->field_map ? ctx : ctx->outer);
2029 install_var_field (array, true, 3, octx);
2030 install_var_local (array, octx);
2032 /* Insert it into the current context. */
2033 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
2034 oacc_get_reduction_array_id (var),
2035 (splay_tree_value) array);
2036 splay_tree_insert (ctx->reduction_map,
2037 (splay_tree_key) array,
2038 (splay_tree_value) array);
2040 break;
2042 case OMP_CLAUSE_USE_DEVICE_PTR:
2043 decl = OMP_CLAUSE_DECL (c);
2044 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2045 install_var_field (decl, true, 3, ctx);
2046 else
2047 install_var_field (decl, false, 3, ctx);
2048 if (DECL_SIZE (decl)
2049 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2051 tree decl2 = DECL_VALUE_EXPR (decl);
2052 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2053 decl2 = TREE_OPERAND (decl2, 0);
2054 gcc_assert (DECL_P (decl2));
2055 install_var_local (decl2, ctx);
2057 install_var_local (decl, ctx);
2058 break;
2060 case OMP_CLAUSE_IS_DEVICE_PTR:
2061 decl = OMP_CLAUSE_DECL (c);
2062 goto do_private;
2064 case OMP_CLAUSE__LOOPTEMP_:
2065 gcc_assert (is_taskreg_ctx (ctx));
2066 decl = OMP_CLAUSE_DECL (c);
2067 install_var_field (decl, false, 3, ctx);
2068 install_var_local (decl, ctx);
2069 break;
2071 case OMP_CLAUSE_COPYPRIVATE:
2072 case OMP_CLAUSE_COPYIN:
2073 decl = OMP_CLAUSE_DECL (c);
2074 by_ref = use_pointer_for_field (decl, NULL);
2075 install_var_field (decl, by_ref, 3, ctx);
2076 break;
2078 case OMP_CLAUSE_DEFAULT:
2079 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2080 break;
2082 case OMP_CLAUSE_FINAL:
2083 case OMP_CLAUSE_IF:
2084 case OMP_CLAUSE_NUM_THREADS:
2085 case OMP_CLAUSE_NUM_TEAMS:
2086 case OMP_CLAUSE_THREAD_LIMIT:
2087 case OMP_CLAUSE_DEVICE:
2088 case OMP_CLAUSE_SCHEDULE:
2089 case OMP_CLAUSE_DIST_SCHEDULE:
2090 case OMP_CLAUSE_DEPEND:
2091 case OMP_CLAUSE_PRIORITY:
2092 case OMP_CLAUSE_GRAINSIZE:
2093 case OMP_CLAUSE_NUM_TASKS:
2094 case OMP_CLAUSE__CILK_FOR_COUNT_:
2095 case OMP_CLAUSE_NUM_GANGS:
2096 case OMP_CLAUSE_NUM_WORKERS:
2097 case OMP_CLAUSE_VECTOR_LENGTH:
2098 if (ctx->outer)
2099 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2100 break;
2102 case OMP_CLAUSE_TO:
2103 case OMP_CLAUSE_FROM:
2104 case OMP_CLAUSE_MAP:
2105 if (ctx->outer)
2106 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2107 decl = OMP_CLAUSE_DECL (c);
2108 /* Global variables with "omp declare target" attribute
2109 don't need to be copied, the receiver side will use them
2110 directly. */
2111 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2112 && DECL_P (decl)
2113 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2114 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2115 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2116 && varpool_node::get_create (decl)->offloadable)
2117 break;
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2121 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2122 not offloaded; there is nothing to map for those. */
2123 if (!is_gimple_omp_offloaded (ctx->stmt)
2124 && !POINTER_TYPE_P (TREE_TYPE (decl))
2125 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2126 break;
2128 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2129 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2131 if (TREE_CODE (decl) == COMPONENT_REF
2132 || (TREE_CODE (decl) == INDIRECT_REF
2133 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2134 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2135 == REFERENCE_TYPE)))
2136 break;
2137 if (DECL_SIZE (decl)
2138 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2140 tree decl2 = DECL_VALUE_EXPR (decl);
2141 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2142 decl2 = TREE_OPERAND (decl2, 0);
2143 gcc_assert (DECL_P (decl2));
2144 install_var_local (decl2, ctx);
2146 install_var_local (decl, ctx);
2147 break;
2149 if (DECL_P (decl))
2151 if (DECL_SIZE (decl)
2152 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2154 tree decl2 = DECL_VALUE_EXPR (decl);
2155 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2156 decl2 = TREE_OPERAND (decl2, 0);
2157 gcc_assert (DECL_P (decl2));
2158 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2159 && OMP_CLAUSE_MAP_PRIVATE (c))
2160 install_var_field (decl2, true, 11, ctx);
2161 else
2162 install_var_field (decl2, true, 3, ctx);
2163 install_var_local (decl2, ctx);
2164 install_var_local (decl, ctx);
2166 else
2168 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2169 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2170 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2171 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2172 install_var_field (decl, true, 7, ctx);
2173 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2174 && OMP_CLAUSE_MAP_PRIVATE (c))
2175 install_var_field (decl, true, 11, ctx);
2176 else
2177 install_var_field (decl, true, 3, ctx);
2178 if (is_gimple_omp_offloaded (ctx->stmt))
2179 install_var_local (decl, ctx);
2182 else
2184 tree base = get_base_address (decl);
2185 tree nc = OMP_CLAUSE_CHAIN (c);
2186 if (DECL_P (base)
2187 && nc != NULL_TREE
2188 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2189 && OMP_CLAUSE_DECL (nc) == base
2190 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2191 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2193 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2194 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2196 else
2198 if (ctx->outer)
2200 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2201 decl = OMP_CLAUSE_DECL (c);
2203 gcc_assert (!splay_tree_lookup (ctx->field_map,
2204 (splay_tree_key) decl));
2205 tree field
2206 = build_decl (OMP_CLAUSE_LOCATION (c),
2207 FIELD_DECL, NULL_TREE, ptr_type_node);
2208 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2209 insert_field_into_struct (ctx->record_type, field);
2210 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2211 (splay_tree_value) field);
2214 break;
2216 case OMP_CLAUSE_NOWAIT:
2217 case OMP_CLAUSE_ORDERED:
2218 case OMP_CLAUSE_COLLAPSE:
2219 case OMP_CLAUSE_UNTIED:
2220 case OMP_CLAUSE_MERGEABLE:
2221 case OMP_CLAUSE_PROC_BIND:
2222 case OMP_CLAUSE_SAFELEN:
2223 case OMP_CLAUSE_SIMDLEN:
2224 case OMP_CLAUSE_THREADS:
2225 case OMP_CLAUSE_SIMD:
2226 case OMP_CLAUSE_NOGROUP:
2227 case OMP_CLAUSE_DEFAULTMAP:
2228 case OMP_CLAUSE_ASYNC:
2229 case OMP_CLAUSE_WAIT:
2230 case OMP_CLAUSE_GANG:
2231 case OMP_CLAUSE_WORKER:
2232 case OMP_CLAUSE_VECTOR:
2233 break;
2235 case OMP_CLAUSE_ALIGNED:
2236 decl = OMP_CLAUSE_DECL (c);
2237 if (is_global_var (decl)
2238 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2239 install_var_local (decl, ctx);
2240 break;
2242 case OMP_CLAUSE_DEVICE_RESIDENT:
2243 case OMP_CLAUSE_USE_DEVICE:
2244 case OMP_CLAUSE__CACHE_:
2245 case OMP_CLAUSE_INDEPENDENT:
2246 case OMP_CLAUSE_AUTO:
2247 case OMP_CLAUSE_SEQ:
2248 sorry ("Clause not supported yet");
2249 break;
2251 default:
2252 gcc_unreachable ();
2256 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2258 switch (OMP_CLAUSE_CODE (c))
2260 case OMP_CLAUSE_LASTPRIVATE:
2261 /* Let the corresponding firstprivate clause create
2262 the variable. */
2263 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2264 scan_array_reductions = true;
2265 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2266 break;
2267 /* FALLTHRU */
2269 case OMP_CLAUSE_FIRSTPRIVATE:
2270 if (is_gimple_omp_oacc (ctx->stmt))
2272 sorry ("clause not supported yet");
2273 break;
2275 /* FALLTHRU */
2276 case OMP_CLAUSE_PRIVATE:
2277 case OMP_CLAUSE_LINEAR:
2278 case OMP_CLAUSE_IS_DEVICE_PTR:
2279 decl = OMP_CLAUSE_DECL (c);
2280 if (is_variable_sized (decl))
2282 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2283 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2284 && is_gimple_omp_offloaded (ctx->stmt))
2286 tree decl2 = DECL_VALUE_EXPR (decl);
2287 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2288 decl2 = TREE_OPERAND (decl2, 0);
2289 gcc_assert (DECL_P (decl2));
2290 install_var_local (decl2, ctx);
2291 fixup_remapped_decl (decl2, ctx, false);
2293 install_var_local (decl, ctx);
2295 fixup_remapped_decl (decl, ctx,
2296 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2297 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2298 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2299 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2300 scan_array_reductions = true;
2301 break;
2303 case OMP_CLAUSE_REDUCTION:
2304 decl = OMP_CLAUSE_DECL (c);
2305 if (TREE_CODE (decl) != MEM_REF)
2307 if (is_variable_sized (decl))
2308 install_var_local (decl, ctx);
2309 fixup_remapped_decl (decl, ctx, false);
2311 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2312 scan_array_reductions = true;
2313 break;
2315 case OMP_CLAUSE_SHARED:
2316 /* Ignore shared directives in teams construct. */
2317 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2318 break;
2319 decl = OMP_CLAUSE_DECL (c);
2320 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2321 break;
2322 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2324 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2325 ctx->outer)))
2326 break;
2327 bool by_ref = use_pointer_for_field (decl, ctx);
2328 install_var_field (decl, by_ref, 11, ctx);
2329 break;
2331 fixup_remapped_decl (decl, ctx, false);
2332 break;
2334 case OMP_CLAUSE_MAP:
2335 if (!is_gimple_omp_offloaded (ctx->stmt))
2336 break;
2337 decl = OMP_CLAUSE_DECL (c);
2338 if (DECL_P (decl)
2339 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2340 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2341 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2342 && varpool_node::get_create (decl)->offloadable)
2343 break;
2344 if (DECL_P (decl))
2346 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2347 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2348 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2349 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2351 tree new_decl = lookup_decl (decl, ctx);
2352 TREE_TYPE (new_decl)
2353 = remap_type (TREE_TYPE (decl), &ctx->cb);
2355 else if (DECL_SIZE (decl)
2356 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2358 tree decl2 = DECL_VALUE_EXPR (decl);
2359 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2360 decl2 = TREE_OPERAND (decl2, 0);
2361 gcc_assert (DECL_P (decl2));
2362 fixup_remapped_decl (decl2, ctx, false);
2363 fixup_remapped_decl (decl, ctx, true);
2365 else
2366 fixup_remapped_decl (decl, ctx, false);
2368 break;
2370 case OMP_CLAUSE_COPYPRIVATE:
2371 case OMP_CLAUSE_COPYIN:
2372 case OMP_CLAUSE_DEFAULT:
2373 case OMP_CLAUSE_IF:
2374 case OMP_CLAUSE_NUM_THREADS:
2375 case OMP_CLAUSE_NUM_TEAMS:
2376 case OMP_CLAUSE_THREAD_LIMIT:
2377 case OMP_CLAUSE_DEVICE:
2378 case OMP_CLAUSE_SCHEDULE:
2379 case OMP_CLAUSE_DIST_SCHEDULE:
2380 case OMP_CLAUSE_NOWAIT:
2381 case OMP_CLAUSE_ORDERED:
2382 case OMP_CLAUSE_COLLAPSE:
2383 case OMP_CLAUSE_UNTIED:
2384 case OMP_CLAUSE_FINAL:
2385 case OMP_CLAUSE_MERGEABLE:
2386 case OMP_CLAUSE_PROC_BIND:
2387 case OMP_CLAUSE_SAFELEN:
2388 case OMP_CLAUSE_SIMDLEN:
2389 case OMP_CLAUSE_ALIGNED:
2390 case OMP_CLAUSE_DEPEND:
2391 case OMP_CLAUSE__LOOPTEMP_:
2392 case OMP_CLAUSE_TO:
2393 case OMP_CLAUSE_FROM:
2394 case OMP_CLAUSE_PRIORITY:
2395 case OMP_CLAUSE_GRAINSIZE:
2396 case OMP_CLAUSE_NUM_TASKS:
2397 case OMP_CLAUSE_THREADS:
2398 case OMP_CLAUSE_SIMD:
2399 case OMP_CLAUSE_NOGROUP:
2400 case OMP_CLAUSE_DEFAULTMAP:
2401 case OMP_CLAUSE_USE_DEVICE_PTR:
2402 case OMP_CLAUSE__CILK_FOR_COUNT_:
2403 case OMP_CLAUSE_ASYNC:
2404 case OMP_CLAUSE_WAIT:
2405 case OMP_CLAUSE_NUM_GANGS:
2406 case OMP_CLAUSE_NUM_WORKERS:
2407 case OMP_CLAUSE_VECTOR_LENGTH:
2408 case OMP_CLAUSE_GANG:
2409 case OMP_CLAUSE_WORKER:
2410 case OMP_CLAUSE_VECTOR:
2411 break;
2413 case OMP_CLAUSE_DEVICE_RESIDENT:
2414 case OMP_CLAUSE_USE_DEVICE:
2415 case OMP_CLAUSE__CACHE_:
2416 case OMP_CLAUSE_INDEPENDENT:
2417 case OMP_CLAUSE_AUTO:
2418 case OMP_CLAUSE_SEQ:
2419 sorry ("Clause not supported yet");
2420 break;
2422 default:
2423 gcc_unreachable ();
2427 gcc_checking_assert (!scan_array_reductions
2428 || !is_gimple_omp_oacc (ctx->stmt));
2429 if (scan_array_reductions)
2430 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2432 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2434 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2435 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2437 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2438 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2439 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2440 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2441 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2442 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2445 /* Create a new name for omp child function. Returns an identifier. If
2446 IS_CILK_FOR is true then the suffix for the child function is
2447 "_cilk_for_fn." */
2449 static tree
2450 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2452 if (is_cilk_for)
2453 return clone_function_name (current_function_decl, "_cilk_for_fn");
2454 return clone_function_name (current_function_decl,
2455 task_copy ? "_omp_cpyfn" : "_omp_fn");
2458 /* Returns the type of the induction variable for the child function for
2459 _Cilk_for and the types for _high and _low variables based on TYPE. */
2461 static tree
2462 cilk_for_check_loop_diff_type (tree type)
2464 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2466 if (TYPE_UNSIGNED (type))
2467 return uint32_type_node;
2468 else
2469 return integer_type_node;
2471 else
2473 if (TYPE_UNSIGNED (type))
2474 return uint64_type_node;
2475 else
2476 return long_long_integer_type_node;
2480 /* Build a decl for the omp child function. It'll not contain a body
2481 yet, just the bare decl. */
2483 static void
2484 create_omp_child_function (omp_context *ctx, bool task_copy)
2486 tree decl, type, name, t;
2488 tree cilk_for_count
2489 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2490 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2491 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2492 tree cilk_var_type = NULL_TREE;
2494 name = create_omp_child_function_name (task_copy,
2495 cilk_for_count != NULL_TREE);
2496 if (task_copy)
2497 type = build_function_type_list (void_type_node, ptr_type_node,
2498 ptr_type_node, NULL_TREE);
2499 else if (cilk_for_count)
2501 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2502 cilk_var_type = cilk_for_check_loop_diff_type (type);
2503 type = build_function_type_list (void_type_node, ptr_type_node,
2504 cilk_var_type, cilk_var_type, NULL_TREE);
2506 else
2507 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2509 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2511 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2512 || !task_copy);
2513 if (!task_copy)
2514 ctx->cb.dst_fn = decl;
2515 else
2516 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2518 TREE_STATIC (decl) = 1;
2519 TREE_USED (decl) = 1;
2520 DECL_ARTIFICIAL (decl) = 1;
2521 DECL_IGNORED_P (decl) = 0;
2522 TREE_PUBLIC (decl) = 0;
2523 DECL_UNINLINABLE (decl) = 1;
2524 DECL_EXTERNAL (decl) = 0;
2525 DECL_CONTEXT (decl) = NULL_TREE;
2526 DECL_INITIAL (decl) = make_node (BLOCK);
2527 if (cgraph_node::get (current_function_decl)->offloadable)
2528 cgraph_node::get_create (decl)->offloadable = 1;
2529 else
2531 omp_context *octx;
2532 for (octx = ctx; octx; octx = octx->outer)
2533 if (is_gimple_omp_offloaded (octx->stmt))
2535 cgraph_node::get_create (decl)->offloadable = 1;
2536 #ifdef ENABLE_OFFLOADING
2537 g->have_offload = true;
2538 #endif
2539 break;
2543 if (cgraph_node::get_create (decl)->offloadable
2544 && !lookup_attribute ("omp declare target",
2545 DECL_ATTRIBUTES (current_function_decl)))
2546 DECL_ATTRIBUTES (decl)
2547 = tree_cons (get_identifier ("omp target entrypoint"),
2548 NULL_TREE, DECL_ATTRIBUTES (decl));
2550 t = build_decl (DECL_SOURCE_LOCATION (decl),
2551 RESULT_DECL, NULL_TREE, void_type_node);
2552 DECL_ARTIFICIAL (t) = 1;
2553 DECL_IGNORED_P (t) = 1;
2554 DECL_CONTEXT (t) = decl;
2555 DECL_RESULT (decl) = t;
2557 /* _Cilk_for's child function requires two extra parameters called
2558 __low and __high that are set the by Cilk runtime when it calls this
2559 function. */
2560 if (cilk_for_count)
2562 t = build_decl (DECL_SOURCE_LOCATION (decl),
2563 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2564 DECL_ARTIFICIAL (t) = 1;
2565 DECL_NAMELESS (t) = 1;
2566 DECL_ARG_TYPE (t) = ptr_type_node;
2567 DECL_CONTEXT (t) = current_function_decl;
2568 TREE_USED (t) = 1;
2569 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2570 DECL_ARGUMENTS (decl) = t;
2572 t = build_decl (DECL_SOURCE_LOCATION (decl),
2573 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2574 DECL_ARTIFICIAL (t) = 1;
2575 DECL_NAMELESS (t) = 1;
2576 DECL_ARG_TYPE (t) = ptr_type_node;
2577 DECL_CONTEXT (t) = current_function_decl;
2578 TREE_USED (t) = 1;
2579 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2580 DECL_ARGUMENTS (decl) = t;
2583 tree data_name = get_identifier (".omp_data_i");
2584 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2585 ptr_type_node);
2586 DECL_ARTIFICIAL (t) = 1;
2587 DECL_NAMELESS (t) = 1;
2588 DECL_ARG_TYPE (t) = ptr_type_node;
2589 DECL_CONTEXT (t) = current_function_decl;
2590 TREE_USED (t) = 1;
2591 TREE_READONLY (t) = 1;
2592 if (cilk_for_count)
2593 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2594 DECL_ARGUMENTS (decl) = t;
2595 if (!task_copy)
2596 ctx->receiver_decl = t;
2597 else
2599 t = build_decl (DECL_SOURCE_LOCATION (decl),
2600 PARM_DECL, get_identifier (".omp_data_o"),
2601 ptr_type_node);
2602 DECL_ARTIFICIAL (t) = 1;
2603 DECL_NAMELESS (t) = 1;
2604 DECL_ARG_TYPE (t) = ptr_type_node;
2605 DECL_CONTEXT (t) = current_function_decl;
2606 TREE_USED (t) = 1;
2607 TREE_ADDRESSABLE (t) = 1;
2608 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2609 DECL_ARGUMENTS (decl) = t;
2612 /* Allocate memory for the function structure. The call to
2613 allocate_struct_function clobbers CFUN, so we need to restore
2614 it afterward. */
2615 push_struct_function (decl);
2616 cfun->function_end_locus = gimple_location (ctx->stmt);
2617 pop_cfun ();
2620 /* Callback for walk_gimple_seq. Check if combined parallel
2621 contains gimple_omp_for_combined_into_p OMP_FOR. */
2623 static tree
2624 find_combined_for (gimple_stmt_iterator *gsi_p,
2625 bool *handled_ops_p,
2626 struct walk_stmt_info *wi)
2628 gimple *stmt = gsi_stmt (*gsi_p);
2630 *handled_ops_p = true;
2631 switch (gimple_code (stmt))
2633 WALK_SUBSTMTS;
2635 case GIMPLE_OMP_FOR:
2636 if (gimple_omp_for_combined_into_p (stmt)
2637 && gimple_omp_for_kind (stmt)
2638 == *(const enum gf_mask *) (wi->info))
2640 wi->info = stmt;
2641 return integer_zero_node;
2643 break;
2644 default:
2645 break;
2647 return NULL;
2650 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2652 static void
2653 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2654 omp_context *outer_ctx)
2656 struct walk_stmt_info wi;
2658 memset (&wi, 0, sizeof (wi));
2659 wi.val_only = true;
2660 wi.info = (void *) &msk;
2661 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2662 if (wi.info != (void *) &msk)
2664 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2665 struct omp_for_data fd;
2666 extract_omp_for_data (for_stmt, &fd, NULL);
2667 /* We need two temporaries with fd.loop.v type (istart/iend)
2668 and then (fd.collapse - 1) temporaries with the same
2669 type for count2 ... countN-1 vars if not constant. */
2670 size_t count = 2, i;
2671 tree type = fd.iter_type;
2672 if (fd.collapse > 1
2673 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2675 count += fd.collapse - 1;
2676 /* For taskloop, if there are lastprivate clauses on the inner
2677 GIMPLE_OMP_FOR, add one more temporaries for the total number
2678 of iterations (product of count1 ... countN-1). */
2679 if (msk == GF_OMP_FOR_KIND_TASKLOOP
2680 && find_omp_clause (gimple_omp_for_clauses (for_stmt),
2681 OMP_CLAUSE_LASTPRIVATE))
2682 count++;
2684 for (i = 0; i < count; i++)
2686 tree temp = create_tmp_var (type);
2687 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2688 insert_decl_map (&outer_ctx->cb, temp, temp);
2689 OMP_CLAUSE_DECL (c) = temp;
2690 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2691 gimple_omp_taskreg_set_clauses (stmt, c);
2696 /* Scan an OpenMP parallel directive. */
2698 static void
2699 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2701 omp_context *ctx;
2702 tree name;
2703 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2705 /* Ignore parallel directives with empty bodies, unless there
2706 are copyin clauses. */
2707 if (optimize > 0
2708 && empty_body_p (gimple_omp_body (stmt))
2709 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2710 OMP_CLAUSE_COPYIN) == NULL)
2712 gsi_replace (gsi, gimple_build_nop (), false);
2713 return;
2716 if (gimple_omp_parallel_combined_p (stmt))
2717 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2719 ctx = new_omp_context (stmt, outer_ctx);
2720 taskreg_contexts.safe_push (ctx);
2721 if (taskreg_nesting_level > 1)
2722 ctx->is_nested = true;
2723 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2724 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2725 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2726 name = create_tmp_var_name (".omp_data_s");
2727 name = build_decl (gimple_location (stmt),
2728 TYPE_DECL, name, ctx->record_type);
2729 DECL_ARTIFICIAL (name) = 1;
2730 DECL_NAMELESS (name) = 1;
2731 TYPE_NAME (ctx->record_type) = name;
2732 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2733 create_omp_child_function (ctx, false);
2734 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2736 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2737 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2739 if (TYPE_FIELDS (ctx->record_type) == NULL)
2740 ctx->record_type = ctx->receiver_decl = NULL;
2743 /* Scan an OpenMP task directive. */
2745 static void
2746 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2748 omp_context *ctx;
2749 tree name, t;
2750 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2752 /* Ignore task directives with empty bodies. */
2753 if (optimize > 0
2754 && empty_body_p (gimple_omp_body (stmt)))
2756 gsi_replace (gsi, gimple_build_nop (), false);
2757 return;
2760 if (gimple_omp_task_taskloop_p (stmt))
2761 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2763 ctx = new_omp_context (stmt, outer_ctx);
2764 taskreg_contexts.safe_push (ctx);
2765 if (taskreg_nesting_level > 1)
2766 ctx->is_nested = true;
2767 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2768 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2769 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2770 name = create_tmp_var_name (".omp_data_s");
2771 name = build_decl (gimple_location (stmt),
2772 TYPE_DECL, name, ctx->record_type);
2773 DECL_ARTIFICIAL (name) = 1;
2774 DECL_NAMELESS (name) = 1;
2775 TYPE_NAME (ctx->record_type) = name;
2776 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2777 create_omp_child_function (ctx, false);
2778 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2780 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2782 if (ctx->srecord_type)
2784 name = create_tmp_var_name (".omp_data_a");
2785 name = build_decl (gimple_location (stmt),
2786 TYPE_DECL, name, ctx->srecord_type);
2787 DECL_ARTIFICIAL (name) = 1;
2788 DECL_NAMELESS (name) = 1;
2789 TYPE_NAME (ctx->srecord_type) = name;
2790 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2791 create_omp_child_function (ctx, true);
2794 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2796 if (TYPE_FIELDS (ctx->record_type) == NULL)
2798 ctx->record_type = ctx->receiver_decl = NULL;
2799 t = build_int_cst (long_integer_type_node, 0);
2800 gimple_omp_task_set_arg_size (stmt, t);
2801 t = build_int_cst (long_integer_type_node, 1);
2802 gimple_omp_task_set_arg_align (stmt, t);
2807 /* If any decls have been made addressable during scan_omp,
2808 adjust their fields if needed, and layout record types
2809 of parallel/task constructs. */
2811 static void
2812 finish_taskreg_scan (omp_context *ctx)
2814 if (ctx->record_type == NULL_TREE)
2815 return;
2817 /* If any task_shared_vars were needed, verify all
2818 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2819 statements if use_pointer_for_field hasn't changed
2820 because of that. If it did, update field types now. */
2821 if (task_shared_vars)
2823 tree c;
2825 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2826 c; c = OMP_CLAUSE_CHAIN (c))
2827 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2828 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2830 tree decl = OMP_CLAUSE_DECL (c);
2832 /* Global variables don't need to be copied,
2833 the receiver side will use them directly. */
2834 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2835 continue;
2836 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2837 || !use_pointer_for_field (decl, ctx))
2838 continue;
2839 tree field = lookup_field (decl, ctx);
2840 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2841 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2842 continue;
2843 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2844 TREE_THIS_VOLATILE (field) = 0;
2845 DECL_USER_ALIGN (field) = 0;
2846 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2847 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2848 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2849 if (ctx->srecord_type)
2851 tree sfield = lookup_sfield (decl, ctx);
2852 TREE_TYPE (sfield) = TREE_TYPE (field);
2853 TREE_THIS_VOLATILE (sfield) = 0;
2854 DECL_USER_ALIGN (sfield) = 0;
2855 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2856 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2857 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2862 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2864 layout_type (ctx->record_type);
2865 fixup_child_record_type (ctx);
2867 else
2869 location_t loc = gimple_location (ctx->stmt);
2870 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2871 /* Move VLA fields to the end. */
2872 p = &TYPE_FIELDS (ctx->record_type);
2873 while (*p)
2874 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2875 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2877 *q = *p;
2878 *p = TREE_CHAIN (*p);
2879 TREE_CHAIN (*q) = NULL_TREE;
2880 q = &TREE_CHAIN (*q);
2882 else
2883 p = &DECL_CHAIN (*p);
2884 *p = vla_fields;
2885 if (gimple_omp_task_taskloop_p (ctx->stmt))
2887 /* Move fields corresponding to first and second _looptemp_
2888 clause first. There are filled by GOMP_taskloop
2889 and thus need to be in specific positions. */
2890 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2891 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2892 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2893 OMP_CLAUSE__LOOPTEMP_);
2894 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2895 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2896 p = &TYPE_FIELDS (ctx->record_type);
2897 while (*p)
2898 if (*p == f1 || *p == f2)
2899 *p = DECL_CHAIN (*p);
2900 else
2901 p = &DECL_CHAIN (*p);
2902 DECL_CHAIN (f1) = f2;
2903 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2904 TYPE_FIELDS (ctx->record_type) = f1;
2905 if (ctx->srecord_type)
2907 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2908 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2909 p = &TYPE_FIELDS (ctx->srecord_type);
2910 while (*p)
2911 if (*p == f1 || *p == f2)
2912 *p = DECL_CHAIN (*p);
2913 else
2914 p = &DECL_CHAIN (*p);
2915 DECL_CHAIN (f1) = f2;
2916 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2917 TYPE_FIELDS (ctx->srecord_type) = f1;
2920 layout_type (ctx->record_type);
2921 fixup_child_record_type (ctx);
2922 if (ctx->srecord_type)
2923 layout_type (ctx->srecord_type);
2924 tree t = fold_convert_loc (loc, long_integer_type_node,
2925 TYPE_SIZE_UNIT (ctx->record_type));
2926 gimple_omp_task_set_arg_size (ctx->stmt, t);
2927 t = build_int_cst (long_integer_type_node,
2928 TYPE_ALIGN_UNIT (ctx->record_type));
2929 gimple_omp_task_set_arg_align (ctx->stmt, t);
2933 /* Find the enclosing offload context. */
2935 static omp_context *
2936 enclosing_target_ctx (omp_context *ctx)
2938 for (; ctx; ctx = ctx->outer)
2939 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2940 break;
2942 return ctx;
2945 /* Return true if ctx is part of an oacc kernels region. */
2947 static bool
2948 ctx_in_oacc_kernels_region (omp_context *ctx)
2950 for (;ctx != NULL; ctx = ctx->outer)
2952 gimple *stmt = ctx->stmt;
2953 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2954 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2955 return true;
2958 return false;
2961 /* Check the parallelism clauses inside a kernels regions.
2962 Until kernels handling moves to use the same loop indirection
2963 scheme as parallel, we need to do this checking early. */
2965 static unsigned
2966 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2968 bool checking = true;
2969 unsigned outer_mask = 0;
2970 unsigned this_mask = 0;
2971 bool has_seq = false, has_auto = false;
2973 if (ctx->outer)
2974 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2975 if (!stmt)
2977 checking = false;
2978 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2979 return outer_mask;
2980 stmt = as_a <gomp_for *> (ctx->stmt);
2983 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2985 switch (OMP_CLAUSE_CODE (c))
2987 case OMP_CLAUSE_GANG:
2988 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2989 break;
2990 case OMP_CLAUSE_WORKER:
2991 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2992 break;
2993 case OMP_CLAUSE_VECTOR:
2994 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2995 break;
2996 case OMP_CLAUSE_SEQ:
2997 has_seq = true;
2998 break;
2999 case OMP_CLAUSE_AUTO:
3000 has_auto = true;
3001 break;
3002 default:
3003 break;
3007 if (checking)
3009 if (has_seq && (this_mask || has_auto))
3010 error_at (gimple_location (stmt), "%<seq%> overrides other"
3011 " OpenACC loop specifiers");
3012 else if (has_auto && this_mask)
3013 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
3014 " OpenACC loop specifiers");
3016 if (this_mask & outer_mask)
3017 error_at (gimple_location (stmt), "inner loop uses same"
3018 " OpenACC parallelism as containing loop");
3021 return outer_mask | this_mask;
3024 /* Scan a GIMPLE_OMP_FOR. */
3026 static void
3027 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
3029 omp_context *ctx;
3030 size_t i;
3031 tree clauses = gimple_omp_for_clauses (stmt);
3033 ctx = new_omp_context (stmt, outer_ctx);
3035 if (is_gimple_omp_oacc (stmt))
3037 omp_context *tgt = enclosing_target_ctx (outer_ctx);
3039 if (!tgt || is_oacc_parallel (tgt))
3040 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3042 char const *check = NULL;
3044 switch (OMP_CLAUSE_CODE (c))
3046 case OMP_CLAUSE_GANG:
3047 check = "gang";
3048 break;
3050 case OMP_CLAUSE_WORKER:
3051 check = "worker";
3052 break;
3054 case OMP_CLAUSE_VECTOR:
3055 check = "vector";
3056 break;
3058 default:
3059 break;
3062 if (check && OMP_CLAUSE_OPERAND (c, 0))
3063 error_at (gimple_location (stmt),
3064 "argument not permitted on %qs clause in"
3065 " OpenACC %<parallel%>", check);
3068 if (tgt && is_oacc_kernels (tgt))
3070 /* Strip out reductions, as they are not handled yet. */
3071 tree *prev_ptr = &clauses;
3073 while (tree probe = *prev_ptr)
3075 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3077 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3078 *prev_ptr = *next_ptr;
3079 else
3080 prev_ptr = next_ptr;
3083 gimple_omp_for_set_clauses (stmt, clauses);
3084 check_oacc_kernel_gwv (stmt, ctx);
3088 scan_sharing_clauses (clauses, ctx);
3090 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3091 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3093 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3094 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3095 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3096 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3098 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3101 /* Scan an OpenMP sections directive. */
3103 static void
3104 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3106 omp_context *ctx;
3108 ctx = new_omp_context (stmt, outer_ctx);
3109 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3110 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3113 /* Scan an OpenMP single directive. */
3115 static void
3116 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3118 omp_context *ctx;
3119 tree name;
3121 ctx = new_omp_context (stmt, outer_ctx);
3122 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3123 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3124 name = create_tmp_var_name (".omp_copy_s");
3125 name = build_decl (gimple_location (stmt),
3126 TYPE_DECL, name, ctx->record_type);
3127 TYPE_NAME (ctx->record_type) = name;
3129 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3130 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3132 if (TYPE_FIELDS (ctx->record_type) == NULL)
3133 ctx->record_type = NULL;
3134 else
3135 layout_type (ctx->record_type);
3138 /* Scan a GIMPLE_OMP_TARGET. */
3140 static void
3141 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3143 omp_context *ctx;
3144 tree name;
3145 bool offloaded = is_gimple_omp_offloaded (stmt);
3146 tree clauses = gimple_omp_target_clauses (stmt);
3148 ctx = new_omp_context (stmt, outer_ctx);
3149 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3150 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3151 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3152 name = create_tmp_var_name (".omp_data_t");
3153 name = build_decl (gimple_location (stmt),
3154 TYPE_DECL, name, ctx->record_type);
3155 DECL_ARTIFICIAL (name) = 1;
3156 DECL_NAMELESS (name) = 1;
3157 TYPE_NAME (ctx->record_type) = name;
3158 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3159 if (offloaded)
3161 if (is_gimple_omp_oacc (stmt))
3162 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
3163 0, 0);
3165 create_omp_child_function (ctx, false);
3166 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3169 scan_sharing_clauses (clauses, ctx);
3170 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3172 if (TYPE_FIELDS (ctx->record_type) == NULL)
3173 ctx->record_type = ctx->receiver_decl = NULL;
3174 else
3176 TYPE_FIELDS (ctx->record_type)
3177 = nreverse (TYPE_FIELDS (ctx->record_type));
3178 if (flag_checking)
3180 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3181 for (tree field = TYPE_FIELDS (ctx->record_type);
3182 field;
3183 field = DECL_CHAIN (field))
3184 gcc_assert (DECL_ALIGN (field) == align);
3186 layout_type (ctx->record_type);
3187 if (offloaded)
3188 fixup_child_record_type (ctx);
3192 /* Scan an OpenMP teams directive. */
3194 static void
3195 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3197 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3198 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3199 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3202 /* Check nesting restrictions. */
3203 static bool
3204 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3206 tree c;
3208 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3209 inside an OpenACC CTX. */
3210 if (!(is_gimple_omp (stmt)
3211 && is_gimple_omp_oacc (stmt)))
3213 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
3214 if (is_gimple_omp (ctx_->stmt)
3215 && is_gimple_omp_oacc (ctx_->stmt))
3217 error_at (gimple_location (stmt),
3218 "non-OpenACC construct inside of OpenACC region");
3219 return false;
3223 if (ctx != NULL)
3225 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3226 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3228 c = NULL_TREE;
3229 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3231 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3232 if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD)
3233 return true;
3235 error_at (gimple_location (stmt),
3236 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3237 " may not be nested inside simd region");
3238 return false;
3240 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3242 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3243 || (gimple_omp_for_kind (stmt)
3244 != GF_OMP_FOR_KIND_DISTRIBUTE))
3245 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3247 error_at (gimple_location (stmt),
3248 "only distribute or parallel constructs are allowed to "
3249 "be closely nested inside teams construct");
3250 return false;
3254 switch (gimple_code (stmt))
3256 case GIMPLE_OMP_FOR:
3257 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3258 return true;
3259 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3261 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3263 error_at (gimple_location (stmt),
3264 "distribute construct must be closely nested inside "
3265 "teams construct");
3266 return false;
3268 return true;
3270 /* We split taskloop into task and nested taskloop in it. */
3271 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3272 return true;
3273 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3275 bool ok = false;
3277 if (ctx)
3278 switch (gimple_code (ctx->stmt))
3280 case GIMPLE_OMP_FOR:
3281 ok = (gimple_omp_for_kind (ctx->stmt)
3282 == GF_OMP_FOR_KIND_OACC_LOOP);
3283 break;
3285 case GIMPLE_OMP_TARGET:
3286 switch (gimple_omp_target_kind (ctx->stmt))
3288 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3289 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3290 ok = true;
3291 break;
3293 default:
3294 break;
3297 default:
3298 break;
3300 else if (get_oacc_fn_attrib (current_function_decl))
3301 ok = true;
3302 if (!ok)
3304 error_at (gimple_location (stmt),
3305 "OpenACC loop directive must be associated with"
3306 " an OpenACC compute region");
3307 return false;
3310 /* FALLTHRU */
3311 case GIMPLE_CALL:
3312 if (is_gimple_call (stmt)
3313 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3314 == BUILT_IN_GOMP_CANCEL
3315 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3316 == BUILT_IN_GOMP_CANCELLATION_POINT))
3318 const char *bad = NULL;
3319 const char *kind = NULL;
3320 if (ctx == NULL)
3322 error_at (gimple_location (stmt), "orphaned %qs construct",
3323 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3324 == BUILT_IN_GOMP_CANCEL
3325 ? "#pragma omp cancel"
3326 : "#pragma omp cancellation point");
3327 return false;
3329 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3330 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3331 : 0)
3333 case 1:
3334 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3335 bad = "#pragma omp parallel";
3336 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3337 == BUILT_IN_GOMP_CANCEL
3338 && !integer_zerop (gimple_call_arg (stmt, 1)))
3339 ctx->cancellable = true;
3340 kind = "parallel";
3341 break;
3342 case 2:
3343 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3344 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3345 bad = "#pragma omp for";
3346 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3347 == BUILT_IN_GOMP_CANCEL
3348 && !integer_zerop (gimple_call_arg (stmt, 1)))
3350 ctx->cancellable = true;
3351 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3352 OMP_CLAUSE_NOWAIT))
3353 warning_at (gimple_location (stmt), 0,
3354 "%<#pragma omp cancel for%> inside "
3355 "%<nowait%> for construct");
3356 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3357 OMP_CLAUSE_ORDERED))
3358 warning_at (gimple_location (stmt), 0,
3359 "%<#pragma omp cancel for%> inside "
3360 "%<ordered%> for construct");
3362 kind = "for";
3363 break;
3364 case 4:
3365 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3366 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3367 bad = "#pragma omp sections";
3368 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCEL
3370 && !integer_zerop (gimple_call_arg (stmt, 1)))
3372 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3374 ctx->cancellable = true;
3375 if (find_omp_clause (gimple_omp_sections_clauses
3376 (ctx->stmt),
3377 OMP_CLAUSE_NOWAIT))
3378 warning_at (gimple_location (stmt), 0,
3379 "%<#pragma omp cancel sections%> inside "
3380 "%<nowait%> sections construct");
3382 else
3384 gcc_assert (ctx->outer
3385 && gimple_code (ctx->outer->stmt)
3386 == GIMPLE_OMP_SECTIONS);
3387 ctx->outer->cancellable = true;
3388 if (find_omp_clause (gimple_omp_sections_clauses
3389 (ctx->outer->stmt),
3390 OMP_CLAUSE_NOWAIT))
3391 warning_at (gimple_location (stmt), 0,
3392 "%<#pragma omp cancel sections%> inside "
3393 "%<nowait%> sections construct");
3396 kind = "sections";
3397 break;
3398 case 8:
3399 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3400 bad = "#pragma omp task";
3401 else
3402 ctx->cancellable = true;
3403 kind = "taskgroup";
3404 break;
3405 default:
3406 error_at (gimple_location (stmt), "invalid arguments");
3407 return false;
3409 if (bad)
3411 error_at (gimple_location (stmt),
3412 "%<%s %s%> construct not closely nested inside of %qs",
3413 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3414 == BUILT_IN_GOMP_CANCEL
3415 ? "#pragma omp cancel"
3416 : "#pragma omp cancellation point", kind, bad);
3417 return false;
3420 /* FALLTHRU */
3421 case GIMPLE_OMP_SECTIONS:
3422 case GIMPLE_OMP_SINGLE:
3423 for (; ctx != NULL; ctx = ctx->outer)
3424 switch (gimple_code (ctx->stmt))
3426 case GIMPLE_OMP_FOR:
3427 case GIMPLE_OMP_SECTIONS:
3428 case GIMPLE_OMP_SINGLE:
3429 case GIMPLE_OMP_ORDERED:
3430 case GIMPLE_OMP_MASTER:
3431 case GIMPLE_OMP_TASK:
3432 case GIMPLE_OMP_CRITICAL:
3433 if (is_gimple_call (stmt))
3435 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3436 != BUILT_IN_GOMP_BARRIER)
3437 return true;
3438 error_at (gimple_location (stmt),
3439 "barrier region may not be closely nested inside "
3440 "of work-sharing, critical, ordered, master or "
3441 "explicit task region");
3442 return false;
3444 error_at (gimple_location (stmt),
3445 "work-sharing region may not be closely nested inside "
3446 "of work-sharing, critical, ordered, master or explicit "
3447 "task region");
3448 return false;
3449 case GIMPLE_OMP_PARALLEL:
3450 return true;
3451 default:
3452 break;
3454 break;
3455 case GIMPLE_OMP_MASTER:
3456 for (; ctx != NULL; ctx = ctx->outer)
3457 switch (gimple_code (ctx->stmt))
3459 case GIMPLE_OMP_FOR:
3460 case GIMPLE_OMP_SECTIONS:
3461 case GIMPLE_OMP_SINGLE:
3462 case GIMPLE_OMP_TASK:
3463 error_at (gimple_location (stmt),
3464 "master region may not be closely nested inside "
3465 "of work-sharing or explicit task region");
3466 return false;
3467 case GIMPLE_OMP_PARALLEL:
3468 return true;
3469 default:
3470 break;
3472 break;
3473 case GIMPLE_OMP_TASK:
3474 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3475 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3476 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3477 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3479 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3480 error_at (OMP_CLAUSE_LOCATION (c),
3481 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3482 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3483 return false;
3485 break;
3486 case GIMPLE_OMP_ORDERED:
3487 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3488 c; c = OMP_CLAUSE_CHAIN (c))
3490 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3492 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3493 || (ctx == NULL
3494 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD));
3495 continue;
3497 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3498 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3499 || kind == OMP_CLAUSE_DEPEND_SINK)
3501 tree oclause;
3502 /* Look for containing ordered(N) loop. */
3503 if (ctx == NULL
3504 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3505 || (oclause
3506 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3507 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3509 error_at (OMP_CLAUSE_LOCATION (c),
3510 "%<depend%> clause must be closely nested "
3511 "inside an ordered loop");
3512 return false;
3514 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3516 error_at (OMP_CLAUSE_LOCATION (c),
3517 "%<depend%> clause must be closely nested "
3518 "inside a loop with %<ordered%> clause with "
3519 "a parameter");
3520 return false;
3523 else
3525 error_at (OMP_CLAUSE_LOCATION (c),
3526 "invalid depend kind in omp ordered depend");
3527 return false;
3530 for (; ctx != NULL; ctx = ctx->outer)
3531 switch (gimple_code (ctx->stmt))
3533 case GIMPLE_OMP_CRITICAL:
3534 case GIMPLE_OMP_TASK:
3535 error_at (gimple_location (stmt),
3536 "ordered region may not be closely nested inside "
3537 "of critical or explicit task region");
3538 return false;
3539 case GIMPLE_OMP_FOR:
3540 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3541 OMP_CLAUSE_ORDERED) == NULL)
3543 error_at (gimple_location (stmt),
3544 "ordered region must be closely nested inside "
3545 "a loop region with an ordered clause");
3546 return false;
3548 return true;
3549 case GIMPLE_OMP_PARALLEL:
3550 error_at (gimple_location (stmt),
3551 "ordered region must be closely nested inside "
3552 "a loop region with an ordered clause");
3553 return false;
3554 default:
3555 break;
3557 break;
3558 case GIMPLE_OMP_CRITICAL:
3560 tree this_stmt_name
3561 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3562 for (; ctx != NULL; ctx = ctx->outer)
3563 if (gomp_critical *other_crit
3564 = dyn_cast <gomp_critical *> (ctx->stmt))
3565 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3567 error_at (gimple_location (stmt),
3568 "critical region may not be nested inside a critical "
3569 "region with the same name");
3570 return false;
3573 break;
3574 case GIMPLE_OMP_TEAMS:
3575 if (ctx == NULL
3576 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3577 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3579 error_at (gimple_location (stmt),
3580 "teams construct not closely nested inside of target "
3581 "region");
3582 return false;
3584 break;
3585 case GIMPLE_OMP_TARGET:
3586 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3587 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3588 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3589 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3591 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3592 error_at (OMP_CLAUSE_LOCATION (c),
3593 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3594 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3595 return false;
3597 for (; ctx != NULL; ctx = ctx->outer)
3599 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3601 if (is_gimple_omp (stmt)
3602 && is_gimple_omp_oacc (stmt)
3603 && is_gimple_omp (ctx->stmt))
3605 error_at (gimple_location (stmt),
3606 "OpenACC construct inside of non-OpenACC region");
3607 return false;
3609 continue;
3612 const char *stmt_name, *ctx_stmt_name;
3613 switch (gimple_omp_target_kind (stmt))
3615 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3616 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3617 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3618 case GF_OMP_TARGET_KIND_ENTER_DATA:
3619 stmt_name = "target enter data"; break;
3620 case GF_OMP_TARGET_KIND_EXIT_DATA:
3621 stmt_name = "target exit data"; break;
3622 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3623 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3624 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3625 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3626 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3627 stmt_name = "enter/exit data"; break;
3628 default: gcc_unreachable ();
3630 switch (gimple_omp_target_kind (ctx->stmt))
3632 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3633 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3634 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3635 ctx_stmt_name = "parallel"; break;
3636 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3637 ctx_stmt_name = "kernels"; break;
3638 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3639 default: gcc_unreachable ();
3642 /* OpenACC/OpenMP mismatch? */
3643 if (is_gimple_omp_oacc (stmt)
3644 != is_gimple_omp_oacc (ctx->stmt))
3646 error_at (gimple_location (stmt),
3647 "%s %s construct inside of %s %s region",
3648 (is_gimple_omp_oacc (stmt)
3649 ? "OpenACC" : "OpenMP"), stmt_name,
3650 (is_gimple_omp_oacc (ctx->stmt)
3651 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3652 return false;
3654 if (is_gimple_omp_offloaded (ctx->stmt))
3656 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3657 if (is_gimple_omp_oacc (ctx->stmt))
3659 error_at (gimple_location (stmt),
3660 "%s construct inside of %s region",
3661 stmt_name, ctx_stmt_name);
3662 return false;
3664 else
3666 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3667 warning_at (gimple_location (stmt), 0,
3668 "%s construct inside of %s region",
3669 stmt_name, ctx_stmt_name);
3673 break;
3674 default:
3675 break;
3677 return true;
3681 /* Helper function scan_omp.
3683 Callback for walk_tree or operators in walk_gimple_stmt used to
3684 scan for OMP directives in TP. */
3686 static tree
3687 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3689 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3690 omp_context *ctx = (omp_context *) wi->info;
3691 tree t = *tp;
3693 switch (TREE_CODE (t))
3695 case VAR_DECL:
3696 case PARM_DECL:
3697 case LABEL_DECL:
3698 case RESULT_DECL:
3699 if (ctx)
3700 *tp = remap_decl (t, &ctx->cb);
3701 break;
3703 default:
3704 if (ctx && TYPE_P (t))
3705 *tp = remap_type (t, &ctx->cb);
3706 else if (!DECL_P (t))
3708 *walk_subtrees = 1;
3709 if (ctx)
3711 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3712 if (tem != TREE_TYPE (t))
3714 if (TREE_CODE (t) == INTEGER_CST)
3715 *tp = wide_int_to_tree (tem, t);
3716 else
3717 TREE_TYPE (t) = tem;
3721 break;
3724 return NULL_TREE;
3727 /* Return true if FNDECL is a setjmp or a longjmp. */
3729 static bool
3730 setjmp_or_longjmp_p (const_tree fndecl)
3732 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3733 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3734 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3735 return true;
3737 tree declname = DECL_NAME (fndecl);
3738 if (!declname)
3739 return false;
3740 const char *name = IDENTIFIER_POINTER (declname);
3741 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3745 /* Helper function for scan_omp.
3747 Callback for walk_gimple_stmt used to scan for OMP directives in
3748 the current statement in GSI. */
3750 static tree
3751 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3752 struct walk_stmt_info *wi)
3754 gimple *stmt = gsi_stmt (*gsi);
3755 omp_context *ctx = (omp_context *) wi->info;
3757 if (gimple_has_location (stmt))
3758 input_location = gimple_location (stmt);
3760 /* Check the nesting restrictions. */
3761 bool remove = false;
3762 if (is_gimple_omp (stmt))
3763 remove = !check_omp_nesting_restrictions (stmt, ctx);
3764 else if (is_gimple_call (stmt))
3766 tree fndecl = gimple_call_fndecl (stmt);
3767 if (fndecl)
3769 if (setjmp_or_longjmp_p (fndecl)
3770 && ctx
3771 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3772 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3774 remove = true;
3775 error_at (gimple_location (stmt),
3776 "setjmp/longjmp inside simd construct");
3778 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3779 switch (DECL_FUNCTION_CODE (fndecl))
3781 case BUILT_IN_GOMP_BARRIER:
3782 case BUILT_IN_GOMP_CANCEL:
3783 case BUILT_IN_GOMP_CANCELLATION_POINT:
3784 case BUILT_IN_GOMP_TASKYIELD:
3785 case BUILT_IN_GOMP_TASKWAIT:
3786 case BUILT_IN_GOMP_TASKGROUP_START:
3787 case BUILT_IN_GOMP_TASKGROUP_END:
3788 remove = !check_omp_nesting_restrictions (stmt, ctx);
3789 break;
3790 default:
3791 break;
3795 if (remove)
3797 stmt = gimple_build_nop ();
3798 gsi_replace (gsi, stmt, false);
3801 *handled_ops_p = true;
3803 switch (gimple_code (stmt))
3805 case GIMPLE_OMP_PARALLEL:
3806 taskreg_nesting_level++;
3807 scan_omp_parallel (gsi, ctx);
3808 taskreg_nesting_level--;
3809 break;
3811 case GIMPLE_OMP_TASK:
3812 taskreg_nesting_level++;
3813 scan_omp_task (gsi, ctx);
3814 taskreg_nesting_level--;
3815 break;
3817 case GIMPLE_OMP_FOR:
3818 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3819 break;
3821 case GIMPLE_OMP_SECTIONS:
3822 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3823 break;
3825 case GIMPLE_OMP_SINGLE:
3826 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3827 break;
3829 case GIMPLE_OMP_SECTION:
3830 case GIMPLE_OMP_MASTER:
3831 case GIMPLE_OMP_TASKGROUP:
3832 case GIMPLE_OMP_ORDERED:
3833 case GIMPLE_OMP_CRITICAL:
3834 ctx = new_omp_context (stmt, ctx);
3835 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3836 break;
3838 case GIMPLE_OMP_TARGET:
3839 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3840 break;
3842 case GIMPLE_OMP_TEAMS:
3843 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3844 break;
3846 case GIMPLE_BIND:
3848 tree var;
3850 *handled_ops_p = false;
3851 if (ctx)
3852 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3853 var ;
3854 var = DECL_CHAIN (var))
3855 insert_decl_map (&ctx->cb, var, var);
3857 break;
3858 default:
3859 *handled_ops_p = false;
3860 break;
3863 return NULL_TREE;
3867 /* Scan all the statements starting at the current statement. CTX
3868 contains context information about the OMP directives and
3869 clauses found during the scan. */
3871 static void
3872 scan_omp (gimple_seq *body_p, omp_context *ctx)
3874 location_t saved_location;
3875 struct walk_stmt_info wi;
3877 memset (&wi, 0, sizeof (wi));
3878 wi.info = ctx;
3879 wi.want_locations = true;
3881 saved_location = input_location;
3882 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3883 input_location = saved_location;
3886 /* Re-gimplification and code generation routines. */
3888 /* Build a call to GOMP_barrier. */
3890 static gimple *
3891 build_omp_barrier (tree lhs)
3893 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3894 : BUILT_IN_GOMP_BARRIER);
3895 gcall *g = gimple_build_call (fndecl, 0);
3896 if (lhs)
3897 gimple_call_set_lhs (g, lhs);
3898 return g;
3901 /* If a context was created for STMT when it was scanned, return it. */
3903 static omp_context *
3904 maybe_lookup_ctx (gimple *stmt)
3906 splay_tree_node n;
3907 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3908 return n ? (omp_context *) n->value : NULL;
3912 /* Find the mapping for DECL in CTX or the immediately enclosing
3913 context that has a mapping for DECL.
3915 If CTX is a nested parallel directive, we may have to use the decl
3916 mappings created in CTX's parent context. Suppose that we have the
3917 following parallel nesting (variable UIDs showed for clarity):
3919 iD.1562 = 0;
3920 #omp parallel shared(iD.1562) -> outer parallel
3921 iD.1562 = iD.1562 + 1;
3923 #omp parallel shared (iD.1562) -> inner parallel
3924 iD.1562 = iD.1562 - 1;
3926 Each parallel structure will create a distinct .omp_data_s structure
3927 for copying iD.1562 in/out of the directive:
3929 outer parallel .omp_data_s.1.i -> iD.1562
3930 inner parallel .omp_data_s.2.i -> iD.1562
3932 A shared variable mapping will produce a copy-out operation before
3933 the parallel directive and a copy-in operation after it. So, in
3934 this case we would have:
3936 iD.1562 = 0;
3937 .omp_data_o.1.i = iD.1562;
3938 #omp parallel shared(iD.1562) -> outer parallel
3939 .omp_data_i.1 = &.omp_data_o.1
3940 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3942 .omp_data_o.2.i = iD.1562; -> **
3943 #omp parallel shared(iD.1562) -> inner parallel
3944 .omp_data_i.2 = &.omp_data_o.2
3945 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3948 ** This is a problem. The symbol iD.1562 cannot be referenced
3949 inside the body of the outer parallel region. But since we are
3950 emitting this copy operation while expanding the inner parallel
3951 directive, we need to access the CTX structure of the outer
3952 parallel directive to get the correct mapping:
3954 .omp_data_o.2.i = .omp_data_i.1->i
3956 Since there may be other workshare or parallel directives enclosing
3957 the parallel directive, it may be necessary to walk up the context
3958 parent chain. This is not a problem in general because nested
3959 parallelism happens only rarely. */
3961 static tree
3962 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3964 tree t;
3965 omp_context *up;
3967 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3968 t = maybe_lookup_decl (decl, up);
3970 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3972 return t ? t : decl;
3976 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3977 in outer contexts. */
3979 static tree
3980 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3982 tree t = NULL;
3983 omp_context *up;
3985 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3986 t = maybe_lookup_decl (decl, up);
3988 return t ? t : decl;
3992 /* Construct the initialization value for reduction operation OP. */
3994 tree
3995 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3997 switch (op)
3999 case PLUS_EXPR:
4000 case MINUS_EXPR:
4001 case BIT_IOR_EXPR:
4002 case BIT_XOR_EXPR:
4003 case TRUTH_OR_EXPR:
4004 case TRUTH_ORIF_EXPR:
4005 case TRUTH_XOR_EXPR:
4006 case NE_EXPR:
4007 return build_zero_cst (type);
4009 case MULT_EXPR:
4010 case TRUTH_AND_EXPR:
4011 case TRUTH_ANDIF_EXPR:
4012 case EQ_EXPR:
4013 return fold_convert_loc (loc, type, integer_one_node);
4015 case BIT_AND_EXPR:
4016 return fold_convert_loc (loc, type, integer_minus_one_node);
4018 case MAX_EXPR:
4019 if (SCALAR_FLOAT_TYPE_P (type))
4021 REAL_VALUE_TYPE max, min;
4022 if (HONOR_INFINITIES (type))
4024 real_inf (&max);
4025 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4027 else
4028 real_maxval (&min, 1, TYPE_MODE (type));
4029 return build_real (type, min);
4031 else if (POINTER_TYPE_P (type))
4033 wide_int min
4034 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4035 return wide_int_to_tree (type, min);
4037 else
4039 gcc_assert (INTEGRAL_TYPE_P (type));
4040 return TYPE_MIN_VALUE (type);
4043 case MIN_EXPR:
4044 if (SCALAR_FLOAT_TYPE_P (type))
4046 REAL_VALUE_TYPE max;
4047 if (HONOR_INFINITIES (type))
4048 real_inf (&max);
4049 else
4050 real_maxval (&max, 0, TYPE_MODE (type));
4051 return build_real (type, max);
4053 else if (POINTER_TYPE_P (type))
4055 wide_int max
4056 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4057 return wide_int_to_tree (type, max);
4059 else
4061 gcc_assert (INTEGRAL_TYPE_P (type));
4062 return TYPE_MAX_VALUE (type);
4065 default:
4066 gcc_unreachable ();
4070 /* Construct the initialization value for reduction CLAUSE. */
4072 tree
4073 omp_reduction_init (tree clause, tree type)
4075 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4076 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4079 /* Return alignment to be assumed for var in CLAUSE, which should be
4080 OMP_CLAUSE_ALIGNED. */
4082 static tree
4083 omp_clause_aligned_alignment (tree clause)
4085 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4086 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4088 /* Otherwise return implementation defined alignment. */
4089 unsigned int al = 1;
4090 machine_mode mode, vmode;
4091 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4092 if (vs)
4093 vs = 1 << floor_log2 (vs);
4094 static enum mode_class classes[]
4095 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4096 for (int i = 0; i < 4; i += 2)
4097 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4098 mode != VOIDmode;
4099 mode = GET_MODE_WIDER_MODE (mode))
4101 vmode = targetm.vectorize.preferred_simd_mode (mode);
4102 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4103 continue;
4104 while (vs
4105 && GET_MODE_SIZE (vmode) < vs
4106 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4107 vmode = GET_MODE_2XWIDER_MODE (vmode);
4109 tree type = lang_hooks.types.type_for_mode (mode, 1);
4110 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4111 continue;
4112 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4113 / GET_MODE_SIZE (mode));
4114 if (TYPE_MODE (type) != vmode)
4115 continue;
4116 if (TYPE_ALIGN_UNIT (type) > al)
4117 al = TYPE_ALIGN_UNIT (type);
4119 return build_int_cst (integer_type_node, al);
4122 /* Return maximum possible vectorization factor for the target. */
4124 static int
4125 omp_max_vf (void)
4127 if (!optimize
4128 || optimize_debug
4129 || !flag_tree_loop_optimize
4130 || (!flag_tree_loop_vectorize
4131 && (global_options_set.x_flag_tree_loop_vectorize
4132 || global_options_set.x_flag_tree_vectorize)))
4133 return 1;
4135 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4136 if (vs)
4138 vs = 1 << floor_log2 (vs);
4139 return vs;
4141 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4142 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4143 return GET_MODE_NUNITS (vqimode);
4144 return 1;
4147 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4148 privatization. */
4150 static bool
4151 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4152 tree &idx, tree &lane, tree &ivar, tree &lvar)
4154 if (max_vf == 0)
4156 max_vf = omp_max_vf ();
4157 if (max_vf > 1)
4159 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4160 OMP_CLAUSE_SAFELEN);
4161 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4162 max_vf = 1;
4163 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4164 max_vf) == -1)
4165 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4167 if (max_vf > 1)
4169 idx = create_tmp_var (unsigned_type_node);
4170 lane = create_tmp_var (unsigned_type_node);
4173 if (max_vf == 1)
4174 return false;
4176 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4177 tree avar = create_tmp_var_raw (atype);
4178 if (TREE_ADDRESSABLE (new_var))
4179 TREE_ADDRESSABLE (avar) = 1;
4180 DECL_ATTRIBUTES (avar)
4181 = tree_cons (get_identifier ("omp simd array"), NULL,
4182 DECL_ATTRIBUTES (avar));
4183 gimple_add_tmp_var (avar);
4184 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4185 NULL_TREE, NULL_TREE);
4186 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4187 NULL_TREE, NULL_TREE);
4188 if (DECL_P (new_var))
4190 SET_DECL_VALUE_EXPR (new_var, lvar);
4191 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4193 return true;
4196 /* Helper function of lower_rec_input_clauses. For a reference
4197 in simd reduction, add an underlying variable it will reference. */
4199 static void
4200 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4202 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4203 if (TREE_CONSTANT (z))
4205 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4206 get_name (new_vard));
4207 gimple_add_tmp_var (z);
4208 TREE_ADDRESSABLE (z) = 1;
4209 z = build_fold_addr_expr_loc (loc, z);
4210 gimplify_assign (new_vard, z, ilist);
4214 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4215 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4216 private variables. Initialization statements go in ILIST, while calls
4217 to destructors go in DLIST. */
4219 static void
4220 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4221 omp_context *ctx, struct omp_for_data *fd)
4223 tree c, dtor, copyin_seq, x, ptr;
4224 bool copyin_by_ref = false;
4225 bool lastprivate_firstprivate = false;
4226 bool reduction_omp_orig_ref = false;
4227 int pass;
4228 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4229 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4230 int max_vf = 0;
4231 tree lane = NULL_TREE, idx = NULL_TREE;
4232 tree ivar = NULL_TREE, lvar = NULL_TREE;
4233 gimple_seq llist[2] = { NULL, NULL };
4235 copyin_seq = NULL;
4237 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4238 with data sharing clauses referencing variable sized vars. That
4239 is unnecessarily hard to support and very unlikely to result in
4240 vectorized code anyway. */
4241 if (is_simd)
4242 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4243 switch (OMP_CLAUSE_CODE (c))
4245 case OMP_CLAUSE_LINEAR:
4246 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4247 max_vf = 1;
4248 /* FALLTHRU */
4249 case OMP_CLAUSE_PRIVATE:
4250 case OMP_CLAUSE_FIRSTPRIVATE:
4251 case OMP_CLAUSE_LASTPRIVATE:
4252 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4253 max_vf = 1;
4254 break;
4255 case OMP_CLAUSE_REDUCTION:
4256 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4257 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4258 max_vf = 1;
4259 break;
4260 default:
4261 continue;
4264 /* Do all the fixed sized types in the first pass, and the variable sized
4265 types in the second pass. This makes sure that the scalar arguments to
4266 the variable sized types are processed before we use them in the
4267 variable sized operations. */
4268 for (pass = 0; pass < 2; ++pass)
4270 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4272 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4273 tree var, new_var;
4274 bool by_ref;
4275 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4277 switch (c_kind)
4279 case OMP_CLAUSE_PRIVATE:
4280 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4281 continue;
4282 break;
4283 case OMP_CLAUSE_SHARED:
4284 /* Ignore shared directives in teams construct. */
4285 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4286 continue;
4287 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4289 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4290 || is_global_var (OMP_CLAUSE_DECL (c)));
4291 continue;
4293 case OMP_CLAUSE_FIRSTPRIVATE:
4294 case OMP_CLAUSE_COPYIN:
4295 break;
4296 case OMP_CLAUSE_LINEAR:
4297 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4298 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4299 lastprivate_firstprivate = true;
4300 break;
4301 case OMP_CLAUSE_REDUCTION:
4302 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4303 reduction_omp_orig_ref = true;
4304 break;
4305 case OMP_CLAUSE__LOOPTEMP_:
4306 /* Handle _looptemp_ clauses only on parallel/task. */
4307 if (fd)
4308 continue;
4309 break;
4310 case OMP_CLAUSE_LASTPRIVATE:
4311 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4313 lastprivate_firstprivate = true;
4314 if (pass != 0 || is_taskloop_ctx (ctx))
4315 continue;
4317 /* Even without corresponding firstprivate, if
4318 decl is Fortran allocatable, it needs outer var
4319 reference. */
4320 else if (pass == 0
4321 && lang_hooks.decls.omp_private_outer_ref
4322 (OMP_CLAUSE_DECL (c)))
4323 lastprivate_firstprivate = true;
4324 break;
4325 case OMP_CLAUSE_ALIGNED:
4326 if (pass == 0)
4327 continue;
4328 var = OMP_CLAUSE_DECL (c);
4329 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4330 && !is_global_var (var))
4332 new_var = maybe_lookup_decl (var, ctx);
4333 if (new_var == NULL_TREE)
4334 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4335 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4336 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4337 omp_clause_aligned_alignment (c));
4338 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4339 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4340 gimplify_and_add (x, ilist);
4342 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4343 && is_global_var (var))
4345 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4346 new_var = lookup_decl (var, ctx);
4347 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4348 t = build_fold_addr_expr_loc (clause_loc, t);
4349 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4350 t = build_call_expr_loc (clause_loc, t2, 2, t,
4351 omp_clause_aligned_alignment (c));
4352 t = fold_convert_loc (clause_loc, ptype, t);
4353 x = create_tmp_var (ptype);
4354 t = build2 (MODIFY_EXPR, ptype, x, t);
4355 gimplify_and_add (t, ilist);
4356 t = build_simple_mem_ref_loc (clause_loc, x);
4357 SET_DECL_VALUE_EXPR (new_var, t);
4358 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4360 continue;
4361 default:
4362 continue;
4365 new_var = var = OMP_CLAUSE_DECL (c);
4366 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4368 var = TREE_OPERAND (var, 0);
4369 if (TREE_CODE (var) == INDIRECT_REF
4370 || TREE_CODE (var) == ADDR_EXPR)
4371 var = TREE_OPERAND (var, 0);
4372 if (is_variable_sized (var))
4374 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4375 var = DECL_VALUE_EXPR (var);
4376 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4377 var = TREE_OPERAND (var, 0);
4378 gcc_assert (DECL_P (var));
4380 new_var = var;
4382 if (c_kind != OMP_CLAUSE_COPYIN)
4383 new_var = lookup_decl (var, ctx);
4385 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4387 if (pass != 0)
4388 continue;
4390 /* C/C++ array section reductions. */
4391 else if (c_kind == OMP_CLAUSE_REDUCTION
4392 && var != OMP_CLAUSE_DECL (c))
4394 if (pass == 0)
4395 continue;
4397 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4398 if (TREE_CODE (orig_var) == INDIRECT_REF
4399 || TREE_CODE (orig_var) == ADDR_EXPR)
4400 orig_var = TREE_OPERAND (orig_var, 0);
4401 tree d = OMP_CLAUSE_DECL (c);
4402 tree type = TREE_TYPE (d);
4403 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4404 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4405 const char *name = get_name (orig_var);
4406 if (TREE_CONSTANT (v))
4408 x = create_tmp_var_raw (type, name);
4409 gimple_add_tmp_var (x);
4410 TREE_ADDRESSABLE (x) = 1;
4411 x = build_fold_addr_expr_loc (clause_loc, x);
4413 else
4415 tree atmp
4416 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4417 tree t = maybe_lookup_decl (v, ctx);
4418 if (t)
4419 v = t;
4420 else
4421 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4422 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4423 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4424 TREE_TYPE (v), v,
4425 build_int_cst (TREE_TYPE (v), 1));
4426 t = fold_build2_loc (clause_loc, MULT_EXPR,
4427 TREE_TYPE (v), t,
4428 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4429 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4430 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4433 tree ptype = build_pointer_type (TREE_TYPE (type));
4434 x = fold_convert_loc (clause_loc, ptype, x);
4435 tree y = create_tmp_var (ptype, name);
4436 gimplify_assign (y, x, ilist);
4437 x = y;
4438 if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4440 if (orig_var != var)
4442 gcc_assert (is_variable_sized (orig_var));
4443 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4445 gimplify_assign (new_var, x, ilist);
4446 tree new_orig_var = lookup_decl (orig_var, ctx);
4447 tree t = build_fold_indirect_ref (new_var);
4448 DECL_IGNORED_P (new_var) = 0;
4449 TREE_THIS_NOTRAP (t);
4450 SET_DECL_VALUE_EXPR (new_orig_var, t);
4451 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4453 else
4455 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4456 build_int_cst (ptype, 0));
4457 SET_DECL_VALUE_EXPR (new_var, x);
4458 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4461 else
4463 gcc_assert (orig_var == var);
4464 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4466 x = create_tmp_var (ptype, name);
4467 TREE_ADDRESSABLE (x) = 1;
4468 gimplify_assign (x, y, ilist);
4469 x = build_fold_addr_expr_loc (clause_loc, x);
4471 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4472 gimplify_assign (new_var, x, ilist);
4474 tree y1 = create_tmp_var (ptype, NULL);
4475 gimplify_assign (y1, y, ilist);
4476 tree i2 = NULL_TREE, y2 = NULL_TREE;
4477 tree body2 = NULL_TREE, end2 = NULL_TREE;
4478 tree y3 = NULL_TREE, y4 = NULL_TREE;
4479 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4481 y2 = create_tmp_var (ptype, NULL);
4482 gimplify_assign (y2, y, ilist);
4483 tree ref = build_outer_var_ref (var, ctx);
4484 /* For ref build_outer_var_ref already performs this. */
4485 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4486 gcc_assert (is_reference (var));
4487 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4488 ref = build_fold_addr_expr (ref);
4489 else if (is_reference (var))
4490 ref = build_fold_addr_expr (ref);
4491 ref = fold_convert_loc (clause_loc, ptype, ref);
4492 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4493 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4495 y3 = create_tmp_var (ptype, NULL);
4496 gimplify_assign (y3, unshare_expr (ref), ilist);
4498 if (is_simd)
4500 y4 = create_tmp_var (ptype, NULL);
4501 gimplify_assign (y4, ref, dlist);
4504 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4505 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4506 tree body = create_artificial_label (UNKNOWN_LOCATION);
4507 tree end = create_artificial_label (UNKNOWN_LOCATION);
4508 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4509 if (y2)
4511 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4512 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4513 body2 = create_artificial_label (UNKNOWN_LOCATION);
4514 end2 = create_artificial_label (UNKNOWN_LOCATION);
4515 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4517 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4519 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4520 tree decl_placeholder
4521 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4522 SET_DECL_VALUE_EXPR (decl_placeholder,
4523 build_simple_mem_ref (y1));
4524 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4525 SET_DECL_VALUE_EXPR (placeholder,
4526 y3 ? build_simple_mem_ref (y3)
4527 : error_mark_node);
4528 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4529 x = lang_hooks.decls.omp_clause_default_ctor
4530 (c, build_simple_mem_ref (y1),
4531 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4532 if (x)
4533 gimplify_and_add (x, ilist);
4534 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4536 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4537 lower_omp (&tseq, ctx);
4538 gimple_seq_add_seq (ilist, tseq);
4540 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4541 if (is_simd)
4543 SET_DECL_VALUE_EXPR (decl_placeholder,
4544 build_simple_mem_ref (y2));
4545 SET_DECL_VALUE_EXPR (placeholder,
4546 build_simple_mem_ref (y4));
4547 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4548 lower_omp (&tseq, ctx);
4549 gimple_seq_add_seq (dlist, tseq);
4550 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4552 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4553 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4554 x = lang_hooks.decls.omp_clause_dtor
4555 (c, build_simple_mem_ref (y2));
4556 if (x)
4558 gimple_seq tseq = NULL;
4559 dtor = x;
4560 gimplify_stmt (&dtor, &tseq);
4561 gimple_seq_add_seq (dlist, tseq);
4564 else
4566 x = omp_reduction_init (c, TREE_TYPE (type));
4567 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4569 /* reduction(-:var) sums up the partial results, so it
4570 acts identically to reduction(+:var). */
4571 if (code == MINUS_EXPR)
4572 code = PLUS_EXPR;
4574 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4575 if (is_simd)
4577 x = build2 (code, TREE_TYPE (type),
4578 build_simple_mem_ref (y4),
4579 build_simple_mem_ref (y2));
4580 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4583 gimple *g
4584 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4585 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4586 gimple_seq_add_stmt (ilist, g);
4587 if (y3)
4589 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4590 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4591 gimple_seq_add_stmt (ilist, g);
4593 g = gimple_build_assign (i, PLUS_EXPR, i,
4594 build_int_cst (TREE_TYPE (i), 1));
4595 gimple_seq_add_stmt (ilist, g);
4596 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4597 gimple_seq_add_stmt (ilist, g);
4598 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4599 if (y2)
4601 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4602 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4603 gimple_seq_add_stmt (dlist, g);
4604 if (y4)
4606 g = gimple_build_assign
4607 (y4, POINTER_PLUS_EXPR, y4,
4608 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4609 gimple_seq_add_stmt (dlist, g);
4611 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4612 build_int_cst (TREE_TYPE (i2), 1));
4613 gimple_seq_add_stmt (dlist, g);
4614 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4615 gimple_seq_add_stmt (dlist, g);
4616 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4618 continue;
4620 else if (is_variable_sized (var))
4622 /* For variable sized types, we need to allocate the
4623 actual storage here. Call alloca and store the
4624 result in the pointer decl that we created elsewhere. */
4625 if (pass == 0)
4626 continue;
4628 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4630 gcall *stmt;
4631 tree tmp, atmp;
4633 ptr = DECL_VALUE_EXPR (new_var);
4634 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4635 ptr = TREE_OPERAND (ptr, 0);
4636 gcc_assert (DECL_P (ptr));
4637 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4639 /* void *tmp = __builtin_alloca */
4640 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4641 stmt = gimple_build_call (atmp, 2, x,
4642 size_int (DECL_ALIGN (var)));
4643 tmp = create_tmp_var_raw (ptr_type_node);
4644 gimple_add_tmp_var (tmp);
4645 gimple_call_set_lhs (stmt, tmp);
4647 gimple_seq_add_stmt (ilist, stmt);
4649 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4650 gimplify_assign (ptr, x, ilist);
4653 else if (is_reference (var))
4655 /* For references that are being privatized for Fortran,
4656 allocate new backing storage for the new pointer
4657 variable. This allows us to avoid changing all the
4658 code that expects a pointer to something that expects
4659 a direct variable. */
4660 if (pass == 0)
4661 continue;
4663 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4664 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4666 x = build_receiver_ref (var, false, ctx);
4667 x = build_fold_addr_expr_loc (clause_loc, x);
4669 else if (TREE_CONSTANT (x))
4671 /* For reduction in SIMD loop, defer adding the
4672 initialization of the reference, because if we decide
4673 to use SIMD array for it, the initilization could cause
4674 expansion ICE. */
4675 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4676 x = NULL_TREE;
4677 else
4679 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4680 get_name (var));
4681 gimple_add_tmp_var (x);
4682 TREE_ADDRESSABLE (x) = 1;
4683 x = build_fold_addr_expr_loc (clause_loc, x);
4686 else
4688 tree atmp
4689 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4690 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4691 tree al = size_int (TYPE_ALIGN (rtype));
4692 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4695 if (x)
4697 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4698 gimplify_assign (new_var, x, ilist);
4701 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4703 else if (c_kind == OMP_CLAUSE_REDUCTION
4704 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4706 if (pass == 0)
4707 continue;
4709 else if (pass != 0)
4710 continue;
4712 switch (OMP_CLAUSE_CODE (c))
4714 case OMP_CLAUSE_SHARED:
4715 /* Ignore shared directives in teams construct. */
4716 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4717 continue;
4718 /* Shared global vars are just accessed directly. */
4719 if (is_global_var (new_var))
4720 break;
4721 /* For taskloop firstprivate/lastprivate, represented
4722 as firstprivate and shared clause on the task, new_var
4723 is the firstprivate var. */
4724 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4725 break;
4726 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4727 needs to be delayed until after fixup_child_record_type so
4728 that we get the correct type during the dereference. */
4729 by_ref = use_pointer_for_field (var, ctx);
4730 x = build_receiver_ref (var, by_ref, ctx);
4731 SET_DECL_VALUE_EXPR (new_var, x);
4732 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4734 /* ??? If VAR is not passed by reference, and the variable
4735 hasn't been initialized yet, then we'll get a warning for
4736 the store into the omp_data_s structure. Ideally, we'd be
4737 able to notice this and not store anything at all, but
4738 we're generating code too early. Suppress the warning. */
4739 if (!by_ref)
4740 TREE_NO_WARNING (var) = 1;
4741 break;
4743 case OMP_CLAUSE_LASTPRIVATE:
4744 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4745 break;
4746 /* FALLTHRU */
4748 case OMP_CLAUSE_PRIVATE:
4749 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4750 x = build_outer_var_ref (var, ctx);
4751 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4753 if (is_task_ctx (ctx))
4754 x = build_receiver_ref (var, false, ctx);
4755 else
4756 x = build_outer_var_ref (var, ctx);
4758 else
4759 x = NULL;
4760 do_private:
4761 tree nx;
4762 nx = lang_hooks.decls.omp_clause_default_ctor
4763 (c, unshare_expr (new_var), x);
4764 if (is_simd)
4766 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4767 if ((TREE_ADDRESSABLE (new_var) || nx || y
4768 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4769 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4770 idx, lane, ivar, lvar))
4772 if (nx)
4773 x = lang_hooks.decls.omp_clause_default_ctor
4774 (c, unshare_expr (ivar), x);
4775 if (nx && x)
4776 gimplify_and_add (x, &llist[0]);
4777 if (y)
4779 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4780 if (y)
4782 gimple_seq tseq = NULL;
4784 dtor = y;
4785 gimplify_stmt (&dtor, &tseq);
4786 gimple_seq_add_seq (&llist[1], tseq);
4789 break;
4792 if (nx)
4793 gimplify_and_add (nx, ilist);
4794 /* FALLTHRU */
4796 do_dtor:
4797 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4798 if (x)
4800 gimple_seq tseq = NULL;
4802 dtor = x;
4803 gimplify_stmt (&dtor, &tseq);
4804 gimple_seq_add_seq (dlist, tseq);
4806 break;
4808 case OMP_CLAUSE_LINEAR:
4809 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4810 goto do_firstprivate;
4811 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4812 x = NULL;
4813 else
4814 x = build_outer_var_ref (var, ctx);
4815 goto do_private;
4817 case OMP_CLAUSE_FIRSTPRIVATE:
4818 if (is_task_ctx (ctx))
4820 if (is_reference (var) || is_variable_sized (var))
4821 goto do_dtor;
4822 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4823 ctx))
4824 || use_pointer_for_field (var, NULL))
4826 x = build_receiver_ref (var, false, ctx);
4827 SET_DECL_VALUE_EXPR (new_var, x);
4828 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4829 goto do_dtor;
4832 do_firstprivate:
4833 x = build_outer_var_ref (var, ctx);
4834 if (is_simd)
4836 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4837 && gimple_omp_for_combined_into_p (ctx->stmt))
4839 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4840 tree stept = TREE_TYPE (t);
4841 tree ct = find_omp_clause (clauses,
4842 OMP_CLAUSE__LOOPTEMP_);
4843 gcc_assert (ct);
4844 tree l = OMP_CLAUSE_DECL (ct);
4845 tree n1 = fd->loop.n1;
4846 tree step = fd->loop.step;
4847 tree itype = TREE_TYPE (l);
4848 if (POINTER_TYPE_P (itype))
4849 itype = signed_type_for (itype);
4850 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4851 if (TYPE_UNSIGNED (itype)
4852 && fd->loop.cond_code == GT_EXPR)
4853 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4854 fold_build1 (NEGATE_EXPR, itype, l),
4855 fold_build1 (NEGATE_EXPR,
4856 itype, step));
4857 else
4858 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
4859 t = fold_build2 (MULT_EXPR, stept,
4860 fold_convert (stept, l), t);
4862 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4864 x = lang_hooks.decls.omp_clause_linear_ctor
4865 (c, new_var, x, t);
4866 gimplify_and_add (x, ilist);
4867 goto do_dtor;
4870 if (POINTER_TYPE_P (TREE_TYPE (x)))
4871 x = fold_build2 (POINTER_PLUS_EXPR,
4872 TREE_TYPE (x), x, t);
4873 else
4874 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4877 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4878 || TREE_ADDRESSABLE (new_var))
4879 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4880 idx, lane, ivar, lvar))
4882 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4884 tree iv = create_tmp_var (TREE_TYPE (new_var));
4885 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4886 gimplify_and_add (x, ilist);
4887 gimple_stmt_iterator gsi
4888 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4889 gassign *g
4890 = gimple_build_assign (unshare_expr (lvar), iv);
4891 gsi_insert_before_without_update (&gsi, g,
4892 GSI_SAME_STMT);
4893 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4894 enum tree_code code = PLUS_EXPR;
4895 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4896 code = POINTER_PLUS_EXPR;
4897 g = gimple_build_assign (iv, code, iv, t);
4898 gsi_insert_before_without_update (&gsi, g,
4899 GSI_SAME_STMT);
4900 break;
4902 x = lang_hooks.decls.omp_clause_copy_ctor
4903 (c, unshare_expr (ivar), x);
4904 gimplify_and_add (x, &llist[0]);
4905 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4906 if (x)
4908 gimple_seq tseq = NULL;
4910 dtor = x;
4911 gimplify_stmt (&dtor, &tseq);
4912 gimple_seq_add_seq (&llist[1], tseq);
4914 break;
4917 x = lang_hooks.decls.omp_clause_copy_ctor
4918 (c, unshare_expr (new_var), x);
4919 gimplify_and_add (x, ilist);
4920 goto do_dtor;
4922 case OMP_CLAUSE__LOOPTEMP_:
4923 gcc_assert (is_taskreg_ctx (ctx));
4924 x = build_outer_var_ref (var, ctx);
4925 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4926 gimplify_and_add (x, ilist);
4927 break;
4929 case OMP_CLAUSE_COPYIN:
4930 by_ref = use_pointer_for_field (var, NULL);
4931 x = build_receiver_ref (var, by_ref, ctx);
4932 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4933 append_to_statement_list (x, &copyin_seq);
4934 copyin_by_ref |= by_ref;
4935 break;
4937 case OMP_CLAUSE_REDUCTION:
4938 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4940 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4941 gimple *tseq;
4942 x = build_outer_var_ref (var, ctx);
4944 if (is_reference (var)
4945 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4946 TREE_TYPE (x)))
4947 x = build_fold_addr_expr_loc (clause_loc, x);
4948 SET_DECL_VALUE_EXPR (placeholder, x);
4949 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4950 tree new_vard = new_var;
4951 if (is_reference (var))
4953 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4954 new_vard = TREE_OPERAND (new_var, 0);
4955 gcc_assert (DECL_P (new_vard));
4957 if (is_simd
4958 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4959 idx, lane, ivar, lvar))
4961 if (new_vard == new_var)
4963 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4964 SET_DECL_VALUE_EXPR (new_var, ivar);
4966 else
4968 SET_DECL_VALUE_EXPR (new_vard,
4969 build_fold_addr_expr (ivar));
4970 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4972 x = lang_hooks.decls.omp_clause_default_ctor
4973 (c, unshare_expr (ivar),
4974 build_outer_var_ref (var, ctx));
4975 if (x)
4976 gimplify_and_add (x, &llist[0]);
4977 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4979 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4980 lower_omp (&tseq, ctx);
4981 gimple_seq_add_seq (&llist[0], tseq);
4983 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4984 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4985 lower_omp (&tseq, ctx);
4986 gimple_seq_add_seq (&llist[1], tseq);
4987 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4988 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4989 if (new_vard == new_var)
4990 SET_DECL_VALUE_EXPR (new_var, lvar);
4991 else
4992 SET_DECL_VALUE_EXPR (new_vard,
4993 build_fold_addr_expr (lvar));
4994 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4995 if (x)
4997 tseq = NULL;
4998 dtor = x;
4999 gimplify_stmt (&dtor, &tseq);
5000 gimple_seq_add_seq (&llist[1], tseq);
5002 break;
5004 /* If this is a reference to constant size reduction var
5005 with placeholder, we haven't emitted the initializer
5006 for it because it is undesirable if SIMD arrays are used.
5007 But if they aren't used, we need to emit the deferred
5008 initialization now. */
5009 else if (is_reference (var) && is_simd)
5010 handle_simd_reference (clause_loc, new_vard, ilist);
5011 x = lang_hooks.decls.omp_clause_default_ctor
5012 (c, unshare_expr (new_var),
5013 build_outer_var_ref (var, ctx));
5014 if (x)
5015 gimplify_and_add (x, ilist);
5016 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5018 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5019 lower_omp (&tseq, ctx);
5020 gimple_seq_add_seq (ilist, tseq);
5022 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5023 if (is_simd)
5025 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5026 lower_omp (&tseq, ctx);
5027 gimple_seq_add_seq (dlist, tseq);
5028 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5030 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5031 goto do_dtor;
5033 else
5035 x = omp_reduction_init (c, TREE_TYPE (new_var));
5036 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5037 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5039 /* reduction(-:var) sums up the partial results, so it
5040 acts identically to reduction(+:var). */
5041 if (code == MINUS_EXPR)
5042 code = PLUS_EXPR;
5044 tree new_vard = new_var;
5045 if (is_simd && is_reference (var))
5047 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5048 new_vard = TREE_OPERAND (new_var, 0);
5049 gcc_assert (DECL_P (new_vard));
5051 if (is_simd
5052 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5053 idx, lane, ivar, lvar))
5055 tree ref = build_outer_var_ref (var, ctx);
5057 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5059 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5060 ref = build_outer_var_ref (var, ctx);
5061 gimplify_assign (ref, x, &llist[1]);
5063 if (new_vard != new_var)
5065 SET_DECL_VALUE_EXPR (new_vard,
5066 build_fold_addr_expr (lvar));
5067 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5070 else
5072 if (is_reference (var) && is_simd)
5073 handle_simd_reference (clause_loc, new_vard, ilist);
5074 gimplify_assign (new_var, x, ilist);
5075 if (is_simd)
5077 tree ref = build_outer_var_ref (var, ctx);
5079 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5080 ref = build_outer_var_ref (var, ctx);
5081 gimplify_assign (ref, x, dlist);
5085 break;
5087 default:
5088 gcc_unreachable ();
5093 if (lane)
5095 tree uid = create_tmp_var (ptr_type_node, "simduid");
5096 /* Don't want uninit warnings on simduid, it is always uninitialized,
5097 but we use it not for the value, but for the DECL_UID only. */
5098 TREE_NO_WARNING (uid) = 1;
5099 gimple *g
5100 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5101 gimple_call_set_lhs (g, lane);
5102 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5103 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5104 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5105 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5106 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5107 gimple_omp_for_set_clauses (ctx->stmt, c);
5108 g = gimple_build_assign (lane, INTEGER_CST,
5109 build_int_cst (unsigned_type_node, 0));
5110 gimple_seq_add_stmt (ilist, g);
5111 for (int i = 0; i < 2; i++)
5112 if (llist[i])
5114 tree vf = create_tmp_var (unsigned_type_node);
5115 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5116 gimple_call_set_lhs (g, vf);
5117 gimple_seq *seq = i == 0 ? ilist : dlist;
5118 gimple_seq_add_stmt (seq, g);
5119 tree t = build_int_cst (unsigned_type_node, 0);
5120 g = gimple_build_assign (idx, INTEGER_CST, t);
5121 gimple_seq_add_stmt (seq, g);
5122 tree body = create_artificial_label (UNKNOWN_LOCATION);
5123 tree header = create_artificial_label (UNKNOWN_LOCATION);
5124 tree end = create_artificial_label (UNKNOWN_LOCATION);
5125 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5126 gimple_seq_add_stmt (seq, gimple_build_label (body));
5127 gimple_seq_add_seq (seq, llist[i]);
5128 t = build_int_cst (unsigned_type_node, 1);
5129 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5130 gimple_seq_add_stmt (seq, g);
5131 gimple_seq_add_stmt (seq, gimple_build_label (header));
5132 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5133 gimple_seq_add_stmt (seq, g);
5134 gimple_seq_add_stmt (seq, gimple_build_label (end));
5138 /* The copyin sequence is not to be executed by the main thread, since
5139 that would result in self-copies. Perhaps not visible to scalars,
5140 but it certainly is to C++ operator=. */
5141 if (copyin_seq)
5143 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5145 x = build2 (NE_EXPR, boolean_type_node, x,
5146 build_int_cst (TREE_TYPE (x), 0));
5147 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5148 gimplify_and_add (x, ilist);
5151 /* If any copyin variable is passed by reference, we must ensure the
5152 master thread doesn't modify it before it is copied over in all
5153 threads. Similarly for variables in both firstprivate and
5154 lastprivate clauses we need to ensure the lastprivate copying
5155 happens after firstprivate copying in all threads. And similarly
5156 for UDRs if initializer expression refers to omp_orig. */
5157 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5159 /* Don't add any barrier for #pragma omp simd or
5160 #pragma omp distribute. */
5161 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5162 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5163 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5166 /* If max_vf is non-zero, then we can use only a vectorization factor
5167 up to the max_vf we chose. So stick it into the safelen clause. */
5168 if (max_vf)
5170 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5171 OMP_CLAUSE_SAFELEN);
5172 if (c == NULL_TREE
5173 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5174 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5175 max_vf) == 1))
5177 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5178 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5179 max_vf);
5180 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5181 gimple_omp_for_set_clauses (ctx->stmt, c);
5187 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5188 both parallel and workshare constructs. PREDICATE may be NULL if it's
5189 always true. */
5191 static void
5192 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5193 omp_context *ctx)
5195 tree x, c, label = NULL, orig_clauses = clauses;
5196 bool par_clauses = false;
5197 tree simduid = NULL, lastlane = NULL;
5199 /* Early exit if there are no lastprivate or linear clauses. */
5200 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5201 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5202 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5203 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5204 break;
5205 if (clauses == NULL)
5207 /* If this was a workshare clause, see if it had been combined
5208 with its parallel. In that case, look for the clauses on the
5209 parallel statement itself. */
5210 if (is_parallel_ctx (ctx))
5211 return;
5213 ctx = ctx->outer;
5214 if (ctx == NULL || !is_parallel_ctx (ctx))
5215 return;
5217 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5218 OMP_CLAUSE_LASTPRIVATE);
5219 if (clauses == NULL)
5220 return;
5221 par_clauses = true;
5224 if (predicate)
5226 gcond *stmt;
5227 tree label_true, arm1, arm2;
5229 label = create_artificial_label (UNKNOWN_LOCATION);
5230 label_true = create_artificial_label (UNKNOWN_LOCATION);
5231 arm1 = TREE_OPERAND (predicate, 0);
5232 arm2 = TREE_OPERAND (predicate, 1);
5233 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5234 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5235 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5236 label_true, label);
5237 gimple_seq_add_stmt (stmt_list, stmt);
5238 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5241 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5242 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5244 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5245 if (simduid)
5246 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5249 for (c = clauses; c ;)
5251 tree var, new_var;
5252 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5254 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5255 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5256 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5258 var = OMP_CLAUSE_DECL (c);
5259 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5260 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5261 && is_taskloop_ctx (ctx))
5263 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5264 new_var = lookup_decl (var, ctx->outer);
5266 else
5267 new_var = lookup_decl (var, ctx);
5269 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5271 tree val = DECL_VALUE_EXPR (new_var);
5272 if (TREE_CODE (val) == ARRAY_REF
5273 && VAR_P (TREE_OPERAND (val, 0))
5274 && lookup_attribute ("omp simd array",
5275 DECL_ATTRIBUTES (TREE_OPERAND (val,
5276 0))))
5278 if (lastlane == NULL)
5280 lastlane = create_tmp_var (unsigned_type_node);
5281 gcall *g
5282 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5283 2, simduid,
5284 TREE_OPERAND (val, 1));
5285 gimple_call_set_lhs (g, lastlane);
5286 gimple_seq_add_stmt (stmt_list, g);
5288 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5289 TREE_OPERAND (val, 0), lastlane,
5290 NULL_TREE, NULL_TREE);
5294 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5295 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5297 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5298 gimple_seq_add_seq (stmt_list,
5299 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5300 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5302 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5303 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5305 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5306 gimple_seq_add_seq (stmt_list,
5307 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5308 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5311 x = NULL_TREE;
5312 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5313 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5315 gcc_checking_assert (is_taskloop_ctx (ctx));
5316 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5317 ctx->outer->outer);
5318 if (is_global_var (ovar))
5319 x = ovar;
5321 if (!x)
5322 x = build_outer_var_ref (var, ctx, true);
5323 if (is_reference (var))
5324 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5325 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5326 gimplify_and_add (x, stmt_list);
5328 c = OMP_CLAUSE_CHAIN (c);
5329 if (c == NULL && !par_clauses)
5331 /* If this was a workshare clause, see if it had been combined
5332 with its parallel. In that case, continue looking for the
5333 clauses also on the parallel statement itself. */
5334 if (is_parallel_ctx (ctx))
5335 break;
5337 ctx = ctx->outer;
5338 if (ctx == NULL || !is_parallel_ctx (ctx))
5339 break;
5341 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5342 OMP_CLAUSE_LASTPRIVATE);
5343 par_clauses = true;
5347 if (label)
5348 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5351 static void
5352 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
5353 tree tid, tree var, tree new_var)
5355 /* The atomic add at the end of the sum creates unnecessary
5356 write contention on accelerators. To work around this,
5357 create an array to store the partial reductions. Later, in
5358 lower_omp_for (for openacc), the values of array will be
5359 combined. */
5361 tree t = NULL_TREE, array, x;
5362 tree type = get_base_type (var);
5363 gimple *stmt;
5365 /* Now insert the partial reductions into the array. */
5367 /* Find the reduction array. */
5369 tree ptype = build_pointer_type (type);
5371 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
5372 t = build_receiver_ref (t, false, ctx->outer);
5374 array = create_tmp_var (ptype);
5375 gimplify_assign (array, t, stmt_seqp);
5377 tree ptr = create_tmp_var (TREE_TYPE (array));
5379 /* Find the reduction array. */
5381 /* testing a unary conversion. */
5382 tree offset = create_tmp_var (sizetype);
5383 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
5384 stmt_seqp);
5385 t = create_tmp_var (sizetype);
5386 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
5387 stmt_seqp);
5388 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
5389 gimple_seq_add_stmt (stmt_seqp, stmt);
5391 /* Offset expression. Does the POINTER_PLUS_EXPR take care
5392 of adding sizeof(var) to the array? */
5393 ptr = create_tmp_var (ptype);
5394 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
5395 offset);
5396 gimple_seq_add_stmt (stmt_seqp, stmt);
5398 /* Move the local sum to gfc$sum[i]. */
5399 x = unshare_expr (build_simple_mem_ref (ptr));
5400 stmt = gimplify_assign (x, new_var, stmt_seqp);
5403 /* Generate code to implement the REDUCTION clauses. */
5405 static void
5406 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5408 gimple_seq sub_seq = NULL;
5409 gimple *stmt;
5410 tree x, c, tid = NULL_TREE;
5411 int count = 0;
5413 /* SIMD reductions are handled in lower_rec_input_clauses. */
5414 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5415 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5416 return;
5418 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5419 update in that case, otherwise use a lock. */
5420 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5421 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5423 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5424 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5426 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5427 count = -1;
5428 break;
5430 count++;
5433 if (count == 0)
5434 return;
5436 /* Initialize thread info for OpenACC. */
5437 if (is_gimple_omp_oacc (ctx->stmt))
5439 /* Get the current thread id. */
5440 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
5441 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
5442 gimple *stmt = gimple_build_call (call, 0);
5443 gimple_call_set_lhs (stmt, tid);
5444 gimple_seq_add_stmt (stmt_seqp, stmt);
5447 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5449 tree var, ref, new_var, orig_var;
5450 enum tree_code code;
5451 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5453 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5454 continue;
5456 orig_var = var = OMP_CLAUSE_DECL (c);
5457 if (TREE_CODE (var) == MEM_REF)
5459 var = TREE_OPERAND (var, 0);
5460 if (TREE_CODE (var) == INDIRECT_REF
5461 || TREE_CODE (var) == ADDR_EXPR)
5462 var = TREE_OPERAND (var, 0);
5463 orig_var = var;
5464 if (is_variable_sized (var))
5466 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5467 var = DECL_VALUE_EXPR (var);
5468 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5469 var = TREE_OPERAND (var, 0);
5470 gcc_assert (DECL_P (var));
5473 new_var = lookup_decl (var, ctx);
5474 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5475 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5476 ref = build_outer_var_ref (var, ctx);
5477 code = OMP_CLAUSE_REDUCTION_CODE (c);
5479 /* reduction(-:var) sums up the partial results, so it acts
5480 identically to reduction(+:var). */
5481 if (code == MINUS_EXPR)
5482 code = PLUS_EXPR;
5484 if (is_gimple_omp_oacc (ctx->stmt))
5486 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
5488 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
5490 else if (count == 1)
5492 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5494 addr = save_expr (addr);
5495 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5496 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5497 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5498 gimplify_and_add (x, stmt_seqp);
5499 return;
5501 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5503 tree d = OMP_CLAUSE_DECL (c);
5504 tree type = TREE_TYPE (d);
5505 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5506 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5507 tree ptype = build_pointer_type (TREE_TYPE (type));
5508 /* For ref build_outer_var_ref already performs this, so
5509 only new_var needs a dereference. */
5510 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
5512 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5513 gcc_assert (is_reference (var) && var == orig_var);
5515 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
5517 if (orig_var == var)
5519 new_var = build_fold_addr_expr (new_var);
5520 ref = build_fold_addr_expr (ref);
5523 else
5525 gcc_assert (orig_var == var);
5526 if (is_reference (var))
5527 ref = build_fold_addr_expr (ref);
5529 if (DECL_P (v))
5531 tree t = maybe_lookup_decl (v, ctx);
5532 if (t)
5533 v = t;
5534 else
5535 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5536 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5538 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5539 ref = fold_convert_loc (clause_loc, ptype, ref);
5540 tree m = create_tmp_var (ptype, NULL);
5541 gimplify_assign (m, new_var, stmt_seqp);
5542 new_var = m;
5543 m = create_tmp_var (ptype, NULL);
5544 gimplify_assign (m, ref, stmt_seqp);
5545 ref = m;
5546 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5547 tree body = create_artificial_label (UNKNOWN_LOCATION);
5548 tree end = create_artificial_label (UNKNOWN_LOCATION);
5549 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5550 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5551 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5552 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5554 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5555 tree decl_placeholder
5556 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5557 SET_DECL_VALUE_EXPR (placeholder, out);
5558 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5559 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5560 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5561 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5562 gimple_seq_add_seq (&sub_seq,
5563 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5564 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5565 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5566 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5568 else
5570 x = build2 (code, TREE_TYPE (out), out, priv);
5571 out = unshare_expr (out);
5572 gimplify_assign (out, x, &sub_seq);
5574 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5575 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5576 gimple_seq_add_stmt (&sub_seq, g);
5577 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5578 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5579 gimple_seq_add_stmt (&sub_seq, g);
5580 g = gimple_build_assign (i, PLUS_EXPR, i,
5581 build_int_cst (TREE_TYPE (i), 1));
5582 gimple_seq_add_stmt (&sub_seq, g);
5583 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5584 gimple_seq_add_stmt (&sub_seq, g);
5585 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5587 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5589 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5591 if (is_reference (var)
5592 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5593 TREE_TYPE (ref)))
5594 ref = build_fold_addr_expr_loc (clause_loc, ref);
5595 SET_DECL_VALUE_EXPR (placeholder, ref);
5596 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5597 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5598 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5599 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5600 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5602 else
5604 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5605 ref = build_outer_var_ref (var, ctx);
5606 gimplify_assign (ref, x, &sub_seq);
5610 if (is_gimple_omp_oacc (ctx->stmt))
5611 return;
5613 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5615 gimple_seq_add_stmt (stmt_seqp, stmt);
5617 gimple_seq_add_seq (stmt_seqp, sub_seq);
5619 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5621 gimple_seq_add_stmt (stmt_seqp, stmt);
5625 /* Generate code to implement the COPYPRIVATE clauses. */
5627 static void
5628 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5629 omp_context *ctx)
5631 tree c;
5633 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5635 tree var, new_var, ref, x;
5636 bool by_ref;
5637 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5639 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5640 continue;
5642 var = OMP_CLAUSE_DECL (c);
5643 by_ref = use_pointer_for_field (var, NULL);
5645 ref = build_sender_ref (var, ctx);
5646 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5647 if (by_ref)
5649 x = build_fold_addr_expr_loc (clause_loc, new_var);
5650 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5652 gimplify_assign (ref, x, slist);
5654 ref = build_receiver_ref (var, false, ctx);
5655 if (by_ref)
5657 ref = fold_convert_loc (clause_loc,
5658 build_pointer_type (TREE_TYPE (new_var)),
5659 ref);
5660 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5662 if (is_reference (var))
5664 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5665 ref = build_simple_mem_ref_loc (clause_loc, ref);
5666 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5668 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5669 gimplify_and_add (x, rlist);
5674 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5675 and REDUCTION from the sender (aka parent) side. */
5677 static void
5678 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5679 omp_context *ctx)
5681 tree c, t;
5682 int ignored_looptemp = 0;
5683 bool is_taskloop = false;
5685 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5686 by GOMP_taskloop. */
5687 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5689 ignored_looptemp = 2;
5690 is_taskloop = true;
5693 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5695 tree val, ref, x, var;
5696 bool by_ref, do_in = false, do_out = false;
5697 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5699 switch (OMP_CLAUSE_CODE (c))
5701 case OMP_CLAUSE_PRIVATE:
5702 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5703 break;
5704 continue;
5705 case OMP_CLAUSE_FIRSTPRIVATE:
5706 case OMP_CLAUSE_COPYIN:
5707 case OMP_CLAUSE_LASTPRIVATE:
5708 case OMP_CLAUSE_REDUCTION:
5709 break;
5710 case OMP_CLAUSE_SHARED:
5711 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5712 break;
5713 continue;
5714 case OMP_CLAUSE__LOOPTEMP_:
5715 if (ignored_looptemp)
5717 ignored_looptemp--;
5718 continue;
5720 break;
5721 default:
5722 continue;
5725 val = OMP_CLAUSE_DECL (c);
5726 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5727 && TREE_CODE (val) == MEM_REF)
5729 val = TREE_OPERAND (val, 0);
5730 if (TREE_CODE (val) == INDIRECT_REF
5731 || TREE_CODE (val) == ADDR_EXPR)
5732 val = TREE_OPERAND (val, 0);
5733 if (is_variable_sized (val))
5734 continue;
5737 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5738 outer taskloop region. */
5739 omp_context *ctx_for_o = ctx;
5740 if (is_taskloop
5741 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5742 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5743 ctx_for_o = ctx->outer;
5745 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
5747 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5748 && is_global_var (var))
5749 continue;
5751 t = omp_member_access_dummy_var (var);
5752 if (t)
5754 var = DECL_VALUE_EXPR (var);
5755 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5756 if (o != t)
5757 var = unshare_and_remap (var, t, o);
5758 else
5759 var = unshare_expr (var);
5762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5764 /* Handle taskloop firstprivate/lastprivate, where the
5765 lastprivate on GIMPLE_OMP_TASK is represented as
5766 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5767 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5768 x = omp_build_component_ref (ctx->sender_decl, f);
5769 if (use_pointer_for_field (val, ctx))
5770 var = build_fold_addr_expr (var);
5771 gimplify_assign (x, var, ilist);
5772 DECL_ABSTRACT_ORIGIN (f) = NULL;
5773 continue;
5776 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5777 || val == OMP_CLAUSE_DECL (c))
5778 && is_variable_sized (val))
5779 continue;
5780 by_ref = use_pointer_for_field (val, NULL);
5782 switch (OMP_CLAUSE_CODE (c))
5784 case OMP_CLAUSE_PRIVATE:
5785 case OMP_CLAUSE_FIRSTPRIVATE:
5786 case OMP_CLAUSE_COPYIN:
5787 case OMP_CLAUSE__LOOPTEMP_:
5788 do_in = true;
5789 break;
5791 case OMP_CLAUSE_LASTPRIVATE:
5792 if (by_ref || is_reference (val))
5794 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5795 continue;
5796 do_in = true;
5798 else
5800 do_out = true;
5801 if (lang_hooks.decls.omp_private_outer_ref (val))
5802 do_in = true;
5804 break;
5806 case OMP_CLAUSE_REDUCTION:
5807 do_in = true;
5808 if (val == OMP_CLAUSE_DECL (c))
5809 do_out = !(by_ref || is_reference (val));
5810 else
5811 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
5812 break;
5814 default:
5815 gcc_unreachable ();
5818 if (do_in)
5820 ref = build_sender_ref (val, ctx);
5821 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
5822 gimplify_assign (ref, x, ilist);
5823 if (is_task_ctx (ctx))
5824 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
5827 if (do_out)
5829 ref = build_sender_ref (val, ctx);
5830 gimplify_assign (var, ref, olist);
5835 /* Generate code to implement SHARED from the sender (aka parent)
5836 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5837 list things that got automatically shared. */
5839 static void
5840 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
5842 tree var, ovar, nvar, t, f, x, record_type;
5844 if (ctx->record_type == NULL)
5845 return;
5847 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
5848 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
5850 ovar = DECL_ABSTRACT_ORIGIN (f);
5851 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
5852 continue;
5854 nvar = maybe_lookup_decl (ovar, ctx);
5855 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
5856 continue;
5858 /* If CTX is a nested parallel directive. Find the immediately
5859 enclosing parallel or workshare construct that contains a
5860 mapping for OVAR. */
5861 var = lookup_decl_in_outer_ctx (ovar, ctx);
5863 t = omp_member_access_dummy_var (var);
5864 if (t)
5866 var = DECL_VALUE_EXPR (var);
5867 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
5868 if (o != t)
5869 var = unshare_and_remap (var, t, o);
5870 else
5871 var = unshare_expr (var);
5874 if (use_pointer_for_field (ovar, ctx))
5876 x = build_sender_ref (ovar, ctx);
5877 var = build_fold_addr_expr (var);
5878 gimplify_assign (x, var, ilist);
5880 else
5882 x = build_sender_ref (ovar, ctx);
5883 gimplify_assign (x, var, ilist);
5885 if (!TREE_READONLY (var)
5886 /* We don't need to receive a new reference to a result
5887 or parm decl. In fact we may not store to it as we will
5888 invalidate any pending RSO and generate wrong gimple
5889 during inlining. */
5890 && !((TREE_CODE (var) == RESULT_DECL
5891 || TREE_CODE (var) == PARM_DECL)
5892 && DECL_BY_REFERENCE (var)))
5894 x = build_sender_ref (ovar, ctx);
5895 gimplify_assign (var, x, olist);
5901 /* Emit an OpenACC head marker call, encapulating the partitioning and
5902 other information that must be processed by the target compiler.
5903 Return the maximum number of dimensions the associated loop might
5904 be partitioned over. */
5906 static unsigned
5907 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
5908 gimple_seq *seq, omp_context *ctx)
5910 unsigned levels = 0;
5911 unsigned tag = 0;
5912 tree gang_static = NULL_TREE;
5913 auto_vec<tree, 5> args;
5915 args.quick_push (build_int_cst
5916 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
5917 args.quick_push (ddvar);
5918 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5920 switch (OMP_CLAUSE_CODE (c))
5922 case OMP_CLAUSE_GANG:
5923 tag |= OLF_DIM_GANG;
5924 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
5925 /* static:* is represented by -1, and we can ignore it, as
5926 scheduling is always static. */
5927 if (gang_static && integer_minus_onep (gang_static))
5928 gang_static = NULL_TREE;
5929 levels++;
5930 break;
5932 case OMP_CLAUSE_WORKER:
5933 tag |= OLF_DIM_WORKER;
5934 levels++;
5935 break;
5937 case OMP_CLAUSE_VECTOR:
5938 tag |= OLF_DIM_VECTOR;
5939 levels++;
5940 break;
5942 case OMP_CLAUSE_SEQ:
5943 tag |= OLF_SEQ;
5944 break;
5946 case OMP_CLAUSE_AUTO:
5947 tag |= OLF_AUTO;
5948 break;
5950 case OMP_CLAUSE_INDEPENDENT:
5951 tag |= OLF_INDEPENDENT;
5952 break;
5954 default:
5955 continue;
5959 if (gang_static)
5961 if (DECL_P (gang_static))
5962 gang_static = build_outer_var_ref (gang_static, ctx);
5963 tag |= OLF_GANG_STATIC;
5966 /* In a parallel region, loops are implicitly INDEPENDENT. */
5967 omp_context *tgt = enclosing_target_ctx (ctx);
5968 if (!tgt || is_oacc_parallel (tgt))
5969 tag |= OLF_INDEPENDENT;
5971 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
5972 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
5973 | OLF_SEQ)))
5974 tag |= OLF_AUTO;
5976 /* Ensure at least one level. */
5977 if (!levels)
5978 levels++;
5980 args.quick_push (build_int_cst (integer_type_node, levels));
5981 args.quick_push (build_int_cst (integer_type_node, tag));
5982 if (gang_static)
5983 args.quick_push (gang_static);
5985 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
5986 gimple_set_location (call, loc);
5987 gimple_set_lhs (call, ddvar);
5988 gimple_seq_add_stmt (seq, call);
5990 return levels;
5993 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
5994 partitioning level of the enclosed region. */
5996 static void
5997 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
5998 tree tofollow, gimple_seq *seq)
6000 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6001 : IFN_UNIQUE_OACC_TAIL_MARK);
6002 tree marker = build_int_cst (integer_type_node, marker_kind);
6003 int nargs = 2 + (tofollow != NULL_TREE);
6004 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6005 marker, ddvar, tofollow);
6006 gimple_set_location (call, loc);
6007 gimple_set_lhs (call, ddvar);
6008 gimple_seq_add_stmt (seq, call);
6011 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6012 the loop clauses, from which we extract reductions. Initialize
6013 HEAD and TAIL. */
6015 static void
6016 lower_oacc_head_tail (location_t loc, tree clauses,
6017 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6019 bool inner = false;
6020 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6021 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6023 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6024 if (!count)
6025 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6027 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6028 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6030 for (unsigned done = 1; count; count--, done++)
6032 gimple_seq fork_seq = NULL;
6033 gimple_seq join_seq = NULL;
6035 tree place = build_int_cst (integer_type_node, -1);
6036 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6037 fork_kind, ddvar, place);
6038 gimple_set_location (fork, loc);
6039 gimple_set_lhs (fork, ddvar);
6041 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6042 join_kind, ddvar, place);
6043 gimple_set_location (join, loc);
6044 gimple_set_lhs (join, ddvar);
6046 /* Mark the beginning of this level sequence. */
6047 if (inner)
6048 lower_oacc_loop_marker (loc, ddvar, true,
6049 build_int_cst (integer_type_node, count),
6050 &fork_seq);
6051 lower_oacc_loop_marker (loc, ddvar, false,
6052 build_int_cst (integer_type_node, done),
6053 &join_seq);
6055 gimple_seq_add_stmt (&fork_seq, fork);
6056 gimple_seq_add_stmt (&join_seq, join);
6058 /* Append this level to head. */
6059 gimple_seq_add_seq (head, fork_seq);
6060 /* Prepend it to tail. */
6061 gimple_seq_add_seq (&join_seq, *tail);
6062 *tail = join_seq;
6064 inner = true;
6067 /* Mark the end of the sequence. */
6068 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6069 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6072 /* A convenience function to build an empty GIMPLE_COND with just the
6073 condition. */
6075 static gcond *
6076 gimple_build_cond_empty (tree cond)
6078 enum tree_code pred_code;
6079 tree lhs, rhs;
6081 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6082 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6085 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6086 bool = false);
6088 /* Build the function calls to GOMP_parallel_start etc to actually
6089 generate the parallel operation. REGION is the parallel region
6090 being expanded. BB is the block where to insert the code. WS_ARGS
6091 will be set if this is a call to a combined parallel+workshare
6092 construct, it contains the list of additional arguments needed by
6093 the workshare construct. */
6095 static void
6096 expand_parallel_call (struct omp_region *region, basic_block bb,
6097 gomp_parallel *entry_stmt,
6098 vec<tree, va_gc> *ws_args)
6100 tree t, t1, t2, val, cond, c, clauses, flags;
6101 gimple_stmt_iterator gsi;
6102 gimple *stmt;
6103 enum built_in_function start_ix;
6104 int start_ix2;
6105 location_t clause_loc;
6106 vec<tree, va_gc> *args;
6108 clauses = gimple_omp_parallel_clauses (entry_stmt);
6110 /* Determine what flavor of GOMP_parallel we will be
6111 emitting. */
6112 start_ix = BUILT_IN_GOMP_PARALLEL;
6113 if (is_combined_parallel (region))
6115 switch (region->inner->type)
6117 case GIMPLE_OMP_FOR:
6118 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6119 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
6120 + (region->inner->sched_kind
6121 == OMP_CLAUSE_SCHEDULE_RUNTIME
6122 ? 3 : region->inner->sched_kind));
6123 start_ix = (enum built_in_function)start_ix2;
6124 break;
6125 case GIMPLE_OMP_SECTIONS:
6126 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6127 break;
6128 default:
6129 gcc_unreachable ();
6133 /* By default, the value of NUM_THREADS is zero (selected at run time)
6134 and there is no conditional. */
6135 cond = NULL_TREE;
6136 val = build_int_cst (unsigned_type_node, 0);
6137 flags = build_int_cst (unsigned_type_node, 0);
6139 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6140 if (c)
6141 cond = OMP_CLAUSE_IF_EXPR (c);
6143 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6144 if (c)
6146 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6147 clause_loc = OMP_CLAUSE_LOCATION (c);
6149 else
6150 clause_loc = gimple_location (entry_stmt);
6152 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6153 if (c)
6154 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6156 /* Ensure 'val' is of the correct type. */
6157 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6159 /* If we found the clause 'if (cond)', build either
6160 (cond != 0) or (cond ? val : 1u). */
6161 if (cond)
6163 cond = gimple_boolify (cond);
6165 if (integer_zerop (val))
6166 val = fold_build2_loc (clause_loc,
6167 EQ_EXPR, unsigned_type_node, cond,
6168 build_int_cst (TREE_TYPE (cond), 0));
6169 else
6171 basic_block cond_bb, then_bb, else_bb;
6172 edge e, e_then, e_else;
6173 tree tmp_then, tmp_else, tmp_join, tmp_var;
6175 tmp_var = create_tmp_var (TREE_TYPE (val));
6176 if (gimple_in_ssa_p (cfun))
6178 tmp_then = make_ssa_name (tmp_var);
6179 tmp_else = make_ssa_name (tmp_var);
6180 tmp_join = make_ssa_name (tmp_var);
6182 else
6184 tmp_then = tmp_var;
6185 tmp_else = tmp_var;
6186 tmp_join = tmp_var;
6189 e = split_block_after_labels (bb);
6190 cond_bb = e->src;
6191 bb = e->dest;
6192 remove_edge (e);
6194 then_bb = create_empty_bb (cond_bb);
6195 else_bb = create_empty_bb (then_bb);
6196 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6197 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6199 stmt = gimple_build_cond_empty (cond);
6200 gsi = gsi_start_bb (cond_bb);
6201 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6203 gsi = gsi_start_bb (then_bb);
6204 expand_omp_build_assign (&gsi, tmp_then, val, true);
6206 gsi = gsi_start_bb (else_bb);
6207 expand_omp_build_assign (&gsi, tmp_else,
6208 build_int_cst (unsigned_type_node, 1),
6209 true);
6211 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6212 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6213 add_bb_to_loop (then_bb, cond_bb->loop_father);
6214 add_bb_to_loop (else_bb, cond_bb->loop_father);
6215 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6216 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6218 if (gimple_in_ssa_p (cfun))
6220 gphi *phi = create_phi_node (tmp_join, bb);
6221 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6222 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6225 val = tmp_join;
6228 gsi = gsi_start_bb (bb);
6229 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6230 false, GSI_CONTINUE_LINKING);
6233 gsi = gsi_last_bb (bb);
6234 t = gimple_omp_parallel_data_arg (entry_stmt);
6235 if (t == NULL)
6236 t1 = null_pointer_node;
6237 else
6238 t1 = build_fold_addr_expr (t);
6239 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6241 vec_alloc (args, 4 + vec_safe_length (ws_args));
6242 args->quick_push (t2);
6243 args->quick_push (t1);
6244 args->quick_push (val);
6245 if (ws_args)
6246 args->splice (*ws_args);
6247 args->quick_push (flags);
6249 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6250 builtin_decl_explicit (start_ix), args);
6252 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6253 false, GSI_CONTINUE_LINKING);
6256 /* Insert a function call whose name is FUNC_NAME with the information from
6257 ENTRY_STMT into the basic_block BB. */
6259 static void
6260 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6261 vec <tree, va_gc> *ws_args)
6263 tree t, t1, t2;
6264 gimple_stmt_iterator gsi;
6265 vec <tree, va_gc> *args;
6267 gcc_assert (vec_safe_length (ws_args) == 2);
6268 tree func_name = (*ws_args)[0];
6269 tree grain = (*ws_args)[1];
6271 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6272 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6273 gcc_assert (count != NULL_TREE);
6274 count = OMP_CLAUSE_OPERAND (count, 0);
6276 gsi = gsi_last_bb (bb);
6277 t = gimple_omp_parallel_data_arg (entry_stmt);
6278 if (t == NULL)
6279 t1 = null_pointer_node;
6280 else
6281 t1 = build_fold_addr_expr (t);
6282 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6284 vec_alloc (args, 4);
6285 args->quick_push (t2);
6286 args->quick_push (t1);
6287 args->quick_push (count);
6288 args->quick_push (grain);
6289 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6291 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6292 GSI_CONTINUE_LINKING);
6295 /* Build the function call to GOMP_task to actually
6296 generate the task operation. BB is the block where to insert the code. */
6298 static void
6299 expand_task_call (struct omp_region *region, basic_block bb,
6300 gomp_task *entry_stmt)
6302 tree t1, t2, t3;
6303 gimple_stmt_iterator gsi;
6304 location_t loc = gimple_location (entry_stmt);
6306 tree clauses = gimple_omp_task_clauses (entry_stmt);
6308 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6309 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6310 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6311 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6312 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6313 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6315 unsigned int iflags
6316 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6317 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6318 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6320 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6321 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6322 tree num_tasks = NULL_TREE;
6323 bool ull = false;
6324 if (taskloop_p)
6326 gimple *g = last_stmt (region->outer->entry);
6327 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6328 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6329 struct omp_for_data fd;
6330 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6331 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6332 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6333 OMP_CLAUSE__LOOPTEMP_);
6334 startvar = OMP_CLAUSE_DECL (startvar);
6335 endvar = OMP_CLAUSE_DECL (endvar);
6336 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6337 if (fd.loop.cond_code == LT_EXPR)
6338 iflags |= GOMP_TASK_FLAG_UP;
6339 tree tclauses = gimple_omp_for_clauses (g);
6340 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6341 if (num_tasks)
6342 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6343 else
6345 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6346 if (num_tasks)
6348 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6349 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6351 else
6352 num_tasks = integer_zero_node;
6354 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6355 if (ifc == NULL_TREE)
6356 iflags |= GOMP_TASK_FLAG_IF;
6357 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6358 iflags |= GOMP_TASK_FLAG_NOGROUP;
6359 ull = fd.iter_type == long_long_unsigned_type_node;
6361 else if (priority)
6362 iflags |= GOMP_TASK_FLAG_PRIORITY;
6364 tree flags = build_int_cst (unsigned_type_node, iflags);
6366 tree cond = boolean_true_node;
6367 if (ifc)
6369 if (taskloop_p)
6371 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6372 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6373 build_int_cst (unsigned_type_node,
6374 GOMP_TASK_FLAG_IF),
6375 build_int_cst (unsigned_type_node, 0));
6376 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6377 flags, t);
6379 else
6380 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6383 if (finalc)
6385 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6386 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6387 build_int_cst (unsigned_type_node,
6388 GOMP_TASK_FLAG_FINAL),
6389 build_int_cst (unsigned_type_node, 0));
6390 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6392 if (depend)
6393 depend = OMP_CLAUSE_DECL (depend);
6394 else
6395 depend = build_int_cst (ptr_type_node, 0);
6396 if (priority)
6397 priority = fold_convert (integer_type_node,
6398 OMP_CLAUSE_PRIORITY_EXPR (priority));
6399 else
6400 priority = integer_zero_node;
6402 gsi = gsi_last_bb (bb);
6403 tree t = gimple_omp_task_data_arg (entry_stmt);
6404 if (t == NULL)
6405 t2 = null_pointer_node;
6406 else
6407 t2 = build_fold_addr_expr_loc (loc, t);
6408 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6409 t = gimple_omp_task_copy_fn (entry_stmt);
6410 if (t == NULL)
6411 t3 = null_pointer_node;
6412 else
6413 t3 = build_fold_addr_expr_loc (loc, t);
6415 if (taskloop_p)
6416 t = build_call_expr (ull
6417 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6418 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6419 11, t1, t2, t3,
6420 gimple_omp_task_arg_size (entry_stmt),
6421 gimple_omp_task_arg_align (entry_stmt), flags,
6422 num_tasks, priority, startvar, endvar, step);
6423 else
6424 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6425 9, t1, t2, t3,
6426 gimple_omp_task_arg_size (entry_stmt),
6427 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6428 depend, priority);
6430 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6431 false, GSI_CONTINUE_LINKING);
6435 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6436 catch handler and return it. This prevents programs from violating the
6437 structured block semantics with throws. */
6439 static gimple_seq
6440 maybe_catch_exception (gimple_seq body)
6442 gimple *g;
6443 tree decl;
6445 if (!flag_exceptions)
6446 return body;
6448 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6449 decl = lang_hooks.eh_protect_cleanup_actions ();
6450 else
6451 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6453 g = gimple_build_eh_must_not_throw (decl);
6454 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6455 GIMPLE_TRY_CATCH);
6457 return gimple_seq_alloc_with_stmt (g);
6460 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6462 static tree
6463 vec2chain (vec<tree, va_gc> *v)
6465 tree chain = NULL_TREE, t;
6466 unsigned ix;
6468 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6470 DECL_CHAIN (t) = chain;
6471 chain = t;
6474 return chain;
6478 /* Remove barriers in REGION->EXIT's block. Note that this is only
6479 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6480 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6481 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6482 removed. */
6484 static void
6485 remove_exit_barrier (struct omp_region *region)
6487 gimple_stmt_iterator gsi;
6488 basic_block exit_bb;
6489 edge_iterator ei;
6490 edge e;
6491 gimple *stmt;
6492 int any_addressable_vars = -1;
6494 exit_bb = region->exit;
6496 /* If the parallel region doesn't return, we don't have REGION->EXIT
6497 block at all. */
6498 if (! exit_bb)
6499 return;
6501 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6502 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6503 statements that can appear in between are extremely limited -- no
6504 memory operations at all. Here, we allow nothing at all, so the
6505 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6506 gsi = gsi_last_bb (exit_bb);
6507 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6508 gsi_prev (&gsi);
6509 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6510 return;
6512 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6514 gsi = gsi_last_bb (e->src);
6515 if (gsi_end_p (gsi))
6516 continue;
6517 stmt = gsi_stmt (gsi);
6518 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6519 && !gimple_omp_return_nowait_p (stmt))
6521 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6522 in many cases. If there could be tasks queued, the barrier
6523 might be needed to let the tasks run before some local
6524 variable of the parallel that the task uses as shared
6525 runs out of scope. The task can be spawned either
6526 from within current function (this would be easy to check)
6527 or from some function it calls and gets passed an address
6528 of such a variable. */
6529 if (any_addressable_vars < 0)
6531 gomp_parallel *parallel_stmt
6532 = as_a <gomp_parallel *> (last_stmt (region->entry));
6533 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6534 tree local_decls, block, decl;
6535 unsigned ix;
6537 any_addressable_vars = 0;
6538 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6539 if (TREE_ADDRESSABLE (decl))
6541 any_addressable_vars = 1;
6542 break;
6544 for (block = gimple_block (stmt);
6545 !any_addressable_vars
6546 && block
6547 && TREE_CODE (block) == BLOCK;
6548 block = BLOCK_SUPERCONTEXT (block))
6550 for (local_decls = BLOCK_VARS (block);
6551 local_decls;
6552 local_decls = DECL_CHAIN (local_decls))
6553 if (TREE_ADDRESSABLE (local_decls))
6555 any_addressable_vars = 1;
6556 break;
6558 if (block == gimple_block (parallel_stmt))
6559 break;
6562 if (!any_addressable_vars)
6563 gimple_omp_return_set_nowait (stmt);
6568 static void
6569 remove_exit_barriers (struct omp_region *region)
6571 if (region->type == GIMPLE_OMP_PARALLEL)
6572 remove_exit_barrier (region);
6574 if (region->inner)
6576 region = region->inner;
6577 remove_exit_barriers (region);
6578 while (region->next)
6580 region = region->next;
6581 remove_exit_barriers (region);
6586 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6587 calls. These can't be declared as const functions, but
6588 within one parallel body they are constant, so they can be
6589 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6590 which are declared const. Similarly for task body, except
6591 that in untied task omp_get_thread_num () can change at any task
6592 scheduling point. */
6594 static void
6595 optimize_omp_library_calls (gimple *entry_stmt)
6597 basic_block bb;
6598 gimple_stmt_iterator gsi;
6599 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6600 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6601 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6602 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6603 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6604 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6605 OMP_CLAUSE_UNTIED) != NULL);
6607 FOR_EACH_BB_FN (bb, cfun)
6608 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6610 gimple *call = gsi_stmt (gsi);
6611 tree decl;
6613 if (is_gimple_call (call)
6614 && (decl = gimple_call_fndecl (call))
6615 && DECL_EXTERNAL (decl)
6616 && TREE_PUBLIC (decl)
6617 && DECL_INITIAL (decl) == NULL)
6619 tree built_in;
6621 if (DECL_NAME (decl) == thr_num_id)
6623 /* In #pragma omp task untied omp_get_thread_num () can change
6624 during the execution of the task region. */
6625 if (untied_task)
6626 continue;
6627 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6629 else if (DECL_NAME (decl) == num_thr_id)
6630 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6631 else
6632 continue;
6634 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
6635 || gimple_call_num_args (call) != 0)
6636 continue;
6638 if (flag_exceptions && !TREE_NOTHROW (decl))
6639 continue;
6641 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
6642 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6643 TREE_TYPE (TREE_TYPE (built_in))))
6644 continue;
6646 gimple_call_set_fndecl (call, built_in);
6651 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6652 regimplified. */
6654 static tree
6655 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6657 tree t = *tp;
6659 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6660 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6661 return t;
6663 if (TREE_CODE (t) == ADDR_EXPR)
6664 recompute_tree_invariant_for_addr_expr (t);
6666 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6667 return NULL_TREE;
6670 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6672 static void
6673 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6674 bool after)
6676 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6677 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
6678 !after, after ? GSI_CONTINUE_LINKING
6679 : GSI_SAME_STMT);
6680 gimple *stmt = gimple_build_assign (to, from);
6681 if (after)
6682 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6683 else
6684 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
6685 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6686 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6688 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6689 gimple_regimplify_operands (stmt, &gsi);
6693 /* Expand the OpenMP parallel or task directive starting at REGION. */
6695 static void
6696 expand_omp_taskreg (struct omp_region *region)
6698 basic_block entry_bb, exit_bb, new_bb;
6699 struct function *child_cfun;
6700 tree child_fn, block, t;
6701 gimple_stmt_iterator gsi;
6702 gimple *entry_stmt, *stmt;
6703 edge e;
6704 vec<tree, va_gc> *ws_args;
6706 entry_stmt = last_stmt (region->entry);
6707 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
6708 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6710 entry_bb = region->entry;
6711 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6712 exit_bb = region->cont;
6713 else
6714 exit_bb = region->exit;
6716 bool is_cilk_for
6717 = (flag_cilkplus
6718 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6719 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6720 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6722 if (is_cilk_for)
6723 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6724 and the inner statement contains the name of the built-in function
6725 and grain. */
6726 ws_args = region->inner->ws_args;
6727 else if (is_combined_parallel (region))
6728 ws_args = region->ws_args;
6729 else
6730 ws_args = NULL;
6732 if (child_cfun->cfg)
6734 /* Due to inlining, it may happen that we have already outlined
6735 the region, in which case all we need to do is make the
6736 sub-graph unreachable and emit the parallel call. */
6737 edge entry_succ_e, exit_succ_e;
6739 entry_succ_e = single_succ_edge (entry_bb);
6741 gsi = gsi_last_bb (entry_bb);
6742 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6743 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6744 gsi_remove (&gsi, true);
6746 new_bb = entry_bb;
6747 if (exit_bb)
6749 exit_succ_e = single_succ_edge (exit_bb);
6750 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6752 remove_edge_and_dominated_blocks (entry_succ_e);
6754 else
6756 unsigned srcidx, dstidx, num;
6758 /* If the parallel region needs data sent from the parent
6759 function, then the very first statement (except possible
6760 tree profile counter updates) of the parallel body
6761 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6762 &.OMP_DATA_O is passed as an argument to the child function,
6763 we need to replace it with the argument as seen by the child
6764 function.
6766 In most cases, this will end up being the identity assignment
6767 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6768 a function call that has been inlined, the original PARM_DECL
6769 .OMP_DATA_I may have been converted into a different local
6770 variable. In which case, we need to keep the assignment. */
6771 if (gimple_omp_taskreg_data_arg (entry_stmt))
6773 basic_block entry_succ_bb
6774 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6775 : FALLTHRU_EDGE (entry_bb)->dest;
6776 tree arg;
6777 gimple *parcopy_stmt = NULL;
6779 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
6781 gimple *stmt;
6783 gcc_assert (!gsi_end_p (gsi));
6784 stmt = gsi_stmt (gsi);
6785 if (gimple_code (stmt) != GIMPLE_ASSIGN)
6786 continue;
6788 if (gimple_num_ops (stmt) == 2)
6790 tree arg = gimple_assign_rhs1 (stmt);
6792 /* We're ignore the subcode because we're
6793 effectively doing a STRIP_NOPS. */
6795 if (TREE_CODE (arg) == ADDR_EXPR
6796 && TREE_OPERAND (arg, 0)
6797 == gimple_omp_taskreg_data_arg (entry_stmt))
6799 parcopy_stmt = stmt;
6800 break;
6805 gcc_assert (parcopy_stmt != NULL);
6806 arg = DECL_ARGUMENTS (child_fn);
6808 if (!gimple_in_ssa_p (cfun))
6810 if (gimple_assign_lhs (parcopy_stmt) == arg)
6811 gsi_remove (&gsi, true);
6812 else
6814 /* ?? Is setting the subcode really necessary ?? */
6815 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6816 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6819 else
6821 tree lhs = gimple_assign_lhs (parcopy_stmt);
6822 gcc_assert (SSA_NAME_VAR (lhs) == arg);
6823 /* We'd like to set the rhs to the default def in the child_fn,
6824 but it's too early to create ssa names in the child_fn.
6825 Instead, we set the rhs to the parm. In
6826 move_sese_region_to_fn, we introduce a default def for the
6827 parm, map the parm to it's default def, and once we encounter
6828 this stmt, replace the parm with the default def. */
6829 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6830 update_stmt (parcopy_stmt);
6834 /* Declare local variables needed in CHILD_CFUN. */
6835 block = DECL_INITIAL (child_fn);
6836 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
6837 /* The gimplifier could record temporaries in parallel/task block
6838 rather than in containing function's local_decls chain,
6839 which would mean cgraph missed finalizing them. Do it now. */
6840 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
6841 if (TREE_CODE (t) == VAR_DECL
6842 && TREE_STATIC (t)
6843 && !DECL_EXTERNAL (t))
6844 varpool_node::finalize_decl (t);
6845 DECL_SAVED_TREE (child_fn) = NULL;
6846 /* We'll create a CFG for child_fn, so no gimple body is needed. */
6847 gimple_set_body (child_fn, NULL);
6848 TREE_USED (block) = 1;
6850 /* Reset DECL_CONTEXT on function arguments. */
6851 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6852 DECL_CONTEXT (t) = child_fn;
6854 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
6855 so that it can be moved to the child function. */
6856 gsi = gsi_last_bb (entry_bb);
6857 stmt = gsi_stmt (gsi);
6858 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6859 || gimple_code (stmt) == GIMPLE_OMP_TASK));
6860 e = split_block (entry_bb, stmt);
6861 gsi_remove (&gsi, true);
6862 entry_bb = e->dest;
6863 edge e2 = NULL;
6864 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6865 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6866 else
6868 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
6869 gcc_assert (e2->dest == region->exit);
6870 remove_edge (BRANCH_EDGE (entry_bb));
6871 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
6872 gsi = gsi_last_bb (region->exit);
6873 gcc_assert (!gsi_end_p (gsi)
6874 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6875 gsi_remove (&gsi, true);
6878 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
6879 if (exit_bb)
6881 gsi = gsi_last_bb (exit_bb);
6882 gcc_assert (!gsi_end_p (gsi)
6883 && (gimple_code (gsi_stmt (gsi))
6884 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
6885 stmt = gimple_build_return (NULL);
6886 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6887 gsi_remove (&gsi, true);
6890 /* Move the parallel region into CHILD_CFUN. */
6892 if (gimple_in_ssa_p (cfun))
6894 init_tree_ssa (child_cfun);
6895 init_ssa_operands (child_cfun);
6896 child_cfun->gimple_df->in_ssa_p = true;
6897 block = NULL_TREE;
6899 else
6900 block = gimple_block (entry_stmt);
6902 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
6903 if (exit_bb)
6904 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
6905 if (e2)
6907 basic_block dest_bb = e2->dest;
6908 if (!exit_bb)
6909 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
6910 remove_edge (e2);
6911 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
6913 /* When the OMP expansion process cannot guarantee an up-to-date
6914 loop tree arrange for the child function to fixup loops. */
6915 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6916 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
6918 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
6919 num = vec_safe_length (child_cfun->local_decls);
6920 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
6922 t = (*child_cfun->local_decls)[srcidx];
6923 if (DECL_CONTEXT (t) == cfun->decl)
6924 continue;
6925 if (srcidx != dstidx)
6926 (*child_cfun->local_decls)[dstidx] = t;
6927 dstidx++;
6929 if (dstidx != num)
6930 vec_safe_truncate (child_cfun->local_decls, dstidx);
6932 /* Inform the callgraph about the new function. */
6933 child_cfun->curr_properties = cfun->curr_properties;
6934 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
6935 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6936 cgraph_node *node = cgraph_node::get_create (child_fn);
6937 node->parallelized_function = 1;
6938 cgraph_node::add_new_function (child_fn, true);
6940 /* Fix the callgraph edges for child_cfun. Those for cfun will be
6941 fixed in a following pass. */
6942 push_cfun (child_cfun);
6943 if (optimize)
6944 optimize_omp_library_calls (entry_stmt);
6945 cgraph_edge::rebuild_edges ();
6947 /* Some EH regions might become dead, see PR34608. If
6948 pass_cleanup_cfg isn't the first pass to happen with the
6949 new child, these dead EH edges might cause problems.
6950 Clean them up now. */
6951 if (flag_exceptions)
6953 basic_block bb;
6954 bool changed = false;
6956 FOR_EACH_BB_FN (bb, cfun)
6957 changed |= gimple_purge_dead_eh_edges (bb);
6958 if (changed)
6959 cleanup_tree_cfg ();
6961 if (gimple_in_ssa_p (cfun))
6962 update_ssa (TODO_update_ssa);
6963 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6964 verify_loop_structure ();
6965 pop_cfun ();
6968 /* Emit a library call to launch the children threads. */
6969 if (is_cilk_for)
6970 expand_cilk_for_call (new_bb,
6971 as_a <gomp_parallel *> (entry_stmt), ws_args);
6972 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6973 expand_parallel_call (region, new_bb,
6974 as_a <gomp_parallel *> (entry_stmt), ws_args);
6975 else
6976 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
6977 if (gimple_in_ssa_p (cfun))
6978 update_ssa (TODO_update_ssa_only_virtuals);
6981 /* Information about members of an OpenACC collapsed loop nest. */
6983 struct oacc_collapse
6985 tree base; /* Base value. */
6986 tree iters; /* Number of steps. */
6987 tree step; /* step size. */
6990 /* Helper for expand_oacc_for. Determine collapsed loop information.
6991 Fill in COUNTS array. Emit any initialization code before GSI.
6992 Return the calculated outer loop bound of BOUND_TYPE. */
6994 static tree
6995 expand_oacc_collapse_init (const struct omp_for_data *fd,
6996 gimple_stmt_iterator *gsi,
6997 oacc_collapse *counts, tree bound_type)
6999 tree total = build_int_cst (bound_type, 1);
7000 int ix;
7002 gcc_assert (integer_onep (fd->loop.step));
7003 gcc_assert (integer_zerop (fd->loop.n1));
7005 for (ix = 0; ix != fd->collapse; ix++)
7007 const omp_for_data_loop *loop = &fd->loops[ix];
7009 tree iter_type = TREE_TYPE (loop->v);
7010 tree diff_type = iter_type;
7011 tree plus_type = iter_type;
7013 gcc_assert (loop->cond_code == fd->loop.cond_code);
7015 if (POINTER_TYPE_P (iter_type))
7016 plus_type = sizetype;
7017 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7018 diff_type = signed_type_for (diff_type);
7020 tree b = loop->n1;
7021 tree e = loop->n2;
7022 tree s = loop->step;
7023 bool up = loop->cond_code == LT_EXPR;
7024 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7025 bool negating;
7026 tree expr;
7028 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7029 true, GSI_SAME_STMT);
7030 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7031 true, GSI_SAME_STMT);
7033 /* Convert the step, avoiding possible unsigned->signed overflow. */
7034 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7035 if (negating)
7036 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7037 s = fold_convert (diff_type, s);
7038 if (negating)
7039 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7040 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7041 true, GSI_SAME_STMT);
7043 /* Determine the range, avoiding possible unsigned->signed overflow. */
7044 negating = !up && TYPE_UNSIGNED (iter_type);
7045 expr = fold_build2 (MINUS_EXPR, plus_type,
7046 fold_convert (plus_type, negating ? b : e),
7047 fold_convert (plus_type, negating ? e : b));
7048 expr = fold_convert (diff_type, expr);
7049 if (negating)
7050 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7051 tree range = force_gimple_operand_gsi
7052 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7054 /* Determine number of iterations. */
7055 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7056 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7057 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7059 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7060 true, GSI_SAME_STMT);
7062 counts[ix].base = b;
7063 counts[ix].iters = iters;
7064 counts[ix].step = s;
7066 total = fold_build2 (MULT_EXPR, bound_type, total,
7067 fold_convert (bound_type, iters));
7070 return total;
7073 /* Emit initializers for collapsed loop members. IVAR is the outer
7074 loop iteration variable, from which collapsed loop iteration values
7075 are calculated. COUNTS array has been initialized by
7076 expand_oacc_collapse_inits. */
7078 static void
7079 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7080 gimple_stmt_iterator *gsi,
7081 const oacc_collapse *counts, tree ivar)
7083 tree ivar_type = TREE_TYPE (ivar);
7085 /* The most rapidly changing iteration variable is the innermost
7086 one. */
7087 for (int ix = fd->collapse; ix--;)
7089 const omp_for_data_loop *loop = &fd->loops[ix];
7090 const oacc_collapse *collapse = &counts[ix];
7091 tree iter_type = TREE_TYPE (loop->v);
7092 tree diff_type = TREE_TYPE (collapse->step);
7093 tree plus_type = iter_type;
7094 enum tree_code plus_code = PLUS_EXPR;
7095 tree expr;
7097 if (POINTER_TYPE_P (iter_type))
7099 plus_code = POINTER_PLUS_EXPR;
7100 plus_type = sizetype;
7103 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7104 fold_convert (ivar_type, collapse->iters));
7105 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7106 collapse->step);
7107 expr = fold_build2 (plus_code, iter_type, collapse->base,
7108 fold_convert (plus_type, expr));
7109 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7110 true, GSI_SAME_STMT);
7111 gassign *ass = gimple_build_assign (loop->v, expr);
7112 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7114 if (ix)
7116 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7117 fold_convert (ivar_type, collapse->iters));
7118 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7119 true, GSI_SAME_STMT);
7125 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7126 of the combined collapse > 1 loop constructs, generate code like:
7127 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7128 if (cond3 is <)
7129 adj = STEP3 - 1;
7130 else
7131 adj = STEP3 + 1;
7132 count3 = (adj + N32 - N31) / STEP3;
7133 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7134 if (cond2 is <)
7135 adj = STEP2 - 1;
7136 else
7137 adj = STEP2 + 1;
7138 count2 = (adj + N22 - N21) / STEP2;
7139 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7140 if (cond1 is <)
7141 adj = STEP1 - 1;
7142 else
7143 adj = STEP1 + 1;
7144 count1 = (adj + N12 - N11) / STEP1;
7145 count = count1 * count2 * count3;
7146 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7147 count = 0;
7148 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7149 of the combined loop constructs, just initialize COUNTS array
7150 from the _looptemp_ clauses. */
7152 /* NOTE: It *could* be better to moosh all of the BBs together,
7153 creating one larger BB with all the computation and the unexpected
7154 jump at the end. I.e.
7156 bool zero3, zero2, zero1, zero;
7158 zero3 = N32 c3 N31;
7159 count3 = (N32 - N31) /[cl] STEP3;
7160 zero2 = N22 c2 N21;
7161 count2 = (N22 - N21) /[cl] STEP2;
7162 zero1 = N12 c1 N11;
7163 count1 = (N12 - N11) /[cl] STEP1;
7164 zero = zero3 || zero2 || zero1;
7165 count = count1 * count2 * count3;
7166 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7168 After all, we expect the zero=false, and thus we expect to have to
7169 evaluate all of the comparison expressions, so short-circuiting
7170 oughtn't be a win. Since the condition isn't protecting a
7171 denominator, we're not concerned about divide-by-zero, so we can
7172 fully evaluate count even if a numerator turned out to be wrong.
7174 It seems like putting this all together would create much better
7175 scheduling opportunities, and less pressure on the chip's branch
7176 predictor. */
7178 static void
7179 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7180 basic_block &entry_bb, tree *counts,
7181 basic_block &zero_iter1_bb, int &first_zero_iter1,
7182 basic_block &zero_iter2_bb, int &first_zero_iter2,
7183 basic_block &l2_dom_bb)
7185 tree t, type = TREE_TYPE (fd->loop.v);
7186 edge e, ne;
7187 int i;
7189 /* Collapsed loops need work for expansion into SSA form. */
7190 gcc_assert (!gimple_in_ssa_p (cfun));
7192 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7193 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7195 gcc_assert (fd->ordered == 0);
7196 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7197 isn't supposed to be handled, as the inner loop doesn't
7198 use it. */
7199 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7200 OMP_CLAUSE__LOOPTEMP_);
7201 gcc_assert (innerc);
7202 for (i = 0; i < fd->collapse; i++)
7204 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7205 OMP_CLAUSE__LOOPTEMP_);
7206 gcc_assert (innerc);
7207 if (i)
7208 counts[i] = OMP_CLAUSE_DECL (innerc);
7209 else
7210 counts[0] = NULL_TREE;
7212 return;
7215 for (i = fd->collapse; i < fd->ordered; i++)
7217 tree itype = TREE_TYPE (fd->loops[i].v);
7218 counts[i] = NULL_TREE;
7219 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7220 fold_convert (itype, fd->loops[i].n1),
7221 fold_convert (itype, fd->loops[i].n2));
7222 if (t && integer_zerop (t))
7224 for (i = fd->collapse; i < fd->ordered; i++)
7225 counts[i] = build_int_cst (type, 0);
7226 break;
7229 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7231 tree itype = TREE_TYPE (fd->loops[i].v);
7233 if (i >= fd->collapse && counts[i])
7234 continue;
7235 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7236 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7237 fold_convert (itype, fd->loops[i].n1),
7238 fold_convert (itype, fd->loops[i].n2)))
7239 == NULL_TREE || !integer_onep (t)))
7241 gcond *cond_stmt;
7242 tree n1, n2;
7243 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7244 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7245 true, GSI_SAME_STMT);
7246 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7247 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7248 true, GSI_SAME_STMT);
7249 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7250 NULL_TREE, NULL_TREE);
7251 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7252 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7253 expand_omp_regimplify_p, NULL, NULL)
7254 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7255 expand_omp_regimplify_p, NULL, NULL))
7257 *gsi = gsi_for_stmt (cond_stmt);
7258 gimple_regimplify_operands (cond_stmt, gsi);
7260 e = split_block (entry_bb, cond_stmt);
7261 basic_block &zero_iter_bb
7262 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7263 int &first_zero_iter
7264 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7265 if (zero_iter_bb == NULL)
7267 gassign *assign_stmt;
7268 first_zero_iter = i;
7269 zero_iter_bb = create_empty_bb (entry_bb);
7270 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7271 *gsi = gsi_after_labels (zero_iter_bb);
7272 if (i < fd->collapse)
7273 assign_stmt = gimple_build_assign (fd->loop.n2,
7274 build_zero_cst (type));
7275 else
7277 counts[i] = create_tmp_reg (type, ".count");
7278 assign_stmt
7279 = gimple_build_assign (counts[i], build_zero_cst (type));
7281 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7282 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7283 entry_bb);
7285 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7286 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7287 e->flags = EDGE_TRUE_VALUE;
7288 e->probability = REG_BR_PROB_BASE - ne->probability;
7289 if (l2_dom_bb == NULL)
7290 l2_dom_bb = entry_bb;
7291 entry_bb = e->dest;
7292 *gsi = gsi_last_bb (entry_bb);
7295 if (POINTER_TYPE_P (itype))
7296 itype = signed_type_for (itype);
7297 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7298 ? -1 : 1));
7299 t = fold_build2 (PLUS_EXPR, itype,
7300 fold_convert (itype, fd->loops[i].step), t);
7301 t = fold_build2 (PLUS_EXPR, itype, t,
7302 fold_convert (itype, fd->loops[i].n2));
7303 t = fold_build2 (MINUS_EXPR, itype, t,
7304 fold_convert (itype, fd->loops[i].n1));
7305 /* ?? We could probably use CEIL_DIV_EXPR instead of
7306 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7307 generate the same code in the end because generically we
7308 don't know that the values involved must be negative for
7309 GT?? */
7310 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7311 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7312 fold_build1 (NEGATE_EXPR, itype, t),
7313 fold_build1 (NEGATE_EXPR, itype,
7314 fold_convert (itype,
7315 fd->loops[i].step)));
7316 else
7317 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7318 fold_convert (itype, fd->loops[i].step));
7319 t = fold_convert (type, t);
7320 if (TREE_CODE (t) == INTEGER_CST)
7321 counts[i] = t;
7322 else
7324 if (i < fd->collapse || i != first_zero_iter2)
7325 counts[i] = create_tmp_reg (type, ".count");
7326 expand_omp_build_assign (gsi, counts[i], t);
7328 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7330 if (i == 0)
7331 t = counts[0];
7332 else
7333 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7334 expand_omp_build_assign (gsi, fd->loop.n2, t);
7340 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7341 T = V;
7342 V3 = N31 + (T % count3) * STEP3;
7343 T = T / count3;
7344 V2 = N21 + (T % count2) * STEP2;
7345 T = T / count2;
7346 V1 = N11 + T * STEP1;
7347 if this loop doesn't have an inner loop construct combined with it.
7348 If it does have an inner loop construct combined with it and the
7349 iteration count isn't known constant, store values from counts array
7350 into its _looptemp_ temporaries instead. */
7352 static void
7353 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7354 tree *counts, gimple *inner_stmt, tree startvar)
7356 int i;
7357 if (gimple_omp_for_combined_p (fd->for_stmt))
7359 /* If fd->loop.n2 is constant, then no propagation of the counts
7360 is needed, they are constant. */
7361 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7362 return;
7364 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7365 ? gimple_omp_taskreg_clauses (inner_stmt)
7366 : gimple_omp_for_clauses (inner_stmt);
7367 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7368 isn't supposed to be handled, as the inner loop doesn't
7369 use it. */
7370 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7371 gcc_assert (innerc);
7372 for (i = 0; i < fd->collapse; i++)
7374 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7375 OMP_CLAUSE__LOOPTEMP_);
7376 gcc_assert (innerc);
7377 if (i)
7379 tree tem = OMP_CLAUSE_DECL (innerc);
7380 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7381 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7382 false, GSI_CONTINUE_LINKING);
7383 gassign *stmt = gimple_build_assign (tem, t);
7384 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7387 return;
7390 tree type = TREE_TYPE (fd->loop.v);
7391 tree tem = create_tmp_reg (type, ".tem");
7392 gassign *stmt = gimple_build_assign (tem, startvar);
7393 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7395 for (i = fd->collapse - 1; i >= 0; i--)
7397 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7398 itype = vtype;
7399 if (POINTER_TYPE_P (vtype))
7400 itype = signed_type_for (vtype);
7401 if (i != 0)
7402 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7403 else
7404 t = tem;
7405 t = fold_convert (itype, t);
7406 t = fold_build2 (MULT_EXPR, itype, t,
7407 fold_convert (itype, fd->loops[i].step));
7408 if (POINTER_TYPE_P (vtype))
7409 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7410 else
7411 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7412 t = force_gimple_operand_gsi (gsi, t,
7413 DECL_P (fd->loops[i].v)
7414 && TREE_ADDRESSABLE (fd->loops[i].v),
7415 NULL_TREE, false,
7416 GSI_CONTINUE_LINKING);
7417 stmt = gimple_build_assign (fd->loops[i].v, t);
7418 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7419 if (i != 0)
7421 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7422 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7423 false, GSI_CONTINUE_LINKING);
7424 stmt = gimple_build_assign (tem, t);
7425 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7431 /* Helper function for expand_omp_for_*. Generate code like:
7432 L10:
7433 V3 += STEP3;
7434 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7435 L11:
7436 V3 = N31;
7437 V2 += STEP2;
7438 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7439 L12:
7440 V2 = N21;
7441 V1 += STEP1;
7442 goto BODY_BB; */
7444 static basic_block
7445 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7446 basic_block body_bb)
7448 basic_block last_bb, bb, collapse_bb = NULL;
7449 int i;
7450 gimple_stmt_iterator gsi;
7451 edge e;
7452 tree t;
7453 gimple *stmt;
7455 last_bb = cont_bb;
7456 for (i = fd->collapse - 1; i >= 0; i--)
7458 tree vtype = TREE_TYPE (fd->loops[i].v);
7460 bb = create_empty_bb (last_bb);
7461 add_bb_to_loop (bb, last_bb->loop_father);
7462 gsi = gsi_start_bb (bb);
7464 if (i < fd->collapse - 1)
7466 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7467 e->probability = REG_BR_PROB_BASE / 8;
7469 t = fd->loops[i + 1].n1;
7470 t = force_gimple_operand_gsi (&gsi, t,
7471 DECL_P (fd->loops[i + 1].v)
7472 && TREE_ADDRESSABLE (fd->loops[i
7473 + 1].v),
7474 NULL_TREE, false,
7475 GSI_CONTINUE_LINKING);
7476 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7479 else
7480 collapse_bb = bb;
7482 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7484 if (POINTER_TYPE_P (vtype))
7485 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7486 else
7487 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7488 t = force_gimple_operand_gsi (&gsi, t,
7489 DECL_P (fd->loops[i].v)
7490 && TREE_ADDRESSABLE (fd->loops[i].v),
7491 NULL_TREE, false, GSI_CONTINUE_LINKING);
7492 stmt = gimple_build_assign (fd->loops[i].v, t);
7493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7495 if (i > 0)
7497 t = fd->loops[i].n2;
7498 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7499 false, GSI_CONTINUE_LINKING);
7500 tree v = fd->loops[i].v;
7501 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7502 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7503 false, GSI_CONTINUE_LINKING);
7504 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7505 stmt = gimple_build_cond_empty (t);
7506 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7507 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7508 e->probability = REG_BR_PROB_BASE * 7 / 8;
7510 else
7511 make_edge (bb, body_bb, EDGE_FALLTHRU);
7512 last_bb = bb;
7515 return collapse_bb;
7519 /* Expand #pragma omp ordered depend(source). */
7521 static void
7522 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7523 tree *counts, location_t loc)
7525 enum built_in_function source_ix
7526 = fd->iter_type == long_integer_type_node
7527 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7528 gimple *g
7529 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7530 build_fold_addr_expr (counts[fd->ordered]));
7531 gimple_set_location (g, loc);
7532 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7535 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7537 static void
7538 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7539 tree *counts, tree c, location_t loc)
7541 auto_vec<tree, 10> args;
7542 enum built_in_function sink_ix
7543 = fd->iter_type == long_integer_type_node
7544 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7545 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7546 int i;
7547 gimple_stmt_iterator gsi2 = *gsi;
7548 bool warned_step = false;
7550 for (i = 0; i < fd->ordered; i++)
7552 off = TREE_PURPOSE (deps);
7553 if (!integer_zerop (off))
7555 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7556 || fd->loops[i].cond_code == GT_EXPR);
7557 bool forward = fd->loops[i].cond_code == LT_EXPR;
7558 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7559 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7560 "lexically later iteration");
7561 break;
7563 deps = TREE_CHAIN (deps);
7565 /* If all offsets corresponding to the collapsed loops are zero,
7566 this depend clause can be ignored. FIXME: but there is still a
7567 flush needed. We need to emit one __sync_synchronize () for it
7568 though (perhaps conditionally)? Solve this together with the
7569 conservative dependence folding optimization.
7570 if (i >= fd->collapse)
7571 return; */
7573 deps = OMP_CLAUSE_DECL (c);
7574 gsi_prev (&gsi2);
7575 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7576 edge e2 = split_block_after_labels (e1->dest);
7578 *gsi = gsi_after_labels (e1->dest);
7579 for (i = 0; i < fd->ordered; i++)
7581 tree itype = TREE_TYPE (fd->loops[i].v);
7582 if (POINTER_TYPE_P (itype))
7583 itype = sizetype;
7584 if (i)
7585 deps = TREE_CHAIN (deps);
7586 off = TREE_PURPOSE (deps);
7587 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7589 if (integer_zerop (off))
7590 t = boolean_true_node;
7591 else
7593 tree a;
7594 tree co = fold_convert_loc (loc, itype, off);
7595 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7597 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7598 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7599 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7600 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7601 co);
7603 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7604 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7605 fd->loops[i].v, co);
7606 else
7607 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7608 fd->loops[i].v, co);
7609 if (fd->loops[i].cond_code == LT_EXPR)
7611 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7612 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7613 fd->loops[i].n1);
7614 else
7615 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7616 fd->loops[i].n2);
7618 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7619 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7620 fd->loops[i].n2);
7621 else
7622 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7623 fd->loops[i].n1);
7625 if (cond)
7626 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7627 else
7628 cond = t;
7630 off = fold_convert_loc (loc, itype, off);
7632 if (fd->loops[i].cond_code == LT_EXPR
7633 ? !integer_onep (fd->loops[i].step)
7634 : !integer_minus_onep (fd->loops[i].step))
7636 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7637 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7638 fold_build1_loc (loc, NEGATE_EXPR, itype,
7639 s));
7640 else
7641 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7642 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7643 build_int_cst (itype, 0));
7644 if (integer_zerop (t) && !warned_step)
7646 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7647 "in the iteration space");
7648 warned_step = true;
7650 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7651 cond, t);
7654 if (i <= fd->collapse - 1 && fd->collapse > 1)
7655 t = fd->loop.v;
7656 else if (counts[i])
7657 t = counts[i];
7658 else
7660 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7661 fd->loops[i].v, fd->loops[i].n1);
7662 t = fold_convert_loc (loc, fd->iter_type, t);
7664 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7665 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7666 fold_build1_loc (loc, NEGATE_EXPR, itype,
7667 s));
7668 else
7669 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7670 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7671 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7672 off = fold_convert_loc (loc, fd->iter_type, off);
7673 if (i <= fd->collapse - 1 && fd->collapse > 1)
7675 if (i)
7676 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7677 off);
7678 if (i < fd->collapse - 1)
7680 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7681 counts[i]);
7682 continue;
7685 off = unshare_expr (off);
7686 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7687 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7688 true, GSI_SAME_STMT);
7689 args.safe_push (t);
7691 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7692 gimple_set_location (g, loc);
7693 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7695 *gsi = gsi_last_bb (e1->src);
7696 cond = unshare_expr (cond);
7697 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7698 GSI_CONTINUE_LINKING);
7699 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7700 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7701 e3->probability = REG_BR_PROB_BASE / 8;
7702 e1->probability = REG_BR_PROB_BASE - e3->probability;
7703 e1->flags = EDGE_TRUE_VALUE;
7704 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7706 *gsi = gsi_after_labels (e2->dest);
7709 /* Expand all #pragma omp ordered depend(source) and
7710 #pragma omp ordered depend(sink:...) constructs in the current
7711 #pragma omp for ordered(n) region. */
7713 static void
7714 expand_omp_ordered_source_sink (struct omp_region *region,
7715 struct omp_for_data *fd, tree *counts,
7716 basic_block cont_bb)
7718 struct omp_region *inner;
7719 int i;
7720 for (i = fd->collapse - 1; i < fd->ordered; i++)
7721 if (i == fd->collapse - 1 && fd->collapse > 1)
7722 counts[i] = NULL_TREE;
7723 else if (i >= fd->collapse && !cont_bb)
7724 counts[i] = build_zero_cst (fd->iter_type);
7725 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7726 && integer_onep (fd->loops[i].step))
7727 counts[i] = NULL_TREE;
7728 else
7729 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7730 tree atype
7731 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7732 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7733 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7735 for (inner = region->inner; inner; inner = inner->next)
7736 if (inner->type == GIMPLE_OMP_ORDERED)
7738 gomp_ordered *ord_stmt = inner->ord_stmt;
7739 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7740 location_t loc = gimple_location (ord_stmt);
7741 tree c;
7742 for (c = gimple_omp_ordered_clauses (ord_stmt);
7743 c; c = OMP_CLAUSE_CHAIN (c))
7744 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7745 break;
7746 if (c)
7747 expand_omp_ordered_source (&gsi, fd, counts, loc);
7748 for (c = gimple_omp_ordered_clauses (ord_stmt);
7749 c; c = OMP_CLAUSE_CHAIN (c))
7750 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7751 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7752 gsi_remove (&gsi, true);
7756 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
7757 collapsed. */
7759 static basic_block
7760 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7761 basic_block cont_bb, basic_block body_bb,
7762 bool ordered_lastprivate)
7764 if (fd->ordered == fd->collapse)
7765 return cont_bb;
7767 if (!cont_bb)
7769 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7770 for (int i = fd->collapse; i < fd->ordered; i++)
7772 tree type = TREE_TYPE (fd->loops[i].v);
7773 tree n1 = fold_convert (type, fd->loops[i].n1);
7774 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7775 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7776 size_int (i - fd->collapse + 1),
7777 NULL_TREE, NULL_TREE);
7778 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7780 return NULL;
7783 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7785 tree t, type = TREE_TYPE (fd->loops[i].v);
7786 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7787 expand_omp_build_assign (&gsi, fd->loops[i].v,
7788 fold_convert (type, fd->loops[i].n1));
7789 if (counts[i])
7790 expand_omp_build_assign (&gsi, counts[i],
7791 build_zero_cst (fd->iter_type));
7792 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7793 size_int (i - fd->collapse + 1),
7794 NULL_TREE, NULL_TREE);
7795 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7796 if (!gsi_end_p (gsi))
7797 gsi_prev (&gsi);
7798 else
7799 gsi = gsi_last_bb (body_bb);
7800 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7801 basic_block new_body = e1->dest;
7802 if (body_bb == cont_bb)
7803 cont_bb = new_body;
7804 edge e2 = NULL;
7805 basic_block new_header;
7806 if (EDGE_COUNT (cont_bb->preds) > 0)
7808 gsi = gsi_last_bb (cont_bb);
7809 if (POINTER_TYPE_P (type))
7810 t = fold_build_pointer_plus (fd->loops[i].v,
7811 fold_convert (sizetype,
7812 fd->loops[i].step));
7813 else
7814 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
7815 fold_convert (type, fd->loops[i].step));
7816 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7817 if (counts[i])
7819 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
7820 build_int_cst (fd->iter_type, 1));
7821 expand_omp_build_assign (&gsi, counts[i], t);
7822 t = counts[i];
7824 else
7826 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7827 fd->loops[i].v, fd->loops[i].n1);
7828 t = fold_convert (fd->iter_type, t);
7829 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7830 true, GSI_SAME_STMT);
7832 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7833 size_int (i - fd->collapse + 1),
7834 NULL_TREE, NULL_TREE);
7835 expand_omp_build_assign (&gsi, aref, t);
7836 gsi_prev (&gsi);
7837 e2 = split_block (cont_bb, gsi_stmt (gsi));
7838 new_header = e2->dest;
7840 else
7841 new_header = cont_bb;
7842 gsi = gsi_after_labels (new_header);
7843 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
7844 true, GSI_SAME_STMT);
7845 tree n2
7846 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
7847 true, NULL_TREE, true, GSI_SAME_STMT);
7848 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
7849 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
7850 edge e3 = split_block (new_header, gsi_stmt (gsi));
7851 cont_bb = e3->dest;
7852 remove_edge (e1);
7853 make_edge (body_bb, new_header, EDGE_FALLTHRU);
7854 e3->flags = EDGE_FALSE_VALUE;
7855 e3->probability = REG_BR_PROB_BASE / 8;
7856 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
7857 e1->probability = REG_BR_PROB_BASE - e3->probability;
7859 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
7860 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
7862 if (e2)
7864 struct loop *loop = alloc_loop ();
7865 loop->header = new_header;
7866 loop->latch = e2->src;
7867 add_loop (loop, body_bb->loop_father);
7871 /* If there are any lastprivate clauses and it is possible some loops
7872 might have zero iterations, ensure all the decls are initialized,
7873 otherwise we could crash evaluating C++ class iterators with lastprivate
7874 clauses. */
7875 bool need_inits = false;
7876 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
7877 if (need_inits)
7879 tree type = TREE_TYPE (fd->loops[i].v);
7880 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7881 expand_omp_build_assign (&gsi, fd->loops[i].v,
7882 fold_convert (type, fd->loops[i].n1));
7884 else
7886 tree type = TREE_TYPE (fd->loops[i].v);
7887 tree this_cond = fold_build2 (fd->loops[i].cond_code,
7888 boolean_type_node,
7889 fold_convert (type, fd->loops[i].n1),
7890 fold_convert (type, fd->loops[i].n2));
7891 if (!integer_onep (this_cond))
7892 need_inits = true;
7895 return cont_bb;
7899 /* A subroutine of expand_omp_for. Generate code for a parallel
7900 loop with any schedule. Given parameters:
7902 for (V = N1; V cond N2; V += STEP) BODY;
7904 where COND is "<" or ">", we generate pseudocode
7906 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
7907 if (more) goto L0; else goto L3;
7909 V = istart0;
7910 iend = iend0;
7912 BODY;
7913 V += STEP;
7914 if (V cond iend) goto L1; else goto L2;
7916 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7919 If this is a combined omp parallel loop, instead of the call to
7920 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
7921 If this is gimple_omp_for_combined_p loop, then instead of assigning
7922 V and iend in L0 we assign the first two _looptemp_ clause decls of the
7923 inner GIMPLE_OMP_FOR and V += STEP; and
7924 if (V cond iend) goto L1; else goto L2; are removed.
7926 For collapsed loops, given parameters:
7927 collapse(3)
7928 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7929 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7930 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7931 BODY;
7933 we generate pseudocode
7935 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
7936 if (cond3 is <)
7937 adj = STEP3 - 1;
7938 else
7939 adj = STEP3 + 1;
7940 count3 = (adj + N32 - N31) / STEP3;
7941 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
7942 if (cond2 is <)
7943 adj = STEP2 - 1;
7944 else
7945 adj = STEP2 + 1;
7946 count2 = (adj + N22 - N21) / STEP2;
7947 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
7948 if (cond1 is <)
7949 adj = STEP1 - 1;
7950 else
7951 adj = STEP1 + 1;
7952 count1 = (adj + N12 - N11) / STEP1;
7953 count = count1 * count2 * count3;
7954 goto Z1;
7956 count = 0;
7958 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
7959 if (more) goto L0; else goto L3;
7961 V = istart0;
7962 T = V;
7963 V3 = N31 + (T % count3) * STEP3;
7964 T = T / count3;
7965 V2 = N21 + (T % count2) * STEP2;
7966 T = T / count2;
7967 V1 = N11 + T * STEP1;
7968 iend = iend0;
7970 BODY;
7971 V += 1;
7972 if (V < iend) goto L10; else goto L2;
7973 L10:
7974 V3 += STEP3;
7975 if (V3 cond3 N32) goto L1; else goto L11;
7976 L11:
7977 V3 = N31;
7978 V2 += STEP2;
7979 if (V2 cond2 N22) goto L1; else goto L12;
7980 L12:
7981 V2 = N21;
7982 V1 += STEP1;
7983 goto L1;
7985 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7990 static void
7991 expand_omp_for_generic (struct omp_region *region,
7992 struct omp_for_data *fd,
7993 enum built_in_function start_fn,
7994 enum built_in_function next_fn,
7995 gimple *inner_stmt)
7997 tree type, istart0, iend0, iend;
7998 tree t, vmain, vback, bias = NULL_TREE;
7999 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8000 basic_block l2_bb = NULL, l3_bb = NULL;
8001 gimple_stmt_iterator gsi;
8002 gassign *assign_stmt;
8003 bool in_combined_parallel = is_combined_parallel (region);
8004 bool broken_loop = region->cont == NULL;
8005 edge e, ne;
8006 tree *counts = NULL;
8007 int i;
8008 bool ordered_lastprivate = false;
8010 gcc_assert (!broken_loop || !in_combined_parallel);
8011 gcc_assert (fd->iter_type == long_integer_type_node
8012 || !in_combined_parallel);
8014 entry_bb = region->entry;
8015 cont_bb = region->cont;
8016 collapse_bb = NULL;
8017 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8018 gcc_assert (broken_loop
8019 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8020 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8021 l1_bb = single_succ (l0_bb);
8022 if (!broken_loop)
8024 l2_bb = create_empty_bb (cont_bb);
8025 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8026 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8027 == l1_bb));
8028 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8030 else
8031 l2_bb = NULL;
8032 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8033 exit_bb = region->exit;
8035 gsi = gsi_last_bb (entry_bb);
8037 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8038 if (fd->ordered
8039 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8040 OMP_CLAUSE_LASTPRIVATE))
8041 ordered_lastprivate = false;
8042 if (fd->collapse > 1 || fd->ordered)
8044 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8045 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8047 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8048 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8049 zero_iter1_bb, first_zero_iter1,
8050 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8052 if (zero_iter1_bb)
8054 /* Some counts[i] vars might be uninitialized if
8055 some loop has zero iterations. But the body shouldn't
8056 be executed in that case, so just avoid uninit warnings. */
8057 for (i = first_zero_iter1;
8058 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8059 if (SSA_VAR_P (counts[i]))
8060 TREE_NO_WARNING (counts[i]) = 1;
8061 gsi_prev (&gsi);
8062 e = split_block (entry_bb, gsi_stmt (gsi));
8063 entry_bb = e->dest;
8064 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8065 gsi = gsi_last_bb (entry_bb);
8066 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8067 get_immediate_dominator (CDI_DOMINATORS,
8068 zero_iter1_bb));
8070 if (zero_iter2_bb)
8072 /* Some counts[i] vars might be uninitialized if
8073 some loop has zero iterations. But the body shouldn't
8074 be executed in that case, so just avoid uninit warnings. */
8075 for (i = first_zero_iter2; i < fd->ordered; i++)
8076 if (SSA_VAR_P (counts[i]))
8077 TREE_NO_WARNING (counts[i]) = 1;
8078 if (zero_iter1_bb)
8079 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8080 else
8082 gsi_prev (&gsi);
8083 e = split_block (entry_bb, gsi_stmt (gsi));
8084 entry_bb = e->dest;
8085 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8086 gsi = gsi_last_bb (entry_bb);
8087 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8088 get_immediate_dominator
8089 (CDI_DOMINATORS, zero_iter2_bb));
8092 if (fd->collapse == 1)
8094 counts[0] = fd->loop.n2;
8095 fd->loop = fd->loops[0];
8099 type = TREE_TYPE (fd->loop.v);
8100 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8101 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8102 TREE_ADDRESSABLE (istart0) = 1;
8103 TREE_ADDRESSABLE (iend0) = 1;
8105 /* See if we need to bias by LLONG_MIN. */
8106 if (fd->iter_type == long_long_unsigned_type_node
8107 && TREE_CODE (type) == INTEGER_TYPE
8108 && !TYPE_UNSIGNED (type)
8109 && fd->ordered == 0)
8111 tree n1, n2;
8113 if (fd->loop.cond_code == LT_EXPR)
8115 n1 = fd->loop.n1;
8116 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8118 else
8120 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8121 n2 = fd->loop.n1;
8123 if (TREE_CODE (n1) != INTEGER_CST
8124 || TREE_CODE (n2) != INTEGER_CST
8125 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8126 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8129 gimple_stmt_iterator gsif = gsi;
8130 gsi_prev (&gsif);
8132 tree arr = NULL_TREE;
8133 if (in_combined_parallel)
8135 gcc_assert (fd->ordered == 0);
8136 /* In a combined parallel loop, emit a call to
8137 GOMP_loop_foo_next. */
8138 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8139 build_fold_addr_expr (istart0),
8140 build_fold_addr_expr (iend0));
8142 else
8144 tree t0, t1, t2, t3, t4;
8145 /* If this is not a combined parallel loop, emit a call to
8146 GOMP_loop_foo_start in ENTRY_BB. */
8147 t4 = build_fold_addr_expr (iend0);
8148 t3 = build_fold_addr_expr (istart0);
8149 if (fd->ordered)
8151 t0 = build_int_cst (unsigned_type_node,
8152 fd->ordered - fd->collapse + 1);
8153 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8154 fd->ordered
8155 - fd->collapse + 1),
8156 ".omp_counts");
8157 DECL_NAMELESS (arr) = 1;
8158 TREE_ADDRESSABLE (arr) = 1;
8159 TREE_STATIC (arr) = 1;
8160 vec<constructor_elt, va_gc> *v;
8161 vec_alloc (v, fd->ordered - fd->collapse + 1);
8162 int idx;
8164 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8166 tree c;
8167 if (idx == 0 && fd->collapse > 1)
8168 c = fd->loop.n2;
8169 else
8170 c = counts[idx + fd->collapse - 1];
8171 tree purpose = size_int (idx);
8172 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8173 if (TREE_CODE (c) != INTEGER_CST)
8174 TREE_STATIC (arr) = 0;
8177 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8178 if (!TREE_STATIC (arr))
8179 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8180 void_type_node, arr),
8181 true, NULL_TREE, true, GSI_SAME_STMT);
8182 t1 = build_fold_addr_expr (arr);
8183 t2 = NULL_TREE;
8185 else
8187 t2 = fold_convert (fd->iter_type, fd->loop.step);
8188 t1 = fd->loop.n2;
8189 t0 = fd->loop.n1;
8190 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8192 tree innerc
8193 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8194 OMP_CLAUSE__LOOPTEMP_);
8195 gcc_assert (innerc);
8196 t0 = OMP_CLAUSE_DECL (innerc);
8197 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8198 OMP_CLAUSE__LOOPTEMP_);
8199 gcc_assert (innerc);
8200 t1 = OMP_CLAUSE_DECL (innerc);
8202 if (POINTER_TYPE_P (TREE_TYPE (t0))
8203 && TYPE_PRECISION (TREE_TYPE (t0))
8204 != TYPE_PRECISION (fd->iter_type))
8206 /* Avoid casting pointers to integer of a different size. */
8207 tree itype = signed_type_for (type);
8208 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8209 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8211 else
8213 t1 = fold_convert (fd->iter_type, t1);
8214 t0 = fold_convert (fd->iter_type, t0);
8216 if (bias)
8218 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8219 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8222 if (fd->iter_type == long_integer_type_node || fd->ordered)
8224 if (fd->chunk_size)
8226 t = fold_convert (fd->iter_type, fd->chunk_size);
8227 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8228 if (fd->ordered)
8229 t = build_call_expr (builtin_decl_explicit (start_fn),
8230 5, t0, t1, t, t3, t4);
8231 else
8232 t = build_call_expr (builtin_decl_explicit (start_fn),
8233 6, t0, t1, t2, t, t3, t4);
8235 else if (fd->ordered)
8236 t = build_call_expr (builtin_decl_explicit (start_fn),
8237 4, t0, t1, t3, t4);
8238 else
8239 t = build_call_expr (builtin_decl_explicit (start_fn),
8240 5, t0, t1, t2, t3, t4);
8242 else
8244 tree t5;
8245 tree c_bool_type;
8246 tree bfn_decl;
8248 /* The GOMP_loop_ull_*start functions have additional boolean
8249 argument, true for < loops and false for > loops.
8250 In Fortran, the C bool type can be different from
8251 boolean_type_node. */
8252 bfn_decl = builtin_decl_explicit (start_fn);
8253 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8254 t5 = build_int_cst (c_bool_type,
8255 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8256 if (fd->chunk_size)
8258 tree bfn_decl = builtin_decl_explicit (start_fn);
8259 t = fold_convert (fd->iter_type, fd->chunk_size);
8260 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8261 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8263 else
8264 t = build_call_expr (builtin_decl_explicit (start_fn),
8265 6, t5, t0, t1, t2, t3, t4);
8268 if (TREE_TYPE (t) != boolean_type_node)
8269 t = fold_build2 (NE_EXPR, boolean_type_node,
8270 t, build_int_cst (TREE_TYPE (t), 0));
8271 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8272 true, GSI_SAME_STMT);
8273 if (arr && !TREE_STATIC (arr))
8275 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8276 TREE_THIS_VOLATILE (clobber) = 1;
8277 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8278 GSI_SAME_STMT);
8280 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8282 /* Remove the GIMPLE_OMP_FOR statement. */
8283 gsi_remove (&gsi, true);
8285 if (gsi_end_p (gsif))
8286 gsif = gsi_after_labels (gsi_bb (gsif));
8287 gsi_next (&gsif);
8289 /* Iteration setup for sequential loop goes in L0_BB. */
8290 tree startvar = fd->loop.v;
8291 tree endvar = NULL_TREE;
8293 if (gimple_omp_for_combined_p (fd->for_stmt))
8295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8296 && gimple_omp_for_kind (inner_stmt)
8297 == GF_OMP_FOR_KIND_SIMD);
8298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8299 OMP_CLAUSE__LOOPTEMP_);
8300 gcc_assert (innerc);
8301 startvar = OMP_CLAUSE_DECL (innerc);
8302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8303 OMP_CLAUSE__LOOPTEMP_);
8304 gcc_assert (innerc);
8305 endvar = OMP_CLAUSE_DECL (innerc);
8308 gsi = gsi_start_bb (l0_bb);
8309 t = istart0;
8310 if (fd->ordered && fd->collapse == 1)
8311 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8312 fold_convert (fd->iter_type, fd->loop.step));
8313 else if (bias)
8314 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8315 if (fd->ordered && fd->collapse == 1)
8317 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8318 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8319 fd->loop.n1, fold_convert (sizetype, t));
8320 else
8322 t = fold_convert (TREE_TYPE (startvar), t);
8323 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8324 fd->loop.n1, t);
8327 else
8329 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8330 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8331 t = fold_convert (TREE_TYPE (startvar), t);
8333 t = force_gimple_operand_gsi (&gsi, t,
8334 DECL_P (startvar)
8335 && TREE_ADDRESSABLE (startvar),
8336 NULL_TREE, false, GSI_CONTINUE_LINKING);
8337 assign_stmt = gimple_build_assign (startvar, t);
8338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8340 t = iend0;
8341 if (fd->ordered && fd->collapse == 1)
8342 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8343 fold_convert (fd->iter_type, fd->loop.step));
8344 else if (bias)
8345 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8346 if (fd->ordered && fd->collapse == 1)
8348 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8349 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8350 fd->loop.n1, fold_convert (sizetype, t));
8351 else
8353 t = fold_convert (TREE_TYPE (startvar), t);
8354 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8355 fd->loop.n1, t);
8358 else
8360 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8361 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8362 t = fold_convert (TREE_TYPE (startvar), t);
8364 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8365 false, GSI_CONTINUE_LINKING);
8366 if (endvar)
8368 assign_stmt = gimple_build_assign (endvar, iend);
8369 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8370 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8371 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8372 else
8373 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8374 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8376 /* Handle linear clause adjustments. */
8377 tree itercnt = NULL_TREE;
8378 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8379 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8380 c; c = OMP_CLAUSE_CHAIN (c))
8381 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8382 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8384 tree d = OMP_CLAUSE_DECL (c);
8385 bool is_ref = is_reference (d);
8386 tree t = d, a, dest;
8387 if (is_ref)
8388 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8389 tree type = TREE_TYPE (t);
8390 if (POINTER_TYPE_P (type))
8391 type = sizetype;
8392 dest = unshare_expr (t);
8393 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8394 expand_omp_build_assign (&gsif, v, t);
8395 if (itercnt == NULL_TREE)
8397 itercnt = startvar;
8398 tree n1 = fd->loop.n1;
8399 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8401 itercnt
8402 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8403 itercnt);
8404 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8406 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8407 itercnt, n1);
8408 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8409 itercnt, fd->loop.step);
8410 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8411 NULL_TREE, false,
8412 GSI_CONTINUE_LINKING);
8414 a = fold_build2 (MULT_EXPR, type,
8415 fold_convert (type, itercnt),
8416 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8417 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8418 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8419 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8420 false, GSI_CONTINUE_LINKING);
8421 assign_stmt = gimple_build_assign (dest, t);
8422 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8424 if (fd->collapse > 1)
8425 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8427 if (fd->ordered)
8429 /* Until now, counts array contained number of iterations or
8430 variable containing it for ith loop. From now on, we need
8431 those counts only for collapsed loops, and only for the 2nd
8432 till the last collapsed one. Move those one element earlier,
8433 we'll use counts[fd->collapse - 1] for the first source/sink
8434 iteration counter and so on and counts[fd->ordered]
8435 as the array holding the current counter values for
8436 depend(source). */
8437 if (fd->collapse > 1)
8438 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8439 if (broken_loop)
8441 int i;
8442 for (i = fd->collapse; i < fd->ordered; i++)
8444 tree type = TREE_TYPE (fd->loops[i].v);
8445 tree this_cond
8446 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8447 fold_convert (type, fd->loops[i].n1),
8448 fold_convert (type, fd->loops[i].n2));
8449 if (!integer_onep (this_cond))
8450 break;
8452 if (i < fd->ordered)
8454 cont_bb
8455 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8456 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8457 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8458 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8459 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8460 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8461 make_edge (cont_bb, l1_bb, 0);
8462 l2_bb = create_empty_bb (cont_bb);
8463 broken_loop = false;
8466 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8467 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8468 ordered_lastprivate);
8469 if (counts[fd->collapse - 1])
8471 gcc_assert (fd->collapse == 1);
8472 gsi = gsi_last_bb (l0_bb);
8473 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8474 istart0, true);
8475 gsi = gsi_last_bb (cont_bb);
8476 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8477 build_int_cst (fd->iter_type, 1));
8478 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8479 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8480 size_zero_node, NULL_TREE, NULL_TREE);
8481 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8482 t = counts[fd->collapse - 1];
8484 else if (fd->collapse > 1)
8485 t = fd->loop.v;
8486 else
8488 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8489 fd->loops[0].v, fd->loops[0].n1);
8490 t = fold_convert (fd->iter_type, t);
8492 gsi = gsi_last_bb (l0_bb);
8493 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8494 size_zero_node, NULL_TREE, NULL_TREE);
8495 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8496 false, GSI_CONTINUE_LINKING);
8497 expand_omp_build_assign (&gsi, aref, t, true);
8500 if (!broken_loop)
8502 /* Code to control the increment and predicate for the sequential
8503 loop goes in the CONT_BB. */
8504 gsi = gsi_last_bb (cont_bb);
8505 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8506 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8507 vmain = gimple_omp_continue_control_use (cont_stmt);
8508 vback = gimple_omp_continue_control_def (cont_stmt);
8510 if (!gimple_omp_for_combined_p (fd->for_stmt))
8512 if (POINTER_TYPE_P (type))
8513 t = fold_build_pointer_plus (vmain, fd->loop.step);
8514 else
8515 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8516 t = force_gimple_operand_gsi (&gsi, t,
8517 DECL_P (vback)
8518 && TREE_ADDRESSABLE (vback),
8519 NULL_TREE, true, GSI_SAME_STMT);
8520 assign_stmt = gimple_build_assign (vback, t);
8521 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8523 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8525 if (fd->collapse > 1)
8526 t = fd->loop.v;
8527 else
8529 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8530 fd->loops[0].v, fd->loops[0].n1);
8531 t = fold_convert (fd->iter_type, t);
8533 tree aref = build4 (ARRAY_REF, fd->iter_type,
8534 counts[fd->ordered], size_zero_node,
8535 NULL_TREE, NULL_TREE);
8536 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8537 true, GSI_SAME_STMT);
8538 expand_omp_build_assign (&gsi, aref, t);
8541 t = build2 (fd->loop.cond_code, boolean_type_node,
8542 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8543 iend);
8544 gcond *cond_stmt = gimple_build_cond_empty (t);
8545 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8548 /* Remove GIMPLE_OMP_CONTINUE. */
8549 gsi_remove (&gsi, true);
8551 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8552 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8554 /* Emit code to get the next parallel iteration in L2_BB. */
8555 gsi = gsi_start_bb (l2_bb);
8557 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8558 build_fold_addr_expr (istart0),
8559 build_fold_addr_expr (iend0));
8560 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8561 false, GSI_CONTINUE_LINKING);
8562 if (TREE_TYPE (t) != boolean_type_node)
8563 t = fold_build2 (NE_EXPR, boolean_type_node,
8564 t, build_int_cst (TREE_TYPE (t), 0));
8565 gcond *cond_stmt = gimple_build_cond_empty (t);
8566 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8569 /* Add the loop cleanup function. */
8570 gsi = gsi_last_bb (exit_bb);
8571 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8572 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8573 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8574 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8575 else
8576 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8577 gcall *call_stmt = gimple_build_call (t, 0);
8578 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8579 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8580 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8581 if (fd->ordered)
8583 tree arr = counts[fd->ordered];
8584 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8585 TREE_THIS_VOLATILE (clobber) = 1;
8586 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8587 GSI_SAME_STMT);
8589 gsi_remove (&gsi, true);
8591 /* Connect the new blocks. */
8592 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8593 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8595 if (!broken_loop)
8597 gimple_seq phis;
8599 e = find_edge (cont_bb, l3_bb);
8600 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8602 phis = phi_nodes (l3_bb);
8603 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8605 gimple *phi = gsi_stmt (gsi);
8606 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8607 PHI_ARG_DEF_FROM_EDGE (phi, e));
8609 remove_edge (e);
8611 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
8612 e = find_edge (cont_bb, l1_bb);
8613 if (e == NULL)
8615 e = BRANCH_EDGE (cont_bb);
8616 gcc_assert (single_succ (e->dest) == l1_bb);
8618 if (gimple_omp_for_combined_p (fd->for_stmt))
8620 remove_edge (e);
8621 e = NULL;
8623 else if (fd->collapse > 1)
8625 remove_edge (e);
8626 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8628 else
8629 e->flags = EDGE_TRUE_VALUE;
8630 if (e)
8632 e->probability = REG_BR_PROB_BASE * 7 / 8;
8633 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8635 else
8637 e = find_edge (cont_bb, l2_bb);
8638 e->flags = EDGE_FALLTHRU;
8640 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
8642 if (gimple_in_ssa_p (cfun))
8644 /* Add phis to the outer loop that connect to the phis in the inner,
8645 original loop, and move the loop entry value of the inner phi to
8646 the loop entry value of the outer phi. */
8647 gphi_iterator psi;
8648 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8650 source_location locus;
8651 gphi *nphi;
8652 gphi *exit_phi = psi.phi ();
8654 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8655 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8657 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8658 edge latch_to_l1 = find_edge (latch, l1_bb);
8659 gphi *inner_phi
8660 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8662 tree t = gimple_phi_result (exit_phi);
8663 tree new_res = copy_ssa_name (t, NULL);
8664 nphi = create_phi_node (new_res, l0_bb);
8666 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8667 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8668 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8669 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8670 add_phi_arg (nphi, t, entry_to_l0, locus);
8672 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8673 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8675 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8679 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8680 recompute_dominator (CDI_DOMINATORS, l2_bb));
8681 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8682 recompute_dominator (CDI_DOMINATORS, l3_bb));
8683 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8684 recompute_dominator (CDI_DOMINATORS, l0_bb));
8685 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8686 recompute_dominator (CDI_DOMINATORS, l1_bb));
8688 /* We enter expand_omp_for_generic with a loop. This original loop may
8689 have its own loop struct, or it may be part of an outer loop struct
8690 (which may be the fake loop). */
8691 struct loop *outer_loop = entry_bb->loop_father;
8692 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8694 add_bb_to_loop (l2_bb, outer_loop);
8696 /* We've added a new loop around the original loop. Allocate the
8697 corresponding loop struct. */
8698 struct loop *new_loop = alloc_loop ();
8699 new_loop->header = l0_bb;
8700 new_loop->latch = l2_bb;
8701 add_loop (new_loop, outer_loop);
8703 /* Allocate a loop structure for the original loop unless we already
8704 had one. */
8705 if (!orig_loop_has_loop_struct
8706 && !gimple_omp_for_combined_p (fd->for_stmt))
8708 struct loop *orig_loop = alloc_loop ();
8709 orig_loop->header = l1_bb;
8710 /* The loop may have multiple latches. */
8711 add_loop (orig_loop, new_loop);
8717 /* A subroutine of expand_omp_for. Generate code for a parallel
8718 loop with static schedule and no specified chunk size. Given
8719 parameters:
8721 for (V = N1; V cond N2; V += STEP) BODY;
8723 where COND is "<" or ">", we generate pseudocode
8725 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8726 if (cond is <)
8727 adj = STEP - 1;
8728 else
8729 adj = STEP + 1;
8730 if ((__typeof (V)) -1 > 0 && cond is >)
8731 n = -(adj + N2 - N1) / -STEP;
8732 else
8733 n = (adj + N2 - N1) / STEP;
8734 q = n / nthreads;
8735 tt = n % nthreads;
8736 if (threadid < tt) goto L3; else goto L4;
8738 tt = 0;
8739 q = q + 1;
8741 s0 = q * threadid + tt;
8742 e0 = s0 + q;
8743 V = s0 * STEP + N1;
8744 if (s0 >= e0) goto L2; else goto L0;
8746 e = e0 * STEP + N1;
8748 BODY;
8749 V += STEP;
8750 if (V cond e) goto L1;
8754 static void
8755 expand_omp_for_static_nochunk (struct omp_region *region,
8756 struct omp_for_data *fd,
8757 gimple *inner_stmt)
8759 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
8760 tree type, itype, vmain, vback;
8761 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
8762 basic_block body_bb, cont_bb, collapse_bb = NULL;
8763 basic_block fin_bb;
8764 gimple_stmt_iterator gsi;
8765 edge ep;
8766 bool broken_loop = region->cont == NULL;
8767 tree *counts = NULL;
8768 tree n1, n2, step;
8770 itype = type = TREE_TYPE (fd->loop.v);
8771 if (POINTER_TYPE_P (type))
8772 itype = signed_type_for (type);
8774 entry_bb = region->entry;
8775 cont_bb = region->cont;
8776 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8777 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8778 gcc_assert (broken_loop
8779 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
8780 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8781 body_bb = single_succ (seq_start_bb);
8782 if (!broken_loop)
8784 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8785 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
8786 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8788 exit_bb = region->exit;
8790 /* Iteration space partitioning goes in ENTRY_BB. */
8791 gsi = gsi_last_bb (entry_bb);
8792 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8794 if (fd->collapse > 1)
8796 int first_zero_iter = -1, dummy = -1;
8797 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
8799 counts = XALLOCAVEC (tree, fd->collapse);
8800 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8801 fin_bb, first_zero_iter,
8802 dummy_bb, dummy, l2_dom_bb);
8803 t = NULL_TREE;
8805 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8806 t = integer_one_node;
8807 else
8808 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8809 fold_convert (type, fd->loop.n1),
8810 fold_convert (type, fd->loop.n2));
8811 if (fd->collapse == 1
8812 && TYPE_UNSIGNED (type)
8813 && (t == NULL_TREE || !integer_onep (t)))
8815 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
8816 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8817 true, GSI_SAME_STMT);
8818 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
8819 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8820 true, GSI_SAME_STMT);
8821 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
8822 NULL_TREE, NULL_TREE);
8823 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8824 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8825 expand_omp_regimplify_p, NULL, NULL)
8826 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8827 expand_omp_regimplify_p, NULL, NULL))
8829 gsi = gsi_for_stmt (cond_stmt);
8830 gimple_regimplify_operands (cond_stmt, &gsi);
8832 ep = split_block (entry_bb, cond_stmt);
8833 ep->flags = EDGE_TRUE_VALUE;
8834 entry_bb = ep->dest;
8835 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
8836 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
8837 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
8838 if (gimple_in_ssa_p (cfun))
8840 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
8841 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
8842 !gsi_end_p (gpi); gsi_next (&gpi))
8844 gphi *phi = gpi.phi ();
8845 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
8846 ep, UNKNOWN_LOCATION);
8849 gsi = gsi_last_bb (entry_bb);
8852 switch (gimple_omp_for_kind (fd->for_stmt))
8854 case GF_OMP_FOR_KIND_FOR:
8855 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
8856 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8857 break;
8858 case GF_OMP_FOR_KIND_DISTRIBUTE:
8859 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
8860 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
8861 break;
8862 default:
8863 gcc_unreachable ();
8865 nthreads = build_call_expr (nthreads, 0);
8866 nthreads = fold_convert (itype, nthreads);
8867 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
8868 true, GSI_SAME_STMT);
8869 threadid = build_call_expr (threadid, 0);
8870 threadid = fold_convert (itype, threadid);
8871 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
8872 true, GSI_SAME_STMT);
8874 n1 = fd->loop.n1;
8875 n2 = fd->loop.n2;
8876 step = fd->loop.step;
8877 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8879 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8880 OMP_CLAUSE__LOOPTEMP_);
8881 gcc_assert (innerc);
8882 n1 = OMP_CLAUSE_DECL (innerc);
8883 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8884 OMP_CLAUSE__LOOPTEMP_);
8885 gcc_assert (innerc);
8886 n2 = OMP_CLAUSE_DECL (innerc);
8888 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
8889 true, NULL_TREE, true, GSI_SAME_STMT);
8890 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
8891 true, NULL_TREE, true, GSI_SAME_STMT);
8892 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
8893 true, NULL_TREE, true, GSI_SAME_STMT);
8895 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
8896 t = fold_build2 (PLUS_EXPR, itype, step, t);
8897 t = fold_build2 (PLUS_EXPR, itype, t, n2);
8898 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
8899 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
8900 t = fold_build2 (TRUNC_DIV_EXPR, itype,
8901 fold_build1 (NEGATE_EXPR, itype, t),
8902 fold_build1 (NEGATE_EXPR, itype, step));
8903 else
8904 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
8905 t = fold_convert (itype, t);
8906 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8908 q = create_tmp_reg (itype, "q");
8909 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
8910 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8911 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
8913 tt = create_tmp_reg (itype, "tt");
8914 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
8915 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8916 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
8918 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
8919 gcond *cond_stmt = gimple_build_cond_empty (t);
8920 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8922 second_bb = split_block (entry_bb, cond_stmt)->dest;
8923 gsi = gsi_last_bb (second_bb);
8924 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8926 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
8927 GSI_SAME_STMT);
8928 gassign *assign_stmt
8929 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
8930 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8932 third_bb = split_block (second_bb, assign_stmt)->dest;
8933 gsi = gsi_last_bb (third_bb);
8934 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8936 t = build2 (MULT_EXPR, itype, q, threadid);
8937 t = build2 (PLUS_EXPR, itype, t, tt);
8938 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8940 t = fold_build2 (PLUS_EXPR, itype, s0, q);
8941 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8943 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
8944 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8946 /* Remove the GIMPLE_OMP_FOR statement. */
8947 gsi_remove (&gsi, true);
8949 /* Setup code for sequential iteration goes in SEQ_START_BB. */
8950 gsi = gsi_start_bb (seq_start_bb);
8952 tree startvar = fd->loop.v;
8953 tree endvar = NULL_TREE;
8955 if (gimple_omp_for_combined_p (fd->for_stmt))
8957 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
8958 ? gimple_omp_parallel_clauses (inner_stmt)
8959 : gimple_omp_for_clauses (inner_stmt);
8960 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
8961 gcc_assert (innerc);
8962 startvar = OMP_CLAUSE_DECL (innerc);
8963 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8964 OMP_CLAUSE__LOOPTEMP_);
8965 gcc_assert (innerc);
8966 endvar = OMP_CLAUSE_DECL (innerc);
8968 t = fold_convert (itype, s0);
8969 t = fold_build2 (MULT_EXPR, itype, t, step);
8970 if (POINTER_TYPE_P (type))
8971 t = fold_build_pointer_plus (n1, t);
8972 else
8973 t = fold_build2 (PLUS_EXPR, type, t, n1);
8974 t = fold_convert (TREE_TYPE (startvar), t);
8975 t = force_gimple_operand_gsi (&gsi, t,
8976 DECL_P (startvar)
8977 && TREE_ADDRESSABLE (startvar),
8978 NULL_TREE, false, GSI_CONTINUE_LINKING);
8979 assign_stmt = gimple_build_assign (startvar, t);
8980 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8982 t = fold_convert (itype, e0);
8983 t = fold_build2 (MULT_EXPR, itype, t, step);
8984 if (POINTER_TYPE_P (type))
8985 t = fold_build_pointer_plus (n1, t);
8986 else
8987 t = fold_build2 (PLUS_EXPR, type, t, n1);
8988 t = fold_convert (TREE_TYPE (startvar), t);
8989 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8990 false, GSI_CONTINUE_LINKING);
8991 if (endvar)
8993 assign_stmt = gimple_build_assign (endvar, e);
8994 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8995 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
8996 assign_stmt = gimple_build_assign (fd->loop.v, e);
8997 else
8998 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
8999 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9001 /* Handle linear clause adjustments. */
9002 tree itercnt = NULL_TREE;
9003 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9004 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9005 c; c = OMP_CLAUSE_CHAIN (c))
9006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9007 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9009 tree d = OMP_CLAUSE_DECL (c);
9010 bool is_ref = is_reference (d);
9011 tree t = d, a, dest;
9012 if (is_ref)
9013 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9014 if (itercnt == NULL_TREE)
9016 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9018 itercnt = fold_build2 (MINUS_EXPR, itype,
9019 fold_convert (itype, n1),
9020 fold_convert (itype, fd->loop.n1));
9021 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9022 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9023 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9024 NULL_TREE, false,
9025 GSI_CONTINUE_LINKING);
9027 else
9028 itercnt = s0;
9030 tree type = TREE_TYPE (t);
9031 if (POINTER_TYPE_P (type))
9032 type = sizetype;
9033 a = fold_build2 (MULT_EXPR, type,
9034 fold_convert (type, itercnt),
9035 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9036 dest = unshare_expr (t);
9037 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9038 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9039 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9040 false, GSI_CONTINUE_LINKING);
9041 assign_stmt = gimple_build_assign (dest, t);
9042 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9044 if (fd->collapse > 1)
9045 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9047 if (!broken_loop)
9049 /* The code controlling the sequential loop replaces the
9050 GIMPLE_OMP_CONTINUE. */
9051 gsi = gsi_last_bb (cont_bb);
9052 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9053 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9054 vmain = gimple_omp_continue_control_use (cont_stmt);
9055 vback = gimple_omp_continue_control_def (cont_stmt);
9057 if (!gimple_omp_for_combined_p (fd->for_stmt))
9059 if (POINTER_TYPE_P (type))
9060 t = fold_build_pointer_plus (vmain, step);
9061 else
9062 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9063 t = force_gimple_operand_gsi (&gsi, t,
9064 DECL_P (vback)
9065 && TREE_ADDRESSABLE (vback),
9066 NULL_TREE, true, GSI_SAME_STMT);
9067 assign_stmt = gimple_build_assign (vback, t);
9068 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9070 t = build2 (fd->loop.cond_code, boolean_type_node,
9071 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9072 ? t : vback, e);
9073 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9076 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9077 gsi_remove (&gsi, true);
9079 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9080 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9083 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9084 gsi = gsi_last_bb (exit_bb);
9085 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9087 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9088 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9090 gsi_remove (&gsi, true);
9092 /* Connect all the blocks. */
9093 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9094 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9095 ep = find_edge (entry_bb, second_bb);
9096 ep->flags = EDGE_TRUE_VALUE;
9097 ep->probability = REG_BR_PROB_BASE / 4;
9098 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9099 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9101 if (!broken_loop)
9103 ep = find_edge (cont_bb, body_bb);
9104 if (ep == NULL)
9106 ep = BRANCH_EDGE (cont_bb);
9107 gcc_assert (single_succ (ep->dest) == body_bb);
9109 if (gimple_omp_for_combined_p (fd->for_stmt))
9111 remove_edge (ep);
9112 ep = NULL;
9114 else if (fd->collapse > 1)
9116 remove_edge (ep);
9117 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9119 else
9120 ep->flags = EDGE_TRUE_VALUE;
9121 find_edge (cont_bb, fin_bb)->flags
9122 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9125 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9126 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9127 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9129 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9130 recompute_dominator (CDI_DOMINATORS, body_bb));
9131 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9132 recompute_dominator (CDI_DOMINATORS, fin_bb));
9134 struct loop *loop = body_bb->loop_father;
9135 if (loop != entry_bb->loop_father)
9137 gcc_assert (loop->header == body_bb);
9138 gcc_assert (broken_loop
9139 || loop->latch == region->cont
9140 || single_pred (loop->latch) == region->cont);
9141 return;
9144 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9146 loop = alloc_loop ();
9147 loop->header = body_bb;
9148 if (collapse_bb == NULL)
9149 loop->latch = cont_bb;
9150 add_loop (loop, body_bb->loop_father);
9154 /* Return phi in E->DEST with ARG on edge E. */
9156 static gphi *
9157 find_phi_with_arg_on_edge (tree arg, edge e)
9159 basic_block bb = e->dest;
9161 for (gphi_iterator gpi = gsi_start_phis (bb);
9162 !gsi_end_p (gpi);
9163 gsi_next (&gpi))
9165 gphi *phi = gpi.phi ();
9166 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9167 return phi;
9170 return NULL;
9173 /* A subroutine of expand_omp_for. Generate code for a parallel
9174 loop with static schedule and a specified chunk size. Given
9175 parameters:
9177 for (V = N1; V cond N2; V += STEP) BODY;
9179 where COND is "<" or ">", we generate pseudocode
9181 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9182 if (cond is <)
9183 adj = STEP - 1;
9184 else
9185 adj = STEP + 1;
9186 if ((__typeof (V)) -1 > 0 && cond is >)
9187 n = -(adj + N2 - N1) / -STEP;
9188 else
9189 n = (adj + N2 - N1) / STEP;
9190 trip = 0;
9191 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9192 here so that V is defined
9193 if the loop is not entered
9195 s0 = (trip * nthreads + threadid) * CHUNK;
9196 e0 = min(s0 + CHUNK, n);
9197 if (s0 < n) goto L1; else goto L4;
9199 V = s0 * STEP + N1;
9200 e = e0 * STEP + N1;
9202 BODY;
9203 V += STEP;
9204 if (V cond e) goto L2; else goto L3;
9206 trip += 1;
9207 goto L0;
9211 static void
9212 expand_omp_for_static_chunk (struct omp_region *region,
9213 struct omp_for_data *fd, gimple *inner_stmt)
9215 tree n, s0, e0, e, t;
9216 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9217 tree type, itype, vmain, vback, vextra;
9218 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9219 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9220 gimple_stmt_iterator gsi;
9221 edge se;
9222 bool broken_loop = region->cont == NULL;
9223 tree *counts = NULL;
9224 tree n1, n2, step;
9226 itype = type = TREE_TYPE (fd->loop.v);
9227 if (POINTER_TYPE_P (type))
9228 itype = signed_type_for (type);
9230 entry_bb = region->entry;
9231 se = split_block (entry_bb, last_stmt (entry_bb));
9232 entry_bb = se->src;
9233 iter_part_bb = se->dest;
9234 cont_bb = region->cont;
9235 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9236 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9237 gcc_assert (broken_loop
9238 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9239 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9240 body_bb = single_succ (seq_start_bb);
9241 if (!broken_loop)
9243 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9244 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9245 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9246 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9248 exit_bb = region->exit;
9250 /* Trip and adjustment setup goes in ENTRY_BB. */
9251 gsi = gsi_last_bb (entry_bb);
9252 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9254 if (fd->collapse > 1)
9256 int first_zero_iter = -1, dummy = -1;
9257 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9259 counts = XALLOCAVEC (tree, fd->collapse);
9260 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9261 fin_bb, first_zero_iter,
9262 dummy_bb, dummy, l2_dom_bb);
9263 t = NULL_TREE;
9265 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9266 t = integer_one_node;
9267 else
9268 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9269 fold_convert (type, fd->loop.n1),
9270 fold_convert (type, fd->loop.n2));
9271 if (fd->collapse == 1
9272 && TYPE_UNSIGNED (type)
9273 && (t == NULL_TREE || !integer_onep (t)))
9275 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9276 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9277 true, GSI_SAME_STMT);
9278 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9279 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9280 true, GSI_SAME_STMT);
9281 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9282 NULL_TREE, NULL_TREE);
9283 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9284 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9285 expand_omp_regimplify_p, NULL, NULL)
9286 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9287 expand_omp_regimplify_p, NULL, NULL))
9289 gsi = gsi_for_stmt (cond_stmt);
9290 gimple_regimplify_operands (cond_stmt, &gsi);
9292 se = split_block (entry_bb, cond_stmt);
9293 se->flags = EDGE_TRUE_VALUE;
9294 entry_bb = se->dest;
9295 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9296 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9297 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9298 if (gimple_in_ssa_p (cfun))
9300 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9301 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9302 !gsi_end_p (gpi); gsi_next (&gpi))
9304 gphi *phi = gpi.phi ();
9305 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9306 se, UNKNOWN_LOCATION);
9309 gsi = gsi_last_bb (entry_bb);
9312 switch (gimple_omp_for_kind (fd->for_stmt))
9314 case GF_OMP_FOR_KIND_FOR:
9315 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9316 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9317 break;
9318 case GF_OMP_FOR_KIND_DISTRIBUTE:
9319 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9320 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9321 break;
9322 default:
9323 gcc_unreachable ();
9325 nthreads = build_call_expr (nthreads, 0);
9326 nthreads = fold_convert (itype, nthreads);
9327 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9328 true, GSI_SAME_STMT);
9329 threadid = build_call_expr (threadid, 0);
9330 threadid = fold_convert (itype, threadid);
9331 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9332 true, GSI_SAME_STMT);
9334 n1 = fd->loop.n1;
9335 n2 = fd->loop.n2;
9336 step = fd->loop.step;
9337 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9339 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9340 OMP_CLAUSE__LOOPTEMP_);
9341 gcc_assert (innerc);
9342 n1 = OMP_CLAUSE_DECL (innerc);
9343 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9344 OMP_CLAUSE__LOOPTEMP_);
9345 gcc_assert (innerc);
9346 n2 = OMP_CLAUSE_DECL (innerc);
9348 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9349 true, NULL_TREE, true, GSI_SAME_STMT);
9350 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9351 true, NULL_TREE, true, GSI_SAME_STMT);
9352 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9353 true, NULL_TREE, true, GSI_SAME_STMT);
9354 tree chunk_size = fold_convert (itype, fd->chunk_size);
9355 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9356 chunk_size
9357 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9358 GSI_SAME_STMT);
9360 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9361 t = fold_build2 (PLUS_EXPR, itype, step, t);
9362 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9363 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9364 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9365 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9366 fold_build1 (NEGATE_EXPR, itype, t),
9367 fold_build1 (NEGATE_EXPR, itype, step));
9368 else
9369 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9370 t = fold_convert (itype, t);
9371 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9372 true, GSI_SAME_STMT);
9374 trip_var = create_tmp_reg (itype, ".trip");
9375 if (gimple_in_ssa_p (cfun))
9377 trip_init = make_ssa_name (trip_var);
9378 trip_main = make_ssa_name (trip_var);
9379 trip_back = make_ssa_name (trip_var);
9381 else
9383 trip_init = trip_var;
9384 trip_main = trip_var;
9385 trip_back = trip_var;
9388 gassign *assign_stmt
9389 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9390 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9392 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9393 t = fold_build2 (MULT_EXPR, itype, t, step);
9394 if (POINTER_TYPE_P (type))
9395 t = fold_build_pointer_plus (n1, t);
9396 else
9397 t = fold_build2 (PLUS_EXPR, type, t, n1);
9398 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9399 true, GSI_SAME_STMT);
9401 /* Remove the GIMPLE_OMP_FOR. */
9402 gsi_remove (&gsi, true);
9404 gimple_stmt_iterator gsif = gsi;
9406 /* Iteration space partitioning goes in ITER_PART_BB. */
9407 gsi = gsi_last_bb (iter_part_bb);
9409 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9410 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9411 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9412 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9413 false, GSI_CONTINUE_LINKING);
9415 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9416 t = fold_build2 (MIN_EXPR, itype, t, n);
9417 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9418 false, GSI_CONTINUE_LINKING);
9420 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9421 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9423 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9424 gsi = gsi_start_bb (seq_start_bb);
9426 tree startvar = fd->loop.v;
9427 tree endvar = NULL_TREE;
9429 if (gimple_omp_for_combined_p (fd->for_stmt))
9431 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9432 ? gimple_omp_parallel_clauses (inner_stmt)
9433 : gimple_omp_for_clauses (inner_stmt);
9434 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9435 gcc_assert (innerc);
9436 startvar = OMP_CLAUSE_DECL (innerc);
9437 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9438 OMP_CLAUSE__LOOPTEMP_);
9439 gcc_assert (innerc);
9440 endvar = OMP_CLAUSE_DECL (innerc);
9443 t = fold_convert (itype, s0);
9444 t = fold_build2 (MULT_EXPR, itype, t, step);
9445 if (POINTER_TYPE_P (type))
9446 t = fold_build_pointer_plus (n1, t);
9447 else
9448 t = fold_build2 (PLUS_EXPR, type, t, n1);
9449 t = fold_convert (TREE_TYPE (startvar), t);
9450 t = force_gimple_operand_gsi (&gsi, t,
9451 DECL_P (startvar)
9452 && TREE_ADDRESSABLE (startvar),
9453 NULL_TREE, false, GSI_CONTINUE_LINKING);
9454 assign_stmt = gimple_build_assign (startvar, t);
9455 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9457 t = fold_convert (itype, e0);
9458 t = fold_build2 (MULT_EXPR, itype, t, step);
9459 if (POINTER_TYPE_P (type))
9460 t = fold_build_pointer_plus (n1, t);
9461 else
9462 t = fold_build2 (PLUS_EXPR, type, t, n1);
9463 t = fold_convert (TREE_TYPE (startvar), t);
9464 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9465 false, GSI_CONTINUE_LINKING);
9466 if (endvar)
9468 assign_stmt = gimple_build_assign (endvar, e);
9469 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9470 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9471 assign_stmt = gimple_build_assign (fd->loop.v, e);
9472 else
9473 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9474 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9476 /* Handle linear clause adjustments. */
9477 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9478 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9479 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9480 c; c = OMP_CLAUSE_CHAIN (c))
9481 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9482 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9484 tree d = OMP_CLAUSE_DECL (c);
9485 bool is_ref = is_reference (d);
9486 tree t = d, a, dest;
9487 if (is_ref)
9488 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9489 tree type = TREE_TYPE (t);
9490 if (POINTER_TYPE_P (type))
9491 type = sizetype;
9492 dest = unshare_expr (t);
9493 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9494 expand_omp_build_assign (&gsif, v, t);
9495 if (itercnt == NULL_TREE)
9497 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9499 itercntbias
9500 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9501 fold_convert (itype, fd->loop.n1));
9502 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9503 itercntbias, step);
9504 itercntbias
9505 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9506 NULL_TREE, true,
9507 GSI_SAME_STMT);
9508 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9509 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9510 NULL_TREE, false,
9511 GSI_CONTINUE_LINKING);
9513 else
9514 itercnt = s0;
9516 a = fold_build2 (MULT_EXPR, type,
9517 fold_convert (type, itercnt),
9518 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9519 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9520 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9521 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9522 false, GSI_CONTINUE_LINKING);
9523 assign_stmt = gimple_build_assign (dest, t);
9524 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9526 if (fd->collapse > 1)
9527 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9529 if (!broken_loop)
9531 /* The code controlling the sequential loop goes in CONT_BB,
9532 replacing the GIMPLE_OMP_CONTINUE. */
9533 gsi = gsi_last_bb (cont_bb);
9534 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9535 vmain = gimple_omp_continue_control_use (cont_stmt);
9536 vback = gimple_omp_continue_control_def (cont_stmt);
9538 if (!gimple_omp_for_combined_p (fd->for_stmt))
9540 if (POINTER_TYPE_P (type))
9541 t = fold_build_pointer_plus (vmain, step);
9542 else
9543 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9544 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9545 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9546 true, GSI_SAME_STMT);
9547 assign_stmt = gimple_build_assign (vback, t);
9548 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9550 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9551 t = build2 (EQ_EXPR, boolean_type_node,
9552 build_int_cst (itype, 0),
9553 build_int_cst (itype, 1));
9554 else
9555 t = build2 (fd->loop.cond_code, boolean_type_node,
9556 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9557 ? t : vback, e);
9558 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9561 /* Remove GIMPLE_OMP_CONTINUE. */
9562 gsi_remove (&gsi, true);
9564 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9565 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9567 /* Trip update code goes into TRIP_UPDATE_BB. */
9568 gsi = gsi_start_bb (trip_update_bb);
9570 t = build_int_cst (itype, 1);
9571 t = build2 (PLUS_EXPR, itype, trip_main, t);
9572 assign_stmt = gimple_build_assign (trip_back, t);
9573 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9576 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9577 gsi = gsi_last_bb (exit_bb);
9578 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9580 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9581 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9583 gsi_remove (&gsi, true);
9585 /* Connect the new blocks. */
9586 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9587 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
9589 if (!broken_loop)
9591 se = find_edge (cont_bb, body_bb);
9592 if (se == NULL)
9594 se = BRANCH_EDGE (cont_bb);
9595 gcc_assert (single_succ (se->dest) == body_bb);
9597 if (gimple_omp_for_combined_p (fd->for_stmt))
9599 remove_edge (se);
9600 se = NULL;
9602 else if (fd->collapse > 1)
9604 remove_edge (se);
9605 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9607 else
9608 se->flags = EDGE_TRUE_VALUE;
9609 find_edge (cont_bb, trip_update_bb)->flags
9610 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9612 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9615 if (gimple_in_ssa_p (cfun))
9617 gphi_iterator psi;
9618 gphi *phi;
9619 edge re, ene;
9620 edge_var_map *vm;
9621 size_t i;
9623 gcc_assert (fd->collapse == 1 && !broken_loop);
9625 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9626 remove arguments of the phi nodes in fin_bb. We need to create
9627 appropriate phi nodes in iter_part_bb instead. */
9628 se = find_edge (iter_part_bb, fin_bb);
9629 re = single_succ_edge (trip_update_bb);
9630 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
9631 ene = single_succ_edge (entry_bb);
9633 psi = gsi_start_phis (fin_bb);
9634 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
9635 gsi_next (&psi), ++i)
9637 gphi *nphi;
9638 source_location locus;
9640 phi = psi.phi ();
9641 t = gimple_phi_result (phi);
9642 gcc_assert (t == redirect_edge_var_map_result (vm));
9644 if (!single_pred_p (fin_bb))
9645 t = copy_ssa_name (t, phi);
9647 nphi = create_phi_node (t, iter_part_bb);
9649 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
9650 locus = gimple_phi_arg_location_from_edge (phi, se);
9652 /* A special case -- fd->loop.v is not yet computed in
9653 iter_part_bb, we need to use vextra instead. */
9654 if (t == fd->loop.v)
9655 t = vextra;
9656 add_phi_arg (nphi, t, ene, locus);
9657 locus = redirect_edge_var_map_location (vm);
9658 tree back_arg = redirect_edge_var_map_def (vm);
9659 add_phi_arg (nphi, back_arg, re, locus);
9660 edge ce = find_edge (cont_bb, body_bb);
9661 if (ce == NULL)
9663 ce = BRANCH_EDGE (cont_bb);
9664 gcc_assert (single_succ (ce->dest) == body_bb);
9665 ce = single_succ_edge (ce->dest);
9667 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9668 gcc_assert (inner_loop_phi != NULL);
9669 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9670 find_edge (seq_start_bb, body_bb), locus);
9672 if (!single_pred_p (fin_bb))
9673 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
9675 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
9676 redirect_edge_var_map_clear (re);
9677 if (single_pred_p (fin_bb))
9678 while (1)
9680 psi = gsi_start_phis (fin_bb);
9681 if (gsi_end_p (psi))
9682 break;
9683 remove_phi_node (&psi, false);
9686 /* Make phi node for trip. */
9687 phi = create_phi_node (trip_main, iter_part_bb);
9688 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9689 UNKNOWN_LOCATION);
9690 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9691 UNKNOWN_LOCATION);
9694 if (!broken_loop)
9695 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
9696 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9697 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9698 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9699 recompute_dominator (CDI_DOMINATORS, fin_bb));
9700 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9701 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9702 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9703 recompute_dominator (CDI_DOMINATORS, body_bb));
9705 if (!broken_loop)
9707 struct loop *loop = body_bb->loop_father;
9708 struct loop *trip_loop = alloc_loop ();
9709 trip_loop->header = iter_part_bb;
9710 trip_loop->latch = trip_update_bb;
9711 add_loop (trip_loop, iter_part_bb->loop_father);
9713 if (loop != entry_bb->loop_father)
9715 gcc_assert (loop->header == body_bb);
9716 gcc_assert (loop->latch == region->cont
9717 || single_pred (loop->latch) == region->cont);
9718 trip_loop->inner = loop;
9719 return;
9722 if (!gimple_omp_for_combined_p (fd->for_stmt))
9724 loop = alloc_loop ();
9725 loop->header = body_bb;
9726 if (collapse_bb == NULL)
9727 loop->latch = cont_bb;
9728 add_loop (loop, trip_loop);
9733 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9734 Given parameters:
9735 for (V = N1; V cond N2; V += STEP) BODY;
9737 where COND is "<" or ">" or "!=", we generate pseudocode
9739 for (ind_var = low; ind_var < high; ind_var++)
9741 V = n1 + (ind_var * STEP)
9743 <BODY>
9746 In the above pseudocode, low and high are function parameters of the
9747 child function. In the function below, we are inserting a temp.
9748 variable that will be making a call to two OMP functions that will not be
9749 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9750 with _Cilk_for). These functions are replaced with low and high
9751 by the function that handles taskreg. */
9754 static void
9755 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9757 bool broken_loop = region->cont == NULL;
9758 basic_block entry_bb = region->entry;
9759 basic_block cont_bb = region->cont;
9761 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9762 gcc_assert (broken_loop
9763 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
9764 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
9765 basic_block l1_bb, l2_bb;
9767 if (!broken_loop)
9769 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
9770 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9771 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
9772 l2_bb = BRANCH_EDGE (entry_bb)->dest;
9774 else
9776 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
9777 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
9778 l2_bb = single_succ (l1_bb);
9780 basic_block exit_bb = region->exit;
9781 basic_block l2_dom_bb = NULL;
9783 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
9785 /* Below statements until the "tree high_val = ..." are pseudo statements
9786 used to pass information to be used by expand_omp_taskreg.
9787 low_val and high_val will be replaced by the __low and __high
9788 parameter from the child function.
9790 The call_exprs part is a place-holder, it is mainly used
9791 to distinctly identify to the top-level part that this is
9792 where we should put low and high (reasoning given in header
9793 comment). */
9795 tree child_fndecl
9796 = gimple_omp_parallel_child_fn (
9797 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
9798 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
9799 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
9801 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
9802 high_val = t;
9803 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
9804 low_val = t;
9806 gcc_assert (low_val && high_val);
9808 tree type = TREE_TYPE (low_val);
9809 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
9810 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9812 /* Not needed in SSA form right now. */
9813 gcc_assert (!gimple_in_ssa_p (cfun));
9814 if (l2_dom_bb == NULL)
9815 l2_dom_bb = l1_bb;
9817 tree n1 = low_val;
9818 tree n2 = high_val;
9820 gimple *stmt = gimple_build_assign (ind_var, n1);
9822 /* Replace the GIMPLE_OMP_FOR statement. */
9823 gsi_replace (&gsi, stmt, true);
9825 if (!broken_loop)
9827 /* Code to control the increment goes in the CONT_BB. */
9828 gsi = gsi_last_bb (cont_bb);
9829 stmt = gsi_stmt (gsi);
9830 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
9831 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
9832 build_one_cst (type));
9834 /* Replace GIMPLE_OMP_CONTINUE. */
9835 gsi_replace (&gsi, stmt, true);
9838 /* Emit the condition in L1_BB. */
9839 gsi = gsi_after_labels (l1_bb);
9840 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
9841 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
9842 fd->loop.step);
9843 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
9844 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9845 fd->loop.n1, fold_convert (sizetype, t));
9846 else
9847 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9848 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
9849 t = fold_convert (TREE_TYPE (fd->loop.v), t);
9850 expand_omp_build_assign (&gsi, fd->loop.v, t);
9852 /* The condition is always '<' since the runtime will fill in the low
9853 and high values. */
9854 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
9855 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
9857 /* Remove GIMPLE_OMP_RETURN. */
9858 gsi = gsi_last_bb (exit_bb);
9859 gsi_remove (&gsi, true);
9861 /* Connect the new blocks. */
9862 remove_edge (FALLTHRU_EDGE (entry_bb));
9864 edge e, ne;
9865 if (!broken_loop)
9867 remove_edge (BRANCH_EDGE (entry_bb));
9868 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
9870 e = BRANCH_EDGE (l1_bb);
9871 ne = FALLTHRU_EDGE (l1_bb);
9872 e->flags = EDGE_TRUE_VALUE;
9874 else
9876 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9878 ne = single_succ_edge (l1_bb);
9879 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
9882 ne->flags = EDGE_FALSE_VALUE;
9883 e->probability = REG_BR_PROB_BASE * 7 / 8;
9884 ne->probability = REG_BR_PROB_BASE / 8;
9886 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
9887 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
9888 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
9890 if (!broken_loop)
9892 struct loop *loop = alloc_loop ();
9893 loop->header = l1_bb;
9894 loop->latch = cont_bb;
9895 add_loop (loop, l1_bb->loop_father);
9896 loop->safelen = INT_MAX;
9899 /* Pick the correct library function based on the precision of the
9900 induction variable type. */
9901 tree lib_fun = NULL_TREE;
9902 if (TYPE_PRECISION (type) == 32)
9903 lib_fun = cilk_for_32_fndecl;
9904 else if (TYPE_PRECISION (type) == 64)
9905 lib_fun = cilk_for_64_fndecl;
9906 else
9907 gcc_unreachable ();
9909 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
9911 /* WS_ARGS contains the library function flavor to call:
9912 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
9913 user-defined grain value. If the user does not define one, then zero
9914 is passed in by the parser. */
9915 vec_alloc (region->ws_args, 2);
9916 region->ws_args->quick_push (lib_fun);
9917 region->ws_args->quick_push (fd->chunk_size);
9920 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
9921 loop. Given parameters:
9923 for (V = N1; V cond N2; V += STEP) BODY;
9925 where COND is "<" or ">", we generate pseudocode
9927 V = N1;
9928 goto L1;
9930 BODY;
9931 V += STEP;
9933 if (V cond N2) goto L0; else goto L2;
9936 For collapsed loops, given parameters:
9937 collapse(3)
9938 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
9939 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
9940 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
9941 BODY;
9943 we generate pseudocode
9945 if (cond3 is <)
9946 adj = STEP3 - 1;
9947 else
9948 adj = STEP3 + 1;
9949 count3 = (adj + N32 - N31) / STEP3;
9950 if (cond2 is <)
9951 adj = STEP2 - 1;
9952 else
9953 adj = STEP2 + 1;
9954 count2 = (adj + N22 - N21) / STEP2;
9955 if (cond1 is <)
9956 adj = STEP1 - 1;
9957 else
9958 adj = STEP1 + 1;
9959 count1 = (adj + N12 - N11) / STEP1;
9960 count = count1 * count2 * count3;
9961 V = 0;
9962 V1 = N11;
9963 V2 = N21;
9964 V3 = N31;
9965 goto L1;
9967 BODY;
9968 V += 1;
9969 V3 += STEP3;
9970 V2 += (V3 cond3 N32) ? 0 : STEP2;
9971 V3 = (V3 cond3 N32) ? V3 : N31;
9972 V1 += (V2 cond2 N22) ? 0 : STEP1;
9973 V2 = (V2 cond2 N22) ? V2 : N21;
9975 if (V < count) goto L0; else goto L2;
9980 static void
9981 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
9983 tree type, t;
9984 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
9985 gimple_stmt_iterator gsi;
9986 gimple *stmt;
9987 gcond *cond_stmt;
9988 bool broken_loop = region->cont == NULL;
9989 edge e, ne;
9990 tree *counts = NULL;
9991 int i;
9992 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9993 OMP_CLAUSE_SAFELEN);
9994 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9995 OMP_CLAUSE__SIMDUID_);
9996 tree n1, n2;
9998 type = TREE_TYPE (fd->loop.v);
9999 entry_bb = region->entry;
10000 cont_bb = region->cont;
10001 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10002 gcc_assert (broken_loop
10003 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10004 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10005 if (!broken_loop)
10007 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10008 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10009 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10010 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10012 else
10014 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10015 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10016 l2_bb = single_succ (l1_bb);
10018 exit_bb = region->exit;
10019 l2_dom_bb = NULL;
10021 gsi = gsi_last_bb (entry_bb);
10023 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10024 /* Not needed in SSA form right now. */
10025 gcc_assert (!gimple_in_ssa_p (cfun));
10026 if (fd->collapse > 1)
10028 int first_zero_iter = -1, dummy = -1;
10029 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10031 counts = XALLOCAVEC (tree, fd->collapse);
10032 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10033 zero_iter_bb, first_zero_iter,
10034 dummy_bb, dummy, l2_dom_bb);
10036 if (l2_dom_bb == NULL)
10037 l2_dom_bb = l1_bb;
10039 n1 = fd->loop.n1;
10040 n2 = fd->loop.n2;
10041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10044 OMP_CLAUSE__LOOPTEMP_);
10045 gcc_assert (innerc);
10046 n1 = OMP_CLAUSE_DECL (innerc);
10047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10048 OMP_CLAUSE__LOOPTEMP_);
10049 gcc_assert (innerc);
10050 n2 = OMP_CLAUSE_DECL (innerc);
10051 expand_omp_build_assign (&gsi, fd->loop.v,
10052 fold_convert (type, n1));
10053 if (fd->collapse > 1)
10055 gsi_prev (&gsi);
10056 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10057 gsi_next (&gsi);
10060 else
10062 expand_omp_build_assign (&gsi, fd->loop.v,
10063 fold_convert (type, fd->loop.n1));
10064 if (fd->collapse > 1)
10065 for (i = 0; i < fd->collapse; i++)
10067 tree itype = TREE_TYPE (fd->loops[i].v);
10068 if (POINTER_TYPE_P (itype))
10069 itype = signed_type_for (itype);
10070 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10071 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10075 /* Remove the GIMPLE_OMP_FOR statement. */
10076 gsi_remove (&gsi, true);
10078 if (!broken_loop)
10080 /* Code to control the increment goes in the CONT_BB. */
10081 gsi = gsi_last_bb (cont_bb);
10082 stmt = gsi_stmt (gsi);
10083 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10085 if (POINTER_TYPE_P (type))
10086 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10087 else
10088 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10089 expand_omp_build_assign (&gsi, fd->loop.v, t);
10091 if (fd->collapse > 1)
10093 i = fd->collapse - 1;
10094 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10096 t = fold_convert (sizetype, fd->loops[i].step);
10097 t = fold_build_pointer_plus (fd->loops[i].v, t);
10099 else
10101 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10102 fd->loops[i].step);
10103 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10104 fd->loops[i].v, t);
10106 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10108 for (i = fd->collapse - 1; i > 0; i--)
10110 tree itype = TREE_TYPE (fd->loops[i].v);
10111 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10112 if (POINTER_TYPE_P (itype2))
10113 itype2 = signed_type_for (itype2);
10114 t = build3 (COND_EXPR, itype2,
10115 build2 (fd->loops[i].cond_code, boolean_type_node,
10116 fd->loops[i].v,
10117 fold_convert (itype, fd->loops[i].n2)),
10118 build_int_cst (itype2, 0),
10119 fold_convert (itype2, fd->loops[i - 1].step));
10120 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10121 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10122 else
10123 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10124 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10126 t = build3 (COND_EXPR, itype,
10127 build2 (fd->loops[i].cond_code, boolean_type_node,
10128 fd->loops[i].v,
10129 fold_convert (itype, fd->loops[i].n2)),
10130 fd->loops[i].v,
10131 fold_convert (itype, fd->loops[i].n1));
10132 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10136 /* Remove GIMPLE_OMP_CONTINUE. */
10137 gsi_remove (&gsi, true);
10140 /* Emit the condition in L1_BB. */
10141 gsi = gsi_start_bb (l1_bb);
10143 t = fold_convert (type, n2);
10144 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10145 false, GSI_CONTINUE_LINKING);
10146 tree v = fd->loop.v;
10147 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10148 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10149 false, GSI_CONTINUE_LINKING);
10150 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10151 cond_stmt = gimple_build_cond_empty (t);
10152 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10153 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10154 NULL, NULL)
10155 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10156 NULL, NULL))
10158 gsi = gsi_for_stmt (cond_stmt);
10159 gimple_regimplify_operands (cond_stmt, &gsi);
10162 /* Remove GIMPLE_OMP_RETURN. */
10163 gsi = gsi_last_bb (exit_bb);
10164 gsi_remove (&gsi, true);
10166 /* Connect the new blocks. */
10167 remove_edge (FALLTHRU_EDGE (entry_bb));
10169 if (!broken_loop)
10171 remove_edge (BRANCH_EDGE (entry_bb));
10172 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10174 e = BRANCH_EDGE (l1_bb);
10175 ne = FALLTHRU_EDGE (l1_bb);
10176 e->flags = EDGE_TRUE_VALUE;
10178 else
10180 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10182 ne = single_succ_edge (l1_bb);
10183 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10186 ne->flags = EDGE_FALSE_VALUE;
10187 e->probability = REG_BR_PROB_BASE * 7 / 8;
10188 ne->probability = REG_BR_PROB_BASE / 8;
10190 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10191 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10192 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10194 if (!broken_loop)
10196 struct loop *loop = alloc_loop ();
10197 loop->header = l1_bb;
10198 loop->latch = cont_bb;
10199 add_loop (loop, l1_bb->loop_father);
10200 if (safelen == NULL_TREE)
10201 loop->safelen = INT_MAX;
10202 else
10204 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10205 if (TREE_CODE (safelen) != INTEGER_CST)
10206 loop->safelen = 0;
10207 else if (!tree_fits_uhwi_p (safelen)
10208 || tree_to_uhwi (safelen) > INT_MAX)
10209 loop->safelen = INT_MAX;
10210 else
10211 loop->safelen = tree_to_uhwi (safelen);
10212 if (loop->safelen == 1)
10213 loop->safelen = 0;
10215 if (simduid)
10217 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10218 cfun->has_simduid_loops = true;
10220 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10221 the loop. */
10222 if ((flag_tree_loop_vectorize
10223 || (!global_options_set.x_flag_tree_loop_vectorize
10224 && !global_options_set.x_flag_tree_vectorize))
10225 && flag_tree_loop_optimize
10226 && loop->safelen > 1)
10228 loop->force_vectorize = true;
10229 cfun->has_force_vectorize_loops = true;
10232 else if (simduid)
10233 cfun->has_simduid_loops = true;
10236 /* Taskloop construct is represented after gimplification with
10237 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10238 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10239 which should just compute all the needed loop temporaries
10240 for GIMPLE_OMP_TASK. */
10242 static void
10243 expand_omp_taskloop_for_outer (struct omp_region *region,
10244 struct omp_for_data *fd,
10245 gimple *inner_stmt)
10247 tree type, bias = NULL_TREE;
10248 basic_block entry_bb, cont_bb, exit_bb;
10249 gimple_stmt_iterator gsi;
10250 gassign *assign_stmt;
10251 tree *counts = NULL;
10252 int i;
10254 gcc_assert (inner_stmt);
10255 gcc_assert (region->cont);
10256 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10257 && gimple_omp_task_taskloop_p (inner_stmt));
10258 type = TREE_TYPE (fd->loop.v);
10260 /* See if we need to bias by LLONG_MIN. */
10261 if (fd->iter_type == long_long_unsigned_type_node
10262 && TREE_CODE (type) == INTEGER_TYPE
10263 && !TYPE_UNSIGNED (type))
10265 tree n1, n2;
10267 if (fd->loop.cond_code == LT_EXPR)
10269 n1 = fd->loop.n1;
10270 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10272 else
10274 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10275 n2 = fd->loop.n1;
10277 if (TREE_CODE (n1) != INTEGER_CST
10278 || TREE_CODE (n2) != INTEGER_CST
10279 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10280 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10283 entry_bb = region->entry;
10284 cont_bb = region->cont;
10285 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10286 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10287 exit_bb = region->exit;
10289 gsi = gsi_last_bb (entry_bb);
10290 gimple *for_stmt = gsi_stmt (gsi);
10291 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10292 if (fd->collapse > 1)
10294 int first_zero_iter = -1, dummy = -1;
10295 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10297 counts = XALLOCAVEC (tree, fd->collapse);
10298 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10299 zero_iter_bb, first_zero_iter,
10300 dummy_bb, dummy, l2_dom_bb);
10302 if (zero_iter_bb)
10304 /* Some counts[i] vars might be uninitialized if
10305 some loop has zero iterations. But the body shouldn't
10306 be executed in that case, so just avoid uninit warnings. */
10307 for (i = first_zero_iter; i < fd->collapse; i++)
10308 if (SSA_VAR_P (counts[i]))
10309 TREE_NO_WARNING (counts[i]) = 1;
10310 gsi_prev (&gsi);
10311 edge e = split_block (entry_bb, gsi_stmt (gsi));
10312 entry_bb = e->dest;
10313 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10314 gsi = gsi_last_bb (entry_bb);
10315 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10316 get_immediate_dominator (CDI_DOMINATORS,
10317 zero_iter_bb));
10321 tree t0, t1;
10322 t1 = fd->loop.n2;
10323 t0 = fd->loop.n1;
10324 if (POINTER_TYPE_P (TREE_TYPE (t0))
10325 && TYPE_PRECISION (TREE_TYPE (t0))
10326 != TYPE_PRECISION (fd->iter_type))
10328 /* Avoid casting pointers to integer of a different size. */
10329 tree itype = signed_type_for (type);
10330 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10331 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10333 else
10335 t1 = fold_convert (fd->iter_type, t1);
10336 t0 = fold_convert (fd->iter_type, t0);
10338 if (bias)
10340 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10341 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10344 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10345 OMP_CLAUSE__LOOPTEMP_);
10346 gcc_assert (innerc);
10347 tree startvar = OMP_CLAUSE_DECL (innerc);
10348 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10349 gcc_assert (innerc);
10350 tree endvar = OMP_CLAUSE_DECL (innerc);
10351 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10353 gcc_assert (innerc);
10354 for (i = 1; i < fd->collapse; i++)
10356 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10357 OMP_CLAUSE__LOOPTEMP_);
10358 gcc_assert (innerc);
10360 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10361 OMP_CLAUSE__LOOPTEMP_);
10362 if (innerc)
10364 /* If needed (inner taskloop has lastprivate clause), propagate
10365 down the total number of iterations. */
10366 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10367 NULL_TREE, false,
10368 GSI_CONTINUE_LINKING);
10369 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10370 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10374 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10375 GSI_CONTINUE_LINKING);
10376 assign_stmt = gimple_build_assign (startvar, t0);
10377 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10379 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10380 GSI_CONTINUE_LINKING);
10381 assign_stmt = gimple_build_assign (endvar, t1);
10382 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10383 if (fd->collapse > 1)
10384 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10386 /* Remove the GIMPLE_OMP_FOR statement. */
10387 gsi = gsi_for_stmt (for_stmt);
10388 gsi_remove (&gsi, true);
10390 gsi = gsi_last_bb (cont_bb);
10391 gsi_remove (&gsi, true);
10393 gsi = gsi_last_bb (exit_bb);
10394 gsi_remove (&gsi, true);
10396 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10397 remove_edge (BRANCH_EDGE (entry_bb));
10398 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10399 remove_edge (BRANCH_EDGE (cont_bb));
10400 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10401 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10402 recompute_dominator (CDI_DOMINATORS, region->entry));
10405 /* Taskloop construct is represented after gimplification with
10406 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10407 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10408 GOMP_taskloop{,_ull} function arranges for each task to be given just
10409 a single range of iterations. */
10411 static void
10412 expand_omp_taskloop_for_inner (struct omp_region *region,
10413 struct omp_for_data *fd,
10414 gimple *inner_stmt)
10416 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10417 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10418 basic_block fin_bb;
10419 gimple_stmt_iterator gsi;
10420 edge ep;
10421 bool broken_loop = region->cont == NULL;
10422 tree *counts = NULL;
10423 tree n1, n2, step;
10425 itype = type = TREE_TYPE (fd->loop.v);
10426 if (POINTER_TYPE_P (type))
10427 itype = signed_type_for (type);
10429 /* See if we need to bias by LLONG_MIN. */
10430 if (fd->iter_type == long_long_unsigned_type_node
10431 && TREE_CODE (type) == INTEGER_TYPE
10432 && !TYPE_UNSIGNED (type))
10434 tree n1, n2;
10436 if (fd->loop.cond_code == LT_EXPR)
10438 n1 = fd->loop.n1;
10439 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10441 else
10443 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10444 n2 = fd->loop.n1;
10446 if (TREE_CODE (n1) != INTEGER_CST
10447 || TREE_CODE (n2) != INTEGER_CST
10448 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10449 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10452 entry_bb = region->entry;
10453 cont_bb = region->cont;
10454 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10455 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10456 gcc_assert (broken_loop
10457 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10458 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10459 if (!broken_loop)
10461 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10462 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10464 exit_bb = region->exit;
10466 /* Iteration space partitioning goes in ENTRY_BB. */
10467 gsi = gsi_last_bb (entry_bb);
10468 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10470 if (fd->collapse > 1)
10472 int first_zero_iter = -1, dummy = -1;
10473 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10475 counts = XALLOCAVEC (tree, fd->collapse);
10476 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10477 fin_bb, first_zero_iter,
10478 dummy_bb, dummy, l2_dom_bb);
10479 t = NULL_TREE;
10481 else
10482 t = integer_one_node;
10484 step = fd->loop.step;
10485 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10486 OMP_CLAUSE__LOOPTEMP_);
10487 gcc_assert (innerc);
10488 n1 = OMP_CLAUSE_DECL (innerc);
10489 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10490 gcc_assert (innerc);
10491 n2 = OMP_CLAUSE_DECL (innerc);
10492 if (bias)
10494 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10495 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10497 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10498 true, NULL_TREE, true, GSI_SAME_STMT);
10499 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10500 true, NULL_TREE, true, GSI_SAME_STMT);
10501 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10502 true, NULL_TREE, true, GSI_SAME_STMT);
10504 tree startvar = fd->loop.v;
10505 tree endvar = NULL_TREE;
10507 if (gimple_omp_for_combined_p (fd->for_stmt))
10509 tree clauses = gimple_omp_for_clauses (inner_stmt);
10510 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10511 gcc_assert (innerc);
10512 startvar = OMP_CLAUSE_DECL (innerc);
10513 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10514 OMP_CLAUSE__LOOPTEMP_);
10515 gcc_assert (innerc);
10516 endvar = OMP_CLAUSE_DECL (innerc);
10518 t = fold_convert (TREE_TYPE (startvar), n1);
10519 t = force_gimple_operand_gsi (&gsi, t,
10520 DECL_P (startvar)
10521 && TREE_ADDRESSABLE (startvar),
10522 NULL_TREE, false, GSI_CONTINUE_LINKING);
10523 gimple *assign_stmt = gimple_build_assign (startvar, t);
10524 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10526 t = fold_convert (TREE_TYPE (startvar), n2);
10527 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10528 false, GSI_CONTINUE_LINKING);
10529 if (endvar)
10531 assign_stmt = gimple_build_assign (endvar, e);
10532 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10533 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10534 assign_stmt = gimple_build_assign (fd->loop.v, e);
10535 else
10536 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10537 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10539 if (fd->collapse > 1)
10540 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10542 if (!broken_loop)
10544 /* The code controlling the sequential loop replaces the
10545 GIMPLE_OMP_CONTINUE. */
10546 gsi = gsi_last_bb (cont_bb);
10547 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10548 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10549 vmain = gimple_omp_continue_control_use (cont_stmt);
10550 vback = gimple_omp_continue_control_def (cont_stmt);
10552 if (!gimple_omp_for_combined_p (fd->for_stmt))
10554 if (POINTER_TYPE_P (type))
10555 t = fold_build_pointer_plus (vmain, step);
10556 else
10557 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10558 t = force_gimple_operand_gsi (&gsi, t,
10559 DECL_P (vback)
10560 && TREE_ADDRESSABLE (vback),
10561 NULL_TREE, true, GSI_SAME_STMT);
10562 assign_stmt = gimple_build_assign (vback, t);
10563 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10565 t = build2 (fd->loop.cond_code, boolean_type_node,
10566 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10567 ? t : vback, e);
10568 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10571 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10572 gsi_remove (&gsi, true);
10574 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10575 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10578 /* Remove the GIMPLE_OMP_FOR statement. */
10579 gsi = gsi_for_stmt (fd->for_stmt);
10580 gsi_remove (&gsi, true);
10582 /* Remove the GIMPLE_OMP_RETURN statement. */
10583 gsi = gsi_last_bb (exit_bb);
10584 gsi_remove (&gsi, true);
10586 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10587 if (!broken_loop)
10588 remove_edge (BRANCH_EDGE (entry_bb));
10589 else
10591 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10592 region->outer->cont = NULL;
10595 /* Connect all the blocks. */
10596 if (!broken_loop)
10598 ep = find_edge (cont_bb, body_bb);
10599 if (gimple_omp_for_combined_p (fd->for_stmt))
10601 remove_edge (ep);
10602 ep = NULL;
10604 else if (fd->collapse > 1)
10606 remove_edge (ep);
10607 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10609 else
10610 ep->flags = EDGE_TRUE_VALUE;
10611 find_edge (cont_bb, fin_bb)->flags
10612 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10615 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10616 recompute_dominator (CDI_DOMINATORS, body_bb));
10617 if (!broken_loop)
10618 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10619 recompute_dominator (CDI_DOMINATORS, fin_bb));
10621 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10623 struct loop *loop = alloc_loop ();
10624 loop->header = body_bb;
10625 if (collapse_bb == NULL)
10626 loop->latch = cont_bb;
10627 add_loop (loop, body_bb->loop_father);
10631 /* A subroutine of expand_omp_for. Generate code for an OpenACC
10632 partitioned loop. The lowering here is abstracted, in that the
10633 loop parameters are passed through internal functions, which are
10634 further lowered by oacc_device_lower, once we get to the target
10635 compiler. The loop is of the form:
10637 for (V = B; V LTGT E; V += S) {BODY}
10639 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10640 (constant 0 for no chunking) and we will have a GWV partitioning
10641 mask, specifying dimensions over which the loop is to be
10642 partitioned (see note below). We generate code that looks like:
10644 <entry_bb> [incoming FALL->body, BRANCH->exit]
10645 typedef signedintify (typeof (V)) T; // underlying signed integral type
10646 T range = E - B;
10647 T chunk_no = 0;
10648 T DIR = LTGT == '<' ? +1 : -1;
10649 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10650 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10652 <head_bb> [created by splitting end of entry_bb]
10653 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10654 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10655 if (!(offset LTGT bound)) goto bottom_bb;
10657 <body_bb> [incoming]
10658 V = B + offset;
10659 {BODY}
10661 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10662 offset += step;
10663 if (offset LTGT bound) goto body_bb; [*]
10665 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
10666 chunk_no++;
10667 if (chunk < chunk_max) goto head_bb;
10669 <exit_bb> [incoming]
10670 V = B + ((range -/+ 1) / S +/- 1) * S [*]
10672 [*] Needed if V live at end of loop
10674 Note: CHUNKING & GWV mask are specified explicitly here. This is a
10675 transition, and will be specified by a more general mechanism shortly.
10678 static void
10679 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
10681 tree v = fd->loop.v;
10682 enum tree_code cond_code = fd->loop.cond_code;
10683 enum tree_code plus_code = PLUS_EXPR;
10685 tree chunk_size = integer_minus_one_node;
10686 tree gwv = integer_zero_node;
10687 tree iter_type = TREE_TYPE (v);
10688 tree diff_type = iter_type;
10689 tree plus_type = iter_type;
10690 struct oacc_collapse *counts = NULL;
10692 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
10693 == GF_OMP_FOR_KIND_OACC_LOOP);
10694 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
10695 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
10697 if (POINTER_TYPE_P (iter_type))
10699 plus_code = POINTER_PLUS_EXPR;
10700 plus_type = sizetype;
10702 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
10703 diff_type = signed_type_for (diff_type);
10705 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
10706 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
10707 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
10708 basic_block bottom_bb = NULL;
10710 /* entry_bb has two sucessors; the branch edge is to the exit
10711 block, fallthrough edge to body. */
10712 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
10713 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
10715 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
10716 body_bb, or to a block whose only successor is the body_bb. Its
10717 fallthrough successor is the final block (same as the branch
10718 successor of the entry_bb). */
10719 if (cont_bb)
10721 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10722 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
10724 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
10725 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
10727 else
10728 gcc_assert (!gimple_in_ssa_p (cfun));
10730 /* The exit block only has entry_bb and cont_bb as predecessors. */
10731 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
10733 tree chunk_no;
10734 tree chunk_max = NULL_TREE;
10735 tree bound, offset;
10736 tree step = create_tmp_var (diff_type, ".step");
10737 bool up = cond_code == LT_EXPR;
10738 tree dir = build_int_cst (diff_type, up ? +1 : -1);
10739 bool chunking = !gimple_in_ssa_p (cfun);;
10740 bool negating;
10742 /* SSA instances. */
10743 tree offset_incr = NULL_TREE;
10744 tree offset_init = NULL_TREE;
10746 gimple_stmt_iterator gsi;
10747 gassign *ass;
10748 gcall *call;
10749 gimple *stmt;
10750 tree expr;
10751 location_t loc;
10752 edge split, be, fte;
10754 /* Split the end of entry_bb to create head_bb. */
10755 split = split_block (entry_bb, last_stmt (entry_bb));
10756 basic_block head_bb = split->dest;
10757 entry_bb = split->src;
10759 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
10760 gsi = gsi_last_bb (entry_bb);
10761 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
10762 loc = gimple_location (for_stmt);
10764 if (gimple_in_ssa_p (cfun))
10766 offset_init = gimple_omp_for_index (for_stmt, 0);
10767 gcc_assert (integer_zerop (fd->loop.n1));
10768 /* The SSA parallelizer does gang parallelism. */
10769 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
10772 if (fd->collapse > 1)
10774 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
10775 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
10776 TREE_TYPE (fd->loop.n2));
10778 if (SSA_VAR_P (fd->loop.n2))
10780 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
10781 true, GSI_SAME_STMT);
10782 ass = gimple_build_assign (fd->loop.n2, total);
10783 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10788 tree b = fd->loop.n1;
10789 tree e = fd->loop.n2;
10790 tree s = fd->loop.step;
10792 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
10793 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
10795 /* Convert the step, avoiding possible unsigned->signed overflow. */
10796 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
10797 if (negating)
10798 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
10799 s = fold_convert (diff_type, s);
10800 if (negating)
10801 s = fold_build1 (NEGATE_EXPR, diff_type, s);
10802 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
10804 if (!chunking)
10805 chunk_size = integer_zero_node;
10806 expr = fold_convert (diff_type, chunk_size);
10807 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
10808 NULL_TREE, true, GSI_SAME_STMT);
10809 /* Determine the range, avoiding possible unsigned->signed overflow. */
10810 negating = !up && TYPE_UNSIGNED (iter_type);
10811 expr = fold_build2 (MINUS_EXPR, plus_type,
10812 fold_convert (plus_type, negating ? b : e),
10813 fold_convert (plus_type, negating ? e : b));
10814 expr = fold_convert (diff_type, expr);
10815 if (negating)
10816 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
10817 tree range = force_gimple_operand_gsi (&gsi, expr, true,
10818 NULL_TREE, true, GSI_SAME_STMT);
10820 chunk_no = build_int_cst (diff_type, 0);
10821 if (chunking)
10823 gcc_assert (!gimple_in_ssa_p (cfun));
10825 expr = chunk_no;
10826 chunk_max = create_tmp_var (diff_type, ".chunk_max");
10827 chunk_no = create_tmp_var (diff_type, ".chunk_no");
10829 ass = gimple_build_assign (chunk_no, expr);
10830 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10832 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
10833 build_int_cst (integer_type_node,
10834 IFN_GOACC_LOOP_CHUNKS),
10835 dir, range, s, chunk_size, gwv);
10836 gimple_call_set_lhs (call, chunk_max);
10837 gimple_set_location (call, loc);
10838 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
10840 else
10841 chunk_size = chunk_no;
10843 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
10844 build_int_cst (integer_type_node,
10845 IFN_GOACC_LOOP_STEP),
10846 dir, range, s, chunk_size, gwv);
10847 gimple_call_set_lhs (call, step);
10848 gimple_set_location (call, loc);
10849 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
10851 /* Remove the GIMPLE_OMP_FOR. */
10852 gsi_remove (&gsi, true);
10854 /* Fixup edges from head_bb */
10855 be = BRANCH_EDGE (head_bb);
10856 fte = FALLTHRU_EDGE (head_bb);
10857 be->flags |= EDGE_FALSE_VALUE;
10858 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
10860 basic_block body_bb = fte->dest;
10862 if (gimple_in_ssa_p (cfun))
10864 gsi = gsi_last_bb (cont_bb);
10865 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10867 offset = gimple_omp_continue_control_use (cont_stmt);
10868 offset_incr = gimple_omp_continue_control_def (cont_stmt);
10870 else
10872 offset = create_tmp_var (diff_type, ".offset");
10873 offset_init = offset_incr = offset;
10875 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
10877 /* Loop offset & bound go into head_bb. */
10878 gsi = gsi_start_bb (head_bb);
10880 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
10881 build_int_cst (integer_type_node,
10882 IFN_GOACC_LOOP_OFFSET),
10883 dir, range, s,
10884 chunk_size, gwv, chunk_no);
10885 gimple_call_set_lhs (call, offset_init);
10886 gimple_set_location (call, loc);
10887 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
10889 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
10890 build_int_cst (integer_type_node,
10891 IFN_GOACC_LOOP_BOUND),
10892 dir, range, s,
10893 chunk_size, gwv, offset_init);
10894 gimple_call_set_lhs (call, bound);
10895 gimple_set_location (call, loc);
10896 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
10898 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
10899 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
10900 GSI_CONTINUE_LINKING);
10902 /* V assignment goes into body_bb. */
10903 if (!gimple_in_ssa_p (cfun))
10905 gsi = gsi_start_bb (body_bb);
10907 expr = build2 (plus_code, iter_type, b,
10908 fold_convert (plus_type, offset));
10909 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10910 true, GSI_SAME_STMT);
10911 ass = gimple_build_assign (v, expr);
10912 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10913 if (fd->collapse > 1)
10914 expand_oacc_collapse_vars (fd, &gsi, counts, v);
10917 /* Loop increment goes into cont_bb. If this is not a loop, we
10918 will have spawned threads as if it was, and each one will
10919 execute one iteration. The specification is not explicit about
10920 whether such constructs are ill-formed or not, and they can
10921 occur, especially when noreturn routines are involved. */
10922 if (cont_bb)
10924 gsi = gsi_last_bb (cont_bb);
10925 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10926 loc = gimple_location (cont_stmt);
10928 /* Increment offset. */
10929 if (gimple_in_ssa_p (cfun))
10930 expr= build2 (plus_code, iter_type, offset,
10931 fold_convert (plus_type, step));
10932 else
10933 expr = build2 (PLUS_EXPR, diff_type, offset, step);
10934 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10935 true, GSI_SAME_STMT);
10936 ass = gimple_build_assign (offset_incr, expr);
10937 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10938 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
10939 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
10941 /* Remove the GIMPLE_OMP_CONTINUE. */
10942 gsi_remove (&gsi, true);
10944 /* Fixup edges from cont_bb */
10945 be = BRANCH_EDGE (cont_bb);
10946 fte = FALLTHRU_EDGE (cont_bb);
10947 be->flags |= EDGE_TRUE_VALUE;
10948 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
10950 if (chunking)
10952 /* Split the beginning of exit_bb to make bottom_bb. We
10953 need to insert a nop at the start, because splitting is
10954 after a stmt, not before. */
10955 gsi = gsi_start_bb (exit_bb);
10956 stmt = gimple_build_nop ();
10957 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10958 split = split_block (exit_bb, stmt);
10959 bottom_bb = split->src;
10960 exit_bb = split->dest;
10961 gsi = gsi_last_bb (bottom_bb);
10963 /* Chunk increment and test goes into bottom_bb. */
10964 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
10965 build_int_cst (diff_type, 1));
10966 ass = gimple_build_assign (chunk_no, expr);
10967 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
10969 /* Chunk test at end of bottom_bb. */
10970 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
10971 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
10972 GSI_CONTINUE_LINKING);
10974 /* Fixup edges from bottom_bb. */
10975 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
10976 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
10980 gsi = gsi_last_bb (exit_bb);
10981 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
10982 loc = gimple_location (gsi_stmt (gsi));
10984 if (!gimple_in_ssa_p (cfun))
10986 /* Insert the final value of V, in case it is live. This is the
10987 value for the only thread that survives past the join. */
10988 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
10989 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
10990 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
10991 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
10992 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
10993 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10994 true, GSI_SAME_STMT);
10995 ass = gimple_build_assign (v, expr);
10996 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10999 /* Remove the OMP_RETURN. */
11000 gsi_remove (&gsi, true);
11002 if (cont_bb)
11004 /* We now have one or two nested loops. Update the loop
11005 structures. */
11006 struct loop *parent = entry_bb->loop_father;
11007 struct loop *body = body_bb->loop_father;
11009 if (chunking)
11011 struct loop *chunk_loop = alloc_loop ();
11012 chunk_loop->header = head_bb;
11013 chunk_loop->latch = bottom_bb;
11014 add_loop (chunk_loop, parent);
11015 parent = chunk_loop;
11017 else if (parent != body)
11019 gcc_assert (body->header == body_bb);
11020 gcc_assert (body->latch == cont_bb
11021 || single_pred (body->latch) == cont_bb);
11022 parent = NULL;
11025 if (parent)
11027 struct loop *body_loop = alloc_loop ();
11028 body_loop->header = body_bb;
11029 body_loop->latch = cont_bb;
11030 add_loop (body_loop, parent);
11035 /* Expand the OMP loop defined by REGION. */
11037 static void
11038 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11040 struct omp_for_data fd;
11041 struct omp_for_data_loop *loops;
11043 loops
11044 = (struct omp_for_data_loop *)
11045 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11046 * sizeof (struct omp_for_data_loop));
11047 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11048 &fd, loops);
11049 region->sched_kind = fd.sched_kind;
11051 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11052 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11053 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11054 if (region->cont)
11056 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11057 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11058 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11060 else
11061 /* If there isn't a continue then this is a degerate case where
11062 the introduction of abnormal edges during lowering will prevent
11063 original loops from being detected. Fix that up. */
11064 loops_state_set (LOOPS_NEED_FIXUP);
11066 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11067 expand_omp_simd (region, &fd);
11068 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11069 expand_cilk_for (region, &fd);
11070 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11072 gcc_assert (!inner_stmt);
11073 expand_oacc_for (region, &fd);
11075 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11077 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11078 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11079 else
11080 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11082 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11083 && !fd.have_ordered)
11085 if (fd.chunk_size == NULL)
11086 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11087 else
11088 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11090 else
11092 int fn_index, start_ix, next_ix;
11094 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11095 == GF_OMP_FOR_KIND_FOR);
11096 if (fd.chunk_size == NULL
11097 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11098 fd.chunk_size = integer_zero_node;
11099 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11100 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
11101 ? 3 : fd.sched_kind;
11102 if (!fd.ordered)
11103 fn_index += fd.have_ordered * 4;
11104 if (fd.ordered)
11105 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11106 else
11107 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11108 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11109 if (fd.iter_type == long_long_unsigned_type_node)
11111 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11112 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11113 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11114 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11116 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11117 (enum built_in_function) next_ix, inner_stmt);
11120 if (gimple_in_ssa_p (cfun))
11121 update_ssa (TODO_update_ssa_only_virtuals);
11125 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11127 v = GOMP_sections_start (n);
11129 switch (v)
11131 case 0:
11132 goto L2;
11133 case 1:
11134 section 1;
11135 goto L1;
11136 case 2:
11138 case n:
11140 default:
11141 abort ();
11144 v = GOMP_sections_next ();
11145 goto L0;
11147 reduction;
11149 If this is a combined parallel sections, replace the call to
11150 GOMP_sections_start with call to GOMP_sections_next. */
11152 static void
11153 expand_omp_sections (struct omp_region *region)
11155 tree t, u, vin = NULL, vmain, vnext, l2;
11156 unsigned len;
11157 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11158 gimple_stmt_iterator si, switch_si;
11159 gomp_sections *sections_stmt;
11160 gimple *stmt;
11161 gomp_continue *cont;
11162 edge_iterator ei;
11163 edge e;
11164 struct omp_region *inner;
11165 unsigned i, casei;
11166 bool exit_reachable = region->cont != NULL;
11168 gcc_assert (region->exit != NULL);
11169 entry_bb = region->entry;
11170 l0_bb = single_succ (entry_bb);
11171 l1_bb = region->cont;
11172 l2_bb = region->exit;
11173 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11174 l2 = gimple_block_label (l2_bb);
11175 else
11177 /* This can happen if there are reductions. */
11178 len = EDGE_COUNT (l0_bb->succs);
11179 gcc_assert (len > 0);
11180 e = EDGE_SUCC (l0_bb, len - 1);
11181 si = gsi_last_bb (e->dest);
11182 l2 = NULL_TREE;
11183 if (gsi_end_p (si)
11184 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11185 l2 = gimple_block_label (e->dest);
11186 else
11187 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11189 si = gsi_last_bb (e->dest);
11190 if (gsi_end_p (si)
11191 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11193 l2 = gimple_block_label (e->dest);
11194 break;
11198 if (exit_reachable)
11199 default_bb = create_empty_bb (l1_bb->prev_bb);
11200 else
11201 default_bb = create_empty_bb (l0_bb);
11203 /* We will build a switch() with enough cases for all the
11204 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11205 and a default case to abort if something goes wrong. */
11206 len = EDGE_COUNT (l0_bb->succs);
11208 /* Use vec::quick_push on label_vec throughout, since we know the size
11209 in advance. */
11210 auto_vec<tree> label_vec (len);
11212 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11213 GIMPLE_OMP_SECTIONS statement. */
11214 si = gsi_last_bb (entry_bb);
11215 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11216 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11217 vin = gimple_omp_sections_control (sections_stmt);
11218 if (!is_combined_parallel (region))
11220 /* If we are not inside a combined parallel+sections region,
11221 call GOMP_sections_start. */
11222 t = build_int_cst (unsigned_type_node, len - 1);
11223 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11224 stmt = gimple_build_call (u, 1, t);
11226 else
11228 /* Otherwise, call GOMP_sections_next. */
11229 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11230 stmt = gimple_build_call (u, 0);
11232 gimple_call_set_lhs (stmt, vin);
11233 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11234 gsi_remove (&si, true);
11236 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11237 L0_BB. */
11238 switch_si = gsi_last_bb (l0_bb);
11239 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11240 if (exit_reachable)
11242 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11243 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11244 vmain = gimple_omp_continue_control_use (cont);
11245 vnext = gimple_omp_continue_control_def (cont);
11247 else
11249 vmain = vin;
11250 vnext = NULL_TREE;
11253 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11254 label_vec.quick_push (t);
11255 i = 1;
11257 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11258 for (inner = region->inner, casei = 1;
11259 inner;
11260 inner = inner->next, i++, casei++)
11262 basic_block s_entry_bb, s_exit_bb;
11264 /* Skip optional reduction region. */
11265 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11267 --i;
11268 --casei;
11269 continue;
11272 s_entry_bb = inner->entry;
11273 s_exit_bb = inner->exit;
11275 t = gimple_block_label (s_entry_bb);
11276 u = build_int_cst (unsigned_type_node, casei);
11277 u = build_case_label (u, NULL, t);
11278 label_vec.quick_push (u);
11280 si = gsi_last_bb (s_entry_bb);
11281 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11282 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11283 gsi_remove (&si, true);
11284 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11286 if (s_exit_bb == NULL)
11287 continue;
11289 si = gsi_last_bb (s_exit_bb);
11290 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11291 gsi_remove (&si, true);
11293 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11296 /* Error handling code goes in DEFAULT_BB. */
11297 t = gimple_block_label (default_bb);
11298 u = build_case_label (NULL, NULL, t);
11299 make_edge (l0_bb, default_bb, 0);
11300 add_bb_to_loop (default_bb, current_loops->tree_root);
11302 stmt = gimple_build_switch (vmain, u, label_vec);
11303 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11304 gsi_remove (&switch_si, true);
11306 si = gsi_start_bb (default_bb);
11307 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11308 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11310 if (exit_reachable)
11312 tree bfn_decl;
11314 /* Code to get the next section goes in L1_BB. */
11315 si = gsi_last_bb (l1_bb);
11316 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11318 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11319 stmt = gimple_build_call (bfn_decl, 0);
11320 gimple_call_set_lhs (stmt, vnext);
11321 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11322 gsi_remove (&si, true);
11324 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11327 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11328 si = gsi_last_bb (l2_bb);
11329 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11330 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11331 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11332 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11333 else
11334 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11335 stmt = gimple_build_call (t, 0);
11336 if (gimple_omp_return_lhs (gsi_stmt (si)))
11337 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11338 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11339 gsi_remove (&si, true);
11341 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11345 /* Expand code for an OpenMP single directive. We've already expanded
11346 much of the code, here we simply place the GOMP_barrier call. */
11348 static void
11349 expand_omp_single (struct omp_region *region)
11351 basic_block entry_bb, exit_bb;
11352 gimple_stmt_iterator si;
11354 entry_bb = region->entry;
11355 exit_bb = region->exit;
11357 si = gsi_last_bb (entry_bb);
11358 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11359 gsi_remove (&si, true);
11360 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11362 si = gsi_last_bb (exit_bb);
11363 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11365 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11366 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11368 gsi_remove (&si, true);
11369 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11373 /* Generic expansion for OpenMP synchronization directives: master,
11374 ordered and critical. All we need to do here is remove the entry
11375 and exit markers for REGION. */
11377 static void
11378 expand_omp_synch (struct omp_region *region)
11380 basic_block entry_bb, exit_bb;
11381 gimple_stmt_iterator si;
11383 entry_bb = region->entry;
11384 exit_bb = region->exit;
11386 si = gsi_last_bb (entry_bb);
11387 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11388 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11389 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11390 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11391 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11392 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11393 gsi_remove (&si, true);
11394 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11396 if (exit_bb)
11398 si = gsi_last_bb (exit_bb);
11399 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11400 gsi_remove (&si, true);
11401 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11405 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11406 operation as a normal volatile load. */
11408 static bool
11409 expand_omp_atomic_load (basic_block load_bb, tree addr,
11410 tree loaded_val, int index)
11412 enum built_in_function tmpbase;
11413 gimple_stmt_iterator gsi;
11414 basic_block store_bb;
11415 location_t loc;
11416 gimple *stmt;
11417 tree decl, call, type, itype;
11419 gsi = gsi_last_bb (load_bb);
11420 stmt = gsi_stmt (gsi);
11421 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11422 loc = gimple_location (stmt);
11424 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11425 is smaller than word size, then expand_atomic_load assumes that the load
11426 is atomic. We could avoid the builtin entirely in this case. */
11428 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11429 decl = builtin_decl_explicit (tmpbase);
11430 if (decl == NULL_TREE)
11431 return false;
11433 type = TREE_TYPE (loaded_val);
11434 itype = TREE_TYPE (TREE_TYPE (decl));
11436 call = build_call_expr_loc (loc, decl, 2, addr,
11437 build_int_cst (NULL,
11438 gimple_omp_atomic_seq_cst_p (stmt)
11439 ? MEMMODEL_SEQ_CST
11440 : MEMMODEL_RELAXED));
11441 if (!useless_type_conversion_p (type, itype))
11442 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11443 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11445 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11446 gsi_remove (&gsi, true);
11448 store_bb = single_succ (load_bb);
11449 gsi = gsi_last_bb (store_bb);
11450 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11451 gsi_remove (&gsi, true);
11453 if (gimple_in_ssa_p (cfun))
11454 update_ssa (TODO_update_ssa_no_phi);
11456 return true;
11459 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11460 operation as a normal volatile store. */
11462 static bool
11463 expand_omp_atomic_store (basic_block load_bb, tree addr,
11464 tree loaded_val, tree stored_val, int index)
11466 enum built_in_function tmpbase;
11467 gimple_stmt_iterator gsi;
11468 basic_block store_bb = single_succ (load_bb);
11469 location_t loc;
11470 gimple *stmt;
11471 tree decl, call, type, itype;
11472 machine_mode imode;
11473 bool exchange;
11475 gsi = gsi_last_bb (load_bb);
11476 stmt = gsi_stmt (gsi);
11477 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11479 /* If the load value is needed, then this isn't a store but an exchange. */
11480 exchange = gimple_omp_atomic_need_value_p (stmt);
11482 gsi = gsi_last_bb (store_bb);
11483 stmt = gsi_stmt (gsi);
11484 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11485 loc = gimple_location (stmt);
11487 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11488 is smaller than word size, then expand_atomic_store assumes that the store
11489 is atomic. We could avoid the builtin entirely in this case. */
11491 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11492 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11493 decl = builtin_decl_explicit (tmpbase);
11494 if (decl == NULL_TREE)
11495 return false;
11497 type = TREE_TYPE (stored_val);
11499 /* Dig out the type of the function's second argument. */
11500 itype = TREE_TYPE (decl);
11501 itype = TYPE_ARG_TYPES (itype);
11502 itype = TREE_CHAIN (itype);
11503 itype = TREE_VALUE (itype);
11504 imode = TYPE_MODE (itype);
11506 if (exchange && !can_atomic_exchange_p (imode, true))
11507 return false;
11509 if (!useless_type_conversion_p (itype, type))
11510 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11511 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11512 build_int_cst (NULL,
11513 gimple_omp_atomic_seq_cst_p (stmt)
11514 ? MEMMODEL_SEQ_CST
11515 : MEMMODEL_RELAXED));
11516 if (exchange)
11518 if (!useless_type_conversion_p (type, itype))
11519 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11520 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11523 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11524 gsi_remove (&gsi, true);
11526 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11527 gsi = gsi_last_bb (load_bb);
11528 gsi_remove (&gsi, true);
11530 if (gimple_in_ssa_p (cfun))
11531 update_ssa (TODO_update_ssa_no_phi);
11533 return true;
11536 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11537 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11538 size of the data type, and thus usable to find the index of the builtin
11539 decl. Returns false if the expression is not of the proper form. */
11541 static bool
11542 expand_omp_atomic_fetch_op (basic_block load_bb,
11543 tree addr, tree loaded_val,
11544 tree stored_val, int index)
11546 enum built_in_function oldbase, newbase, tmpbase;
11547 tree decl, itype, call;
11548 tree lhs, rhs;
11549 basic_block store_bb = single_succ (load_bb);
11550 gimple_stmt_iterator gsi;
11551 gimple *stmt;
11552 location_t loc;
11553 enum tree_code code;
11554 bool need_old, need_new;
11555 machine_mode imode;
11556 bool seq_cst;
11558 /* We expect to find the following sequences:
11560 load_bb:
11561 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
11563 store_bb:
11564 val = tmp OP something; (or: something OP tmp)
11565 GIMPLE_OMP_STORE (val)
11567 ???FIXME: Allow a more flexible sequence.
11568 Perhaps use data flow to pick the statements.
11572 gsi = gsi_after_labels (store_bb);
11573 stmt = gsi_stmt (gsi);
11574 loc = gimple_location (stmt);
11575 if (!is_gimple_assign (stmt))
11576 return false;
11577 gsi_next (&gsi);
11578 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
11579 return false;
11580 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11581 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
11582 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
11583 gcc_checking_assert (!need_old || !need_new);
11585 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
11586 return false;
11588 /* Check for one of the supported fetch-op operations. */
11589 code = gimple_assign_rhs_code (stmt);
11590 switch (code)
11592 case PLUS_EXPR:
11593 case POINTER_PLUS_EXPR:
11594 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11595 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
11596 break;
11597 case MINUS_EXPR:
11598 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11599 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
11600 break;
11601 case BIT_AND_EXPR:
11602 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11603 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
11604 break;
11605 case BIT_IOR_EXPR:
11606 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11607 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
11608 break;
11609 case BIT_XOR_EXPR:
11610 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11611 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
11612 break;
11613 default:
11614 return false;
11617 /* Make sure the expression is of the proper form. */
11618 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11619 rhs = gimple_assign_rhs2 (stmt);
11620 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11621 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11622 rhs = gimple_assign_rhs1 (stmt);
11623 else
11624 return false;
11626 tmpbase = ((enum built_in_function)
11627 ((need_new ? newbase : oldbase) + index + 1));
11628 decl = builtin_decl_explicit (tmpbase);
11629 if (decl == NULL_TREE)
11630 return false;
11631 itype = TREE_TYPE (TREE_TYPE (decl));
11632 imode = TYPE_MODE (itype);
11634 /* We could test all of the various optabs involved, but the fact of the
11635 matter is that (with the exception of i486 vs i586 and xadd) all targets
11636 that support any atomic operaton optab also implements compare-and-swap.
11637 Let optabs.c take care of expanding any compare-and-swap loop. */
11638 if (!can_compare_and_swap_p (imode, true))
11639 return false;
11641 gsi = gsi_last_bb (load_bb);
11642 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
11644 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
11645 It only requires that the operation happen atomically. Thus we can
11646 use the RELAXED memory model. */
11647 call = build_call_expr_loc (loc, decl, 3, addr,
11648 fold_convert_loc (loc, itype, rhs),
11649 build_int_cst (NULL,
11650 seq_cst ? MEMMODEL_SEQ_CST
11651 : MEMMODEL_RELAXED));
11653 if (need_old || need_new)
11655 lhs = need_old ? loaded_val : stored_val;
11656 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
11657 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
11659 else
11660 call = fold_convert_loc (loc, void_type_node, call);
11661 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11662 gsi_remove (&gsi, true);
11664 gsi = gsi_last_bb (store_bb);
11665 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11666 gsi_remove (&gsi, true);
11667 gsi = gsi_last_bb (store_bb);
11668 gsi_remove (&gsi, true);
11670 if (gimple_in_ssa_p (cfun))
11671 update_ssa (TODO_update_ssa_no_phi);
11673 return true;
11676 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11678 oldval = *addr;
11679 repeat:
11680 newval = rhs; // with oldval replacing *addr in rhs
11681 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
11682 if (oldval != newval)
11683 goto repeat;
11685 INDEX is log2 of the size of the data type, and thus usable to find the
11686 index of the builtin decl. */
11688 static bool
11689 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
11690 tree addr, tree loaded_val, tree stored_val,
11691 int index)
11693 tree loadedi, storedi, initial, new_storedi, old_vali;
11694 tree type, itype, cmpxchg, iaddr;
11695 gimple_stmt_iterator si;
11696 basic_block loop_header = single_succ (load_bb);
11697 gimple *phi, *stmt;
11698 edge e;
11699 enum built_in_function fncode;
11701 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
11702 order to use the RELAXED memory model effectively. */
11703 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
11704 + index + 1);
11705 cmpxchg = builtin_decl_explicit (fncode);
11706 if (cmpxchg == NULL_TREE)
11707 return false;
11708 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11709 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
11711 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
11712 return false;
11714 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
11715 si = gsi_last_bb (load_bb);
11716 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11718 /* For floating-point values, we'll need to view-convert them to integers
11719 so that we can perform the atomic compare and swap. Simplify the
11720 following code by always setting up the "i"ntegral variables. */
11721 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
11723 tree iaddr_val;
11725 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
11726 true));
11727 iaddr_val
11728 = force_gimple_operand_gsi (&si,
11729 fold_convert (TREE_TYPE (iaddr), addr),
11730 false, NULL_TREE, true, GSI_SAME_STMT);
11731 stmt = gimple_build_assign (iaddr, iaddr_val);
11732 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11733 loadedi = create_tmp_var (itype);
11734 if (gimple_in_ssa_p (cfun))
11735 loadedi = make_ssa_name (loadedi);
11737 else
11739 iaddr = addr;
11740 loadedi = loaded_val;
11743 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11744 tree loaddecl = builtin_decl_explicit (fncode);
11745 if (loaddecl)
11746 initial
11747 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
11748 build_call_expr (loaddecl, 2, iaddr,
11749 build_int_cst (NULL_TREE,
11750 MEMMODEL_RELAXED)));
11751 else
11752 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
11753 build_int_cst (TREE_TYPE (iaddr), 0));
11755 initial
11756 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
11757 GSI_SAME_STMT);
11759 /* Move the value to the LOADEDI temporary. */
11760 if (gimple_in_ssa_p (cfun))
11762 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
11763 phi = create_phi_node (loadedi, loop_header);
11764 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
11765 initial);
11767 else
11768 gsi_insert_before (&si,
11769 gimple_build_assign (loadedi, initial),
11770 GSI_SAME_STMT);
11771 if (loadedi != loaded_val)
11773 gimple_stmt_iterator gsi2;
11774 tree x;
11776 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
11777 gsi2 = gsi_start_bb (loop_header);
11778 if (gimple_in_ssa_p (cfun))
11780 gassign *stmt;
11781 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
11782 true, GSI_SAME_STMT);
11783 stmt = gimple_build_assign (loaded_val, x);
11784 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
11786 else
11788 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
11789 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
11790 true, GSI_SAME_STMT);
11793 gsi_remove (&si, true);
11795 si = gsi_last_bb (store_bb);
11796 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
11798 if (iaddr == addr)
11799 storedi = stored_val;
11800 else
11801 storedi =
11802 force_gimple_operand_gsi (&si,
11803 build1 (VIEW_CONVERT_EXPR, itype,
11804 stored_val), true, NULL_TREE, true,
11805 GSI_SAME_STMT);
11807 /* Build the compare&swap statement. */
11808 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
11809 new_storedi = force_gimple_operand_gsi (&si,
11810 fold_convert (TREE_TYPE (loadedi),
11811 new_storedi),
11812 true, NULL_TREE,
11813 true, GSI_SAME_STMT);
11815 if (gimple_in_ssa_p (cfun))
11816 old_vali = loadedi;
11817 else
11819 old_vali = create_tmp_var (TREE_TYPE (loadedi));
11820 stmt = gimple_build_assign (old_vali, loadedi);
11821 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11823 stmt = gimple_build_assign (loadedi, new_storedi);
11824 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11827 /* Note that we always perform the comparison as an integer, even for
11828 floating point. This allows the atomic operation to properly
11829 succeed even with NaNs and -0.0. */
11830 stmt = gimple_build_cond_empty
11831 (build2 (NE_EXPR, boolean_type_node,
11832 new_storedi, old_vali));
11833 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11835 /* Update cfg. */
11836 e = single_succ_edge (store_bb);
11837 e->flags &= ~EDGE_FALLTHRU;
11838 e->flags |= EDGE_FALSE_VALUE;
11840 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
11842 /* Copy the new value to loadedi (we already did that before the condition
11843 if we are not in SSA). */
11844 if (gimple_in_ssa_p (cfun))
11846 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
11847 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
11850 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
11851 gsi_remove (&si, true);
11853 struct loop *loop = alloc_loop ();
11854 loop->header = loop_header;
11855 loop->latch = store_bb;
11856 add_loop (loop, loop_header->loop_father);
11858 if (gimple_in_ssa_p (cfun))
11859 update_ssa (TODO_update_ssa_no_phi);
11861 return true;
11864 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11866 GOMP_atomic_start ();
11867 *addr = rhs;
11868 GOMP_atomic_end ();
11870 The result is not globally atomic, but works so long as all parallel
11871 references are within #pragma omp atomic directives. According to
11872 responses received from omp@openmp.org, appears to be within spec.
11873 Which makes sense, since that's how several other compilers handle
11874 this situation as well.
11875 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
11876 expanding. STORED_VAL is the operand of the matching
11877 GIMPLE_OMP_ATOMIC_STORE.
11879 We replace
11880 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
11881 loaded_val = *addr;
11883 and replace
11884 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
11885 *addr = stored_val;
11888 static bool
11889 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
11890 tree addr, tree loaded_val, tree stored_val)
11892 gimple_stmt_iterator si;
11893 gassign *stmt;
11894 tree t;
11896 si = gsi_last_bb (load_bb);
11897 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11899 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
11900 t = build_call_expr (t, 0);
11901 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11903 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
11904 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11905 gsi_remove (&si, true);
11907 si = gsi_last_bb (store_bb);
11908 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
11910 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
11911 stored_val);
11912 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11914 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
11915 t = build_call_expr (t, 0);
11916 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11917 gsi_remove (&si, true);
11919 if (gimple_in_ssa_p (cfun))
11920 update_ssa (TODO_update_ssa_no_phi);
11921 return true;
11924 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
11925 using expand_omp_atomic_fetch_op. If it failed, we try to
11926 call expand_omp_atomic_pipeline, and if it fails too, the
11927 ultimate fallback is wrapping the operation in a mutex
11928 (expand_omp_atomic_mutex). REGION is the atomic region built
11929 by build_omp_regions_1(). */
11931 static void
11932 expand_omp_atomic (struct omp_region *region)
11934 basic_block load_bb = region->entry, store_bb = region->exit;
11935 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
11936 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
11937 tree loaded_val = gimple_omp_atomic_load_lhs (load);
11938 tree addr = gimple_omp_atomic_load_rhs (load);
11939 tree stored_val = gimple_omp_atomic_store_val (store);
11940 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11941 HOST_WIDE_INT index;
11943 /* Make sure the type is one of the supported sizes. */
11944 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
11945 index = exact_log2 (index);
11946 if (index >= 0 && index <= 4)
11948 unsigned int align = TYPE_ALIGN_UNIT (type);
11950 /* __sync builtins require strict data alignment. */
11951 if (exact_log2 (align) >= index)
11953 /* Atomic load. */
11954 if (loaded_val == stored_val
11955 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11956 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11957 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11958 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
11959 return;
11961 /* Atomic store. */
11962 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11963 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11964 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11965 && store_bb == single_succ (load_bb)
11966 && first_stmt (store_bb) == store
11967 && expand_omp_atomic_store (load_bb, addr, loaded_val,
11968 stored_val, index))
11969 return;
11971 /* When possible, use specialized atomic update functions. */
11972 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
11973 && store_bb == single_succ (load_bb)
11974 && expand_omp_atomic_fetch_op (load_bb, addr,
11975 loaded_val, stored_val, index))
11976 return;
11978 /* If we don't have specialized __sync builtins, try and implement
11979 as a compare and swap loop. */
11980 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
11981 loaded_val, stored_val, index))
11982 return;
11986 /* The ultimate fallback is wrapping the operation in a mutex. */
11987 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
11991 /* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
11992 macro on gomp-constants.h. We do not check for overflow. */
11994 static tree
11995 oacc_launch_pack (unsigned code, tree device, unsigned op)
11997 tree res;
11999 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12000 if (device)
12002 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12003 device, build_int_cst (unsigned_type_node,
12004 GOMP_LAUNCH_DEVICE_SHIFT));
12005 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12007 return res;
12010 /* Look for compute grid dimension clauses and convert to an attribute
12011 attached to FN. This permits the target-side code to (a) massage
12012 the dimensions, (b) emit that data and (c) optimize. Non-constant
12013 dimensions are pushed onto ARGS.
12015 The attribute value is a TREE_LIST. A set of dimensions is
12016 represented as a list of INTEGER_CST. Those that are runtime
12017 expres are represented as an INTEGER_CST of zero.
12019 TOOO. Normally the attribute will just contain a single such list. If
12020 however it contains a list of lists, this will represent the use of
12021 device_type. Each member of the outer list is an assoc list of
12022 dimensions, keyed by the device type. The first entry will be the
12023 default. Well, that's the plan. */
12025 #define OACC_FN_ATTRIB "oacc function"
12027 /* Replace any existing oacc fn attribute with updated dimensions. */
12029 void
12030 replace_oacc_fn_attrib (tree fn, tree dims)
12032 tree ident = get_identifier (OACC_FN_ATTRIB);
12033 tree attribs = DECL_ATTRIBUTES (fn);
12035 /* If we happen to be present as the first attrib, drop it. */
12036 if (attribs && TREE_PURPOSE (attribs) == ident)
12037 attribs = TREE_CHAIN (attribs);
12038 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12041 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12042 function attribute. Push any that are non-constant onto the ARGS
12043 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12045 static void
12046 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12048 /* Must match GOMP_DIM ordering. */
12049 static const omp_clause_code ids[]
12050 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12051 OMP_CLAUSE_VECTOR_LENGTH };
12052 unsigned ix;
12053 tree dims[GOMP_DIM_MAX];
12054 tree attr = NULL_TREE;
12055 unsigned non_const = 0;
12057 for (ix = GOMP_DIM_MAX; ix--;)
12059 tree clause = find_omp_clause (clauses, ids[ix]);
12060 tree dim = NULL_TREE;
12062 if (clause)
12063 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12064 dims[ix] = dim;
12065 if (dim && TREE_CODE (dim) != INTEGER_CST)
12067 dim = integer_zero_node;
12068 non_const |= GOMP_DIM_MASK (ix);
12070 attr = tree_cons (NULL_TREE, dim, attr);
12073 replace_oacc_fn_attrib (fn, attr);
12075 if (non_const)
12077 /* Push a dynamic argument set. */
12078 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12079 NULL_TREE, non_const));
12080 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12081 if (non_const & GOMP_DIM_MASK (ix))
12082 args->safe_push (dims[ix]);
12086 /* Retrieve the oacc function attrib and return it. Non-oacc
12087 functions will return NULL. */
12089 tree
12090 get_oacc_fn_attrib (tree fn)
12092 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12095 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12097 static void
12098 expand_omp_target (struct omp_region *region)
12100 basic_block entry_bb, exit_bb, new_bb;
12101 struct function *child_cfun;
12102 tree child_fn, block, t;
12103 gimple_stmt_iterator gsi;
12104 gomp_target *entry_stmt;
12105 gimple *stmt;
12106 edge e;
12107 bool offloaded, data_region;
12109 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12110 new_bb = region->entry;
12112 offloaded = is_gimple_omp_offloaded (entry_stmt);
12113 switch (gimple_omp_target_kind (entry_stmt))
12115 case GF_OMP_TARGET_KIND_REGION:
12116 case GF_OMP_TARGET_KIND_UPDATE:
12117 case GF_OMP_TARGET_KIND_ENTER_DATA:
12118 case GF_OMP_TARGET_KIND_EXIT_DATA:
12119 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12120 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12121 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12122 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12123 data_region = false;
12124 break;
12125 case GF_OMP_TARGET_KIND_DATA:
12126 case GF_OMP_TARGET_KIND_OACC_DATA:
12127 data_region = true;
12128 break;
12129 default:
12130 gcc_unreachable ();
12133 child_fn = NULL_TREE;
12134 child_cfun = NULL;
12135 if (offloaded)
12137 child_fn = gimple_omp_target_child_fn (entry_stmt);
12138 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12141 /* Supported by expand_omp_taskreg, but not here. */
12142 if (child_cfun != NULL)
12143 gcc_checking_assert (!child_cfun->cfg);
12144 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12146 entry_bb = region->entry;
12147 exit_bb = region->exit;
12149 if (offloaded)
12151 unsigned srcidx, dstidx, num;
12153 /* If the offloading region needs data sent from the parent
12154 function, then the very first statement (except possible
12155 tree profile counter updates) of the offloading body
12156 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12157 &.OMP_DATA_O is passed as an argument to the child function,
12158 we need to replace it with the argument as seen by the child
12159 function.
12161 In most cases, this will end up being the identity assignment
12162 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
12163 a function call that has been inlined, the original PARM_DECL
12164 .OMP_DATA_I may have been converted into a different local
12165 variable. In which case, we need to keep the assignment. */
12166 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12167 if (data_arg)
12169 basic_block entry_succ_bb = single_succ (entry_bb);
12170 gimple_stmt_iterator gsi;
12171 tree arg;
12172 gimple *tgtcopy_stmt = NULL;
12173 tree sender = TREE_VEC_ELT (data_arg, 0);
12175 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12177 gcc_assert (!gsi_end_p (gsi));
12178 stmt = gsi_stmt (gsi);
12179 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12180 continue;
12182 if (gimple_num_ops (stmt) == 2)
12184 tree arg = gimple_assign_rhs1 (stmt);
12186 /* We're ignoring the subcode because we're
12187 effectively doing a STRIP_NOPS. */
12189 if (TREE_CODE (arg) == ADDR_EXPR
12190 && TREE_OPERAND (arg, 0) == sender)
12192 tgtcopy_stmt = stmt;
12193 break;
12198 gcc_assert (tgtcopy_stmt != NULL);
12199 arg = DECL_ARGUMENTS (child_fn);
12201 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12202 gsi_remove (&gsi, true);
12205 /* Declare local variables needed in CHILD_CFUN. */
12206 block = DECL_INITIAL (child_fn);
12207 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
12208 /* The gimplifier could record temporaries in the offloading block
12209 rather than in containing function's local_decls chain,
12210 which would mean cgraph missed finalizing them. Do it now. */
12211 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12212 if (TREE_CODE (t) == VAR_DECL
12213 && TREE_STATIC (t)
12214 && !DECL_EXTERNAL (t))
12215 varpool_node::finalize_decl (t);
12216 DECL_SAVED_TREE (child_fn) = NULL;
12217 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12218 gimple_set_body (child_fn, NULL);
12219 TREE_USED (block) = 1;
12221 /* Reset DECL_CONTEXT on function arguments. */
12222 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12223 DECL_CONTEXT (t) = child_fn;
12225 /* Split ENTRY_BB at GIMPLE_*,
12226 so that it can be moved to the child function. */
12227 gsi = gsi_last_bb (entry_bb);
12228 stmt = gsi_stmt (gsi);
12229 gcc_assert (stmt
12230 && gimple_code (stmt) == gimple_code (entry_stmt));
12231 e = split_block (entry_bb, stmt);
12232 gsi_remove (&gsi, true);
12233 entry_bb = e->dest;
12234 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12236 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12237 if (exit_bb)
12239 gsi = gsi_last_bb (exit_bb);
12240 gcc_assert (!gsi_end_p (gsi)
12241 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12242 stmt = gimple_build_return (NULL);
12243 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12244 gsi_remove (&gsi, true);
12247 /* Move the offloading region into CHILD_CFUN. */
12249 block = gimple_block (entry_stmt);
12251 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12252 if (exit_bb)
12253 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12254 /* When the OMP expansion process cannot guarantee an up-to-date
12255 loop tree arrange for the child function to fixup loops. */
12256 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12257 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12259 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12260 num = vec_safe_length (child_cfun->local_decls);
12261 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12263 t = (*child_cfun->local_decls)[srcidx];
12264 if (DECL_CONTEXT (t) == cfun->decl)
12265 continue;
12266 if (srcidx != dstidx)
12267 (*child_cfun->local_decls)[dstidx] = t;
12268 dstidx++;
12270 if (dstidx != num)
12271 vec_safe_truncate (child_cfun->local_decls, dstidx);
12273 /* Inform the callgraph about the new function. */
12274 child_cfun->curr_properties = cfun->curr_properties;
12275 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12276 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
12277 cgraph_node *node = cgraph_node::get_create (child_fn);
12278 node->parallelized_function = 1;
12279 cgraph_node::add_new_function (child_fn, true);
12281 #ifdef ENABLE_OFFLOADING
12282 /* Add the new function to the offload table. */
12283 vec_safe_push (offload_funcs, child_fn);
12284 #endif
12286 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12287 fixed in a following pass. */
12288 push_cfun (child_cfun);
12289 cgraph_edge::rebuild_edges ();
12291 #ifdef ENABLE_OFFLOADING
12292 /* Prevent IPA from removing child_fn as unreachable, since there are no
12293 refs from the parent function to child_fn in offload LTO mode. */
12294 cgraph_node::get (child_fn)->mark_force_output ();
12295 #endif
12297 /* Some EH regions might become dead, see PR34608. If
12298 pass_cleanup_cfg isn't the first pass to happen with the
12299 new child, these dead EH edges might cause problems.
12300 Clean them up now. */
12301 if (flag_exceptions)
12303 basic_block bb;
12304 bool changed = false;
12306 FOR_EACH_BB_FN (bb, cfun)
12307 changed |= gimple_purge_dead_eh_edges (bb);
12308 if (changed)
12309 cleanup_tree_cfg ();
12311 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12312 verify_loop_structure ();
12313 pop_cfun ();
12316 /* Emit a library call to launch the offloading region, or do data
12317 transfers. */
12318 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
12319 enum built_in_function start_ix;
12320 location_t clause_loc;
12321 unsigned int flags_i = 0;
12323 switch (gimple_omp_target_kind (entry_stmt))
12325 case GF_OMP_TARGET_KIND_REGION:
12326 start_ix = BUILT_IN_GOMP_TARGET;
12327 break;
12328 case GF_OMP_TARGET_KIND_DATA:
12329 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12330 break;
12331 case GF_OMP_TARGET_KIND_UPDATE:
12332 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12333 break;
12334 case GF_OMP_TARGET_KIND_ENTER_DATA:
12335 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12336 break;
12337 case GF_OMP_TARGET_KIND_EXIT_DATA:
12338 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12339 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12340 break;
12341 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12342 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12343 start_ix = BUILT_IN_GOACC_PARALLEL;
12344 break;
12345 case GF_OMP_TARGET_KIND_OACC_DATA:
12346 start_ix = BUILT_IN_GOACC_DATA_START;
12347 break;
12348 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12349 start_ix = BUILT_IN_GOACC_UPDATE;
12350 break;
12351 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12352 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12353 break;
12354 default:
12355 gcc_unreachable ();
12358 clauses = gimple_omp_target_clauses (entry_stmt);
12360 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12361 library choose) and there is no conditional. */
12362 cond = NULL_TREE;
12363 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
12365 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12366 if (c)
12367 cond = OMP_CLAUSE_IF_EXPR (c);
12369 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12370 if (c)
12372 /* Even if we pass it to all library function calls, it is currently only
12373 defined/used for the OpenMP target ones. */
12374 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12375 || start_ix == BUILT_IN_GOMP_TARGET_DATA
12376 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12377 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
12379 device = OMP_CLAUSE_DEVICE_ID (c);
12380 clause_loc = OMP_CLAUSE_LOCATION (c);
12382 else
12383 clause_loc = gimple_location (entry_stmt);
12385 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12386 if (c)
12387 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12389 /* Ensure 'device' is of the correct type. */
12390 device = fold_convert_loc (clause_loc, integer_type_node, device);
12392 /* If we found the clause 'if (cond)', build
12393 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
12394 if (cond)
12396 cond = gimple_boolify (cond);
12398 basic_block cond_bb, then_bb, else_bb;
12399 edge e;
12400 tree tmp_var;
12402 tmp_var = create_tmp_var (TREE_TYPE (device));
12403 if (offloaded)
12404 e = split_block_after_labels (new_bb);
12405 else
12407 gsi = gsi_last_bb (new_bb);
12408 gsi_prev (&gsi);
12409 e = split_block (new_bb, gsi_stmt (gsi));
12411 cond_bb = e->src;
12412 new_bb = e->dest;
12413 remove_edge (e);
12415 then_bb = create_empty_bb (cond_bb);
12416 else_bb = create_empty_bb (then_bb);
12417 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12418 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12420 stmt = gimple_build_cond_empty (cond);
12421 gsi = gsi_last_bb (cond_bb);
12422 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12424 gsi = gsi_start_bb (then_bb);
12425 stmt = gimple_build_assign (tmp_var, device);
12426 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12428 gsi = gsi_start_bb (else_bb);
12429 stmt = gimple_build_assign (tmp_var,
12430 build_int_cst (integer_type_node,
12431 GOMP_DEVICE_HOST_FALLBACK));
12432 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12434 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12435 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
12436 add_bb_to_loop (then_bb, cond_bb->loop_father);
12437 add_bb_to_loop (else_bb, cond_bb->loop_father);
12438 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12439 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12441 device = tmp_var;
12444 gsi = gsi_last_bb (new_bb);
12445 t = gimple_omp_target_data_arg (entry_stmt);
12446 if (t == NULL)
12448 t1 = size_zero_node;
12449 t2 = build_zero_cst (ptr_type_node);
12450 t3 = t2;
12451 t4 = t2;
12453 else
12455 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12456 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12457 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12458 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12459 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12462 gimple *g;
12463 bool tagging = false;
12464 /* The maximum number used by any start_ix, without varargs. */
12465 auto_vec<tree, 11> args;
12466 args.quick_push (device);
12467 if (offloaded)
12468 args.quick_push (build_fold_addr_expr (child_fn));
12469 args.quick_push (t1);
12470 args.quick_push (t2);
12471 args.quick_push (t3);
12472 args.quick_push (t4);
12473 switch (start_ix)
12475 case BUILT_IN_GOACC_DATA_START:
12476 case BUILT_IN_GOMP_TARGET_DATA:
12477 break;
12478 case BUILT_IN_GOMP_TARGET:
12479 case BUILT_IN_GOMP_TARGET_UPDATE:
12480 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12481 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12482 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12483 if (c)
12484 depend = OMP_CLAUSE_DECL (c);
12485 else
12486 depend = build_int_cst (ptr_type_node, 0);
12487 args.quick_push (depend);
12488 break;
12489 case BUILT_IN_GOACC_PARALLEL:
12491 set_oacc_fn_attrib (child_fn, clauses, &args);
12492 tagging = true;
12494 /* FALLTHRU */
12495 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
12496 case BUILT_IN_GOACC_UPDATE:
12498 tree t_async = NULL_TREE;
12500 /* If present, use the value specified by the respective
12501 clause, making sure that is of the correct type. */
12502 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
12503 if (c)
12504 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12505 integer_type_node,
12506 OMP_CLAUSE_ASYNC_EXPR (c));
12507 else if (!tagging)
12508 /* Default values for t_async. */
12509 t_async = fold_convert_loc (gimple_location (entry_stmt),
12510 integer_type_node,
12511 build_int_cst (integer_type_node,
12512 GOMP_ASYNC_SYNC));
12513 if (tagging && t_async)
12515 unsigned HOST_WIDE_INT i_async;
12517 if (TREE_CODE (t_async) == INTEGER_CST)
12519 /* See if we can pack the async arg in to the tag's
12520 operand. */
12521 i_async = TREE_INT_CST_LOW (t_async);
12523 if (i_async < GOMP_LAUNCH_OP_MAX)
12524 t_async = NULL_TREE;
12526 if (t_async)
12527 i_async = GOMP_LAUNCH_OP_MAX;
12528 args.safe_push (oacc_launch_pack
12529 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
12531 if (t_async)
12532 args.safe_push (t_async);
12534 /* Save the argument index, and ... */
12535 unsigned t_wait_idx = args.length ();
12536 unsigned num_waits = 0;
12537 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
12538 if (!tagging || c)
12539 /* ... push a placeholder. */
12540 args.safe_push (integer_zero_node);
12542 for (; c; c = OMP_CLAUSE_CHAIN (c))
12543 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
12545 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12546 integer_type_node,
12547 OMP_CLAUSE_WAIT_EXPR (c)));
12548 num_waits++;
12551 if (!tagging || num_waits)
12553 tree len;
12555 /* Now that we know the number, update the placeholder. */
12556 if (tagging)
12557 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
12558 else
12559 len = build_int_cst (integer_type_node, num_waits);
12560 len = fold_convert_loc (gimple_location (entry_stmt),
12561 unsigned_type_node, len);
12562 args[t_wait_idx] = len;
12565 break;
12566 default:
12567 gcc_unreachable ();
12569 if (tagging)
12570 /* Push terminal marker - zero. */
12571 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
12573 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
12574 gimple_set_location (g, gimple_location (entry_stmt));
12575 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12576 if (!offloaded)
12578 g = gsi_stmt (gsi);
12579 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
12580 gsi_remove (&gsi, true);
12582 if (data_region && region->exit)
12584 gsi = gsi_last_bb (region->exit);
12585 g = gsi_stmt (gsi);
12586 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
12587 gsi_remove (&gsi, true);
12592 /* Expand the parallel region tree rooted at REGION. Expansion
12593 proceeds in depth-first order. Innermost regions are expanded
12594 first. This way, parallel regions that require a new function to
12595 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
12596 internal dependencies in their body. */
12598 static void
12599 expand_omp (struct omp_region *region)
12601 while (region)
12603 location_t saved_location;
12604 gimple *inner_stmt = NULL;
12606 /* First, determine whether this is a combined parallel+workshare
12607 region. */
12608 if (region->type == GIMPLE_OMP_PARALLEL)
12609 determine_parallel_type (region);
12611 if (region->type == GIMPLE_OMP_FOR
12612 && gimple_omp_for_combined_p (last_stmt (region->entry)))
12613 inner_stmt = last_stmt (region->inner->entry);
12615 if (region->inner)
12616 expand_omp (region->inner);
12618 saved_location = input_location;
12619 if (gimple_has_location (last_stmt (region->entry)))
12620 input_location = gimple_location (last_stmt (region->entry));
12622 switch (region->type)
12624 case GIMPLE_OMP_PARALLEL:
12625 case GIMPLE_OMP_TASK:
12626 expand_omp_taskreg (region);
12627 break;
12629 case GIMPLE_OMP_FOR:
12630 expand_omp_for (region, inner_stmt);
12631 break;
12633 case GIMPLE_OMP_SECTIONS:
12634 expand_omp_sections (region);
12635 break;
12637 case GIMPLE_OMP_SECTION:
12638 /* Individual omp sections are handled together with their
12639 parent GIMPLE_OMP_SECTIONS region. */
12640 break;
12642 case GIMPLE_OMP_SINGLE:
12643 expand_omp_single (region);
12644 break;
12646 case GIMPLE_OMP_ORDERED:
12648 gomp_ordered *ord_stmt
12649 = as_a <gomp_ordered *> (last_stmt (region->entry));
12650 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
12651 OMP_CLAUSE_DEPEND))
12653 /* We'll expand these when expanding corresponding
12654 worksharing region with ordered(n) clause. */
12655 gcc_assert (region->outer
12656 && region->outer->type == GIMPLE_OMP_FOR);
12657 region->ord_stmt = ord_stmt;
12658 break;
12661 /* FALLTHRU */
12662 case GIMPLE_OMP_MASTER:
12663 case GIMPLE_OMP_TASKGROUP:
12664 case GIMPLE_OMP_CRITICAL:
12665 case GIMPLE_OMP_TEAMS:
12666 expand_omp_synch (region);
12667 break;
12669 case GIMPLE_OMP_ATOMIC_LOAD:
12670 expand_omp_atomic (region);
12671 break;
12673 case GIMPLE_OMP_TARGET:
12674 expand_omp_target (region);
12675 break;
12677 default:
12678 gcc_unreachable ();
12681 input_location = saved_location;
12682 region = region->next;
12687 /* Helper for build_omp_regions. Scan the dominator tree starting at
12688 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
12689 true, the function ends once a single tree is built (otherwise, whole
12690 forest of OMP constructs may be built). */
12692 static void
12693 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
12694 bool single_tree)
12696 gimple_stmt_iterator gsi;
12697 gimple *stmt;
12698 basic_block son;
12700 gsi = gsi_last_bb (bb);
12701 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
12703 struct omp_region *region;
12704 enum gimple_code code;
12706 stmt = gsi_stmt (gsi);
12707 code = gimple_code (stmt);
12708 if (code == GIMPLE_OMP_RETURN)
12710 /* STMT is the return point out of region PARENT. Mark it
12711 as the exit point and make PARENT the immediately
12712 enclosing region. */
12713 gcc_assert (parent);
12714 region = parent;
12715 region->exit = bb;
12716 parent = parent->outer;
12718 else if (code == GIMPLE_OMP_ATOMIC_STORE)
12720 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
12721 GIMPLE_OMP_RETURN, but matches with
12722 GIMPLE_OMP_ATOMIC_LOAD. */
12723 gcc_assert (parent);
12724 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
12725 region = parent;
12726 region->exit = bb;
12727 parent = parent->outer;
12729 else if (code == GIMPLE_OMP_CONTINUE)
12731 gcc_assert (parent);
12732 parent->cont = bb;
12734 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
12736 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
12737 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
12739 else
12741 region = new_omp_region (bb, code, parent);
12742 /* Otherwise... */
12743 if (code == GIMPLE_OMP_TARGET)
12745 switch (gimple_omp_target_kind (stmt))
12747 case GF_OMP_TARGET_KIND_REGION:
12748 case GF_OMP_TARGET_KIND_DATA:
12749 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12750 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12751 case GF_OMP_TARGET_KIND_OACC_DATA:
12752 break;
12753 case GF_OMP_TARGET_KIND_UPDATE:
12754 case GF_OMP_TARGET_KIND_ENTER_DATA:
12755 case GF_OMP_TARGET_KIND_EXIT_DATA:
12756 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12757 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12758 /* ..., other than for those stand-alone directives... */
12759 region = NULL;
12760 break;
12761 default:
12762 gcc_unreachable ();
12765 else if (code == GIMPLE_OMP_ORDERED
12766 && find_omp_clause (gimple_omp_ordered_clauses
12767 (as_a <gomp_ordered *> (stmt)),
12768 OMP_CLAUSE_DEPEND))
12769 /* #pragma omp ordered depend is also just a stand-alone
12770 directive. */
12771 region = NULL;
12772 /* ..., this directive becomes the parent for a new region. */
12773 if (region)
12774 parent = region;
12778 if (single_tree && !parent)
12779 return;
12781 for (son = first_dom_son (CDI_DOMINATORS, bb);
12782 son;
12783 son = next_dom_son (CDI_DOMINATORS, son))
12784 build_omp_regions_1 (son, parent, single_tree);
12787 /* Builds the tree of OMP regions rooted at ROOT, storing it to
12788 root_omp_region. */
12790 static void
12791 build_omp_regions_root (basic_block root)
12793 gcc_assert (root_omp_region == NULL);
12794 build_omp_regions_1 (root, NULL, true);
12795 gcc_assert (root_omp_region != NULL);
12798 /* Expands omp construct (and its subconstructs) starting in HEAD. */
12800 void
12801 omp_expand_local (basic_block head)
12803 build_omp_regions_root (head);
12804 if (dump_file && (dump_flags & TDF_DETAILS))
12806 fprintf (dump_file, "\nOMP region tree\n\n");
12807 dump_omp_region (dump_file, root_omp_region, 0);
12808 fprintf (dump_file, "\n");
12811 remove_exit_barriers (root_omp_region);
12812 expand_omp (root_omp_region);
12814 free_omp_regions ();
12817 /* Scan the CFG and build a tree of OMP regions. Return the root of
12818 the OMP region tree. */
12820 static void
12821 build_omp_regions (void)
12823 gcc_assert (root_omp_region == NULL);
12824 calculate_dominance_info (CDI_DOMINATORS);
12825 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
12828 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
12830 static unsigned int
12831 execute_expand_omp (void)
12833 build_omp_regions ();
12835 if (!root_omp_region)
12836 return 0;
12838 if (dump_file)
12840 fprintf (dump_file, "\nOMP region tree\n\n");
12841 dump_omp_region (dump_file, root_omp_region, 0);
12842 fprintf (dump_file, "\n");
12845 remove_exit_barriers (root_omp_region);
12847 expand_omp (root_omp_region);
12849 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12850 verify_loop_structure ();
12851 cleanup_tree_cfg ();
12853 free_omp_regions ();
12855 return 0;
12858 /* OMP expansion -- the default pass, run before creation of SSA form. */
12860 namespace {
12862 const pass_data pass_data_expand_omp =
12864 GIMPLE_PASS, /* type */
12865 "ompexp", /* name */
12866 OPTGROUP_NONE, /* optinfo_flags */
12867 TV_NONE, /* tv_id */
12868 PROP_gimple_any, /* properties_required */
12869 PROP_gimple_eomp, /* properties_provided */
12870 0, /* properties_destroyed */
12871 0, /* todo_flags_start */
12872 0, /* todo_flags_finish */
12875 class pass_expand_omp : public gimple_opt_pass
12877 public:
12878 pass_expand_omp (gcc::context *ctxt)
12879 : gimple_opt_pass (pass_data_expand_omp, ctxt)
12882 /* opt_pass methods: */
12883 virtual unsigned int execute (function *)
12885 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
12886 || flag_openmp_simd != 0)
12887 && !seen_error ());
12889 /* This pass always runs, to provide PROP_gimple_eomp.
12890 But often, there is nothing to do. */
12891 if (!gate)
12892 return 0;
12894 return execute_expand_omp ();
12897 }; // class pass_expand_omp
12899 } // anon namespace
12901 gimple_opt_pass *
12902 make_pass_expand_omp (gcc::context *ctxt)
12904 return new pass_expand_omp (ctxt);
12907 namespace {
12909 const pass_data pass_data_expand_omp_ssa =
12911 GIMPLE_PASS, /* type */
12912 "ompexpssa", /* name */
12913 OPTGROUP_NONE, /* optinfo_flags */
12914 TV_NONE, /* tv_id */
12915 PROP_cfg | PROP_ssa, /* properties_required */
12916 PROP_gimple_eomp, /* properties_provided */
12917 0, /* properties_destroyed */
12918 0, /* todo_flags_start */
12919 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
12922 class pass_expand_omp_ssa : public gimple_opt_pass
12924 public:
12925 pass_expand_omp_ssa (gcc::context *ctxt)
12926 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
12929 /* opt_pass methods: */
12930 virtual bool gate (function *fun)
12932 return !(fun->curr_properties & PROP_gimple_eomp);
12934 virtual unsigned int execute (function *) { return execute_expand_omp (); }
12936 }; // class pass_expand_omp_ssa
12938 } // anon namespace
12940 gimple_opt_pass *
12941 make_pass_expand_omp_ssa (gcc::context *ctxt)
12943 return new pass_expand_omp_ssa (ctxt);
12946 /* Routines to lower OMP directives into OMP-GIMPLE. */
12948 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
12949 convert it to gimple. */
12950 static void
12951 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
12953 gimple *stmt;
12955 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
12957 stmt = gimple_build_assign (dest, op, dest, src);
12958 gimple_seq_add_stmt (seq, stmt);
12959 return;
12962 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12963 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12964 gimplify_assign (t, rdest, seq);
12965 rdest = t;
12967 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12968 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12969 gimplify_assign (t, idest, seq);
12970 idest = t;
12972 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12973 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12974 gimplify_assign (t, rsrc, seq);
12975 rsrc = t;
12977 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12978 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12979 gimplify_assign (t, isrc, seq);
12980 isrc = t;
12982 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12983 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12984 tree result;
12986 if (op == PLUS_EXPR)
12988 stmt = gimple_build_assign (r, op, rdest, rsrc);
12989 gimple_seq_add_stmt (seq, stmt);
12991 stmt = gimple_build_assign (i, op, idest, isrc);
12992 gimple_seq_add_stmt (seq, stmt);
12994 else if (op == MULT_EXPR)
12996 /* Let x = a + ib = dest, y = c + id = src.
12997 x * y = (ac - bd) + i(ad + bc) */
12998 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12999 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13000 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13001 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13003 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
13004 gimple_seq_add_stmt (seq, stmt);
13006 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
13007 gimple_seq_add_stmt (seq, stmt);
13009 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
13010 gimple_seq_add_stmt (seq, stmt);
13012 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
13013 gimple_seq_add_stmt (seq, stmt);
13015 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
13016 gimple_seq_add_stmt (seq, stmt);
13018 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
13019 gimple_seq_add_stmt (seq, stmt);
13021 else
13022 gcc_unreachable ();
13024 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
13025 gimplify_assign (dest, result, seq);
13028 /* Initialize the reduction array with default values. */
13030 static void
13031 oacc_init_reduction_array (tree array, tree init, tree nthreads,
13032 gimple_seq *stmt_seqp)
13034 tree type = TREE_TYPE (TREE_TYPE (array));
13035 tree x, loop_header, loop_body, loop_exit;
13036 gimple *stmt;
13038 /* Create for loop.
13040 let var = the original reduction variable
13041 let array = reduction variable array
13043 for (i = 0; i < nthreads; i++)
13044 var op= array[i]
13047 loop_header = create_artificial_label (UNKNOWN_LOCATION);
13048 loop_body = create_artificial_label (UNKNOWN_LOCATION);
13049 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
13051 /* Create and initialize an index variable. */
13052 tree ix = create_tmp_var (sizetype);
13053 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
13054 stmt_seqp);
13056 /* Insert the loop header label here. */
13057 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
13059 /* Exit loop if ix >= nthreads. */
13060 x = create_tmp_var (sizetype);
13061 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
13062 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
13063 gimple_seq_add_stmt (stmt_seqp, stmt);
13065 /* Insert the loop body label here. */
13066 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
13068 /* Calculate the array offset. */
13069 tree offset = create_tmp_var (sizetype);
13070 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
13071 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
13072 gimple_seq_add_stmt (stmt_seqp, stmt);
13074 tree ptr = create_tmp_var (TREE_TYPE (array));
13075 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
13076 gimple_seq_add_stmt (stmt_seqp, stmt);
13078 /* Assign init. */
13079 gimplify_assign (build_simple_mem_ref (ptr), init, stmt_seqp);
13081 /* Increment the induction variable. */
13082 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
13083 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
13084 gimple_seq_add_stmt (stmt_seqp, stmt);
13086 /* Go back to the top of the loop. */
13087 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
13089 /* Place the loop exit label here. */
13090 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
13093 /* Helper function to initialize local data for the reduction arrays.
13094 The reduction arrays need to be placed inside the calling function
13095 for accelerators, or else the host won't be able to preform the final
13096 reduction. */
13098 static void
13099 oacc_initialize_reduction_data (tree clauses, tree nthreads,
13100 gimple_seq *stmt_seqp, omp_context *ctx)
13102 tree c, t, oc;
13103 gimple *stmt;
13104 omp_context *octx;
13106 /* Find the innermost OpenACC parallel context. */
13107 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
13108 && (gimple_omp_target_kind (ctx->stmt)
13109 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
13110 octx = ctx;
13111 else
13112 octx = ctx->outer;
13113 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
13114 && (gimple_omp_target_kind (octx->stmt)
13115 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
13117 /* Extract the clauses. */
13118 oc = gimple_omp_target_clauses (octx->stmt);
13120 /* Find the last outer clause. */
13121 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
13124 /* Allocate arrays for each reduction variable. */
13125 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13127 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
13128 continue;
13130 tree var = OMP_CLAUSE_DECL (c);
13131 tree type = get_base_type (var);
13132 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
13133 ctx);
13134 tree size, call;
13136 /* Calculate size of the reduction array. */
13137 t = create_tmp_var (TREE_TYPE (nthreads));
13138 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
13139 fold_convert (TREE_TYPE (nthreads),
13140 TYPE_SIZE_UNIT (type)));
13141 gimple_seq_add_stmt (stmt_seqp, stmt);
13143 size = create_tmp_var (sizetype);
13144 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
13146 /* Now allocate memory for it. */
13147 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
13148 stmt = gimple_build_call (call, 1, size);
13149 gimple_call_set_lhs (stmt, array);
13150 gimple_seq_add_stmt (stmt_seqp, stmt);
13152 /* Initialize array. */
13153 tree init = omp_reduction_init_op (OMP_CLAUSE_LOCATION (c),
13154 OMP_CLAUSE_REDUCTION_CODE (c),
13155 type);
13156 oacc_init_reduction_array (array, init, nthreads, stmt_seqp);
13158 /* Map this array into the accelerator. */
13160 /* Add the reduction array to the list of clauses. */
13161 tree x = array;
13162 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
13163 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_TOFROM);
13164 OMP_CLAUSE_DECL (t) = x;
13165 OMP_CLAUSE_CHAIN (t) = NULL;
13166 if (oc)
13167 OMP_CLAUSE_CHAIN (oc) = t;
13168 else
13169 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
13170 OMP_CLAUSE_SIZE (t) = size;
13171 oc = t;
13175 /* Helper function to process the array of partial reductions. Nthreads
13176 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
13177 cannot be used here, because nthreads on the host may be different than
13178 on the accelerator. */
13180 static void
13181 oacc_finalize_reduction_data (tree clauses, tree nthreads,
13182 gimple_seq *stmt_seqp, omp_context *ctx)
13184 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
13185 gimple *stmt;
13187 /* Create for loop.
13189 let var = the original reduction variable
13190 let array = reduction variable array
13192 for (i = 0; i < nthreads; i++)
13193 var op= array[i]
13196 loop_header = create_artificial_label (UNKNOWN_LOCATION);
13197 loop_body = create_artificial_label (UNKNOWN_LOCATION);
13198 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
13200 /* Create and initialize an index variable. */
13201 tree ix = create_tmp_var (sizetype);
13202 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
13203 stmt_seqp);
13205 /* Insert the loop header label here. */
13206 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
13208 /* Exit loop if ix >= nthreads. */
13209 x = create_tmp_var (sizetype);
13210 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
13211 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
13212 gimple_seq_add_stmt (stmt_seqp, stmt);
13214 /* Insert the loop body label here. */
13215 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
13217 /* Collapse each reduction array, one element at a time. */
13218 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13220 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
13221 continue;
13223 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
13225 /* reduction(-:var) sums up the partial results, so it acts
13226 identically to reduction(+:var). */
13227 if (reduction_code == MINUS_EXPR)
13228 reduction_code = PLUS_EXPR;
13230 /* Set up reduction variable var. */
13231 var = OMP_CLAUSE_DECL (c);
13232 type = get_base_type (var);
13233 array = lookup_oacc_reduction (oacc_get_reduction_array_id
13234 (OMP_CLAUSE_DECL (c)), ctx);
13236 /* Calculate the array offset. */
13237 tree offset = create_tmp_var (sizetype);
13238 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
13239 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
13240 gimple_seq_add_stmt (stmt_seqp, stmt);
13242 tree ptr = create_tmp_var (TREE_TYPE (array));
13243 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
13244 gimple_seq_add_stmt (stmt_seqp, stmt);
13246 /* Extract array[ix] into mem. */
13247 tree mem = create_tmp_var (type);
13248 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
13250 /* Find the original reduction variable. */
13251 if (is_reference (var))
13252 var = build_simple_mem_ref (var);
13254 tree t = create_tmp_var (type);
13256 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
13257 gimplify_and_add (unshare_expr(x), stmt_seqp);
13259 /* var = var op mem */
13260 switch (OMP_CLAUSE_REDUCTION_CODE (c))
13262 case TRUTH_ANDIF_EXPR:
13263 case TRUTH_ORIF_EXPR:
13264 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
13265 t, mem);
13266 gimplify_and_add (t, stmt_seqp);
13267 break;
13268 default:
13269 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
13270 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
13271 stmt_seqp);
13274 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
13275 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
13276 gimplify_and_add (unshare_expr(x), stmt_seqp);
13279 /* Increment the induction variable. */
13280 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
13281 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
13282 gimple_seq_add_stmt (stmt_seqp, stmt);
13284 /* Go back to the top of the loop. */
13285 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
13287 /* Place the loop exit label here. */
13288 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
13291 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
13292 scan that for reductions. */
13294 static void
13295 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
13296 gimple_seq *out_stmt_seqp, omp_context *ctx)
13298 gimple_stmt_iterator gsi;
13299 gimple_seq inner = NULL;
13301 /* A collapse clause may have inserted a new bind block. */
13302 gsi = gsi_start (*body);
13303 while (!gsi_end_p (gsi))
13305 gimple *stmt = gsi_stmt (gsi);
13306 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
13308 inner = gimple_bind_body (bind_stmt);
13309 body = &inner;
13310 gsi = gsi_start (*body);
13312 else if (dyn_cast <gomp_for *> (stmt))
13313 break;
13314 else
13315 gsi_next (&gsi);
13318 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
13320 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
13321 enter, exit;
13322 bool reduction_found = false;
13324 gimple *stmt = gsi_stmt (gsi);
13326 switch (gimple_code (stmt))
13328 case GIMPLE_OMP_FOR:
13329 clauses = gimple_omp_for_clauses (stmt);
13331 /* Search for a reduction clause. */
13332 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13333 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
13335 reduction_found = true;
13336 break;
13339 if (!reduction_found)
13340 break;
13342 ctx = maybe_lookup_ctx (stmt);
13343 t = NULL_TREE;
13345 /* Extract the number of threads. */
13346 nthreads = create_tmp_var (sizetype);
13347 t = oacc_max_threads (ctx);
13348 gimplify_assign (nthreads, t, in_stmt_seqp);
13350 /* Determine if this is kernel will be executed on the host. */
13351 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
13352 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
13353 stmt = gimple_build_call (call, 0);
13354 gimple_call_set_lhs (stmt, acc_device);
13355 gimple_seq_add_stmt (in_stmt_seqp, stmt);
13357 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
13358 acc_device_host = create_tmp_var (integer_type_node,
13359 ".acc_device_host");
13360 gimplify_assign (acc_device_host,
13361 build_int_cst (integer_type_node,
13362 GOMP_DEVICE_HOST),
13363 in_stmt_seqp);
13365 enter = create_artificial_label (UNKNOWN_LOCATION);
13366 exit = create_artificial_label (UNKNOWN_LOCATION);
13368 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
13369 enter, exit);
13370 gimple_seq_add_stmt (in_stmt_seqp, stmt);
13371 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
13372 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
13373 integer_one_node),
13374 in_stmt_seqp);
13375 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
13377 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
13378 ctx);
13379 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
13380 break;
13381 default:
13382 // Scan for other directives which support reduction here.
13383 break;
13388 /* If ctx is a worksharing context inside of a cancellable parallel
13389 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13390 and conditional branch to parallel's cancel_label to handle
13391 cancellation in the implicit barrier. */
13393 static void
13394 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13396 gimple *omp_return = gimple_seq_last_stmt (*body);
13397 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13398 if (gimple_omp_return_nowait_p (omp_return))
13399 return;
13400 if (ctx->outer
13401 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13402 && ctx->outer->cancellable)
13404 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13405 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
13406 tree lhs = create_tmp_var (c_bool_type);
13407 gimple_omp_return_set_lhs (omp_return, lhs);
13408 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
13409 gimple *g = gimple_build_cond (NE_EXPR, lhs,
13410 fold_convert (c_bool_type,
13411 boolean_false_node),
13412 ctx->outer->cancel_label, fallthru_label);
13413 gimple_seq_add_stmt (body, g);
13414 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13418 /* Lower the OpenMP sections directive in the current statement in GSI_P.
13419 CTX is the enclosing OMP context for the current statement. */
13421 static void
13422 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13424 tree block, control;
13425 gimple_stmt_iterator tgsi;
13426 gomp_sections *stmt;
13427 gimple *t;
13428 gbind *new_stmt, *bind;
13429 gimple_seq ilist, dlist, olist, new_body;
13431 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
13433 push_gimplify_context ();
13435 dlist = NULL;
13436 ilist = NULL;
13437 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
13438 &ilist, &dlist, ctx, NULL);
13440 new_body = gimple_omp_body (stmt);
13441 gimple_omp_set_body (stmt, NULL);
13442 tgsi = gsi_start (new_body);
13443 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
13445 omp_context *sctx;
13446 gimple *sec_start;
13448 sec_start = gsi_stmt (tgsi);
13449 sctx = maybe_lookup_ctx (sec_start);
13450 gcc_assert (sctx);
13452 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13453 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13454 GSI_CONTINUE_LINKING);
13455 gimple_omp_set_body (sec_start, NULL);
13457 if (gsi_one_before_end_p (tgsi))
13459 gimple_seq l = NULL;
13460 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
13461 &l, ctx);
13462 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
13463 gimple_omp_section_set_last (sec_start);
13466 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13467 GSI_CONTINUE_LINKING);
13470 block = make_node (BLOCK);
13471 bind = gimple_build_bind (NULL, new_body, block);
13473 olist = NULL;
13474 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
13476 block = make_node (BLOCK);
13477 new_stmt = gimple_build_bind (NULL, NULL, block);
13478 gsi_replace (gsi_p, new_stmt, true);
13480 pop_gimplify_context (new_stmt);
13481 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13482 BLOCK_VARS (block) = gimple_bind_vars (bind);
13483 if (BLOCK_VARS (block))
13484 TREE_USED (block) = 1;
13486 new_body = NULL;
13487 gimple_seq_add_seq (&new_body, ilist);
13488 gimple_seq_add_stmt (&new_body, stmt);
13489 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13490 gimple_seq_add_stmt (&new_body, bind);
13492 control = create_tmp_var (unsigned_type_node, ".section");
13493 t = gimple_build_omp_continue (control, control);
13494 gimple_omp_sections_set_control (stmt, control);
13495 gimple_seq_add_stmt (&new_body, t);
13497 gimple_seq_add_seq (&new_body, olist);
13498 if (ctx->cancellable)
13499 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
13500 gimple_seq_add_seq (&new_body, dlist);
13502 new_body = maybe_catch_exception (new_body);
13504 t = gimple_build_omp_return
13505 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13506 OMP_CLAUSE_NOWAIT));
13507 gimple_seq_add_stmt (&new_body, t);
13508 maybe_add_implicit_barrier_cancel (ctx, &new_body);
13510 gimple_bind_set_body (new_stmt, new_body);
13514 /* A subroutine of lower_omp_single. Expand the simple form of
13515 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
13517 if (GOMP_single_start ())
13518 BODY;
13519 [ GOMP_barrier (); ] -> unless 'nowait' is present.
13521 FIXME. It may be better to delay expanding the logic of this until
13522 pass_expand_omp. The expanded logic may make the job more difficult
13523 to a synchronization analysis pass. */
13525 static void
13526 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
13528 location_t loc = gimple_location (single_stmt);
13529 tree tlabel = create_artificial_label (loc);
13530 tree flabel = create_artificial_label (loc);
13531 gimple *call, *cond;
13532 tree lhs, decl;
13534 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
13535 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
13536 call = gimple_build_call (decl, 0);
13537 gimple_call_set_lhs (call, lhs);
13538 gimple_seq_add_stmt (pre_p, call);
13540 cond = gimple_build_cond (EQ_EXPR, lhs,
13541 fold_convert_loc (loc, TREE_TYPE (lhs),
13542 boolean_true_node),
13543 tlabel, flabel);
13544 gimple_seq_add_stmt (pre_p, cond);
13545 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13546 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13547 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
13551 /* A subroutine of lower_omp_single. Expand the simple form of
13552 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
13554 #pragma omp single copyprivate (a, b, c)
13556 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13559 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13561 BODY;
13562 copyout.a = a;
13563 copyout.b = b;
13564 copyout.c = c;
13565 GOMP_single_copy_end (&copyout);
13567 else
13569 a = copyout_p->a;
13570 b = copyout_p->b;
13571 c = copyout_p->c;
13573 GOMP_barrier ();
13576 FIXME. It may be better to delay expanding the logic of this until
13577 pass_expand_omp. The expanded logic may make the job more difficult
13578 to a synchronization analysis pass. */
13580 static void
13581 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13582 omp_context *ctx)
13584 tree ptr_type, t, l0, l1, l2, bfn_decl;
13585 gimple_seq copyin_seq;
13586 location_t loc = gimple_location (single_stmt);
13588 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13590 ptr_type = build_pointer_type (ctx->record_type);
13591 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13593 l0 = create_artificial_label (loc);
13594 l1 = create_artificial_label (loc);
13595 l2 = create_artificial_label (loc);
13597 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13598 t = build_call_expr_loc (loc, bfn_decl, 0);
13599 t = fold_convert_loc (loc, ptr_type, t);
13600 gimplify_assign (ctx->receiver_decl, t, pre_p);
13602 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13603 build_int_cst (ptr_type, 0));
13604 t = build3 (COND_EXPR, void_type_node, t,
13605 build_and_jump (&l0), build_and_jump (&l1));
13606 gimplify_and_add (t, pre_p);
13608 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
13610 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13612 copyin_seq = NULL;
13613 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
13614 &copyin_seq, ctx);
13616 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13617 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13618 t = build_call_expr_loc (loc, bfn_decl, 1, t);
13619 gimplify_and_add (t, pre_p);
13621 t = build_and_jump (&l2);
13622 gimplify_and_add (t, pre_p);
13624 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
13626 gimple_seq_add_seq (pre_p, copyin_seq);
13628 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
13632 /* Expand code for an OpenMP single directive. */
13634 static void
13635 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13637 tree block;
13638 gimple *t;
13639 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13640 gbind *bind;
13641 gimple_seq bind_body, bind_body_tail = NULL, dlist;
13643 push_gimplify_context ();
13645 block = make_node (BLOCK);
13646 bind = gimple_build_bind (NULL, NULL, block);
13647 gsi_replace (gsi_p, bind, true);
13648 bind_body = NULL;
13649 dlist = NULL;
13650 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
13651 &bind_body, &dlist, ctx, NULL);
13652 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
13654 gimple_seq_add_stmt (&bind_body, single_stmt);
13656 if (ctx->record_type)
13657 lower_omp_single_copy (single_stmt, &bind_body, ctx);
13658 else
13659 lower_omp_single_simple (single_stmt, &bind_body);
13661 gimple_omp_set_body (single_stmt, NULL);
13663 gimple_seq_add_seq (&bind_body, dlist);
13665 bind_body = maybe_catch_exception (bind_body);
13667 t = gimple_build_omp_return
13668 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13669 OMP_CLAUSE_NOWAIT));
13670 gimple_seq_add_stmt (&bind_body_tail, t);
13671 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13672 if (ctx->record_type)
13674 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13675 tree clobber = build_constructor (ctx->record_type, NULL);
13676 TREE_THIS_VOLATILE (clobber) = 1;
13677 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13678 clobber), GSI_SAME_STMT);
13680 gimple_seq_add_seq (&bind_body, bind_body_tail);
13681 gimple_bind_set_body (bind, bind_body);
13683 pop_gimplify_context (bind);
13685 gimple_bind_append_vars (bind, ctx->block_vars);
13686 BLOCK_VARS (block) = ctx->block_vars;
13687 if (BLOCK_VARS (block))
13688 TREE_USED (block) = 1;
13692 /* Expand code for an OpenMP master directive. */
13694 static void
13695 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13697 tree block, lab = NULL, x, bfn_decl;
13698 gimple *stmt = gsi_stmt (*gsi_p);
13699 gbind *bind;
13700 location_t loc = gimple_location (stmt);
13701 gimple_seq tseq;
13703 push_gimplify_context ();
13705 block = make_node (BLOCK);
13706 bind = gimple_build_bind (NULL, NULL, block);
13707 gsi_replace (gsi_p, bind, true);
13708 gimple_bind_add_stmt (bind, stmt);
13710 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13711 x = build_call_expr_loc (loc, bfn_decl, 0);
13712 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13713 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
13714 tseq = NULL;
13715 gimplify_and_add (x, &tseq);
13716 gimple_bind_add_seq (bind, tseq);
13718 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13719 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13720 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13721 gimple_omp_set_body (stmt, NULL);
13723 gimple_bind_add_stmt (bind, gimple_build_label (lab));
13725 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13727 pop_gimplify_context (bind);
13729 gimple_bind_append_vars (bind, ctx->block_vars);
13730 BLOCK_VARS (block) = ctx->block_vars;
13734 /* Expand code for an OpenMP taskgroup directive. */
13736 static void
13737 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13739 gimple *stmt = gsi_stmt (*gsi_p);
13740 gcall *x;
13741 gbind *bind;
13742 tree block = make_node (BLOCK);
13744 bind = gimple_build_bind (NULL, NULL, block);
13745 gsi_replace (gsi_p, bind, true);
13746 gimple_bind_add_stmt (bind, stmt);
13748 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13750 gimple_bind_add_stmt (bind, x);
13752 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13753 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13754 gimple_omp_set_body (stmt, NULL);
13756 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13758 gimple_bind_append_vars (bind, ctx->block_vars);
13759 BLOCK_VARS (block) = ctx->block_vars;
13763 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13765 static void
13766 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13767 omp_context *ctx)
13769 struct omp_for_data fd;
13770 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13771 return;
13773 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13774 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13775 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13776 if (!fd.ordered)
13777 return;
13779 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13780 tree c = gimple_omp_ordered_clauses (ord_stmt);
13781 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13782 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13784 /* Merge depend clauses from multiple adjacent
13785 #pragma omp ordered depend(sink:...) constructs
13786 into one #pragma omp ordered depend(sink:...), so that
13787 we can optimize them together. */
13788 gimple_stmt_iterator gsi = *gsi_p;
13789 gsi_next (&gsi);
13790 while (!gsi_end_p (gsi))
13792 gimple *stmt = gsi_stmt (gsi);
13793 if (is_gimple_debug (stmt)
13794 || gimple_code (stmt) == GIMPLE_NOP)
13796 gsi_next (&gsi);
13797 continue;
13799 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13800 break;
13801 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13802 c = gimple_omp_ordered_clauses (ord_stmt2);
13803 if (c == NULL_TREE
13804 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13805 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13806 break;
13807 while (*list_p)
13808 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13809 *list_p = c;
13810 gsi_remove (&gsi, true);
13814 /* Canonicalize sink dependence clauses into one folded clause if
13815 possible.
13817 The basic algorithm is to create a sink vector whose first
13818 element is the GCD of all the first elements, and whose remaining
13819 elements are the minimum of the subsequent columns.
13821 We ignore dependence vectors whose first element is zero because
13822 such dependencies are known to be executed by the same thread.
13824 We take into account the direction of the loop, so a minimum
13825 becomes a maximum if the loop is iterating forwards. We also
13826 ignore sink clauses where the loop direction is unknown, or where
13827 the offsets are clearly invalid because they are not a multiple
13828 of the loop increment.
13830 For example:
13832 #pragma omp for ordered(2)
13833 for (i=0; i < N; ++i)
13834 for (j=0; j < M; ++j)
13836 #pragma omp ordered \
13837 depend(sink:i-8,j-2) \
13838 depend(sink:i,j-1) \ // Completely ignored because i+0.
13839 depend(sink:i-4,j-3) \
13840 depend(sink:i-6,j-4)
13841 #pragma omp ordered depend(source)
13844 Folded clause is:
13846 depend(sink:-gcd(8,4,6),-min(2,3,4))
13847 -or-
13848 depend(sink:-2,-2)
13851 /* FIXME: Computing GCD's where the first element is zero is
13852 non-trivial in the presence of collapsed loops. Do this later. */
13853 if (fd.collapse > 1)
13854 return;
13856 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13857 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13858 tree folded_dep = NULL_TREE;
13859 /* TRUE if the first dimension's offset is negative. */
13860 bool neg_offset_p = false;
13862 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13863 unsigned int i;
13864 while ((c = *list_p) != NULL)
13866 bool remove = false;
13868 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13869 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13870 goto next_ordered_clause;
13872 tree vec;
13873 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13874 vec && TREE_CODE (vec) == TREE_LIST;
13875 vec = TREE_CHAIN (vec), ++i)
13877 gcc_assert (i < len);
13879 /* extract_omp_for_data has canonicalized the condition. */
13880 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13881 || fd.loops[i].cond_code == GT_EXPR);
13882 bool forward = fd.loops[i].cond_code == LT_EXPR;
13883 bool maybe_lexically_later = true;
13885 /* While the committee makes up its mind, bail if we have any
13886 non-constant steps. */
13887 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13888 goto lower_omp_ordered_ret;
13890 tree itype = TREE_TYPE (TREE_VALUE (vec));
13891 if (POINTER_TYPE_P (itype))
13892 itype = sizetype;
13893 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13894 TYPE_PRECISION (itype),
13895 TYPE_SIGN (itype));
13897 /* Ignore invalid offsets that are not multiples of the step. */
13898 if (!wi::multiple_of_p
13899 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13900 UNSIGNED))
13902 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13903 "ignoring sink clause with offset that is not "
13904 "a multiple of the loop step");
13905 remove = true;
13906 goto next_ordered_clause;
13909 /* Calculate the first dimension. The first dimension of
13910 the folded dependency vector is the GCD of the first
13911 elements, while ignoring any first elements whose offset
13912 is 0. */
13913 if (i == 0)
13915 /* Ignore dependence vectors whose first dimension is 0. */
13916 if (offset == 0)
13918 remove = true;
13919 goto next_ordered_clause;
13921 else
13923 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13925 error_at (OMP_CLAUSE_LOCATION (c),
13926 "first offset must be in opposite direction "
13927 "of loop iterations");
13928 goto lower_omp_ordered_ret;
13930 if (forward)
13931 offset = -offset;
13932 neg_offset_p = forward;
13933 /* Initialize the first time around. */
13934 if (folded_dep == NULL_TREE)
13936 folded_dep = c;
13937 folded_deps[0] = offset;
13939 else
13940 folded_deps[0] = wi::gcd (folded_deps[0],
13941 offset, UNSIGNED);
13944 /* Calculate minimum for the remaining dimensions. */
13945 else
13947 folded_deps[len + i - 1] = offset;
13948 if (folded_dep == c)
13949 folded_deps[i] = offset;
13950 else if (maybe_lexically_later
13951 && !wi::eq_p (folded_deps[i], offset))
13953 if (forward ^ wi::gts_p (folded_deps[i], offset))
13955 unsigned int j;
13956 folded_dep = c;
13957 for (j = 1; j <= i; j++)
13958 folded_deps[j] = folded_deps[len + j - 1];
13960 else
13961 maybe_lexically_later = false;
13965 gcc_assert (i == len);
13967 remove = true;
13969 next_ordered_clause:
13970 if (remove)
13971 *list_p = OMP_CLAUSE_CHAIN (c);
13972 else
13973 list_p = &OMP_CLAUSE_CHAIN (c);
13976 if (folded_dep)
13978 if (neg_offset_p)
13979 folded_deps[0] = -folded_deps[0];
13981 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13982 if (POINTER_TYPE_P (itype))
13983 itype = sizetype;
13985 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13986 = wide_int_to_tree (itype, folded_deps[0]);
13987 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13988 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13991 lower_omp_ordered_ret:
13993 /* Ordered without clauses is #pragma omp threads, while we want
13994 a nop instead if we remove all clauses. */
13995 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13996 gsi_replace (gsi_p, gimple_build_nop (), true);
14000 /* Expand code for an OpenMP ordered directive. */
14002 static void
14003 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14005 tree block;
14006 gimple *stmt = gsi_stmt (*gsi_p);
14007 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14008 gcall *x;
14009 gbind *bind;
14010 bool simd
14011 = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt), OMP_CLAUSE_SIMD);
14013 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14014 OMP_CLAUSE_DEPEND))
14016 /* FIXME: This is needs to be moved to the expansion to verify various
14017 conditions only testable on cfg with dominators computed, and also
14018 all the depend clauses to be merged still might need to be available
14019 for the runtime checks. */
14020 if (0)
14021 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14022 return;
14025 push_gimplify_context ();
14027 block = make_node (BLOCK);
14028 bind = gimple_build_bind (NULL, NULL, block);
14029 gsi_replace (gsi_p, bind, true);
14030 gimple_bind_add_stmt (bind, stmt);
14032 if (simd)
14034 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 0);
14035 cfun->has_simduid_loops = true;
14037 else
14038 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14040 gimple_bind_add_stmt (bind, x);
14042 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14043 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14044 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14045 gimple_omp_set_body (stmt, NULL);
14047 if (simd)
14048 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 0);
14049 else
14050 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14052 gimple_bind_add_stmt (bind, x);
14054 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14056 pop_gimplify_context (bind);
14058 gimple_bind_append_vars (bind, ctx->block_vars);
14059 BLOCK_VARS (block) = gimple_bind_vars (bind);
14063 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14064 substitution of a couple of function calls. But in the NAMED case,
14065 requires that languages coordinate a symbol name. It is therefore
14066 best put here in common code. */
14068 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14070 static void
14071 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14073 tree block;
14074 tree name, lock, unlock;
14075 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14076 gbind *bind;
14077 location_t loc = gimple_location (stmt);
14078 gimple_seq tbody;
14080 name = gimple_omp_critical_name (stmt);
14081 if (name)
14083 tree decl;
14085 if (!critical_name_mutexes)
14086 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14088 tree *n = critical_name_mutexes->get (name);
14089 if (n == NULL)
14091 char *new_str;
14093 decl = create_tmp_var_raw (ptr_type_node);
14095 new_str = ACONCAT ((".gomp_critical_user_",
14096 IDENTIFIER_POINTER (name), NULL));
14097 DECL_NAME (decl) = get_identifier (new_str);
14098 TREE_PUBLIC (decl) = 1;
14099 TREE_STATIC (decl) = 1;
14100 DECL_COMMON (decl) = 1;
14101 DECL_ARTIFICIAL (decl) = 1;
14102 DECL_IGNORED_P (decl) = 1;
14104 varpool_node::finalize_decl (decl);
14106 critical_name_mutexes->put (name, decl);
14108 else
14109 decl = *n;
14111 /* If '#pragma omp critical' is inside offloaded region or
14112 inside function marked as offloadable, the symbol must be
14113 marked as offloadable too. */
14114 omp_context *octx;
14115 if (cgraph_node::get (current_function_decl)->offloadable)
14116 varpool_node::get_create (decl)->offloadable = 1;
14117 else
14118 for (octx = ctx->outer; octx; octx = octx->outer)
14119 if (is_gimple_omp_offloaded (octx->stmt))
14121 varpool_node::get_create (decl)->offloadable = 1;
14122 break;
14125 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14126 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14128 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14129 unlock = build_call_expr_loc (loc, unlock, 1,
14130 build_fold_addr_expr_loc (loc, decl));
14132 else
14134 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14135 lock = build_call_expr_loc (loc, lock, 0);
14137 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14138 unlock = build_call_expr_loc (loc, unlock, 0);
14141 push_gimplify_context ();
14143 block = make_node (BLOCK);
14144 bind = gimple_build_bind (NULL, NULL, block);
14145 gsi_replace (gsi_p, bind, true);
14146 gimple_bind_add_stmt (bind, stmt);
14148 tbody = gimple_bind_body (bind);
14149 gimplify_and_add (lock, &tbody);
14150 gimple_bind_set_body (bind, tbody);
14152 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14153 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14154 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14155 gimple_omp_set_body (stmt, NULL);
14157 tbody = gimple_bind_body (bind);
14158 gimplify_and_add (unlock, &tbody);
14159 gimple_bind_set_body (bind, tbody);
14161 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14163 pop_gimplify_context (bind);
14164 gimple_bind_append_vars (bind, ctx->block_vars);
14165 BLOCK_VARS (block) = gimple_bind_vars (bind);
14169 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14170 for a lastprivate clause. Given a loop control predicate of (V
14171 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14172 is appended to *DLIST, iterator initialization is appended to
14173 *BODY_P. */
14175 static void
14176 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14177 gimple_seq *dlist, struct omp_context *ctx)
14179 tree clauses, cond, vinit;
14180 enum tree_code cond_code;
14181 gimple_seq stmts;
14183 cond_code = fd->loop.cond_code;
14184 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14186 /* When possible, use a strict equality expression. This can let VRP
14187 type optimizations deduce the value and remove a copy. */
14188 if (tree_fits_shwi_p (fd->loop.step))
14190 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14191 if (step == 1 || step == -1)
14192 cond_code = EQ_EXPR;
14195 tree n2 = fd->loop.n2;
14196 if (fd->collapse > 1
14197 && TREE_CODE (n2) != INTEGER_CST
14198 && gimple_omp_for_combined_into_p (fd->for_stmt))
14200 struct omp_context *task_ctx = NULL;
14201 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14203 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14204 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
14206 struct omp_for_data outer_fd;
14207 extract_omp_for_data (gfor, &outer_fd, NULL);
14208 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14210 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14211 task_ctx = ctx->outer->outer;
14213 else if (is_task_ctx (ctx->outer))
14214 task_ctx = ctx->outer;
14215 if (task_ctx)
14217 int i;
14218 tree innerc
14219 = find_omp_clause (gimple_omp_task_clauses (task_ctx->stmt),
14220 OMP_CLAUSE__LOOPTEMP_);
14221 gcc_assert (innerc);
14222 for (i = 0; i < fd->collapse; i++)
14224 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14225 OMP_CLAUSE__LOOPTEMP_);
14226 gcc_assert (innerc);
14228 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14229 OMP_CLAUSE__LOOPTEMP_);
14230 if (innerc)
14231 n2 = fold_convert (TREE_TYPE (n2),
14232 lookup_decl (OMP_CLAUSE_DECL (innerc),
14233 task_ctx));
14236 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14238 clauses = gimple_omp_for_clauses (fd->for_stmt);
14239 stmts = NULL;
14240 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14241 if (!gimple_seq_empty_p (stmts))
14243 gimple_seq_add_seq (&stmts, *dlist);
14244 *dlist = stmts;
14246 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14247 vinit = fd->loop.n1;
14248 if (cond_code == EQ_EXPR
14249 && tree_fits_shwi_p (fd->loop.n2)
14250 && ! integer_zerop (fd->loop.n2))
14251 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14252 else
14253 vinit = unshare_expr (vinit);
14255 /* Initialize the iterator variable, so that threads that don't execute
14256 any iterations don't execute the lastprivate clauses by accident. */
14257 gimplify_assign (fd->loop.v, vinit, body_p);
14262 /* Lower code for an OMP loop directive. */
14264 static void
14265 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14267 tree *rhs_p, block;
14268 struct omp_for_data fd, *fdp = NULL;
14269 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14270 gbind *new_stmt;
14271 gimple_seq omp_for_body, body, dlist;
14272 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14273 size_t i;
14275 push_gimplify_context ();
14277 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14279 block = make_node (BLOCK);
14280 new_stmt = gimple_build_bind (NULL, NULL, block);
14281 /* Replace at gsi right away, so that 'stmt' is no member
14282 of a sequence anymore as we're going to add to a different
14283 one below. */
14284 gsi_replace (gsi_p, new_stmt, true);
14286 /* Move declaration of temporaries in the loop body before we make
14287 it go away. */
14288 omp_for_body = gimple_omp_body (stmt);
14289 if (!gimple_seq_empty_p (omp_for_body)
14290 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14292 gbind *inner_bind
14293 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14294 tree vars = gimple_bind_vars (inner_bind);
14295 gimple_bind_append_vars (new_stmt, vars);
14296 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14297 keep them on the inner_bind and it's block. */
14298 gimple_bind_set_vars (inner_bind, NULL_TREE);
14299 if (gimple_bind_block (inner_bind))
14300 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
14303 if (gimple_omp_for_combined_into_p (stmt))
14305 extract_omp_for_data (stmt, &fd, NULL);
14306 fdp = &fd;
14308 /* We need two temporaries with fd.loop.v type (istart/iend)
14309 and then (fd.collapse - 1) temporaries with the same
14310 type for count2 ... countN-1 vars if not constant. */
14311 size_t count = 2;
14312 tree type = fd.iter_type;
14313 if (fd.collapse > 1
14314 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14315 count += fd.collapse - 1;
14316 bool taskreg_for
14317 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14318 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
14319 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14320 tree clauses = *pc;
14321 if (taskreg_for)
14322 outerc
14323 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
14324 OMP_CLAUSE__LOOPTEMP_);
14325 for (i = 0; i < count; i++)
14327 tree temp;
14328 if (taskreg_for)
14330 gcc_assert (outerc);
14331 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14332 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14333 OMP_CLAUSE__LOOPTEMP_);
14335 else
14337 temp = create_tmp_var (type);
14338 insert_decl_map (&ctx->outer->cb, temp, temp);
14340 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14341 OMP_CLAUSE_DECL (*pc) = temp;
14342 pc = &OMP_CLAUSE_CHAIN (*pc);
14344 *pc = clauses;
14347 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
14348 dlist = NULL;
14349 body = NULL;
14350 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14351 fdp);
14352 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
14354 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14356 /* Lower the header expressions. At this point, we can assume that
14357 the header is of the form:
14359 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14361 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14362 using the .omp_data_s mapping, if needed. */
14363 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
14365 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
14366 if (!is_gimple_min_invariant (*rhs_p))
14367 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14369 rhs_p = gimple_omp_for_final_ptr (stmt, i);
14370 if (!is_gimple_min_invariant (*rhs_p))
14371 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14373 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
14374 if (!is_gimple_min_invariant (*rhs_p))
14375 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14378 /* Once lowered, extract the bounds and clauses. */
14379 extract_omp_for_data (stmt, &fd, NULL);
14381 if (is_gimple_omp_oacc (ctx->stmt)
14382 && !ctx_in_oacc_kernels_region (ctx))
14383 lower_oacc_head_tail (gimple_location (stmt),
14384 gimple_omp_for_clauses (stmt),
14385 &oacc_head, &oacc_tail, ctx);
14387 /* Add OpenACC partitioning markers just before the loop */
14388 if (oacc_head)
14389 gimple_seq_add_seq (&body, oacc_head);
14391 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
14393 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14394 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14395 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14396 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14398 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14399 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14400 OMP_CLAUSE_LINEAR_STEP (c)
14401 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14402 ctx);
14405 gimple_seq_add_stmt (&body, stmt);
14406 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
14408 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14409 fd.loop.v));
14411 /* After the loop, add exit clauses. */
14412 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
14414 if (ctx->cancellable)
14415 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14417 gimple_seq_add_seq (&body, dlist);
14419 body = maybe_catch_exception (body);
14421 /* Region exit marker goes at the end of the loop body. */
14422 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
14423 maybe_add_implicit_barrier_cancel (ctx, &body);
14425 /* Add OpenACC joining and reduction markers just after the loop. */
14426 if (oacc_tail)
14427 gimple_seq_add_seq (&body, oacc_tail);
14429 pop_gimplify_context (new_stmt);
14431 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14432 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
14433 if (BLOCK_VARS (block))
14434 TREE_USED (block) = 1;
14436 gimple_bind_set_body (new_stmt, body);
14437 gimple_omp_set_body (stmt, NULL);
14438 gimple_omp_for_set_pre_body (stmt, NULL);
14441 /* Callback for walk_stmts. Check if the current statement only contains
14442 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
14444 static tree
14445 check_combined_parallel (gimple_stmt_iterator *gsi_p,
14446 bool *handled_ops_p,
14447 struct walk_stmt_info *wi)
14449 int *info = (int *) wi->info;
14450 gimple *stmt = gsi_stmt (*gsi_p);
14452 *handled_ops_p = true;
14453 switch (gimple_code (stmt))
14455 WALK_SUBSTMTS;
14457 case GIMPLE_OMP_FOR:
14458 case GIMPLE_OMP_SECTIONS:
14459 *info = *info == 0 ? 1 : -1;
14460 break;
14461 default:
14462 *info = -1;
14463 break;
14465 return NULL;
14468 struct omp_taskcopy_context
14470 /* This field must be at the beginning, as we do "inheritance": Some
14471 callback functions for tree-inline.c (e.g., omp_copy_decl)
14472 receive a copy_body_data pointer that is up-casted to an
14473 omp_context pointer. */
14474 copy_body_data cb;
14475 omp_context *ctx;
14478 static tree
14479 task_copyfn_copy_decl (tree var, copy_body_data *cb)
14481 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14483 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
14484 return create_tmp_var (TREE_TYPE (var));
14486 return var;
14489 static tree
14490 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14492 tree name, new_fields = NULL, type, f;
14494 type = lang_hooks.types.make_type (RECORD_TYPE);
14495 name = DECL_NAME (TYPE_NAME (orig_type));
14496 name = build_decl (gimple_location (tcctx->ctx->stmt),
14497 TYPE_DECL, name, type);
14498 TYPE_NAME (type) = name;
14500 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14502 tree new_f = copy_node (f);
14503 DECL_CONTEXT (new_f) = type;
14504 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14505 TREE_CHAIN (new_f) = new_fields;
14506 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14507 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14508 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14509 &tcctx->cb, NULL);
14510 new_fields = new_f;
14511 tcctx->cb.decl_map->put (f, new_f);
14513 TYPE_FIELDS (type) = nreverse (new_fields);
14514 layout_type (type);
14515 return type;
14518 /* Create task copyfn. */
14520 static void
14521 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
14523 struct function *child_cfun;
14524 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14525 tree record_type, srecord_type, bind, list;
14526 bool record_needs_remap = false, srecord_needs_remap = false;
14527 splay_tree_node n;
14528 struct omp_taskcopy_context tcctx;
14529 location_t loc = gimple_location (task_stmt);
14531 child_fn = gimple_omp_task_copy_fn (task_stmt);
14532 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14533 gcc_assert (child_cfun->cfg == NULL);
14534 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14536 /* Reset DECL_CONTEXT on function arguments. */
14537 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
14538 DECL_CONTEXT (t) = child_fn;
14540 /* Populate the function. */
14541 push_gimplify_context ();
14542 push_cfun (child_cfun);
14544 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14545 TREE_SIDE_EFFECTS (bind) = 1;
14546 list = NULL;
14547 DECL_SAVED_TREE (child_fn) = bind;
14548 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
14550 /* Remap src and dst argument types if needed. */
14551 record_type = ctx->record_type;
14552 srecord_type = ctx->srecord_type;
14553 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
14554 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14556 record_needs_remap = true;
14557 break;
14559 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
14560 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14562 srecord_needs_remap = true;
14563 break;
14566 if (record_needs_remap || srecord_needs_remap)
14568 memset (&tcctx, '\0', sizeof (tcctx));
14569 tcctx.cb.src_fn = ctx->cb.src_fn;
14570 tcctx.cb.dst_fn = child_fn;
14571 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
14572 gcc_checking_assert (tcctx.cb.src_node);
14573 tcctx.cb.dst_node = tcctx.cb.src_node;
14574 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14575 tcctx.cb.copy_decl = task_copyfn_copy_decl;
14576 tcctx.cb.eh_lp_nr = 0;
14577 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
14578 tcctx.cb.decl_map = new hash_map<tree, tree>;
14579 tcctx.ctx = ctx;
14581 if (record_needs_remap)
14582 record_type = task_copyfn_remap_type (&tcctx, record_type);
14583 if (srecord_needs_remap)
14584 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14586 else
14587 tcctx.cb.decl_map = NULL;
14589 arg = DECL_ARGUMENTS (child_fn);
14590 TREE_TYPE (arg) = build_pointer_type (record_type);
14591 sarg = DECL_CHAIN (arg);
14592 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14594 /* First pass: initialize temporaries used in record_type and srecord_type
14595 sizes and field offsets. */
14596 if (tcctx.cb.decl_map)
14597 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14598 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14600 tree *p;
14602 decl = OMP_CLAUSE_DECL (c);
14603 p = tcctx.cb.decl_map->get (decl);
14604 if (p == NULL)
14605 continue;
14606 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14607 sf = (tree) n->value;
14608 sf = *tcctx.cb.decl_map->get (sf);
14609 src = build_simple_mem_ref_loc (loc, sarg);
14610 src = omp_build_component_ref (src, sf);
14611 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
14612 append_to_statement_list (t, &list);
14615 /* Second pass: copy shared var pointers and copy construct non-VLA
14616 firstprivate vars. */
14617 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14618 switch (OMP_CLAUSE_CODE (c))
14620 splay_tree_key key;
14621 case OMP_CLAUSE_SHARED:
14622 decl = OMP_CLAUSE_DECL (c);
14623 key = (splay_tree_key) decl;
14624 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14625 key = (splay_tree_key) &DECL_UID (decl);
14626 n = splay_tree_lookup (ctx->field_map, key);
14627 if (n == NULL)
14628 break;
14629 f = (tree) n->value;
14630 if (tcctx.cb.decl_map)
14631 f = *tcctx.cb.decl_map->get (f);
14632 n = splay_tree_lookup (ctx->sfield_map, key);
14633 sf = (tree) n->value;
14634 if (tcctx.cb.decl_map)
14635 sf = *tcctx.cb.decl_map->get (sf);
14636 src = build_simple_mem_ref_loc (loc, sarg);
14637 src = omp_build_component_ref (src, sf);
14638 dst = build_simple_mem_ref_loc (loc, arg);
14639 dst = omp_build_component_ref (dst, f);
14640 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14641 append_to_statement_list (t, &list);
14642 break;
14643 case OMP_CLAUSE_FIRSTPRIVATE:
14644 decl = OMP_CLAUSE_DECL (c);
14645 if (is_variable_sized (decl))
14646 break;
14647 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14648 if (n == NULL)
14649 break;
14650 f = (tree) n->value;
14651 if (tcctx.cb.decl_map)
14652 f = *tcctx.cb.decl_map->get (f);
14653 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14654 if (n != NULL)
14656 sf = (tree) n->value;
14657 if (tcctx.cb.decl_map)
14658 sf = *tcctx.cb.decl_map->get (sf);
14659 src = build_simple_mem_ref_loc (loc, sarg);
14660 src = omp_build_component_ref (src, sf);
14661 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
14662 src = build_simple_mem_ref_loc (loc, src);
14664 else
14665 src = decl;
14666 dst = build_simple_mem_ref_loc (loc, arg);
14667 dst = omp_build_component_ref (dst, f);
14668 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14669 append_to_statement_list (t, &list);
14670 break;
14671 case OMP_CLAUSE_PRIVATE:
14672 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14673 break;
14674 decl = OMP_CLAUSE_DECL (c);
14675 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14676 f = (tree) n->value;
14677 if (tcctx.cb.decl_map)
14678 f = *tcctx.cb.decl_map->get (f);
14679 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14680 if (n != NULL)
14682 sf = (tree) n->value;
14683 if (tcctx.cb.decl_map)
14684 sf = *tcctx.cb.decl_map->get (sf);
14685 src = build_simple_mem_ref_loc (loc, sarg);
14686 src = omp_build_component_ref (src, sf);
14687 if (use_pointer_for_field (decl, NULL))
14688 src = build_simple_mem_ref_loc (loc, src);
14690 else
14691 src = decl;
14692 dst = build_simple_mem_ref_loc (loc, arg);
14693 dst = omp_build_component_ref (dst, f);
14694 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14695 append_to_statement_list (t, &list);
14696 break;
14697 default:
14698 break;
14701 /* Last pass: handle VLA firstprivates. */
14702 if (tcctx.cb.decl_map)
14703 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14704 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14706 tree ind, ptr, df;
14708 decl = OMP_CLAUSE_DECL (c);
14709 if (!is_variable_sized (decl))
14710 continue;
14711 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14712 if (n == NULL)
14713 continue;
14714 f = (tree) n->value;
14715 f = *tcctx.cb.decl_map->get (f);
14716 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14717 ind = DECL_VALUE_EXPR (decl);
14718 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14719 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14720 n = splay_tree_lookup (ctx->sfield_map,
14721 (splay_tree_key) TREE_OPERAND (ind, 0));
14722 sf = (tree) n->value;
14723 sf = *tcctx.cb.decl_map->get (sf);
14724 src = build_simple_mem_ref_loc (loc, sarg);
14725 src = omp_build_component_ref (src, sf);
14726 src = build_simple_mem_ref_loc (loc, src);
14727 dst = build_simple_mem_ref_loc (loc, arg);
14728 dst = omp_build_component_ref (dst, f);
14729 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14730 append_to_statement_list (t, &list);
14731 n = splay_tree_lookup (ctx->field_map,
14732 (splay_tree_key) TREE_OPERAND (ind, 0));
14733 df = (tree) n->value;
14734 df = *tcctx.cb.decl_map->get (df);
14735 ptr = build_simple_mem_ref_loc (loc, arg);
14736 ptr = omp_build_component_ref (ptr, df);
14737 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
14738 build_fold_addr_expr_loc (loc, dst));
14739 append_to_statement_list (t, &list);
14742 t = build1 (RETURN_EXPR, void_type_node, NULL);
14743 append_to_statement_list (t, &list);
14745 if (tcctx.cb.decl_map)
14746 delete tcctx.cb.decl_map;
14747 pop_gimplify_context (NULL);
14748 BIND_EXPR_BODY (bind) = list;
14749 pop_cfun ();
14752 static void
14753 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
14755 tree c, clauses;
14756 gimple *g;
14757 size_t n_in = 0, n_out = 0, idx = 2, i;
14759 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
14760 gcc_assert (clauses);
14761 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14763 switch (OMP_CLAUSE_DEPEND_KIND (c))
14765 case OMP_CLAUSE_DEPEND_IN:
14766 n_in++;
14767 break;
14768 case OMP_CLAUSE_DEPEND_OUT:
14769 case OMP_CLAUSE_DEPEND_INOUT:
14770 n_out++;
14771 break;
14772 case OMP_CLAUSE_DEPEND_SOURCE:
14773 case OMP_CLAUSE_DEPEND_SINK:
14774 /* FALLTHRU */
14775 default:
14776 gcc_unreachable ();
14778 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
14779 tree array = create_tmp_var (type);
14780 TREE_ADDRESSABLE (array) = 1;
14781 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14782 NULL_TREE);
14783 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14784 gimple_seq_add_stmt (iseq, g);
14785 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14786 NULL_TREE);
14787 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14788 gimple_seq_add_stmt (iseq, g);
14789 for (i = 0; i < 2; i++)
14791 if ((i ? n_in : n_out) == 0)
14792 continue;
14793 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14794 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14795 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14797 tree t = OMP_CLAUSE_DECL (c);
14798 t = fold_convert (ptr_type_node, t);
14799 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14800 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14801 NULL_TREE, NULL_TREE);
14802 g = gimple_build_assign (r, t);
14803 gimple_seq_add_stmt (iseq, g);
14806 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14807 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
14808 OMP_CLAUSE_CHAIN (c) = *pclauses;
14809 *pclauses = c;
14810 tree clobber = build_constructor (type, NULL);
14811 TREE_THIS_VOLATILE (clobber) = 1;
14812 g = gimple_build_assign (array, clobber);
14813 gimple_seq_add_stmt (oseq, g);
14816 /* Lower the OpenMP parallel or task directive in the current statement
14817 in GSI_P. CTX holds context information for the directive. */
14819 static void
14820 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14822 tree clauses;
14823 tree child_fn, t;
14824 gimple *stmt = gsi_stmt (*gsi_p);
14825 gbind *par_bind, *bind, *dep_bind = NULL;
14826 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
14827 location_t loc = gimple_location (stmt);
14829 clauses = gimple_omp_taskreg_clauses (stmt);
14830 par_bind
14831 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
14832 par_body = gimple_bind_body (par_bind);
14833 child_fn = ctx->cb.dst_fn;
14834 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14835 && !gimple_omp_parallel_combined_p (stmt))
14837 struct walk_stmt_info wi;
14838 int ws_num = 0;
14840 memset (&wi, 0, sizeof (wi));
14841 wi.info = &ws_num;
14842 wi.val_only = true;
14843 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
14844 if (ws_num == 1)
14845 gimple_omp_parallel_set_combined_p (stmt, true);
14847 gimple_seq dep_ilist = NULL;
14848 gimple_seq dep_olist = NULL;
14849 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14850 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14852 push_gimplify_context ();
14853 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14854 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14855 &dep_ilist, &dep_olist);
14858 if (ctx->srecord_type)
14859 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
14861 push_gimplify_context ();
14863 par_olist = NULL;
14864 par_ilist = NULL;
14865 par_rlist = NULL;
14866 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
14867 lower_omp (&par_body, ctx);
14868 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
14869 lower_reduction_clauses (clauses, &par_rlist, ctx);
14871 /* Declare all the variables created by mapping and the variables
14872 declared in the scope of the parallel body. */
14873 record_vars_into (ctx->block_vars, child_fn);
14874 record_vars_into (gimple_bind_vars (par_bind), child_fn);
14876 if (ctx->record_type)
14878 ctx->sender_decl
14879 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14880 : ctx->record_type, ".omp_data_o");
14881 DECL_NAMELESS (ctx->sender_decl) = 1;
14882 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
14883 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
14886 olist = NULL;
14887 ilist = NULL;
14888 lower_send_clauses (clauses, &ilist, &olist, ctx);
14889 lower_send_shared_vars (&ilist, &olist, ctx);
14891 if (ctx->record_type)
14893 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14894 TREE_THIS_VOLATILE (clobber) = 1;
14895 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14896 clobber));
14899 /* Once all the expansions are done, sequence all the different
14900 fragments inside gimple_omp_body. */
14902 new_body = NULL;
14904 if (ctx->record_type)
14906 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14907 /* fixup_child_record_type might have changed receiver_decl's type. */
14908 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14909 gimple_seq_add_stmt (&new_body,
14910 gimple_build_assign (ctx->receiver_decl, t));
14913 gimple_seq_add_seq (&new_body, par_ilist);
14914 gimple_seq_add_seq (&new_body, par_body);
14915 gimple_seq_add_seq (&new_body, par_rlist);
14916 if (ctx->cancellable)
14917 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14918 gimple_seq_add_seq (&new_body, par_olist);
14919 new_body = maybe_catch_exception (new_body);
14920 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14921 gimple_seq_add_stmt (&new_body,
14922 gimple_build_omp_continue (integer_zero_node,
14923 integer_zero_node));
14924 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14925 gimple_omp_set_body (stmt, new_body);
14927 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
14928 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14929 gimple_bind_add_seq (bind, ilist);
14930 gimple_bind_add_stmt (bind, stmt);
14931 gimple_bind_add_seq (bind, olist);
14933 pop_gimplify_context (NULL);
14935 if (dep_bind)
14937 gimple_bind_add_seq (dep_bind, dep_ilist);
14938 gimple_bind_add_stmt (dep_bind, bind);
14939 gimple_bind_add_seq (dep_bind, dep_olist);
14940 pop_gimplify_context (dep_bind);
14944 /* Lower the GIMPLE_OMP_TARGET in the current statement
14945 in GSI_P. CTX holds context information for the directive. */
14947 static void
14948 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14950 tree clauses;
14951 tree child_fn, t, c;
14952 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
14953 gbind *tgt_bind, *bind, *dep_bind = NULL;
14954 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
14955 location_t loc = gimple_location (stmt);
14956 bool offloaded, data_region;
14957 unsigned int map_cnt = 0;
14958 bool has_depend = false;
14960 offloaded = is_gimple_omp_offloaded (stmt);
14961 switch (gimple_omp_target_kind (stmt))
14963 case GF_OMP_TARGET_KIND_REGION:
14964 case GF_OMP_TARGET_KIND_UPDATE:
14965 case GF_OMP_TARGET_KIND_ENTER_DATA:
14966 case GF_OMP_TARGET_KIND_EXIT_DATA:
14967 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14968 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14969 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14970 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
14971 data_region = false;
14972 break;
14973 case GF_OMP_TARGET_KIND_DATA:
14974 case GF_OMP_TARGET_KIND_OACC_DATA:
14975 data_region = true;
14976 break;
14977 default:
14978 gcc_unreachable ();
14981 clauses = gimple_omp_target_clauses (stmt);
14983 gimple_seq dep_ilist = NULL;
14984 gimple_seq dep_olist = NULL;
14985 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14987 push_gimplify_context ();
14988 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14989 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14990 &dep_ilist, &dep_olist);
14991 has_depend = true;
14994 tgt_bind = NULL;
14995 tgt_body = NULL;
14996 if (offloaded)
14998 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
14999 tgt_body = gimple_bind_body (tgt_bind);
15001 else if (data_region)
15002 tgt_body = gimple_omp_body (stmt);
15003 child_fn = ctx->cb.dst_fn;
15005 push_gimplify_context ();
15007 irlist = NULL;
15008 orlist = NULL;
15009 if (offloaded
15010 && is_gimple_omp_oacc (stmt))
15011 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
15013 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15014 switch (OMP_CLAUSE_CODE (c))
15016 tree var, x;
15018 default:
15019 break;
15020 case OMP_CLAUSE_MAP:
15021 #if CHECKING_P
15022 /* First check what we're prepared to handle in the following. */
15023 switch (OMP_CLAUSE_MAP_KIND (c))
15025 case GOMP_MAP_ALLOC:
15026 case GOMP_MAP_TO:
15027 case GOMP_MAP_FROM:
15028 case GOMP_MAP_TOFROM:
15029 case GOMP_MAP_POINTER:
15030 case GOMP_MAP_TO_PSET:
15031 case GOMP_MAP_FORCE_DEALLOC:
15032 case GOMP_MAP_RELEASE:
15033 case GOMP_MAP_ALWAYS_TO:
15034 case GOMP_MAP_ALWAYS_FROM:
15035 case GOMP_MAP_ALWAYS_TOFROM:
15036 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15037 case GOMP_MAP_STRUCT:
15038 break;
15039 case GOMP_MAP_FORCE_ALLOC:
15040 case GOMP_MAP_FORCE_TO:
15041 case GOMP_MAP_FORCE_FROM:
15042 case GOMP_MAP_FORCE_TOFROM:
15043 case GOMP_MAP_FORCE_PRESENT:
15044 case GOMP_MAP_FORCE_DEVICEPTR:
15045 gcc_assert (is_gimple_omp_oacc (stmt));
15046 break;
15047 default:
15048 gcc_unreachable ();
15050 #endif
15051 /* FALLTHRU */
15052 case OMP_CLAUSE_TO:
15053 case OMP_CLAUSE_FROM:
15054 var = OMP_CLAUSE_DECL (c);
15055 if (!DECL_P (var))
15057 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15058 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15059 && (OMP_CLAUSE_MAP_KIND (c)
15060 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15061 map_cnt++;
15062 continue;
15065 if (DECL_SIZE (var)
15066 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15068 tree var2 = DECL_VALUE_EXPR (var);
15069 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15070 var2 = TREE_OPERAND (var2, 0);
15071 gcc_assert (DECL_P (var2));
15072 var = var2;
15075 if (offloaded
15076 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15078 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15080 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15081 && varpool_node::get_create (var)->offloadable)
15082 continue;
15084 tree type = build_pointer_type (TREE_TYPE (var));
15085 tree new_var = lookup_decl (var, ctx);
15086 x = create_tmp_var_raw (type, get_name (new_var));
15087 gimple_add_tmp_var (x);
15088 x = build_simple_mem_ref (x);
15089 SET_DECL_VALUE_EXPR (new_var, x);
15090 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15092 continue;
15095 if (offloaded && OMP_CLAUSE_MAP_PRIVATE (c))
15097 map_cnt++;
15098 continue;
15101 if (!maybe_lookup_field (var, ctx))
15102 continue;
15104 if (offloaded)
15106 x = build_receiver_ref (var, true, ctx);
15107 tree new_var = lookup_decl (var, ctx);
15109 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15110 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15111 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15112 x = build_simple_mem_ref (x);
15113 SET_DECL_VALUE_EXPR (new_var, x);
15114 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15116 map_cnt++;
15117 break;
15119 case OMP_CLAUSE_FIRSTPRIVATE:
15120 map_cnt++;
15121 var = OMP_CLAUSE_DECL (c);
15122 if (!is_reference (var)
15123 && !is_gimple_reg_type (TREE_TYPE (var)))
15125 tree new_var = lookup_decl (var, ctx);
15126 if (is_variable_sized (var))
15128 tree pvar = DECL_VALUE_EXPR (var);
15129 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15130 pvar = TREE_OPERAND (pvar, 0);
15131 gcc_assert (DECL_P (pvar));
15132 tree new_pvar = lookup_decl (pvar, ctx);
15133 x = build_fold_indirect_ref (new_pvar);
15134 TREE_THIS_NOTRAP (x) = 1;
15136 else
15137 x = build_receiver_ref (var, true, ctx);
15138 SET_DECL_VALUE_EXPR (new_var, x);
15139 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15141 break;
15143 case OMP_CLAUSE_PRIVATE:
15144 var = OMP_CLAUSE_DECL (c);
15145 if (is_variable_sized (var))
15147 tree new_var = lookup_decl (var, ctx);
15148 tree pvar = DECL_VALUE_EXPR (var);
15149 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15150 pvar = TREE_OPERAND (pvar, 0);
15151 gcc_assert (DECL_P (pvar));
15152 tree new_pvar = lookup_decl (pvar, ctx);
15153 x = build_fold_indirect_ref (new_pvar);
15154 TREE_THIS_NOTRAP (x) = 1;
15155 SET_DECL_VALUE_EXPR (new_var, x);
15156 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15158 break;
15160 case OMP_CLAUSE_USE_DEVICE_PTR:
15161 case OMP_CLAUSE_IS_DEVICE_PTR:
15162 var = OMP_CLAUSE_DECL (c);
15163 map_cnt++;
15164 if (is_variable_sized (var))
15166 tree new_var = lookup_decl (var, ctx);
15167 tree pvar = DECL_VALUE_EXPR (var);
15168 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15169 pvar = TREE_OPERAND (pvar, 0);
15170 gcc_assert (DECL_P (pvar));
15171 tree new_pvar = lookup_decl (pvar, ctx);
15172 x = build_fold_indirect_ref (new_pvar);
15173 TREE_THIS_NOTRAP (x) = 1;
15174 SET_DECL_VALUE_EXPR (new_var, x);
15175 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15177 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15179 tree new_var = lookup_decl (var, ctx);
15180 tree type = build_pointer_type (TREE_TYPE (var));
15181 x = create_tmp_var_raw (type, get_name (new_var));
15182 gimple_add_tmp_var (x);
15183 x = build_simple_mem_ref (x);
15184 SET_DECL_VALUE_EXPR (new_var, x);
15185 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15187 break;
15190 if (offloaded)
15192 target_nesting_level++;
15193 lower_omp (&tgt_body, ctx);
15194 target_nesting_level--;
15196 else if (data_region)
15197 lower_omp (&tgt_body, ctx);
15199 if (offloaded)
15201 /* Declare all the variables created by mapping and the variables
15202 declared in the scope of the target body. */
15203 record_vars_into (ctx->block_vars, child_fn);
15204 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15207 olist = NULL;
15208 ilist = NULL;
15209 if (ctx->record_type)
15211 ctx->sender_decl
15212 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15213 DECL_NAMELESS (ctx->sender_decl) = 1;
15214 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15215 t = make_tree_vec (3);
15216 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15217 TREE_VEC_ELT (t, 1)
15218 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15219 ".omp_data_sizes");
15220 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15221 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15222 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15223 tree tkind_type = short_unsigned_type_node;
15224 int talign_shift = 8;
15225 TREE_VEC_ELT (t, 2)
15226 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15227 ".omp_data_kinds");
15228 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15229 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15230 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15231 gimple_omp_target_set_data_arg (stmt, t);
15233 vec<constructor_elt, va_gc> *vsize;
15234 vec<constructor_elt, va_gc> *vkind;
15235 vec_alloc (vsize, map_cnt);
15236 vec_alloc (vkind, map_cnt);
15237 unsigned int map_idx = 0;
15239 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15240 switch (OMP_CLAUSE_CODE (c))
15242 tree ovar, nc, s, purpose, var, x, type;
15243 unsigned int talign;
15245 default:
15246 break;
15247 case OMP_CLAUSE_MAP:
15248 case OMP_CLAUSE_TO:
15249 case OMP_CLAUSE_FROM:
15250 nc = c;
15251 ovar = OMP_CLAUSE_DECL (c);
15252 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15253 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15254 break;
15255 if (!DECL_P (ovar))
15257 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15258 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15260 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15261 == get_base_address (ovar));
15262 nc = OMP_CLAUSE_CHAIN (c);
15263 ovar = OMP_CLAUSE_DECL (nc);
15265 else
15267 tree x = build_sender_ref (ovar, ctx);
15268 tree v
15269 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15270 gimplify_assign (x, v, &ilist);
15271 nc = NULL_TREE;
15274 else
15276 if (DECL_SIZE (ovar)
15277 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15279 tree ovar2 = DECL_VALUE_EXPR (ovar);
15280 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15281 ovar2 = TREE_OPERAND (ovar2, 0);
15282 gcc_assert (DECL_P (ovar2));
15283 ovar = ovar2;
15285 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15286 && OMP_CLAUSE_MAP_PRIVATE (c))
15288 if (!maybe_lookup_field ((splay_tree_key) &DECL_UID (ovar),
15289 ctx))
15290 continue;
15292 else if (!maybe_lookup_field (ovar, ctx))
15293 continue;
15296 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
15297 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15298 talign = DECL_ALIGN_UNIT (ovar);
15299 if (nc)
15301 var = lookup_decl_in_outer_ctx (ovar, ctx);
15302 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15303 && OMP_CLAUSE_MAP_PRIVATE (c))
15304 x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar),
15305 ctx);
15306 else
15307 x = build_sender_ref (ovar, ctx);
15308 if (maybe_lookup_oacc_reduction (var, ctx))
15310 gcc_checking_assert (offloaded
15311 && is_gimple_omp_oacc (stmt));
15312 gimplify_assign (x, var, &ilist);
15314 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15315 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15316 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15317 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
15319 gcc_assert (offloaded);
15320 tree avar
15321 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
15322 mark_addressable (avar);
15323 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
15324 talign = DECL_ALIGN_UNIT (avar);
15325 avar = build_fold_addr_expr (avar);
15326 gimplify_assign (x, avar, &ilist);
15328 else if (is_gimple_reg (var))
15330 gcc_assert (offloaded);
15331 tree avar = create_tmp_var (TREE_TYPE (var));
15332 mark_addressable (avar);
15333 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15334 if (GOMP_MAP_COPY_TO_P (map_kind)
15335 || map_kind == GOMP_MAP_POINTER
15336 || map_kind == GOMP_MAP_TO_PSET
15337 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15338 gimplify_assign (avar, var, &ilist);
15339 avar = build_fold_addr_expr (avar);
15340 gimplify_assign (x, avar, &ilist);
15341 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15342 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15343 && !TYPE_READONLY (TREE_TYPE (var)))
15345 x = unshare_expr (x);
15346 x = build_simple_mem_ref (x);
15347 gimplify_assign (var, x, &olist);
15350 else
15352 var = build_fold_addr_expr (var);
15353 gimplify_assign (x, var, &ilist);
15356 s = OMP_CLAUSE_SIZE (c);
15357 if (s == NULL_TREE)
15358 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15359 s = fold_convert (size_type_node, s);
15360 purpose = size_int (map_idx++);
15361 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15362 if (TREE_CODE (s) != INTEGER_CST)
15363 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15365 unsigned HOST_WIDE_INT tkind, tkind_zero;
15366 switch (OMP_CLAUSE_CODE (c))
15368 case OMP_CLAUSE_MAP:
15369 tkind = OMP_CLAUSE_MAP_KIND (c);
15370 tkind_zero = tkind;
15371 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15372 switch (tkind)
15374 case GOMP_MAP_ALLOC:
15375 case GOMP_MAP_TO:
15376 case GOMP_MAP_FROM:
15377 case GOMP_MAP_TOFROM:
15378 case GOMP_MAP_ALWAYS_TO:
15379 case GOMP_MAP_ALWAYS_FROM:
15380 case GOMP_MAP_ALWAYS_TOFROM:
15381 case GOMP_MAP_RELEASE:
15382 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15383 break;
15384 case GOMP_MAP_DELETE:
15385 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15386 default:
15387 break;
15389 if (tkind_zero != tkind)
15391 if (integer_zerop (s))
15392 tkind = tkind_zero;
15393 else if (integer_nonzerop (s))
15394 tkind_zero = tkind;
15396 break;
15397 case OMP_CLAUSE_TO:
15398 tkind = GOMP_MAP_TO;
15399 tkind_zero = tkind;
15400 break;
15401 case OMP_CLAUSE_FROM:
15402 tkind = GOMP_MAP_FROM;
15403 tkind_zero = tkind;
15404 break;
15405 default:
15406 gcc_unreachable ();
15408 gcc_checking_assert (tkind
15409 < (HOST_WIDE_INT_C (1U) << talign_shift));
15410 gcc_checking_assert (tkind_zero
15411 < (HOST_WIDE_INT_C (1U) << talign_shift));
15412 talign = ceil_log2 (talign);
15413 tkind |= talign << talign_shift;
15414 tkind_zero |= talign << talign_shift;
15415 gcc_checking_assert (tkind
15416 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15417 gcc_checking_assert (tkind_zero
15418 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15419 if (tkind == tkind_zero)
15420 x = build_int_cstu (tkind_type, tkind);
15421 else
15423 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15424 x = build3 (COND_EXPR, tkind_type,
15425 fold_build2 (EQ_EXPR, boolean_type_node,
15426 unshare_expr (s), size_zero_node),
15427 build_int_cstu (tkind_type, tkind_zero),
15428 build_int_cstu (tkind_type, tkind));
15430 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
15431 if (nc && nc != c)
15432 c = nc;
15433 break;
15435 case OMP_CLAUSE_FIRSTPRIVATE:
15436 ovar = OMP_CLAUSE_DECL (c);
15437 if (is_reference (ovar))
15438 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15439 else
15440 talign = DECL_ALIGN_UNIT (ovar);
15441 var = lookup_decl_in_outer_ctx (ovar, ctx);
15442 x = build_sender_ref (ovar, ctx);
15443 tkind = GOMP_MAP_FIRSTPRIVATE;
15444 type = TREE_TYPE (ovar);
15445 if (is_reference (ovar))
15446 type = TREE_TYPE (type);
15447 bool use_firstprivate_int, force_addr;
15448 use_firstprivate_int = false;
15449 force_addr = false;
15450 if ((INTEGRAL_TYPE_P (type)
15451 && TYPE_PRECISION (type) <= POINTER_SIZE)
15452 || TREE_CODE (type) == POINTER_TYPE)
15453 use_firstprivate_int = true;
15454 if (has_depend)
15456 if (is_reference (var))
15457 use_firstprivate_int = false;
15458 else if (is_gimple_reg (var))
15460 if (DECL_HAS_VALUE_EXPR_P (var))
15462 tree v = get_base_address (var);
15463 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15465 use_firstprivate_int = false;
15466 force_addr = true;
15468 else
15469 switch (TREE_CODE (v))
15471 case INDIRECT_REF:
15472 case MEM_REF:
15473 use_firstprivate_int = false;
15474 force_addr = true;
15475 break;
15476 default:
15477 break;
15481 else
15482 use_firstprivate_int = false;
15484 if (use_firstprivate_int)
15486 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15487 tree t = var;
15488 if (is_reference (var))
15489 t = build_simple_mem_ref (var);
15490 if (TREE_CODE (type) != POINTER_TYPE)
15491 t = fold_convert (pointer_sized_int_node, t);
15492 t = fold_convert (TREE_TYPE (x), t);
15493 gimplify_assign (x, t, &ilist);
15495 else if (is_reference (var))
15496 gimplify_assign (x, var, &ilist);
15497 else if (!force_addr && is_gimple_reg (var))
15499 tree avar = create_tmp_var (TREE_TYPE (var));
15500 mark_addressable (avar);
15501 gimplify_assign (avar, var, &ilist);
15502 avar = build_fold_addr_expr (avar);
15503 gimplify_assign (x, avar, &ilist);
15505 else
15507 var = build_fold_addr_expr (var);
15508 gimplify_assign (x, var, &ilist);
15510 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15511 s = size_int (0);
15512 else if (is_reference (var))
15513 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15514 else
15515 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15516 s = fold_convert (size_type_node, s);
15517 purpose = size_int (map_idx++);
15518 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15519 if (TREE_CODE (s) != INTEGER_CST)
15520 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15522 gcc_checking_assert (tkind
15523 < (HOST_WIDE_INT_C (1U) << talign_shift));
15524 talign = ceil_log2 (talign);
15525 tkind |= talign << talign_shift;
15526 gcc_checking_assert (tkind
15527 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15528 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15529 build_int_cstu (tkind_type, tkind));
15530 break;
15532 case OMP_CLAUSE_USE_DEVICE_PTR:
15533 case OMP_CLAUSE_IS_DEVICE_PTR:
15534 ovar = OMP_CLAUSE_DECL (c);
15535 var = lookup_decl_in_outer_ctx (ovar, ctx);
15536 x = build_sender_ref (ovar, ctx);
15537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15538 tkind = GOMP_MAP_USE_DEVICE_PTR;
15539 else
15540 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15541 type = TREE_TYPE (ovar);
15542 if (TREE_CODE (type) == ARRAY_TYPE)
15543 var = build_fold_addr_expr (var);
15544 else
15546 if (is_reference (ovar))
15548 type = TREE_TYPE (type);
15549 if (TREE_CODE (type) != ARRAY_TYPE)
15550 var = build_simple_mem_ref (var);
15551 var = fold_convert (TREE_TYPE (x), var);
15554 gimplify_assign (x, var, &ilist);
15555 s = size_int (0);
15556 purpose = size_int (map_idx++);
15557 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15558 gcc_checking_assert (tkind
15559 < (HOST_WIDE_INT_C (1U) << talign_shift));
15560 gcc_checking_assert (tkind
15561 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15562 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15563 build_int_cstu (tkind_type, tkind));
15564 break;
15567 gcc_assert (map_idx == map_cnt);
15569 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15570 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15571 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15572 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
15573 for (int i = 1; i <= 2; i++)
15574 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15576 gimple_seq initlist = NULL;
15577 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15578 TREE_VEC_ELT (t, i)),
15579 &initlist, true, NULL_TREE);
15580 gimple_seq_add_seq (&ilist, initlist);
15582 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15583 NULL);
15584 TREE_THIS_VOLATILE (clobber) = 1;
15585 gimple_seq_add_stmt (&olist,
15586 gimple_build_assign (TREE_VEC_ELT (t, i),
15587 clobber));
15590 tree clobber = build_constructor (ctx->record_type, NULL);
15591 TREE_THIS_VOLATILE (clobber) = 1;
15592 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15593 clobber));
15596 /* Once all the expansions are done, sequence all the different
15597 fragments inside gimple_omp_body. */
15599 new_body = NULL;
15601 if (offloaded
15602 && ctx->record_type)
15604 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15605 /* fixup_child_record_type might have changed receiver_decl's type. */
15606 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15607 gimple_seq_add_stmt (&new_body,
15608 gimple_build_assign (ctx->receiver_decl, t));
15611 if (offloaded || data_region)
15613 tree prev = NULL_TREE;
15614 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15615 switch (OMP_CLAUSE_CODE (c))
15617 tree var, x;
15618 default:
15619 break;
15620 case OMP_CLAUSE_FIRSTPRIVATE:
15621 var = OMP_CLAUSE_DECL (c);
15622 if (is_reference (var)
15623 || is_gimple_reg_type (TREE_TYPE (var)))
15625 tree new_var = lookup_decl (var, ctx);
15626 tree type;
15627 type = TREE_TYPE (var);
15628 if (is_reference (var))
15629 type = TREE_TYPE (type);
15630 bool use_firstprivate_int;
15631 use_firstprivate_int = false;
15632 if ((INTEGRAL_TYPE_P (type)
15633 && TYPE_PRECISION (type) <= POINTER_SIZE)
15634 || TREE_CODE (type) == POINTER_TYPE)
15635 use_firstprivate_int = true;
15636 if (has_depend)
15638 tree v = lookup_decl_in_outer_ctx (var, ctx);
15639 if (is_reference (v))
15640 use_firstprivate_int = false;
15641 else if (is_gimple_reg (v))
15643 if (DECL_HAS_VALUE_EXPR_P (v))
15645 v = get_base_address (v);
15646 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15647 use_firstprivate_int = false;
15648 else
15649 switch (TREE_CODE (v))
15651 case INDIRECT_REF:
15652 case MEM_REF:
15653 use_firstprivate_int = false;
15654 break;
15655 default:
15656 break;
15660 else
15661 use_firstprivate_int = false;
15663 if (use_firstprivate_int)
15665 x = build_receiver_ref (var, false, ctx);
15666 if (TREE_CODE (type) != POINTER_TYPE)
15667 x = fold_convert (pointer_sized_int_node, x);
15668 x = fold_convert (type, x);
15669 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15670 fb_rvalue);
15671 if (is_reference (var))
15673 tree v = create_tmp_var_raw (type, get_name (var));
15674 gimple_add_tmp_var (v);
15675 TREE_ADDRESSABLE (v) = 1;
15676 gimple_seq_add_stmt (&new_body,
15677 gimple_build_assign (v, x));
15678 x = build_fold_addr_expr (v);
15680 gimple_seq_add_stmt (&new_body,
15681 gimple_build_assign (new_var, x));
15683 else
15685 x = build_receiver_ref (var, !is_reference (var), ctx);
15686 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15687 fb_rvalue);
15688 gimple_seq_add_stmt (&new_body,
15689 gimple_build_assign (new_var, x));
15692 else if (is_variable_sized (var))
15694 tree pvar = DECL_VALUE_EXPR (var);
15695 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15696 pvar = TREE_OPERAND (pvar, 0);
15697 gcc_assert (DECL_P (pvar));
15698 tree new_var = lookup_decl (pvar, ctx);
15699 x = build_receiver_ref (var, false, ctx);
15700 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15701 gimple_seq_add_stmt (&new_body,
15702 gimple_build_assign (new_var, x));
15704 break;
15705 case OMP_CLAUSE_PRIVATE:
15706 var = OMP_CLAUSE_DECL (c);
15707 if (is_reference (var))
15709 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15710 tree new_var = lookup_decl (var, ctx);
15711 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15712 if (TREE_CONSTANT (x))
15714 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15715 get_name (var));
15716 gimple_add_tmp_var (x);
15717 TREE_ADDRESSABLE (x) = 1;
15718 x = build_fold_addr_expr_loc (clause_loc, x);
15720 else
15722 tree atmp
15723 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15724 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15725 tree al = size_int (TYPE_ALIGN (rtype));
15726 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15729 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15730 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15731 gimple_seq_add_stmt (&new_body,
15732 gimple_build_assign (new_var, x));
15734 break;
15735 case OMP_CLAUSE_USE_DEVICE_PTR:
15736 case OMP_CLAUSE_IS_DEVICE_PTR:
15737 var = OMP_CLAUSE_DECL (c);
15738 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15739 x = build_sender_ref (var, ctx);
15740 else
15741 x = build_receiver_ref (var, false, ctx);
15742 if (is_variable_sized (var))
15744 tree pvar = DECL_VALUE_EXPR (var);
15745 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15746 pvar = TREE_OPERAND (pvar, 0);
15747 gcc_assert (DECL_P (pvar));
15748 tree new_var = lookup_decl (pvar, ctx);
15749 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15750 gimple_seq_add_stmt (&new_body,
15751 gimple_build_assign (new_var, x));
15753 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15755 tree new_var = lookup_decl (var, ctx);
15756 new_var = DECL_VALUE_EXPR (new_var);
15757 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15758 new_var = TREE_OPERAND (new_var, 0);
15759 gcc_assert (DECL_P (new_var));
15760 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15761 gimple_seq_add_stmt (&new_body,
15762 gimple_build_assign (new_var, x));
15764 else
15766 tree type = TREE_TYPE (var);
15767 tree new_var = lookup_decl (var, ctx);
15768 if (is_reference (var))
15770 type = TREE_TYPE (type);
15771 if (TREE_CODE (type) != ARRAY_TYPE)
15773 tree v = create_tmp_var_raw (type, get_name (var));
15774 gimple_add_tmp_var (v);
15775 TREE_ADDRESSABLE (v) = 1;
15776 x = fold_convert (type, x);
15777 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15778 fb_rvalue);
15779 gimple_seq_add_stmt (&new_body,
15780 gimple_build_assign (v, x));
15781 x = build_fold_addr_expr (v);
15784 x = fold_convert (TREE_TYPE (new_var), x);
15785 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15786 gimple_seq_add_stmt (&new_body,
15787 gimple_build_assign (new_var, x));
15789 break;
15791 /* Handle GOMP_MAP_FIRSTPRIVATE_POINTER in second pass,
15792 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15793 are already handled. */
15794 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15795 switch (OMP_CLAUSE_CODE (c))
15797 tree var;
15798 default:
15799 break;
15800 case OMP_CLAUSE_MAP:
15801 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15803 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15804 HOST_WIDE_INT offset = 0;
15805 gcc_assert (prev);
15806 var = OMP_CLAUSE_DECL (c);
15807 if (DECL_P (var)
15808 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15809 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15810 ctx))
15811 && varpool_node::get_create (var)->offloadable)
15812 break;
15813 if (TREE_CODE (var) == INDIRECT_REF
15814 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15815 var = TREE_OPERAND (var, 0);
15816 if (TREE_CODE (var) == COMPONENT_REF)
15818 var = get_addr_base_and_unit_offset (var, &offset);
15819 gcc_assert (var != NULL_TREE && DECL_P (var));
15821 else if (DECL_SIZE (var)
15822 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15824 tree var2 = DECL_VALUE_EXPR (var);
15825 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15826 var2 = TREE_OPERAND (var2, 0);
15827 gcc_assert (DECL_P (var2));
15828 var = var2;
15830 tree new_var = lookup_decl (var, ctx), x;
15831 tree type = TREE_TYPE (new_var);
15832 bool is_ref;
15833 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15834 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15835 == COMPONENT_REF))
15837 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15838 is_ref = true;
15839 new_var = build2 (MEM_REF, type,
15840 build_fold_addr_expr (new_var),
15841 build_int_cst (build_pointer_type (type),
15842 offset));
15844 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15846 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15847 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15848 new_var = build2 (MEM_REF, type,
15849 build_fold_addr_expr (new_var),
15850 build_int_cst (build_pointer_type (type),
15851 offset));
15853 else
15854 is_ref = is_reference (var);
15855 bool ref_to_array = false;
15856 if (is_ref)
15858 type = TREE_TYPE (type);
15859 if (TREE_CODE (type) == ARRAY_TYPE)
15861 type = build_pointer_type (type);
15862 ref_to_array = true;
15865 else if (TREE_CODE (type) == ARRAY_TYPE)
15867 tree decl2 = DECL_VALUE_EXPR (new_var);
15868 gcc_assert (TREE_CODE (decl2) == MEM_REF);
15869 decl2 = TREE_OPERAND (decl2, 0);
15870 gcc_assert (DECL_P (decl2));
15871 new_var = decl2;
15872 type = TREE_TYPE (new_var);
15874 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
15875 x = fold_convert_loc (clause_loc, type, x);
15876 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
15878 tree bias = OMP_CLAUSE_SIZE (c);
15879 if (DECL_P (bias))
15880 bias = lookup_decl (bias, ctx);
15881 bias = fold_convert_loc (clause_loc, sizetype, bias);
15882 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
15883 bias);
15884 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
15885 TREE_TYPE (x), x, bias);
15887 if (ref_to_array)
15888 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15889 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15890 if (is_ref && !ref_to_array)
15892 tree t = create_tmp_var_raw (type, get_name (var));
15893 gimple_add_tmp_var (t);
15894 TREE_ADDRESSABLE (t) = 1;
15895 gimple_seq_add_stmt (&new_body,
15896 gimple_build_assign (t, x));
15897 x = build_fold_addr_expr_loc (clause_loc, t);
15899 gimple_seq_add_stmt (&new_body,
15900 gimple_build_assign (new_var, x));
15901 prev = NULL_TREE;
15903 else if (OMP_CLAUSE_CHAIN (c)
15904 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
15905 == OMP_CLAUSE_MAP
15906 && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15907 == GOMP_MAP_FIRSTPRIVATE_POINTER)
15908 prev = c;
15909 break;
15910 case OMP_CLAUSE_PRIVATE:
15911 var = OMP_CLAUSE_DECL (c);
15912 if (is_variable_sized (var))
15914 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15915 tree new_var = lookup_decl (var, ctx);
15916 tree pvar = DECL_VALUE_EXPR (var);
15917 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15918 pvar = TREE_OPERAND (pvar, 0);
15919 gcc_assert (DECL_P (pvar));
15920 tree new_pvar = lookup_decl (pvar, ctx);
15921 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15922 tree al = size_int (DECL_ALIGN (var));
15923 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15924 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15925 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15926 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15927 gimple_seq_add_stmt (&new_body,
15928 gimple_build_assign (new_pvar, x));
15930 break;
15933 gimple_seq_add_seq (&new_body, tgt_body);
15935 if (offloaded)
15936 new_body = maybe_catch_exception (new_body);
15938 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15939 gimple_omp_set_body (stmt, new_body);
15942 bind = gimple_build_bind (NULL, NULL,
15943 tgt_bind ? gimple_bind_block (tgt_bind)
15944 : NULL_TREE);
15945 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15946 gimple_bind_add_seq (bind, irlist);
15947 gimple_bind_add_seq (bind, ilist);
15948 gimple_bind_add_stmt (bind, stmt);
15949 gimple_bind_add_seq (bind, olist);
15950 gimple_bind_add_seq (bind, orlist);
15952 pop_gimplify_context (NULL);
15954 if (dep_bind)
15956 gimple_bind_add_seq (dep_bind, dep_ilist);
15957 gimple_bind_add_stmt (dep_bind, bind);
15958 gimple_bind_add_seq (dep_bind, dep_olist);
15959 pop_gimplify_context (dep_bind);
15963 /* Expand code for an OpenMP teams directive. */
15965 static void
15966 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15968 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15969 push_gimplify_context ();
15971 tree block = make_node (BLOCK);
15972 gbind *bind = gimple_build_bind (NULL, NULL, block);
15973 gsi_replace (gsi_p, bind, true);
15974 gimple_seq bind_body = NULL;
15975 gimple_seq dlist = NULL;
15976 gimple_seq olist = NULL;
15978 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15979 OMP_CLAUSE_NUM_TEAMS);
15980 if (num_teams == NULL_TREE)
15981 num_teams = build_int_cst (unsigned_type_node, 0);
15982 else
15984 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
15985 num_teams = fold_convert (unsigned_type_node, num_teams);
15986 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15988 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15989 OMP_CLAUSE_THREAD_LIMIT);
15990 if (thread_limit == NULL_TREE)
15991 thread_limit = build_int_cst (unsigned_type_node, 0);
15992 else
15994 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15995 thread_limit = fold_convert (unsigned_type_node, thread_limit);
15996 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
15997 fb_rvalue);
16000 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16001 &bind_body, &dlist, ctx, NULL);
16002 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16003 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16004 gimple_seq_add_stmt (&bind_body, teams_stmt);
16006 location_t loc = gimple_location (teams_stmt);
16007 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16008 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16009 gimple_set_location (call, loc);
16010 gimple_seq_add_stmt (&bind_body, call);
16012 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16013 gimple_omp_set_body (teams_stmt, NULL);
16014 gimple_seq_add_seq (&bind_body, olist);
16015 gimple_seq_add_seq (&bind_body, dlist);
16016 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16017 gimple_bind_set_body (bind, bind_body);
16019 pop_gimplify_context (bind);
16021 gimple_bind_append_vars (bind, ctx->block_vars);
16022 BLOCK_VARS (block) = ctx->block_vars;
16023 if (BLOCK_VARS (block))
16024 TREE_USED (block) = 1;
16028 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16029 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16030 of OMP context, but with task_shared_vars set. */
16032 static tree
16033 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16034 void *data)
16036 tree t = *tp;
16038 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16039 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16040 return t;
16042 if (task_shared_vars
16043 && DECL_P (t)
16044 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16045 return t;
16047 /* If a global variable has been privatized, TREE_CONSTANT on
16048 ADDR_EXPR might be wrong. */
16049 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16050 recompute_tree_invariant_for_addr_expr (t);
16052 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16053 return NULL_TREE;
16056 /* Data to be communicated between lower_omp_regimplify_operands and
16057 lower_omp_regimplify_operands_p. */
16059 struct lower_omp_regimplify_operands_data
16061 omp_context *ctx;
16062 vec<tree> *decls;
16065 /* Helper function for lower_omp_regimplify_operands. Find
16066 omp_member_access_dummy_var vars and adjust temporarily their
16067 DECL_VALUE_EXPRs if needed. */
16069 static tree
16070 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16071 void *data)
16073 tree t = omp_member_access_dummy_var (*tp);
16074 if (t)
16076 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16077 lower_omp_regimplify_operands_data *ldata
16078 = (lower_omp_regimplify_operands_data *) wi->info;
16079 tree o = maybe_lookup_decl (t, ldata->ctx);
16080 if (o != t)
16082 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16083 ldata->decls->safe_push (*tp);
16084 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16085 SET_DECL_VALUE_EXPR (*tp, v);
16088 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16089 return NULL_TREE;
16092 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16093 of omp_member_access_dummy_var vars during regimplification. */
16095 static void
16096 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16097 gimple_stmt_iterator *gsi_p)
16099 auto_vec<tree, 10> decls;
16100 if (ctx)
16102 struct walk_stmt_info wi;
16103 memset (&wi, '\0', sizeof (wi));
16104 struct lower_omp_regimplify_operands_data data;
16105 data.ctx = ctx;
16106 data.decls = &decls;
16107 wi.info = &data;
16108 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16110 gimple_regimplify_operands (stmt, gsi_p);
16111 while (!decls.is_empty ())
16113 tree t = decls.pop ();
16114 tree v = decls.pop ();
16115 SET_DECL_VALUE_EXPR (t, v);
16119 static void
16120 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16122 gimple *stmt = gsi_stmt (*gsi_p);
16123 struct walk_stmt_info wi;
16124 gcall *call_stmt;
16126 if (gimple_has_location (stmt))
16127 input_location = gimple_location (stmt);
16129 if (task_shared_vars)
16130 memset (&wi, '\0', sizeof (wi));
16132 /* If we have issued syntax errors, avoid doing any heavy lifting.
16133 Just replace the OMP directives with a NOP to avoid
16134 confusing RTL expansion. */
16135 if (seen_error () && is_gimple_omp (stmt))
16137 gsi_replace (gsi_p, gimple_build_nop (), true);
16138 return;
16141 switch (gimple_code (stmt))
16143 case GIMPLE_COND:
16145 gcond *cond_stmt = as_a <gcond *> (stmt);
16146 if ((ctx || task_shared_vars)
16147 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16148 lower_omp_regimplify_p,
16149 ctx ? NULL : &wi, NULL)
16150 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16151 lower_omp_regimplify_p,
16152 ctx ? NULL : &wi, NULL)))
16153 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16155 break;
16156 case GIMPLE_CATCH:
16157 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16158 break;
16159 case GIMPLE_EH_FILTER:
16160 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16161 break;
16162 case GIMPLE_TRY:
16163 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16164 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16165 break;
16166 case GIMPLE_TRANSACTION:
16167 lower_omp (gimple_transaction_body_ptr (
16168 as_a <gtransaction *> (stmt)),
16169 ctx);
16170 break;
16171 case GIMPLE_BIND:
16172 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16173 break;
16174 case GIMPLE_OMP_PARALLEL:
16175 case GIMPLE_OMP_TASK:
16176 ctx = maybe_lookup_ctx (stmt);
16177 gcc_assert (ctx);
16178 if (ctx->cancellable)
16179 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16180 lower_omp_taskreg (gsi_p, ctx);
16181 break;
16182 case GIMPLE_OMP_FOR:
16183 ctx = maybe_lookup_ctx (stmt);
16184 gcc_assert (ctx);
16185 if (ctx->cancellable)
16186 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16187 lower_omp_for (gsi_p, ctx);
16188 break;
16189 case GIMPLE_OMP_SECTIONS:
16190 ctx = maybe_lookup_ctx (stmt);
16191 gcc_assert (ctx);
16192 if (ctx->cancellable)
16193 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16194 lower_omp_sections (gsi_p, ctx);
16195 break;
16196 case GIMPLE_OMP_SINGLE:
16197 ctx = maybe_lookup_ctx (stmt);
16198 gcc_assert (ctx);
16199 lower_omp_single (gsi_p, ctx);
16200 break;
16201 case GIMPLE_OMP_MASTER:
16202 ctx = maybe_lookup_ctx (stmt);
16203 gcc_assert (ctx);
16204 lower_omp_master (gsi_p, ctx);
16205 break;
16206 case GIMPLE_OMP_TASKGROUP:
16207 ctx = maybe_lookup_ctx (stmt);
16208 gcc_assert (ctx);
16209 lower_omp_taskgroup (gsi_p, ctx);
16210 break;
16211 case GIMPLE_OMP_ORDERED:
16212 ctx = maybe_lookup_ctx (stmt);
16213 gcc_assert (ctx);
16214 lower_omp_ordered (gsi_p, ctx);
16215 break;
16216 case GIMPLE_OMP_CRITICAL:
16217 ctx = maybe_lookup_ctx (stmt);
16218 gcc_assert (ctx);
16219 lower_omp_critical (gsi_p, ctx);
16220 break;
16221 case GIMPLE_OMP_ATOMIC_LOAD:
16222 if ((ctx || task_shared_vars)
16223 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16224 as_a <gomp_atomic_load *> (stmt)),
16225 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
16226 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16227 break;
16228 case GIMPLE_OMP_TARGET:
16229 ctx = maybe_lookup_ctx (stmt);
16230 gcc_assert (ctx);
16231 lower_omp_target (gsi_p, ctx);
16232 break;
16233 case GIMPLE_OMP_TEAMS:
16234 ctx = maybe_lookup_ctx (stmt);
16235 gcc_assert (ctx);
16236 lower_omp_teams (gsi_p, ctx);
16237 break;
16238 case GIMPLE_CALL:
16239 tree fndecl;
16240 call_stmt = as_a <gcall *> (stmt);
16241 fndecl = gimple_call_fndecl (call_stmt);
16242 if (fndecl
16243 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16244 switch (DECL_FUNCTION_CODE (fndecl))
16246 case BUILT_IN_GOMP_BARRIER:
16247 if (ctx == NULL)
16248 break;
16249 /* FALLTHRU */
16250 case BUILT_IN_GOMP_CANCEL:
16251 case BUILT_IN_GOMP_CANCELLATION_POINT:
16252 omp_context *cctx;
16253 cctx = ctx;
16254 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16255 cctx = cctx->outer;
16256 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
16257 if (!cctx->cancellable)
16259 if (DECL_FUNCTION_CODE (fndecl)
16260 == BUILT_IN_GOMP_CANCELLATION_POINT)
16262 stmt = gimple_build_nop ();
16263 gsi_replace (gsi_p, stmt, false);
16265 break;
16267 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16269 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
16270 gimple_call_set_fndecl (call_stmt, fndecl);
16271 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
16273 tree lhs;
16274 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
16275 gimple_call_set_lhs (call_stmt, lhs);
16276 tree fallthru_label;
16277 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
16278 gimple *g;
16279 g = gimple_build_label (fallthru_label);
16280 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16281 g = gimple_build_cond (NE_EXPR, lhs,
16282 fold_convert (TREE_TYPE (lhs),
16283 boolean_false_node),
16284 cctx->cancel_label, fallthru_label);
16285 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16286 break;
16287 default:
16288 break;
16290 /* FALLTHRU */
16291 default:
16292 if ((ctx || task_shared_vars)
16293 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16294 ctx ? NULL : &wi))
16296 /* Just remove clobbers, this should happen only if we have
16297 "privatized" local addressable variables in SIMD regions,
16298 the clobber isn't needed in that case and gimplifying address
16299 of the ARRAY_REF into a pointer and creating MEM_REF based
16300 clobber would create worse code than we get with the clobber
16301 dropped. */
16302 if (gimple_clobber_p (stmt))
16304 gsi_replace (gsi_p, gimple_build_nop (), true);
16305 break;
16307 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16309 break;
16313 static void
16314 lower_omp (gimple_seq *body, omp_context *ctx)
16316 location_t saved_location = input_location;
16317 gimple_stmt_iterator gsi;
16318 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16319 lower_omp_1 (&gsi, ctx);
16320 /* During gimplification, we haven't folded statments inside offloading
16321 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16322 if (target_nesting_level || taskreg_nesting_level)
16323 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16324 fold_stmt (&gsi);
16325 input_location = saved_location;
16328 /* Main entry point. */
16330 static unsigned int
16331 execute_lower_omp (void)
16333 gimple_seq body;
16334 int i;
16335 omp_context *ctx;
16337 /* This pass always runs, to provide PROP_gimple_lomp.
16338 But often, there is nothing to do. */
16339 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16340 && flag_openmp_simd == 0)
16341 return 0;
16343 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16344 delete_omp_context);
16346 body = gimple_body (current_function_decl);
16347 scan_omp (&body, NULL);
16348 gcc_assert (taskreg_nesting_level == 0);
16349 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16350 finish_taskreg_scan (ctx);
16351 taskreg_contexts.release ();
16353 if (all_contexts->root)
16355 if (task_shared_vars)
16356 push_gimplify_context ();
16357 lower_omp (&body, NULL);
16358 if (task_shared_vars)
16359 pop_gimplify_context (NULL);
16362 if (all_contexts)
16364 splay_tree_delete (all_contexts);
16365 all_contexts = NULL;
16367 BITMAP_FREE (task_shared_vars);
16368 return 0;
16371 namespace {
16373 const pass_data pass_data_lower_omp =
16375 GIMPLE_PASS, /* type */
16376 "omplower", /* name */
16377 OPTGROUP_NONE, /* optinfo_flags */
16378 TV_NONE, /* tv_id */
16379 PROP_gimple_any, /* properties_required */
16380 PROP_gimple_lomp, /* properties_provided */
16381 0, /* properties_destroyed */
16382 0, /* todo_flags_start */
16383 0, /* todo_flags_finish */
16386 class pass_lower_omp : public gimple_opt_pass
16388 public:
16389 pass_lower_omp (gcc::context *ctxt)
16390 : gimple_opt_pass (pass_data_lower_omp, ctxt)
16393 /* opt_pass methods: */
16394 virtual unsigned int execute (function *) { return execute_lower_omp (); }
16396 }; // class pass_lower_omp
16398 } // anon namespace
16400 gimple_opt_pass *
16401 make_pass_lower_omp (gcc::context *ctxt)
16403 return new pass_lower_omp (ctxt);
16406 /* The following is a utility to diagnose structured block violations.
16407 It is not part of the "omplower" pass, as that's invoked too late. It
16408 should be invoked by the respective front ends after gimplification. */
16410 static splay_tree all_labels;
16412 /* Check for mismatched contexts and generate an error if needed. Return
16413 true if an error is detected. */
16415 static bool
16416 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
16417 gimple *branch_ctx, gimple *label_ctx)
16419 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16420 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16422 if (label_ctx == branch_ctx)
16423 return false;
16425 const char* kind = NULL;
16427 if (flag_cilkplus)
16429 if ((branch_ctx
16430 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16431 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16432 || (label_ctx
16433 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16434 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16435 kind = "Cilk Plus";
16437 if (flag_openacc)
16439 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16440 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16442 gcc_checking_assert (kind == NULL);
16443 kind = "OpenACC";
16446 if (kind == NULL)
16448 gcc_checking_assert (flag_openmp);
16449 kind = "OpenMP";
16453 Previously we kept track of the label's entire context in diagnose_sb_[12]
16454 so we could traverse it and issue a correct "exit" or "enter" error
16455 message upon a structured block violation.
16457 We built the context by building a list with tree_cons'ing, but there is
16458 no easy counterpart in gimple tuples. It seems like far too much work
16459 for issuing exit/enter error messages. If someone really misses the
16460 distinct error message... patches welcome.
16463 #if 0
16464 /* Try to avoid confusing the user by producing and error message
16465 with correct "exit" or "enter" verbiage. We prefer "exit"
16466 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16467 if (branch_ctx == NULL)
16468 exit_p = false;
16469 else
16471 while (label_ctx)
16473 if (TREE_VALUE (label_ctx) == branch_ctx)
16475 exit_p = false;
16476 break;
16478 label_ctx = TREE_CHAIN (label_ctx);
16482 if (exit_p)
16483 error ("invalid exit from %s structured block", kind);
16484 else
16485 error ("invalid entry to %s structured block", kind);
16486 #endif
16488 /* If it's obvious we have an invalid entry, be specific about the error. */
16489 if (branch_ctx == NULL)
16490 error ("invalid entry to %s structured block", kind);
16491 else
16493 /* Otherwise, be vague and lazy, but efficient. */
16494 error ("invalid branch to/from %s structured block", kind);
16497 gsi_replace (gsi_p, gimple_build_nop (), false);
16498 return true;
16501 /* Pass 1: Create a minimal tree of structured blocks, and record
16502 where each label is found. */
16504 static tree
16505 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16506 struct walk_stmt_info *wi)
16508 gimple *context = (gimple *) wi->info;
16509 gimple *inner_context;
16510 gimple *stmt = gsi_stmt (*gsi_p);
16512 *handled_ops_p = true;
16514 switch (gimple_code (stmt))
16516 WALK_SUBSTMTS;
16518 case GIMPLE_OMP_PARALLEL:
16519 case GIMPLE_OMP_TASK:
16520 case GIMPLE_OMP_SECTIONS:
16521 case GIMPLE_OMP_SINGLE:
16522 case GIMPLE_OMP_SECTION:
16523 case GIMPLE_OMP_MASTER:
16524 case GIMPLE_OMP_ORDERED:
16525 case GIMPLE_OMP_CRITICAL:
16526 case GIMPLE_OMP_TARGET:
16527 case GIMPLE_OMP_TEAMS:
16528 case GIMPLE_OMP_TASKGROUP:
16529 /* The minimal context here is just the current OMP construct. */
16530 inner_context = stmt;
16531 wi->info = inner_context;
16532 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16533 wi->info = context;
16534 break;
16536 case GIMPLE_OMP_FOR:
16537 inner_context = stmt;
16538 wi->info = inner_context;
16539 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16540 walk them. */
16541 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16542 diagnose_sb_1, NULL, wi);
16543 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16544 wi->info = context;
16545 break;
16547 case GIMPLE_LABEL:
16548 splay_tree_insert (all_labels,
16549 (splay_tree_key) gimple_label_label (
16550 as_a <glabel *> (stmt)),
16551 (splay_tree_value) context);
16552 break;
16554 default:
16555 break;
16558 return NULL_TREE;
16561 /* Pass 2: Check each branch and see if its context differs from that of
16562 the destination label's context. */
16564 static tree
16565 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16566 struct walk_stmt_info *wi)
16568 gimple *context = (gimple *) wi->info;
16569 splay_tree_node n;
16570 gimple *stmt = gsi_stmt (*gsi_p);
16572 *handled_ops_p = true;
16574 switch (gimple_code (stmt))
16576 WALK_SUBSTMTS;
16578 case GIMPLE_OMP_PARALLEL:
16579 case GIMPLE_OMP_TASK:
16580 case GIMPLE_OMP_SECTIONS:
16581 case GIMPLE_OMP_SINGLE:
16582 case GIMPLE_OMP_SECTION:
16583 case GIMPLE_OMP_MASTER:
16584 case GIMPLE_OMP_ORDERED:
16585 case GIMPLE_OMP_CRITICAL:
16586 case GIMPLE_OMP_TARGET:
16587 case GIMPLE_OMP_TEAMS:
16588 case GIMPLE_OMP_TASKGROUP:
16589 wi->info = stmt;
16590 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16591 wi->info = context;
16592 break;
16594 case GIMPLE_OMP_FOR:
16595 wi->info = stmt;
16596 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16597 walk them. */
16598 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16599 diagnose_sb_2, NULL, wi);
16600 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16601 wi->info = context;
16602 break;
16604 case GIMPLE_COND:
16606 gcond *cond_stmt = as_a <gcond *> (stmt);
16607 tree lab = gimple_cond_true_label (cond_stmt);
16608 if (lab)
16610 n = splay_tree_lookup (all_labels,
16611 (splay_tree_key) lab);
16612 diagnose_sb_0 (gsi_p, context,
16613 n ? (gimple *) n->value : NULL);
16615 lab = gimple_cond_false_label (cond_stmt);
16616 if (lab)
16618 n = splay_tree_lookup (all_labels,
16619 (splay_tree_key) lab);
16620 diagnose_sb_0 (gsi_p, context,
16621 n ? (gimple *) n->value : NULL);
16624 break;
16626 case GIMPLE_GOTO:
16628 tree lab = gimple_goto_dest (stmt);
16629 if (TREE_CODE (lab) != LABEL_DECL)
16630 break;
16632 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16633 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
16635 break;
16637 case GIMPLE_SWITCH:
16639 gswitch *switch_stmt = as_a <gswitch *> (stmt);
16640 unsigned int i;
16641 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
16643 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
16644 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16645 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
16646 break;
16649 break;
16651 case GIMPLE_RETURN:
16652 diagnose_sb_0 (gsi_p, context, NULL);
16653 break;
16655 default:
16656 break;
16659 return NULL_TREE;
16662 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16663 GIMPLE_* codes. */
16664 bool
16665 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16666 int *region_idx)
16668 gimple *last = last_stmt (bb);
16669 enum gimple_code code = gimple_code (last);
16670 struct omp_region *cur_region = *region;
16671 bool fallthru = false;
16673 switch (code)
16675 case GIMPLE_OMP_PARALLEL:
16676 case GIMPLE_OMP_TASK:
16677 case GIMPLE_OMP_FOR:
16678 case GIMPLE_OMP_SINGLE:
16679 case GIMPLE_OMP_TEAMS:
16680 case GIMPLE_OMP_MASTER:
16681 case GIMPLE_OMP_TASKGROUP:
16682 case GIMPLE_OMP_CRITICAL:
16683 case GIMPLE_OMP_SECTION:
16684 cur_region = new_omp_region (bb, code, cur_region);
16685 fallthru = true;
16686 break;
16688 case GIMPLE_OMP_ORDERED:
16689 cur_region = new_omp_region (bb, code, cur_region);
16690 fallthru = true;
16691 if (find_omp_clause (gimple_omp_ordered_clauses
16692 (as_a <gomp_ordered *> (last)),
16693 OMP_CLAUSE_DEPEND))
16694 cur_region = cur_region->outer;
16695 break;
16697 case GIMPLE_OMP_TARGET:
16698 cur_region = new_omp_region (bb, code, cur_region);
16699 fallthru = true;
16700 switch (gimple_omp_target_kind (last))
16702 case GF_OMP_TARGET_KIND_REGION:
16703 case GF_OMP_TARGET_KIND_DATA:
16704 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16705 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16706 case GF_OMP_TARGET_KIND_OACC_DATA:
16707 break;
16708 case GF_OMP_TARGET_KIND_UPDATE:
16709 case GF_OMP_TARGET_KIND_ENTER_DATA:
16710 case GF_OMP_TARGET_KIND_EXIT_DATA:
16711 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16712 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
16713 cur_region = cur_region->outer;
16714 break;
16715 default:
16716 gcc_unreachable ();
16718 break;
16720 case GIMPLE_OMP_SECTIONS:
16721 cur_region = new_omp_region (bb, code, cur_region);
16722 fallthru = true;
16723 break;
16725 case GIMPLE_OMP_SECTIONS_SWITCH:
16726 fallthru = false;
16727 break;
16729 case GIMPLE_OMP_ATOMIC_LOAD:
16730 case GIMPLE_OMP_ATOMIC_STORE:
16731 fallthru = true;
16732 break;
16734 case GIMPLE_OMP_RETURN:
16735 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16736 somewhere other than the next block. This will be
16737 created later. */
16738 cur_region->exit = bb;
16739 if (cur_region->type == GIMPLE_OMP_TASK)
16740 /* Add an edge corresponding to not scheduling the task
16741 immediately. */
16742 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
16743 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16744 cur_region = cur_region->outer;
16745 break;
16747 case GIMPLE_OMP_CONTINUE:
16748 cur_region->cont = bb;
16749 switch (cur_region->type)
16751 case GIMPLE_OMP_FOR:
16752 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16753 succs edges as abnormal to prevent splitting
16754 them. */
16755 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16756 /* Make the loopback edge. */
16757 make_edge (bb, single_succ (cur_region->entry),
16758 EDGE_ABNORMAL);
16760 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16761 corresponds to the case that the body of the loop
16762 is not executed at all. */
16763 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16764 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16765 fallthru = false;
16766 break;
16768 case GIMPLE_OMP_SECTIONS:
16769 /* Wire up the edges into and out of the nested sections. */
16771 basic_block switch_bb = single_succ (cur_region->entry);
16773 struct omp_region *i;
16774 for (i = cur_region->inner; i ; i = i->next)
16776 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16777 make_edge (switch_bb, i->entry, 0);
16778 make_edge (i->exit, bb, EDGE_FALLTHRU);
16781 /* Make the loopback edge to the block with
16782 GIMPLE_OMP_SECTIONS_SWITCH. */
16783 make_edge (bb, switch_bb, 0);
16785 /* Make the edge from the switch to exit. */
16786 make_edge (switch_bb, bb->next_bb, 0);
16787 fallthru = false;
16789 break;
16791 case GIMPLE_OMP_TASK:
16792 fallthru = true;
16793 break;
16795 default:
16796 gcc_unreachable ();
16798 break;
16800 default:
16801 gcc_unreachable ();
16804 if (*region != cur_region)
16806 *region = cur_region;
16807 if (cur_region)
16808 *region_idx = cur_region->entry->index;
16809 else
16810 *region_idx = 0;
16813 return fallthru;
16816 static unsigned int
16817 diagnose_omp_structured_block_errors (void)
16819 struct walk_stmt_info wi;
16820 gimple_seq body = gimple_body (current_function_decl);
16822 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16824 memset (&wi, 0, sizeof (wi));
16825 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
16827 memset (&wi, 0, sizeof (wi));
16828 wi.want_locations = true;
16829 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16831 gimple_set_body (current_function_decl, body);
16833 splay_tree_delete (all_labels);
16834 all_labels = NULL;
16836 return 0;
16839 namespace {
16841 const pass_data pass_data_diagnose_omp_blocks =
16843 GIMPLE_PASS, /* type */
16844 "*diagnose_omp_blocks", /* name */
16845 OPTGROUP_NONE, /* optinfo_flags */
16846 TV_NONE, /* tv_id */
16847 PROP_gimple_any, /* properties_required */
16848 0, /* properties_provided */
16849 0, /* properties_destroyed */
16850 0, /* todo_flags_start */
16851 0, /* todo_flags_finish */
16854 class pass_diagnose_omp_blocks : public gimple_opt_pass
16856 public:
16857 pass_diagnose_omp_blocks (gcc::context *ctxt)
16858 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
16861 /* opt_pass methods: */
16862 virtual bool gate (function *)
16864 return flag_cilkplus || flag_openacc || flag_openmp;
16866 virtual unsigned int execute (function *)
16868 return diagnose_omp_structured_block_errors ();
16871 }; // class pass_diagnose_omp_blocks
16873 } // anon namespace
16875 gimple_opt_pass *
16876 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
16878 return new pass_diagnose_omp_blocks (ctxt);
16881 /* SIMD clone supporting code. */
16883 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
16884 of arguments to reserve space for. */
16886 static struct cgraph_simd_clone *
16887 simd_clone_struct_alloc (int nargs)
16889 struct cgraph_simd_clone *clone_info;
16890 size_t len = (sizeof (struct cgraph_simd_clone)
16891 + nargs * sizeof (struct cgraph_simd_clone_arg));
16892 clone_info = (struct cgraph_simd_clone *)
16893 ggc_internal_cleared_alloc (len);
16894 return clone_info;
16897 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
16899 static inline void
16900 simd_clone_struct_copy (struct cgraph_simd_clone *to,
16901 struct cgraph_simd_clone *from)
16903 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
16904 + ((from->nargs - from->inbranch)
16905 * sizeof (struct cgraph_simd_clone_arg))));
16908 /* Return vector of parameter types of function FNDECL. This uses
16909 TYPE_ARG_TYPES if available, otherwise falls back to types of
16910 DECL_ARGUMENTS types. */
16912 vec<tree>
16913 simd_clone_vector_of_formal_parm_types (tree fndecl)
16915 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16916 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16917 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16918 unsigned int i;
16919 tree arg;
16920 FOR_EACH_VEC_ELT (args, i, arg)
16921 args[i] = TREE_TYPE (args[i]);
16922 return args;
16925 /* Given a simd function in NODE, extract the simd specific
16926 information from the OMP clauses passed in CLAUSES, and return
16927 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16928 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16929 otherwise set to FALSE. */
16931 static struct cgraph_simd_clone *
16932 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16933 bool *inbranch_specified)
16935 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
16936 tree t;
16937 int n;
16938 *inbranch_specified = false;
16940 n = args.length ();
16941 if (n > 0 && args.last () == void_type_node)
16942 n--;
16944 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16945 be cloned have a distinctive artificial label in addition to "omp
16946 declare simd". */
16947 bool cilk_clone
16948 = (flag_cilkplus
16949 && lookup_attribute ("cilk simd function",
16950 DECL_ATTRIBUTES (node->decl)));
16952 /* Allocate one more than needed just in case this is an in-branch
16953 clone which will require a mask argument. */
16954 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
16955 clone_info->nargs = n;
16956 clone_info->cilk_elemental = cilk_clone;
16958 if (!clauses)
16960 args.release ();
16961 return clone_info;
16963 clauses = TREE_VALUE (clauses);
16964 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
16965 return clone_info;
16967 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16969 switch (OMP_CLAUSE_CODE (t))
16971 case OMP_CLAUSE_INBRANCH:
16972 clone_info->inbranch = 1;
16973 *inbranch_specified = true;
16974 break;
16975 case OMP_CLAUSE_NOTINBRANCH:
16976 clone_info->inbranch = 0;
16977 *inbranch_specified = true;
16978 break;
16979 case OMP_CLAUSE_SIMDLEN:
16980 clone_info->simdlen
16981 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
16982 break;
16983 case OMP_CLAUSE_LINEAR:
16985 tree decl = OMP_CLAUSE_DECL (t);
16986 tree step = OMP_CLAUSE_LINEAR_STEP (t);
16987 int argno = TREE_INT_CST_LOW (decl);
16988 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
16990 clone_info->args[argno].arg_type
16991 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
16992 clone_info->args[argno].linear_step = tree_to_shwi (step);
16993 gcc_assert (clone_info->args[argno].linear_step >= 0
16994 && clone_info->args[argno].linear_step < n);
16996 else
16998 if (POINTER_TYPE_P (args[argno]))
16999 step = fold_convert (ssizetype, step);
17000 if (!tree_fits_shwi_p (step))
17002 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17003 "ignoring large linear step");
17004 args.release ();
17005 return NULL;
17007 else if (integer_zerop (step))
17009 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17010 "ignoring zero linear step");
17011 args.release ();
17012 return NULL;
17014 else
17016 enum cgraph_simd_clone_arg_type arg_type;
17017 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17018 switch (OMP_CLAUSE_LINEAR_KIND (t))
17020 case OMP_CLAUSE_LINEAR_REF:
17021 arg_type
17022 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17023 break;
17024 case OMP_CLAUSE_LINEAR_UVAL:
17025 arg_type
17026 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17027 break;
17028 case OMP_CLAUSE_LINEAR_VAL:
17029 case OMP_CLAUSE_LINEAR_DEFAULT:
17030 arg_type
17031 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17032 break;
17033 default:
17034 gcc_unreachable ();
17036 else
17037 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17038 clone_info->args[argno].arg_type = arg_type;
17039 clone_info->args[argno].linear_step = tree_to_shwi (step);
17042 break;
17044 case OMP_CLAUSE_UNIFORM:
17046 tree decl = OMP_CLAUSE_DECL (t);
17047 int argno = tree_to_uhwi (decl);
17048 clone_info->args[argno].arg_type
17049 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17050 break;
17052 case OMP_CLAUSE_ALIGNED:
17054 tree decl = OMP_CLAUSE_DECL (t);
17055 int argno = tree_to_uhwi (decl);
17056 clone_info->args[argno].alignment
17057 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17058 break;
17060 default:
17061 break;
17064 args.release ();
17065 return clone_info;
17068 /* Given a SIMD clone in NODE, calculate the characteristic data
17069 type and return the coresponding type. The characteristic data
17070 type is computed as described in the Intel Vector ABI. */
17072 static tree
17073 simd_clone_compute_base_data_type (struct cgraph_node *node,
17074 struct cgraph_simd_clone *clone_info)
17076 tree type = integer_type_node;
17077 tree fndecl = node->decl;
17079 /* a) For non-void function, the characteristic data type is the
17080 return type. */
17081 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17082 type = TREE_TYPE (TREE_TYPE (fndecl));
17084 /* b) If the function has any non-uniform, non-linear parameters,
17085 then the characteristic data type is the type of the first
17086 such parameter. */
17087 else
17089 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17090 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17091 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17093 type = map[i];
17094 break;
17096 map.release ();
17099 /* c) If the characteristic data type determined by a) or b) above
17100 is struct, union, or class type which is pass-by-value (except
17101 for the type that maps to the built-in complex data type), the
17102 characteristic data type is int. */
17103 if (RECORD_OR_UNION_TYPE_P (type)
17104 && !aggregate_value_p (type, NULL)
17105 && TREE_CODE (type) != COMPLEX_TYPE)
17106 return integer_type_node;
17108 /* d) If none of the above three classes is applicable, the
17109 characteristic data type is int. */
17111 return type;
17113 /* e) For Intel Xeon Phi native and offload compilation, if the
17114 resulting characteristic data type is 8-bit or 16-bit integer
17115 data type, the characteristic data type is int. */
17116 /* Well, we don't handle Xeon Phi yet. */
17119 static tree
17120 simd_clone_mangle (struct cgraph_node *node,
17121 struct cgraph_simd_clone *clone_info)
17123 char vecsize_mangle = clone_info->vecsize_mangle;
17124 char mask = clone_info->inbranch ? 'M' : 'N';
17125 unsigned int simdlen = clone_info->simdlen;
17126 unsigned int n;
17127 pretty_printer pp;
17129 gcc_assert (vecsize_mangle && simdlen);
17131 pp_string (&pp, "_ZGV");
17132 pp_character (&pp, vecsize_mangle);
17133 pp_character (&pp, mask);
17134 pp_decimal_int (&pp, simdlen);
17136 for (n = 0; n < clone_info->nargs; ++n)
17138 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17140 switch (arg.arg_type)
17142 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17143 pp_character (&pp, 'u');
17144 break;
17145 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17146 pp_character (&pp, 'l');
17147 goto mangle_linear;
17148 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17149 pp_character (&pp, 'R');
17150 goto mangle_linear;
17151 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17152 pp_character (&pp, 'L');
17153 goto mangle_linear;
17154 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17155 pp_character (&pp, 'U');
17156 goto mangle_linear;
17157 mangle_linear:
17158 gcc_assert (arg.linear_step != 0);
17159 if (arg.linear_step > 1)
17160 pp_unsigned_wide_integer (&pp, arg.linear_step);
17161 else if (arg.linear_step < 0)
17163 pp_character (&pp, 'n');
17164 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17165 arg.linear_step));
17167 break;
17168 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17169 pp_character (&pp, 's');
17170 pp_unsigned_wide_integer (&pp, arg.linear_step);
17171 break;
17172 default:
17173 pp_character (&pp, 'v');
17175 if (arg.alignment)
17177 pp_character (&pp, 'a');
17178 pp_decimal_int (&pp, arg.alignment);
17182 pp_underscore (&pp);
17183 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17184 if (*str == '*')
17185 ++str;
17186 pp_string (&pp, str);
17187 str = pp_formatted_text (&pp);
17189 /* If there already is a SIMD clone with the same mangled name, don't
17190 add another one. This can happen e.g. for
17191 #pragma omp declare simd
17192 #pragma omp declare simd simdlen(8)
17193 int foo (int, int);
17194 if the simdlen is assumed to be 8 for the first one, etc. */
17195 for (struct cgraph_node *clone = node->simd_clones; clone;
17196 clone = clone->simdclone->next_clone)
17197 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17198 str) == 0)
17199 return NULL_TREE;
17201 return get_identifier (str);
17204 /* Create a simd clone of OLD_NODE and return it. */
17206 static struct cgraph_node *
17207 simd_clone_create (struct cgraph_node *old_node)
17209 struct cgraph_node *new_node;
17210 if (old_node->definition)
17212 if (!old_node->has_gimple_body_p ())
17213 return NULL;
17214 old_node->get_body ();
17215 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17216 false, NULL, NULL,
17217 "simdclone");
17219 else
17221 tree old_decl = old_node->decl;
17222 tree new_decl = copy_node (old_node->decl);
17223 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17224 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17225 SET_DECL_RTL (new_decl, NULL);
17226 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17227 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
17228 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
17229 if (old_node->in_other_partition)
17230 new_node->in_other_partition = 1;
17231 symtab->call_cgraph_insertion_hooks (new_node);
17233 if (new_node == NULL)
17234 return new_node;
17236 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17238 /* The function cgraph_function_versioning () will force the new
17239 symbol local. Undo this, and inherit external visability from
17240 the old node. */
17241 new_node->local.local = old_node->local.local;
17242 new_node->externally_visible = old_node->externally_visible;
17244 return new_node;
17247 /* Adjust the return type of the given function to its appropriate
17248 vector counterpart. Returns a simd array to be used throughout the
17249 function as a return value. */
17251 static tree
17252 simd_clone_adjust_return_type (struct cgraph_node *node)
17254 tree fndecl = node->decl;
17255 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17256 unsigned int veclen;
17257 tree t;
17259 /* Adjust the function return type. */
17260 if (orig_rettype == void_type_node)
17261 return NULL_TREE;
17262 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
17263 t = TREE_TYPE (TREE_TYPE (fndecl));
17264 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
17265 veclen = node->simdclone->vecsize_int;
17266 else
17267 veclen = node->simdclone->vecsize_float;
17268 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
17269 if (veclen > node->simdclone->simdlen)
17270 veclen = node->simdclone->simdlen;
17271 if (POINTER_TYPE_P (t))
17272 t = pointer_sized_int_node;
17273 if (veclen == node->simdclone->simdlen)
17274 t = build_vector_type (t, node->simdclone->simdlen);
17275 else
17277 t = build_vector_type (t, veclen);
17278 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
17280 TREE_TYPE (TREE_TYPE (fndecl)) = t;
17281 if (!node->definition)
17282 return NULL_TREE;
17284 t = DECL_RESULT (fndecl);
17285 /* Adjust the DECL_RESULT. */
17286 gcc_assert (TREE_TYPE (t) != void_type_node);
17287 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17288 relayout_decl (t);
17290 tree atype = build_array_type_nelts (orig_rettype,
17291 node->simdclone->simdlen);
17292 if (veclen != node->simdclone->simdlen)
17293 return build1 (VIEW_CONVERT_EXPR, atype, t);
17295 /* Set up a SIMD array to use as the return value. */
17296 tree retval = create_tmp_var_raw (atype, "retval");
17297 gimple_add_tmp_var (retval);
17298 return retval;
17301 /* Each vector argument has a corresponding array to be used locally
17302 as part of the eventual loop. Create such temporary array and
17303 return it.
17305 PREFIX is the prefix to be used for the temporary.
17307 TYPE is the inner element type.
17309 SIMDLEN is the number of elements. */
17311 static tree
17312 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17314 tree atype = build_array_type_nelts (type, simdlen);
17315 tree avar = create_tmp_var_raw (atype, prefix);
17316 gimple_add_tmp_var (avar);
17317 return avar;
17320 /* Modify the function argument types to their corresponding vector
17321 counterparts if appropriate. Also, create one array for each simd
17322 argument to be used locally when using the function arguments as
17323 part of the loop.
17325 NODE is the function whose arguments are to be adjusted.
17327 Returns an adjustment vector that will be filled describing how the
17328 argument types will be adjusted. */
17330 static ipa_parm_adjustment_vec
17331 simd_clone_adjust_argument_types (struct cgraph_node *node)
17333 vec<tree> args;
17334 ipa_parm_adjustment_vec adjustments;
17336 if (node->definition)
17337 args = ipa_get_vector_of_formal_parms (node->decl);
17338 else
17339 args = simd_clone_vector_of_formal_parm_types (node->decl);
17340 adjustments.create (args.length ());
17341 unsigned i, j, veclen;
17342 struct ipa_parm_adjustment adj;
17343 for (i = 0; i < node->simdclone->nargs; ++i)
17345 memset (&adj, 0, sizeof (adj));
17346 tree parm = args[i];
17347 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17348 adj.base_index = i;
17349 adj.base = parm;
17351 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17352 node->simdclone->args[i].orig_type = parm_type;
17354 switch (node->simdclone->args[i].arg_type)
17356 default:
17357 /* No adjustment necessary for scalar arguments. */
17358 adj.op = IPA_PARM_OP_COPY;
17359 break;
17360 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17361 if (node->definition)
17362 node->simdclone->args[i].simd_array
17363 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17364 TREE_TYPE (parm_type),
17365 node->simdclone->simdlen);
17366 adj.op = IPA_PARM_OP_COPY;
17367 break;
17368 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17369 case SIMD_CLONE_ARG_TYPE_VECTOR:
17370 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17371 veclen = node->simdclone->vecsize_int;
17372 else
17373 veclen = node->simdclone->vecsize_float;
17374 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17375 if (veclen > node->simdclone->simdlen)
17376 veclen = node->simdclone->simdlen;
17377 adj.arg_prefix = "simd";
17378 if (POINTER_TYPE_P (parm_type))
17379 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17380 else
17381 adj.type = build_vector_type (parm_type, veclen);
17382 node->simdclone->args[i].vector_type = adj.type;
17383 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17385 adjustments.safe_push (adj);
17386 if (j == veclen)
17388 memset (&adj, 0, sizeof (adj));
17389 adj.op = IPA_PARM_OP_NEW;
17390 adj.arg_prefix = "simd";
17391 adj.base_index = i;
17392 adj.type = node->simdclone->args[i].vector_type;
17396 if (node->definition)
17397 node->simdclone->args[i].simd_array
17398 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17399 parm_type, node->simdclone->simdlen);
17401 adjustments.safe_push (adj);
17404 if (node->simdclone->inbranch)
17406 tree base_type
17407 = simd_clone_compute_base_data_type (node->simdclone->origin,
17408 node->simdclone);
17410 memset (&adj, 0, sizeof (adj));
17411 adj.op = IPA_PARM_OP_NEW;
17412 adj.arg_prefix = "mask";
17414 adj.base_index = i;
17415 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17416 veclen = node->simdclone->vecsize_int;
17417 else
17418 veclen = node->simdclone->vecsize_float;
17419 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17420 if (veclen > node->simdclone->simdlen)
17421 veclen = node->simdclone->simdlen;
17422 if (POINTER_TYPE_P (base_type))
17423 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17424 else
17425 adj.type = build_vector_type (base_type, veclen);
17426 adjustments.safe_push (adj);
17428 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17429 adjustments.safe_push (adj);
17431 /* We have previously allocated one extra entry for the mask. Use
17432 it and fill it. */
17433 struct cgraph_simd_clone *sc = node->simdclone;
17434 sc->nargs++;
17435 if (node->definition)
17437 sc->args[i].orig_arg
17438 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17439 sc->args[i].simd_array
17440 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17442 sc->args[i].orig_type = base_type;
17443 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17446 if (node->definition)
17447 ipa_modify_formal_parameters (node->decl, adjustments);
17448 else
17450 tree new_arg_types = NULL_TREE, new_reversed;
17451 bool last_parm_void = false;
17452 if (args.length () > 0 && args.last () == void_type_node)
17453 last_parm_void = true;
17455 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17456 j = adjustments.length ();
17457 for (i = 0; i < j; i++)
17459 struct ipa_parm_adjustment *adj = &adjustments[i];
17460 tree ptype;
17461 if (adj->op == IPA_PARM_OP_COPY)
17462 ptype = args[adj->base_index];
17463 else
17464 ptype = adj->type;
17465 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17467 new_reversed = nreverse (new_arg_types);
17468 if (last_parm_void)
17470 if (new_reversed)
17471 TREE_CHAIN (new_arg_types) = void_list_node;
17472 else
17473 new_reversed = void_list_node;
17476 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17477 TYPE_ARG_TYPES (new_type) = new_reversed;
17478 TREE_TYPE (node->decl) = new_type;
17480 adjustments.release ();
17482 args.release ();
17483 return adjustments;
17486 /* Initialize and copy the function arguments in NODE to their
17487 corresponding local simd arrays. Returns a fresh gimple_seq with
17488 the instruction sequence generated. */
17490 static gimple_seq
17491 simd_clone_init_simd_arrays (struct cgraph_node *node,
17492 ipa_parm_adjustment_vec adjustments)
17494 gimple_seq seq = NULL;
17495 unsigned i = 0, j = 0, k;
17497 for (tree arg = DECL_ARGUMENTS (node->decl);
17498 arg;
17499 arg = DECL_CHAIN (arg), i++, j++)
17501 if (adjustments[j].op == IPA_PARM_OP_COPY
17502 || POINTER_TYPE_P (TREE_TYPE (arg)))
17503 continue;
17505 node->simdclone->args[i].vector_arg = arg;
17507 tree array = node->simdclone->args[i].simd_array;
17508 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17510 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17511 tree ptr = build_fold_addr_expr (array);
17512 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17513 build_int_cst (ptype, 0));
17514 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17515 gimplify_and_add (t, &seq);
17517 else
17519 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17520 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17521 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17523 tree ptr = build_fold_addr_expr (array);
17524 int elemsize;
17525 if (k)
17527 arg = DECL_CHAIN (arg);
17528 j++;
17530 elemsize
17531 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17532 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17533 build_int_cst (ptype, k * elemsize));
17534 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17535 gimplify_and_add (t, &seq);
17539 return seq;
17542 /* Callback info for ipa_simd_modify_stmt_ops below. */
17544 struct modify_stmt_info {
17545 ipa_parm_adjustment_vec adjustments;
17546 gimple *stmt;
17547 /* True if the parent statement was modified by
17548 ipa_simd_modify_stmt_ops. */
17549 bool modified;
17552 /* Callback for walk_gimple_op.
17554 Adjust operands from a given statement as specified in the
17555 adjustments vector in the callback data. */
17557 static tree
17558 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17560 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17561 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17562 tree *orig_tp = tp;
17563 if (TREE_CODE (*tp) == ADDR_EXPR)
17564 tp = &TREE_OPERAND (*tp, 0);
17565 struct ipa_parm_adjustment *cand = NULL;
17566 if (TREE_CODE (*tp) == PARM_DECL)
17567 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17568 else
17570 if (TYPE_P (*tp))
17571 *walk_subtrees = 0;
17574 tree repl = NULL_TREE;
17575 if (cand)
17576 repl = unshare_expr (cand->new_decl);
17577 else
17579 if (tp != orig_tp)
17581 *walk_subtrees = 0;
17582 bool modified = info->modified;
17583 info->modified = false;
17584 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17585 if (!info->modified)
17587 info->modified = modified;
17588 return NULL_TREE;
17590 info->modified = modified;
17591 repl = *tp;
17593 else
17594 return NULL_TREE;
17597 if (tp != orig_tp)
17599 repl = build_fold_addr_expr (repl);
17600 gimple *stmt;
17601 if (is_gimple_debug (info->stmt))
17603 tree vexpr = make_node (DEBUG_EXPR_DECL);
17604 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17605 DECL_ARTIFICIAL (vexpr) = 1;
17606 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17607 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17608 repl = vexpr;
17610 else
17612 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
17613 repl = gimple_assign_lhs (stmt);
17615 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
17616 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17617 *orig_tp = repl;
17619 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
17621 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17622 *tp = vce;
17624 else
17625 *tp = repl;
17627 info->modified = true;
17628 return NULL_TREE;
17631 /* Traverse the function body and perform all modifications as
17632 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17633 modified such that the replacement/reduction value will now be an
17634 offset into the corresponding simd_array.
17636 This function will replace all function argument uses with their
17637 corresponding simd array elements, and ajust the return values
17638 accordingly. */
17640 static void
17641 ipa_simd_modify_function_body (struct cgraph_node *node,
17642 ipa_parm_adjustment_vec adjustments,
17643 tree retval_array, tree iter)
17645 basic_block bb;
17646 unsigned int i, j, l;
17648 /* Re-use the adjustments array, but this time use it to replace
17649 every function argument use to an offset into the corresponding
17650 simd_array. */
17651 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17653 if (!node->simdclone->args[i].vector_arg)
17654 continue;
17656 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17657 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17658 adjustments[j].new_decl
17659 = build4 (ARRAY_REF,
17660 basetype,
17661 node->simdclone->args[i].simd_array,
17662 iter,
17663 NULL_TREE, NULL_TREE);
17664 if (adjustments[j].op == IPA_PARM_OP_NONE
17665 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17666 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17669 l = adjustments.length ();
17670 for (i = 1; i < num_ssa_names; i++)
17672 tree name = ssa_name (i);
17673 if (name
17674 && SSA_NAME_VAR (name)
17675 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17677 for (j = 0; j < l; j++)
17678 if (SSA_NAME_VAR (name) == adjustments[j].base
17679 && adjustments[j].new_decl)
17681 tree base_var;
17682 if (adjustments[j].new_ssa_base == NULL_TREE)
17684 base_var
17685 = copy_var_decl (adjustments[j].base,
17686 DECL_NAME (adjustments[j].base),
17687 TREE_TYPE (adjustments[j].base));
17688 adjustments[j].new_ssa_base = base_var;
17690 else
17691 base_var = adjustments[j].new_ssa_base;
17692 if (SSA_NAME_IS_DEFAULT_DEF (name))
17694 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17695 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17696 tree new_decl = unshare_expr (adjustments[j].new_decl);
17697 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17698 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17699 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
17700 gimple *stmt = gimple_build_assign (name, new_decl);
17701 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17703 else
17704 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17709 struct modify_stmt_info info;
17710 info.adjustments = adjustments;
17712 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17714 gimple_stmt_iterator gsi;
17716 gsi = gsi_start_bb (bb);
17717 while (!gsi_end_p (gsi))
17719 gimple *stmt = gsi_stmt (gsi);
17720 info.stmt = stmt;
17721 struct walk_stmt_info wi;
17723 memset (&wi, 0, sizeof (wi));
17724 info.modified = false;
17725 wi.info = &info;
17726 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17728 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
17730 tree retval = gimple_return_retval (return_stmt);
17731 if (!retval)
17733 gsi_remove (&gsi, true);
17734 continue;
17737 /* Replace `return foo' with `retval_array[iter] = foo'. */
17738 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17739 retval_array, iter, NULL, NULL);
17740 stmt = gimple_build_assign (ref, retval);
17741 gsi_replace (&gsi, stmt, true);
17742 info.modified = true;
17745 if (info.modified)
17747 update_stmt (stmt);
17748 if (maybe_clean_eh_stmt (stmt))
17749 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17751 gsi_next (&gsi);
17756 /* Adjust the argument types in NODE to their appropriate vector
17757 counterparts. */
17759 static void
17760 simd_clone_adjust (struct cgraph_node *node)
17762 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
17764 targetm.simd_clone.adjust (node);
17766 tree retval = simd_clone_adjust_return_type (node);
17767 ipa_parm_adjustment_vec adjustments
17768 = simd_clone_adjust_argument_types (node);
17770 push_gimplify_context ();
17772 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
17774 /* Adjust all uses of vector arguments accordingly. Adjust all
17775 return values accordingly. */
17776 tree iter = create_tmp_var (unsigned_type_node, "iter");
17777 tree iter1 = make_ssa_name (iter);
17778 tree iter2 = make_ssa_name (iter);
17779 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
17781 /* Initialize the iteration variable. */
17782 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17783 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
17784 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17785 /* Insert the SIMD array and iv initialization at function
17786 entry. */
17787 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
17789 pop_gimplify_context (NULL);
17791 /* Create a new BB right before the original exit BB, to hold the
17792 iteration increment and the condition/branch. */
17793 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
17794 basic_block incr_bb = create_empty_bb (orig_exit);
17795 add_bb_to_loop (incr_bb, body_bb->loop_father);
17796 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
17797 flag. Set it now to be a FALLTHRU_EDGE. */
17798 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
17799 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
17800 for (unsigned i = 0;
17801 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
17803 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
17804 redirect_edge_succ (e, incr_bb);
17806 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
17807 e->probability = REG_BR_PROB_BASE;
17808 gsi = gsi_last_bb (incr_bb);
17809 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
17810 build_int_cst (unsigned_type_node, 1));
17811 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17813 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
17814 struct loop *loop = alloc_loop ();
17815 cfun->has_force_vectorize_loops = true;
17816 loop->safelen = node->simdclone->simdlen;
17817 loop->force_vectorize = true;
17818 loop->header = body_bb;
17820 /* Branch around the body if the mask applies. */
17821 if (node->simdclone->inbranch)
17823 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
17824 tree mask_array
17825 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
17826 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
17827 tree aref = build4 (ARRAY_REF,
17828 TREE_TYPE (TREE_TYPE (mask_array)),
17829 mask_array, iter1,
17830 NULL, NULL);
17831 g = gimple_build_assign (mask, aref);
17832 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17833 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
17834 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
17836 aref = build1 (VIEW_CONVERT_EXPR,
17837 build_nonstandard_integer_type (bitsize, 0), mask);
17838 mask = make_ssa_name (TREE_TYPE (aref));
17839 g = gimple_build_assign (mask, aref);
17840 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17843 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
17844 NULL, NULL);
17845 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17846 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
17847 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
17850 /* Generate the condition. */
17851 g = gimple_build_cond (LT_EXPR,
17852 iter2,
17853 build_int_cst (unsigned_type_node,
17854 node->simdclone->simdlen),
17855 NULL, NULL);
17856 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17857 e = split_block (incr_bb, gsi_stmt (gsi));
17858 basic_block latch_bb = e->dest;
17859 basic_block new_exit_bb;
17860 new_exit_bb = split_block_after_labels (latch_bb)->dest;
17861 loop->latch = latch_bb;
17863 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
17865 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
17866 /* The successor of incr_bb is already pointing to latch_bb; just
17867 change the flags.
17868 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
17869 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
17871 gphi *phi = create_phi_node (iter1, body_bb);
17872 edge preheader_edge = find_edge (entry_bb, body_bb);
17873 edge latch_edge = single_succ_edge (latch_bb);
17874 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
17875 UNKNOWN_LOCATION);
17876 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17878 /* Generate the new return. */
17879 gsi = gsi_last_bb (new_exit_bb);
17880 if (retval
17881 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
17882 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
17883 retval = TREE_OPERAND (retval, 0);
17884 else if (retval)
17886 retval = build1 (VIEW_CONVERT_EXPR,
17887 TREE_TYPE (TREE_TYPE (node->decl)),
17888 retval);
17889 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
17890 false, GSI_CONTINUE_LINKING);
17892 g = gimple_build_return (retval);
17893 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17895 /* Handle aligned clauses by replacing default defs of the aligned
17896 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
17897 lhs. Handle linear by adding PHIs. */
17898 for (unsigned i = 0; i < node->simdclone->nargs; i++)
17899 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
17900 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
17901 || !is_gimple_reg_type
17902 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
17904 tree orig_arg = node->simdclone->args[i].orig_arg;
17905 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
17906 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
17907 else
17909 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
17910 gimple_add_tmp_var (iter1);
17912 gsi = gsi_after_labels (entry_bb);
17913 g = gimple_build_assign (iter1, orig_arg);
17914 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17915 gsi = gsi_after_labels (body_bb);
17916 g = gimple_build_assign (orig_arg, iter1);
17917 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17919 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
17920 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
17921 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17922 == REFERENCE_TYPE
17923 && TREE_ADDRESSABLE
17924 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
17926 tree orig_arg = node->simdclone->args[i].orig_arg;
17927 tree def = ssa_default_def (cfun, orig_arg);
17928 if (def && !has_zero_uses (def))
17930 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
17931 gimple_add_tmp_var (iter1);
17932 gsi = gsi_after_labels (entry_bb);
17933 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
17934 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17935 gsi = gsi_after_labels (body_bb);
17936 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
17937 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17940 else if (node->simdclone->args[i].alignment
17941 && node->simdclone->args[i].arg_type
17942 == SIMD_CLONE_ARG_TYPE_UNIFORM
17943 && (node->simdclone->args[i].alignment
17944 & (node->simdclone->args[i].alignment - 1)) == 0
17945 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17946 == POINTER_TYPE)
17948 unsigned int alignment = node->simdclone->args[i].alignment;
17949 tree orig_arg = node->simdclone->args[i].orig_arg;
17950 tree def = ssa_default_def (cfun, orig_arg);
17951 if (def && !has_zero_uses (def))
17953 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
17954 gimple_seq seq = NULL;
17955 bool need_cvt = false;
17956 gcall *call
17957 = gimple_build_call (fn, 2, def, size_int (alignment));
17958 g = call;
17959 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
17960 ptr_type_node))
17961 need_cvt = true;
17962 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
17963 gimple_call_set_lhs (g, t);
17964 gimple_seq_add_stmt_without_update (&seq, g);
17965 if (need_cvt)
17967 t = make_ssa_name (orig_arg);
17968 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
17969 gimple_seq_add_stmt_without_update (&seq, g);
17971 gsi_insert_seq_on_edge_immediate
17972 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
17974 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17975 int freq = compute_call_stmt_bb_frequency (current_function_decl,
17976 entry_bb);
17977 node->create_edge (cgraph_node::get_create (fn),
17978 call, entry_bb->count, freq);
17980 imm_use_iterator iter;
17981 use_operand_p use_p;
17982 gimple *use_stmt;
17983 tree repl = gimple_get_lhs (g);
17984 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
17985 if (is_gimple_debug (use_stmt) || use_stmt == call)
17986 continue;
17987 else
17988 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
17989 SET_USE (use_p, repl);
17992 else if ((node->simdclone->args[i].arg_type
17993 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
17994 || (node->simdclone->args[i].arg_type
17995 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP))
17997 tree orig_arg = node->simdclone->args[i].orig_arg;
17998 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
17999 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
18000 tree def = NULL_TREE;
18001 if (TREE_ADDRESSABLE (orig_arg))
18003 def = make_ssa_name (TREE_TYPE (orig_arg));
18004 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18005 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18006 gsi = gsi_after_labels (entry_bb);
18007 g = gimple_build_assign (def, orig_arg);
18008 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18010 else
18012 def = ssa_default_def (cfun, orig_arg);
18013 if (!def || has_zero_uses (def))
18014 def = NULL_TREE;
18015 else
18017 iter1 = make_ssa_name (orig_arg);
18018 iter2 = make_ssa_name (orig_arg);
18021 if (def)
18023 phi = create_phi_node (iter1, body_bb);
18024 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18025 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18026 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18027 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18028 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18029 ? TREE_TYPE (orig_arg) : sizetype;
18030 tree addcst
18031 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
18032 g = gimple_build_assign (iter2, code, iter1, addcst);
18033 gsi = gsi_last_bb (incr_bb);
18034 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18036 imm_use_iterator iter;
18037 use_operand_p use_p;
18038 gimple *use_stmt;
18039 if (TREE_ADDRESSABLE (orig_arg))
18041 gsi = gsi_after_labels (body_bb);
18042 g = gimple_build_assign (orig_arg, iter1);
18043 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18045 else
18046 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18047 if (use_stmt == phi)
18048 continue;
18049 else
18050 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18051 SET_USE (use_p, iter1);
18054 else if (node->simdclone->args[i].arg_type
18055 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP)
18057 tree orig_arg = node->simdclone->args[i].orig_arg;
18058 tree def = ssa_default_def (cfun, orig_arg);
18059 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18060 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18061 if (def && !has_zero_uses (def))
18063 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18064 iter1 = make_ssa_name (orig_arg);
18065 iter2 = make_ssa_name (orig_arg);
18066 tree iter3 = make_ssa_name (rtype);
18067 tree iter4 = make_ssa_name (rtype);
18068 tree iter5 = make_ssa_name (rtype);
18069 gsi = gsi_after_labels (entry_bb);
18070 gimple *load
18071 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18072 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18074 tree array = node->simdclone->args[i].simd_array;
18075 TREE_ADDRESSABLE (array) = 1;
18076 tree ptr = build_fold_addr_expr (array);
18077 phi = create_phi_node (iter1, body_bb);
18078 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18079 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18080 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18081 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18082 gsi = gsi_last_bb (incr_bb);
18083 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18085 phi = create_phi_node (iter4, body_bb);
18086 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18087 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18088 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18089 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18090 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18091 ? TREE_TYPE (iter3) : sizetype;
18092 tree addcst
18093 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
18094 g = gimple_build_assign (iter5, code, iter4, addcst);
18095 gsi = gsi_last_bb (incr_bb);
18096 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18098 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18099 gsi = gsi_after_labels (body_bb);
18100 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18102 imm_use_iterator iter;
18103 use_operand_p use_p;
18104 gimple *use_stmt;
18105 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18106 if (use_stmt == load)
18107 continue;
18108 else
18109 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18110 SET_USE (use_p, iter1);
18112 if (!TYPE_READONLY (rtype))
18114 tree v = make_ssa_name (rtype);
18115 tree aref = build4 (ARRAY_REF, rtype, array,
18116 size_zero_node, NULL_TREE,
18117 NULL_TREE);
18118 gsi = gsi_after_labels (new_exit_bb);
18119 g = gimple_build_assign (v, aref);
18120 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18121 g = gimple_build_assign (build_simple_mem_ref (def), v);
18122 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18127 calculate_dominance_info (CDI_DOMINATORS);
18128 add_loop (loop, loop->header->loop_father);
18129 update_ssa (TODO_update_ssa);
18131 pop_cfun ();
18134 /* If the function in NODE is tagged as an elemental SIMD function,
18135 create the appropriate SIMD clones. */
18137 static void
18138 expand_simd_clones (struct cgraph_node *node)
18140 tree attr = lookup_attribute ("omp declare simd",
18141 DECL_ATTRIBUTES (node->decl));
18142 if (attr == NULL_TREE
18143 || node->global.inlined_to
18144 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
18145 return;
18147 /* Ignore
18148 #pragma omp declare simd
18149 extern int foo ();
18150 in C, there we don't know the argument types at all. */
18151 if (!node->definition
18152 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18153 return;
18157 /* Start with parsing the "omp declare simd" attribute(s). */
18158 bool inbranch_clause_specified;
18159 struct cgraph_simd_clone *clone_info
18160 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18161 &inbranch_clause_specified);
18162 if (clone_info == NULL)
18163 continue;
18165 int orig_simdlen = clone_info->simdlen;
18166 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18167 /* The target can return 0 (no simd clones should be created),
18168 1 (just one ISA of simd clones should be created) or higher
18169 count of ISA variants. In that case, clone_info is initialized
18170 for the first ISA variant. */
18171 int count
18172 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18173 base_type, 0);
18174 if (count == 0)
18175 continue;
18177 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18178 also create one inbranch and one !inbranch clone of it. */
18179 for (int i = 0; i < count * 2; i++)
18181 struct cgraph_simd_clone *clone = clone_info;
18182 if (inbranch_clause_specified && (i & 1) != 0)
18183 continue;
18185 if (i != 0)
18187 clone = simd_clone_struct_alloc (clone_info->nargs
18188 + ((i & 1) != 0));
18189 simd_clone_struct_copy (clone, clone_info);
18190 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18191 and simd_clone_adjust_argument_types did to the first
18192 clone's info. */
18193 clone->nargs -= clone_info->inbranch;
18194 clone->simdlen = orig_simdlen;
18195 /* And call the target hook again to get the right ISA. */
18196 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18197 base_type,
18198 i / 2);
18199 if ((i & 1) != 0)
18200 clone->inbranch = 1;
18203 /* simd_clone_mangle might fail if such a clone has been created
18204 already. */
18205 tree id = simd_clone_mangle (node, clone);
18206 if (id == NULL_TREE)
18207 continue;
18209 /* Only when we are sure we want to create the clone actually
18210 clone the function (or definitions) or create another
18211 extern FUNCTION_DECL (for prototypes without definitions). */
18212 struct cgraph_node *n = simd_clone_create (node);
18213 if (n == NULL)
18214 continue;
18216 n->simdclone = clone;
18217 clone->origin = node;
18218 clone->next_clone = NULL;
18219 if (node->simd_clones == NULL)
18221 clone->prev_clone = n;
18222 node->simd_clones = n;
18224 else
18226 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18227 clone->prev_clone->simdclone->next_clone = n;
18228 node->simd_clones->simdclone->prev_clone = n;
18230 symtab->change_decl_assembler_name (n->decl, id);
18231 /* And finally adjust the return type, parameters and for
18232 definitions also function body. */
18233 if (node->definition)
18234 simd_clone_adjust (n);
18235 else
18237 simd_clone_adjust_return_type (n);
18238 simd_clone_adjust_argument_types (n);
18242 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18245 /* Entry point for IPA simd clone creation pass. */
18247 static unsigned int
18248 ipa_omp_simd_clone (void)
18250 struct cgraph_node *node;
18251 FOR_EACH_FUNCTION (node)
18252 expand_simd_clones (node);
18253 return 0;
18256 namespace {
18258 const pass_data pass_data_omp_simd_clone =
18260 SIMPLE_IPA_PASS, /* type */
18261 "simdclone", /* name */
18262 OPTGROUP_NONE, /* optinfo_flags */
18263 TV_NONE, /* tv_id */
18264 ( PROP_ssa | PROP_cfg ), /* properties_required */
18265 0, /* properties_provided */
18266 0, /* properties_destroyed */
18267 0, /* todo_flags_start */
18268 0, /* todo_flags_finish */
18271 class pass_omp_simd_clone : public simple_ipa_opt_pass
18273 public:
18274 pass_omp_simd_clone(gcc::context *ctxt)
18275 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18278 /* opt_pass methods: */
18279 virtual bool gate (function *);
18280 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
18283 bool
18284 pass_omp_simd_clone::gate (function *)
18286 return ((flag_openmp || flag_openmp_simd
18287 || flag_cilkplus
18288 || (in_lto_p && !flag_wpa))
18289 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
18292 } // anon namespace
18294 simple_ipa_opt_pass *
18295 make_pass_omp_simd_clone (gcc::context *ctxt)
18297 return new pass_omp_simd_clone (ctxt);
18300 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18301 adds their addresses and sizes to constructor-vector V_CTOR. */
18302 static void
18303 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18304 vec<constructor_elt, va_gc> *v_ctor)
18306 unsigned len = vec_safe_length (v_decls);
18307 for (unsigned i = 0; i < len; i++)
18309 tree it = (*v_decls)[i];
18310 bool is_function = TREE_CODE (it) != VAR_DECL;
18312 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
18313 if (!is_function)
18314 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
18315 fold_convert (const_ptr_type_node,
18316 DECL_SIZE_UNIT (it)));
18320 /* Create new symbols containing (address, size) pairs for global variables,
18321 marked with "omp declare target" attribute, as well as addresses for the
18322 functions, which are outlined offloading regions. */
18323 void
18324 omp_finish_file (void)
18326 unsigned num_funcs = vec_safe_length (offload_funcs);
18327 unsigned num_vars = vec_safe_length (offload_vars);
18329 if (num_funcs == 0 && num_vars == 0)
18330 return;
18332 if (targetm_common.have_named_sections)
18334 vec<constructor_elt, va_gc> *v_f, *v_v;
18335 vec_alloc (v_f, num_funcs);
18336 vec_alloc (v_v, num_vars * 2);
18338 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18339 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18341 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18342 num_vars * 2);
18343 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18344 num_funcs);
18345 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18346 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18347 tree ctor_v = build_constructor (vars_decl_type, v_v);
18348 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18349 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18350 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18351 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18352 get_identifier (".offload_func_table"),
18353 funcs_decl_type);
18354 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18355 get_identifier (".offload_var_table"),
18356 vars_decl_type);
18357 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18358 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18359 otherwise a joint table in a binary will contain padding between
18360 tables from multiple object files. */
18361 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18362 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18363 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18364 DECL_INITIAL (funcs_decl) = ctor_f;
18365 DECL_INITIAL (vars_decl) = ctor_v;
18366 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18367 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18369 varpool_node::finalize_decl (vars_decl);
18370 varpool_node::finalize_decl (funcs_decl);
18372 else
18374 for (unsigned i = 0; i < num_funcs; i++)
18376 tree it = (*offload_funcs)[i];
18377 targetm.record_offload_symbol (it);
18379 for (unsigned i = 0; i < num_vars; i++)
18381 tree it = (*offload_vars)[i];
18382 targetm.record_offload_symbol (it);
18387 /* Find the number of threads (POS = false), or thread number (POS =
18388 true) for an OpenACC region partitioned as MASK. Setup code
18389 required for the calculation is added to SEQ. */
18391 static tree
18392 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18394 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18395 unsigned ix;
18397 /* Start at gang level, and examine relevant dimension indices. */
18398 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18399 if (GOMP_DIM_MASK (ix) & mask)
18401 tree arg = build_int_cst (unsigned_type_node, ix);
18403 if (res)
18405 /* We had an outer index, so scale that by the size of
18406 this dimension. */
18407 tree n = create_tmp_var (integer_type_node);
18408 gimple *call
18409 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18411 gimple_call_set_lhs (call, n);
18412 gimple_seq_add_stmt (seq, call);
18413 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18415 if (pos)
18417 /* Determine index in this dimension. */
18418 tree id = create_tmp_var (integer_type_node);
18419 gimple *call = gimple_build_call_internal
18420 (IFN_GOACC_DIM_POS, 1, arg);
18422 gimple_call_set_lhs (call, id);
18423 gimple_seq_add_stmt (seq, call);
18424 if (res)
18425 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18426 else
18427 res = id;
18431 if (res == NULL_TREE)
18432 res = integer_zero_node;
18434 return res;
18437 /* Transform IFN_GOACC_LOOP calls to actual code. See
18438 expand_oacc_for for where these are generated. At the vector
18439 level, we stride loops, such that each member of a warp will
18440 operate on adjacent iterations. At the worker and gang level,
18441 each gang/warp executes a set of contiguous iterations. Chunking
18442 can override this such that each iteration engine executes a
18443 contiguous chunk, and then moves on to stride to the next chunk. */
18445 static void
18446 oacc_xform_loop (gcall *call)
18448 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18449 enum ifn_goacc_loop_kind code
18450 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18451 tree dir = gimple_call_arg (call, 1);
18452 tree range = gimple_call_arg (call, 2);
18453 tree step = gimple_call_arg (call, 3);
18454 tree chunk_size = NULL_TREE;
18455 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18456 tree lhs = gimple_call_lhs (call);
18457 tree type = TREE_TYPE (lhs);
18458 tree diff_type = TREE_TYPE (range);
18459 tree r = NULL_TREE;
18460 gimple_seq seq = NULL;
18461 bool chunking = false, striding = true;
18462 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18463 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18465 #ifdef ACCEL_COMPILER
18466 chunk_size = gimple_call_arg (call, 4);
18467 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18468 || integer_zerop (chunk_size)) /* Default (also static). */
18470 /* If we're at the gang level, we want each to execute a
18471 contiguous run of iterations. Otherwise we want each element
18472 to stride. */
18473 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18474 chunking = false;
18476 else
18478 /* Chunk of size 1 is striding. */
18479 striding = integer_onep (chunk_size);
18480 chunking = !striding;
18482 #endif
18484 /* striding=true, chunking=true
18485 -> invalid.
18486 striding=true, chunking=false
18487 -> chunks=1
18488 striding=false,chunking=true
18489 -> chunks=ceil (range/(chunksize*threads*step))
18490 striding=false,chunking=false
18491 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18492 push_gimplify_context (true);
18494 switch (code)
18496 default: gcc_unreachable ();
18498 case IFN_GOACC_LOOP_CHUNKS:
18499 if (!chunking)
18500 r = build_int_cst (type, 1);
18501 else
18503 /* chunk_max
18504 = (range - dir) / (chunks * step * num_threads) + dir */
18505 tree per = oacc_thread_numbers (false, mask, &seq);
18506 per = fold_convert (type, per);
18507 chunk_size = fold_convert (type, chunk_size);
18508 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18509 per = fold_build2 (MULT_EXPR, type, per, step);
18510 r = build2 (MINUS_EXPR, type, range, dir);
18511 r = build2 (PLUS_EXPR, type, r, per);
18512 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18514 break;
18516 case IFN_GOACC_LOOP_STEP:
18518 /* If striding, step by the entire compute volume, otherwise
18519 step by the inner volume. */
18520 unsigned volume = striding ? mask : inner_mask;
18522 r = oacc_thread_numbers (false, volume, &seq);
18523 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18525 break;
18527 case IFN_GOACC_LOOP_OFFSET:
18528 if (striding)
18530 r = oacc_thread_numbers (true, mask, &seq);
18531 r = fold_convert (diff_type, r);
18533 else
18535 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18536 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18537 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18538 inner_size, outer_size);
18540 volume = fold_convert (diff_type, volume);
18541 if (chunking)
18542 chunk_size = fold_convert (diff_type, chunk_size);
18543 else
18545 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18547 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18548 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18549 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18552 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18553 fold_convert (diff_type, inner_size));
18554 r = oacc_thread_numbers (true, outer_mask, &seq);
18555 r = fold_convert (diff_type, r);
18556 r = build2 (MULT_EXPR, diff_type, r, span);
18558 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18559 inner = fold_convert (diff_type, inner);
18560 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18562 if (chunking)
18564 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18565 tree per
18566 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18567 per = build2 (MULT_EXPR, diff_type, per, chunk);
18569 r = build2 (PLUS_EXPR, diff_type, r, per);
18572 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18573 if (type != diff_type)
18574 r = fold_convert (type, r);
18575 break;
18577 case IFN_GOACC_LOOP_BOUND:
18578 if (striding)
18579 r = range;
18580 else
18582 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18583 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18584 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18585 inner_size, outer_size);
18587 volume = fold_convert (diff_type, volume);
18588 if (chunking)
18589 chunk_size = fold_convert (diff_type, chunk_size);
18590 else
18592 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18594 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18595 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18596 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18599 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18600 fold_convert (diff_type, inner_size));
18602 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18604 tree offset = gimple_call_arg (call, 6);
18605 r = build2 (PLUS_EXPR, diff_type, r,
18606 fold_convert (diff_type, offset));
18607 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18608 diff_type, r, range);
18610 if (diff_type != type)
18611 r = fold_convert (type, r);
18612 break;
18615 gimplify_assign (lhs, r, &seq);
18617 pop_gimplify_context (NULL);
18619 gsi_replace_with_seq (&gsi, seq, true);
18622 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18623 raw attribute. DIMS is an array of dimensions, which is returned.
18624 Returns the function level dimensionality -- the level at which an
18625 offload routine wishes to partition a loop. */
18627 static int
18628 oacc_validate_dims (tree fn, tree attrs, int *dims)
18630 tree purpose[GOMP_DIM_MAX];
18631 unsigned ix;
18632 tree pos = TREE_VALUE (attrs);
18633 int fn_level = -1;
18635 /* Make sure the attribute creator attached the dimension
18636 information. */
18637 gcc_assert (pos);
18639 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18641 purpose[ix] = TREE_PURPOSE (pos);
18643 if (purpose[ix])
18645 if (integer_zerop (purpose[ix]))
18646 fn_level = ix + 1;
18647 else if (fn_level < 0)
18648 fn_level = ix;
18651 tree val = TREE_VALUE (pos);
18652 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18653 pos = TREE_CHAIN (pos);
18656 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18658 /* Default anything left to 1. */
18659 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18660 if (dims[ix] < 0)
18662 dims[ix] = 1;
18663 changed = true;
18666 if (changed)
18668 /* Replace the attribute with new values. */
18669 pos = NULL_TREE;
18670 for (ix = GOMP_DIM_MAX; ix--;)
18671 pos = tree_cons (purpose[ix],
18672 build_int_cst (integer_type_node, dims[ix]),
18673 pos);
18674 replace_oacc_fn_attrib (fn, pos);
18677 return fn_level;
18680 /* Create an empty OpenACC loop structure at LOC. */
18682 static oacc_loop *
18683 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18685 oacc_loop *loop = XCNEW (oacc_loop);
18687 loop->parent = parent;
18688 loop->child = loop->sibling = NULL;
18690 if (parent)
18692 loop->sibling = parent->child;
18693 parent->child = loop;
18696 loop->loc = loc;
18697 loop->marker = NULL;
18698 memset (loop->heads, 0, sizeof (loop->heads));
18699 memset (loop->tails, 0, sizeof (loop->tails));
18700 loop->routine = NULL_TREE;
18702 loop->mask = loop->flags = 0;
18703 loop->chunk_size = 0;
18704 loop->head_end = NULL;
18706 return loop;
18709 /* Create an outermost, dummy OpenACC loop for offloaded function
18710 DECL. */
18712 static oacc_loop *
18713 new_oacc_loop_outer (tree decl)
18715 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18718 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18719 Link into PARENT loop. Return the new loop. */
18721 static oacc_loop *
18722 new_oacc_loop (oacc_loop *parent, gcall *marker)
18724 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18726 loop->marker = marker;
18728 /* TODO: This is where device_type flattening would occur for the loop
18729 flags. */
18731 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18733 tree chunk_size = integer_zero_node;
18734 if (loop->flags & OLF_GANG_STATIC)
18735 chunk_size = gimple_call_arg (marker, 4);
18736 loop->chunk_size = chunk_size;
18738 return loop;
18741 /* Create a dummy loop encompassing a call to a openACC routine.
18742 Extract the routine's partitioning requirements. */
18744 static void
18745 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18747 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18748 int dims[GOMP_DIM_MAX];
18749 int level = oacc_validate_dims (decl, attrs, dims);
18751 gcc_assert (level >= 0);
18753 loop->marker = call;
18754 loop->routine = decl;
18755 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18756 ^ (GOMP_DIM_MASK (level) - 1));
18759 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18760 Return the parent loop. */
18762 static oacc_loop *
18763 finish_oacc_loop (oacc_loop *loop)
18765 return loop->parent;
18768 /* Free all OpenACC loop structures within LOOP (inclusive). */
18770 static void
18771 free_oacc_loop (oacc_loop *loop)
18773 if (loop->sibling)
18774 free_oacc_loop (loop->sibling);
18775 if (loop->child)
18776 free_oacc_loop (loop->child);
18778 free (loop);
18781 /* Dump out the OpenACC loop head or tail beginning at FROM. */
18783 static void
18784 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
18785 const char *title, int level)
18787 enum ifn_unique_kind kind
18788 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
18790 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
18791 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
18793 gimple *stmt = gsi_stmt (gsi);
18795 if (is_gimple_call (stmt)
18796 && gimple_call_internal_p (stmt)
18797 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
18799 enum ifn_unique_kind k
18800 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
18801 (gimple_call_arg (stmt, 0)));
18803 if (k == kind && stmt != from)
18804 break;
18806 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
18808 gsi_next (&gsi);
18809 while (gsi_end_p (gsi))
18810 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
18814 /* Dump OpenACC loops LOOP, its siblings and its children. */
18816 static void
18817 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
18819 int ix;
18821 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
18822 loop->flags, loop->mask,
18823 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
18825 if (loop->marker)
18826 print_gimple_stmt (file, loop->marker, depth * 2, 0);
18828 if (loop->routine)
18829 fprintf (file, "%*sRoutine %s:%u:%s\n",
18830 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
18831 DECL_SOURCE_LINE (loop->routine),
18832 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
18834 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18835 if (loop->heads[ix])
18836 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
18837 for (ix = GOMP_DIM_MAX; ix--;)
18838 if (loop->tails[ix])
18839 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
18841 if (loop->child)
18842 dump_oacc_loop (file, loop->child, depth + 1);
18843 if (loop->sibling)
18844 dump_oacc_loop (file, loop->sibling, depth);
18847 void debug_oacc_loop (oacc_loop *);
18849 /* Dump loops to stderr. */
18851 DEBUG_FUNCTION void
18852 debug_oacc_loop (oacc_loop *loop)
18854 dump_oacc_loop (stderr, loop, 0);
18857 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
18858 structures as we go. By construction these loops are properly
18859 nested. */
18861 static void
18862 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
18864 int marker = 0;
18865 int remaining = 0;
18867 if (bb->flags & BB_VISITED)
18868 return;
18870 follow:
18871 bb->flags |= BB_VISITED;
18873 /* Scan for loop markers. */
18874 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
18875 gsi_next (&gsi))
18877 gimple *stmt = gsi_stmt (gsi);
18879 if (!is_gimple_call (stmt))
18880 continue;
18882 gcall *call = as_a <gcall *> (stmt);
18884 /* If this is a routine, make a dummy loop for it. */
18885 if (tree decl = gimple_call_fndecl (call))
18886 if (tree attrs = get_oacc_fn_attrib (decl))
18888 gcc_assert (!marker);
18889 new_oacc_loop_routine (loop, call, decl, attrs);
18892 if (!gimple_call_internal_p (call))
18893 continue;
18895 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
18896 continue;
18898 enum ifn_unique_kind kind
18899 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18900 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
18901 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
18903 if (gimple_call_num_args (call) == 2)
18905 gcc_assert (marker && !remaining);
18906 marker = 0;
18907 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
18908 loop = finish_oacc_loop (loop);
18909 else
18910 loop->head_end = call;
18912 else
18914 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
18916 if (!marker)
18918 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
18919 loop = new_oacc_loop (loop, call);
18920 remaining = count;
18922 gcc_assert (count == remaining);
18923 if (remaining)
18925 remaining--;
18926 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
18927 loop->heads[marker] = call;
18928 else
18929 loop->tails[remaining] = call;
18931 marker++;
18935 if (remaining || marker)
18937 bb = single_succ (bb);
18938 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
18939 goto follow;
18942 /* Walk successor blocks. */
18943 edge e;
18944 edge_iterator ei;
18946 FOR_EACH_EDGE (e, ei, bb->succs)
18947 oacc_loop_discover_walk (loop, e->dest);
18950 /* LOOP is the first sibling. Reverse the order in place and return
18951 the new first sibling. Recurse to child loops. */
18953 static oacc_loop *
18954 oacc_loop_sibling_nreverse (oacc_loop *loop)
18956 oacc_loop *last = NULL;
18959 if (loop->child)
18960 loop->child = oacc_loop_sibling_nreverse (loop->child);
18962 oacc_loop *next = loop->sibling;
18963 loop->sibling = last;
18964 last = loop;
18965 loop = next;
18967 while (loop);
18969 return last;
18972 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
18973 the current function. */
18975 static oacc_loop *
18976 oacc_loop_discovery ()
18978 basic_block bb;
18980 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
18981 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
18983 /* The siblings were constructed in reverse order, reverse them so
18984 that diagnostics come out in an unsurprising order. */
18985 top = oacc_loop_sibling_nreverse (top);
18987 /* Reset the visited flags. */
18988 FOR_ALL_BB_FN (bb, cfun)
18989 bb->flags &= ~BB_VISITED;
18991 return top;
18994 /* Transform the abstract internal function markers starting at FROM
18995 to be for partitioning level LEVEL. Stop when we meet another HEAD
18996 or TAIL marker. */
18998 static void
18999 oacc_loop_xform_head_tail (gcall *from, int level)
19001 enum ifn_unique_kind kind
19002 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19003 tree replacement = build_int_cst (unsigned_type_node, level);
19005 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19007 gimple *stmt = gsi_stmt (gsi);
19009 if (is_gimple_call (stmt)
19010 && gimple_call_internal_p (stmt)
19011 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19013 enum ifn_unique_kind k
19014 = ((enum ifn_unique_kind)
19015 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19017 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19018 *gimple_call_arg_ptr (stmt, 2) = replacement;
19019 else if (k == kind && stmt != from)
19020 break;
19022 gsi_next (&gsi);
19023 while (gsi_end_p (gsi))
19024 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19028 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19029 determined partitioning mask and chunking argument. */
19031 static void
19032 oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19034 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19036 for (;;)
19038 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19040 gimple *stmt = gsi_stmt (gsi);
19042 if (!is_gimple_call (stmt))
19043 continue;
19045 gcall *call = as_a <gcall *> (stmt);
19047 if (!gimple_call_internal_p (call))
19048 continue;
19050 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19051 continue;
19053 *gimple_call_arg_ptr (call, 5) = mask_arg;
19054 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19055 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19056 == IFN_GOACC_LOOP_BOUND)
19057 return;
19060 /* If we didn't see LOOP_BOUND, it should be in the single
19061 successor block. */
19062 basic_block bb = single_succ (gsi_bb (gsi));
19063 gsi = gsi_start_bb (bb);
19067 /* Process the discovered OpenACC loops, setting the correct
19068 partitioning level etc. */
19070 static void
19071 oacc_loop_process (oacc_loop *loop)
19073 if (loop->child)
19074 oacc_loop_process (loop->child);
19076 if (loop->mask && !loop->routine)
19078 int ix;
19079 unsigned mask = loop->mask;
19080 unsigned dim = GOMP_DIM_GANG;
19081 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19082 tree chunk_arg = loop->chunk_size;
19084 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19086 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19088 gcc_assert (mask);
19090 while (!(GOMP_DIM_MASK (dim) & mask))
19091 dim++;
19093 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19094 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19096 mask ^= GOMP_DIM_MASK (dim);
19100 if (loop->sibling)
19101 oacc_loop_process (loop->sibling);
19104 /* Walk the OpenACC loop heirarchy checking and assigning the
19105 programmer-specified partitionings. OUTER_MASK is the partitioning
19106 this loop is contained within. Return partitiong mask used within
19107 this loop nest. */
19109 static unsigned
19110 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19112 unsigned this_mask = loop->mask;
19113 bool has_auto = false;
19114 bool noisy = true;
19116 #ifdef ACCEL_COMPILER
19117 /* When device_type is supported, we want the device compiler to be
19118 noisy, if the loop parameters are device_type-specific. */
19119 noisy = false;
19120 #endif
19122 if (!loop->routine)
19124 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19125 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19127 this_mask = ((loop->flags >> OLF_DIM_BASE)
19128 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19130 if ((this_mask != 0) + auto_par + seq_par > 1)
19132 if (noisy)
19133 error_at (loop->loc,
19134 seq_par
19135 ? "%<seq%> overrides other OpenACC loop specifiers"
19136 : "%<auto%> conflicts with other OpenACC loop specifiers");
19137 auto_par = false;
19138 loop->flags &= ~OLF_AUTO;
19139 if (seq_par)
19141 loop->flags &=
19142 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19143 this_mask = 0;
19146 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19147 has_auto = true;
19150 if (this_mask & outer_mask)
19152 const oacc_loop *outer;
19153 for (outer = loop->parent; outer; outer = outer->parent)
19154 if (outer->mask & this_mask)
19155 break;
19157 if (noisy)
19159 if (outer)
19161 error_at (loop->loc,
19162 "%s uses same OpenACC parallelism as containing loop",
19163 loop->routine ? "routine call" : "inner loop");
19164 inform (outer->loc, "containing loop here");
19166 else
19167 error_at (loop->loc,
19168 "%s uses OpenACC parallelism disallowed by containing routine",
19169 loop->routine ? "routine call" : "loop");
19171 if (loop->routine)
19172 inform (DECL_SOURCE_LOCATION (loop->routine),
19173 "routine %qD declared here", loop->routine);
19175 this_mask &= ~outer_mask;
19177 else
19179 unsigned outermost = this_mask & -this_mask;
19181 if (outermost && outermost <= outer_mask)
19183 if (noisy)
19185 error_at (loop->loc,
19186 "incorrectly nested OpenACC loop parallelism");
19188 const oacc_loop *outer;
19189 for (outer = loop->parent;
19190 outer->flags && outer->flags < outermost;
19191 outer = outer->parent)
19192 continue;
19193 inform (outer->loc, "containing loop here");
19196 this_mask &= ~outermost;
19200 loop->mask = this_mask;
19202 if (loop->child
19203 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19204 has_auto = true;
19206 if (loop->sibling
19207 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19208 has_auto = true;
19210 return has_auto;
19213 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19214 axes. */
19216 static void
19217 oacc_loop_partition (oacc_loop *loop, int fn_level)
19219 unsigned outer_mask = 0;
19221 if (fn_level >= 0)
19222 outer_mask = GOMP_DIM_MASK (fn_level) - 1;
19224 oacc_loop_fixed_partitions (loop, outer_mask);
19227 /* Default fork/join early expander. Delete the function calls if
19228 there is no RTL expander. */
19230 bool
19231 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19232 const int *ARG_UNUSED (dims), bool is_fork)
19234 if (is_fork)
19235 return targetm.have_oacc_fork ();
19236 else
19237 return targetm.have_oacc_join ();
19240 /* Main entry point for oacc transformations which run on the device
19241 compiler after LTO, so we know what the target device is at this
19242 point (including the host fallback). */
19244 static unsigned int
19245 execute_oacc_device_lower ()
19247 tree attrs = get_oacc_fn_attrib (current_function_decl);
19248 int dims[GOMP_DIM_MAX];
19250 if (!attrs)
19251 /* Not an offloaded function. */
19252 return 0;
19254 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19256 /* Discover, partition and process the loops. */
19257 oacc_loop *loops = oacc_loop_discovery ();
19258 oacc_loop_partition (loops, fn_level);
19259 oacc_loop_process (loops);
19260 if (dump_file)
19262 fprintf (dump_file, "OpenACC loops\n");
19263 dump_oacc_loop (dump_file, loops, 0);
19264 fprintf (dump_file, "\n");
19267 /* Now lower internal loop functions to target-specific code
19268 sequences. */
19269 basic_block bb;
19270 FOR_ALL_BB_FN (bb, cfun)
19271 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19273 gimple *stmt = gsi_stmt (gsi);
19274 if (!is_gimple_call (stmt))
19276 gsi_next (&gsi);
19277 continue;
19280 gcall *call = as_a <gcall *> (stmt);
19281 if (!gimple_call_internal_p (call))
19283 gsi_next (&gsi);
19284 continue;
19287 /* Rewind to allow rescan. */
19288 gsi_prev (&gsi);
19289 bool rescan = false, remove = false;
19290 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19292 switch (ifn_code)
19294 default: break;
19296 case IFN_GOACC_LOOP:
19297 oacc_xform_loop (call);
19298 rescan = true;
19299 break;
19301 case IFN_UNIQUE:
19303 enum ifn_unique_kind kind
19304 = ((enum ifn_unique_kind)
19305 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19307 switch (kind)
19309 default:
19310 gcc_unreachable ();
19312 case IFN_UNIQUE_OACC_FORK:
19313 case IFN_UNIQUE_OACC_JOIN:
19314 if (integer_minus_onep (gimple_call_arg (call, 2)))
19315 remove = true;
19316 else if (!targetm.goacc.fork_join
19317 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19318 remove = true;
19319 break;
19321 case IFN_UNIQUE_OACC_HEAD_MARK:
19322 case IFN_UNIQUE_OACC_TAIL_MARK:
19323 remove = true;
19324 break;
19326 break;
19330 if (gsi_end_p (gsi))
19331 /* We rewound past the beginning of the BB. */
19332 gsi = gsi_start_bb (bb);
19333 else
19334 /* Undo the rewind. */
19335 gsi_next (&gsi);
19337 if (remove)
19339 if (gimple_vdef (call))
19340 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19341 if (gimple_call_lhs (call))
19343 /* Propagate the data dependency var. */
19344 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19345 gimple_call_arg (call, 1));
19346 gsi_replace (&gsi, ass, false);
19348 else
19349 gsi_remove (&gsi, true);
19351 else if (!rescan)
19352 /* If not rescanning, advance over the call. */
19353 gsi_next (&gsi);
19356 free_oacc_loop (loops);
19358 return 0;
19361 /* Default launch dimension validator. Force everything to 1. A
19362 backend that wants to provide larger dimensions must override this
19363 hook. */
19365 bool
19366 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19367 int ARG_UNUSED (fn_level))
19369 bool changed = false;
19371 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19373 if (dims[ix] != 1)
19375 dims[ix] = 1;
19376 changed = true;
19380 return changed;
19383 namespace {
19385 const pass_data pass_data_oacc_device_lower =
19387 GIMPLE_PASS, /* type */
19388 "oaccdevlow", /* name */
19389 OPTGROUP_NONE, /* optinfo_flags */
19390 TV_NONE, /* tv_id */
19391 PROP_cfg, /* properties_required */
19392 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19393 0, /* properties_destroyed */
19394 0, /* todo_flags_start */
19395 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19398 class pass_oacc_device_lower : public gimple_opt_pass
19400 public:
19401 pass_oacc_device_lower (gcc::context *ctxt)
19402 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19405 /* opt_pass methods: */
19406 virtual unsigned int execute (function *)
19408 bool gate = flag_openacc != 0;
19410 if (!gate)
19411 return 0;
19413 return execute_oacc_device_lower ();
19416 }; // class pass_oacc_transform
19418 } // anon namespace
19420 gimple_opt_pass *
19421 make_pass_oacc_device_lower (gcc::context *ctxt)
19423 return new pass_oacc_device_lower (ctxt);
19426 #include "gt-omp-low.h"