svn merge -r215707:216846 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / gcc / omp-low.c
bloba04b0128ef6e72f06894d4d76f0bca0c5ffb3d9f
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "predict.h"
33 #include "vec.h"
34 #include "hashtab.h"
35 #include "hash-set.h"
36 #include "machmode.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
62 #include "cgraph.h"
63 #include "tree-cfg.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "optabs.h"
77 #include "cfgloop.h"
78 #include "target.h"
79 #include "common/common-target.h"
80 #include "omp-low.h"
81 #include "gimple-low.h"
82 #include "tree-cfgcleanup.h"
83 #include "pretty-print.h"
84 #include "alloc-pool.h"
85 #include "ipa-prop.h"
86 #include "tree-nested.h"
87 #include "tree-eh.h"
88 #include "cilk.h"
89 #include "lto-section-names.h"
92 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
93 phases. The first phase scans the function looking for OMP statements
94 and then for variables that must be replaced to satisfy data sharing
95 clauses. The second phase expands code for the constructs, as well as
96 re-gimplifying things when variables have been replaced with complex
97 expressions.
99 Final code generation is done by pass_expand_omp. The flowgraph is
100 scanned for parallel regions which are then moved to a new
101 function, to be invoked by the thread library. */
103 /* Parallel region information. Every parallel and workshare
104 directive is enclosed between two markers, the OMP_* directive
105 and a corresponding OMP_RETURN statement. */
107 struct omp_region
109 /* The enclosing region. */
110 struct omp_region *outer;
112 /* First child region. */
113 struct omp_region *inner;
115 /* Next peer region. */
116 struct omp_region *next;
118 /* Block containing the omp directive as its last stmt. */
119 basic_block entry;
121 /* Block containing the OMP_RETURN as its last stmt. */
122 basic_block exit;
124 /* Block containing the OMP_CONTINUE as its last stmt. */
125 basic_block cont;
127 /* If this is a combined parallel+workshare region, this is a list
128 of additional arguments needed by the combined parallel+workshare
129 library call. */
130 vec<tree, va_gc> *ws_args;
132 /* The code for the omp directive of this region. */
133 enum gimple_code type;
135 /* Schedule kind, only used for OMP_FOR type regions. */
136 enum omp_clause_schedule_kind sched_kind;
138 /* True if this is a combined parallel+workshare region. */
139 bool is_combined_parallel;
142 /* Context structure. Used to store information about each parallel
143 directive in the code. */
145 typedef struct omp_context
147 /* This field must be at the beginning, as we do "inheritance": Some
148 callback functions for tree-inline.c (e.g., omp_copy_decl)
149 receive a copy_body_data pointer that is up-casted to an
150 omp_context pointer. */
151 copy_body_data cb;
153 /* The tree of contexts corresponding to the encountered constructs. */
154 struct omp_context *outer;
155 gimple stmt;
157 /* Map variables to fields in a structure that allows communication
158 between sending and receiving threads. */
159 splay_tree field_map;
160 tree record_type;
161 tree sender_decl;
162 tree receiver_decl;
164 /* These are used just by task contexts, if task firstprivate fn is
165 needed. srecord_type is used to communicate from the thread
166 that encountered the task construct to task firstprivate fn,
167 record_type is allocated by GOMP_task, initialized by task firstprivate
168 fn and passed to the task body fn. */
169 splay_tree sfield_map;
170 tree srecord_type;
172 /* A chain of variables to add to the top-level block surrounding the
173 construct. In the case of a parallel, this is in the child function. */
174 tree block_vars;
176 /* A map of reduction pointer variables. For accelerators, each
177 reduction variable is replaced with an array. Each thread, in turn,
178 is assigned to a slot on that array. */
179 splay_tree reduction_map;
181 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
182 barriers should jump to during omplower pass. */
183 tree cancel_label;
185 /* What to do with variables with implicitly determined sharing
186 attributes. */
187 enum omp_clause_default_kind default_kind;
189 /* Nesting depth of this context. Used to beautify error messages re
190 invalid gotos. The outermost ctx is depth 1, with depth 0 being
191 reserved for the main body of the function. */
192 int depth;
194 /* True if this parallel directive is nested within another. */
195 bool is_nested;
197 /* True if this construct can be cancelled. */
198 bool cancellable;
199 } omp_context;
201 /* A structure holding the elements of:
202 for (V = N1; V cond N2; V += STEP) [...] */
204 struct omp_for_data_loop
206 tree v, n1, n2, step;
207 enum tree_code cond_code;
210 /* A structure describing the main elements of a parallel loop. */
212 struct omp_for_data
214 struct omp_for_data_loop loop;
215 tree chunk_size;
216 gimple for_stmt;
217 tree pre, iter_type;
218 int collapse;
219 bool have_nowait, have_ordered;
220 enum omp_clause_schedule_kind sched_kind;
221 struct omp_for_data_loop *loops;
225 static splay_tree all_contexts;
226 static int taskreg_nesting_level;
227 static int target_nesting_level;
228 static struct omp_region *root_omp_region;
229 static bitmap task_shared_vars;
230 static vec<omp_context *> taskreg_contexts;
232 static void scan_omp (gimple_seq *, omp_context *);
233 static tree scan_omp_1_op (tree *, int *, void *);
235 #define WALK_SUBSTMTS \
236 case GIMPLE_BIND: \
237 case GIMPLE_TRY: \
238 case GIMPLE_CATCH: \
239 case GIMPLE_EH_FILTER: \
240 case GIMPLE_TRANSACTION: \
241 /* The sub-statements for these should be walked. */ \
242 *handled_ops_p = false; \
243 break;
245 /* Helper function to get the reduction array name */
246 static const char *
247 omp_get_id (tree node)
249 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
250 int len = strlen ("omp$") + strlen (id);
251 char *temp_name = (char *)alloca (len+1);
252 snprintf (temp_name, len+1, "gfc$%s", id);
253 return IDENTIFIER_POINTER(get_identifier (temp_name));
256 /* Holds a decl for __OPENMP_TARGET__. */
257 static GTY(()) tree offload_symbol_decl;
259 /* Holds offload tables with decls. */
260 vec<tree, va_gc> *offload_funcs, *offload_vars;
262 /* Get the __OPENMP_TARGET__ symbol. */
263 static tree
264 get_offload_symbol_decl (void)
266 if (!offload_symbol_decl)
268 tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
269 get_identifier ("__OPENMP_TARGET__"),
270 ptr_type_node);
271 TREE_ADDRESSABLE (decl) = 1;
272 TREE_PUBLIC (decl) = 1;
273 DECL_EXTERNAL (decl) = 1;
274 DECL_WEAK (decl) = 1;
275 DECL_ATTRIBUTES (decl)
276 = tree_cons (get_identifier ("weak"),
277 NULL_TREE, DECL_ATTRIBUTES (decl));
278 offload_symbol_decl = decl;
280 return offload_symbol_decl;
283 /* Convenience function for calling scan_omp_1_op on tree operands. */
285 static inline tree
286 scan_omp_op (tree *tp, omp_context *ctx)
288 struct walk_stmt_info wi;
290 memset (&wi, 0, sizeof (wi));
291 wi.info = ctx;
292 wi.want_locations = true;
294 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
297 static void lower_omp (gimple_seq *, omp_context *);
298 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
299 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
301 /* Find an OpenMP clause of type KIND within CLAUSES. */
303 tree
304 find_omp_clause (tree clauses, enum omp_clause_code kind)
306 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
307 if (OMP_CLAUSE_CODE (clauses) == kind)
308 return clauses;
310 return NULL_TREE;
313 /* Return true if CTX is for an omp parallel. */
315 static inline bool
316 is_parallel_ctx (omp_context *ctx)
318 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
322 /* Return true if CTX is for an omp task. */
324 static inline bool
325 is_task_ctx (omp_context *ctx)
327 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
331 /* Return true if CTX is for an omp parallel or omp task. */
333 static inline bool
334 is_taskreg_ctx (omp_context *ctx)
336 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
337 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
341 /* Return true if REGION is a combined parallel+workshare region. */
343 static inline bool
344 is_combined_parallel (struct omp_region *region)
346 return region->is_combined_parallel;
350 /* Extract the header elements of parallel loop FOR_STMT and store
351 them into *FD. */
353 static void
354 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
355 struct omp_for_data_loop *loops)
357 tree t, var, *collapse_iter, *collapse_count;
358 tree count = NULL_TREE, iter_type = long_integer_type_node;
359 struct omp_for_data_loop *loop;
360 int i;
361 struct omp_for_data_loop dummy_loop;
362 location_t loc = gimple_location (for_stmt);
363 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
364 bool distribute = gimple_omp_for_kind (for_stmt)
365 == GF_OMP_FOR_KIND_DISTRIBUTE;
367 fd->for_stmt = for_stmt;
368 fd->pre = NULL;
369 fd->collapse = gimple_omp_for_collapse (for_stmt);
370 if (fd->collapse > 1)
371 fd->loops = loops;
372 else
373 fd->loops = &fd->loop;
375 fd->have_nowait = (gimple_omp_for_kind (for_stmt) != GF_OMP_FOR_KIND_FOR);
376 fd->have_ordered = false;
377 fd->sched_kind = /* TODO: OACC_LOOP */ OMP_CLAUSE_SCHEDULE_STATIC;
378 fd->chunk_size = NULL_TREE;
379 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
380 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
381 collapse_iter = NULL;
382 collapse_count = NULL;
384 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
385 switch (OMP_CLAUSE_CODE (t))
387 case OMP_CLAUSE_NOWAIT:
388 fd->have_nowait = true;
389 break;
390 case OMP_CLAUSE_ORDERED:
391 fd->have_ordered = true;
392 break;
393 case OMP_CLAUSE_SCHEDULE:
394 gcc_assert (!distribute);
395 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
396 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
397 break;
398 case OMP_CLAUSE_DIST_SCHEDULE:
399 gcc_assert (distribute);
400 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
401 break;
402 case OMP_CLAUSE_COLLAPSE:
403 if (fd->collapse > 1)
405 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
406 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
408 break;
409 default:
410 break;
413 /* FIXME: for now map schedule(auto) to schedule(static).
414 There should be analysis to determine whether all iterations
415 are approximately the same amount of work (then schedule(static)
416 is best) or if it varies (then schedule(dynamic,N) is better). */
417 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
419 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
420 gcc_assert (fd->chunk_size == NULL);
422 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
423 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
424 gcc_assert (fd->chunk_size == NULL);
425 else if (fd->chunk_size == NULL)
427 /* We only need to compute a default chunk size for ordered
428 static loops and dynamic loops. */
429 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
430 || fd->have_ordered)
431 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
432 ? integer_zero_node : integer_one_node;
435 for (i = 0; i < fd->collapse; i++)
437 if (fd->collapse == 1)
438 loop = &fd->loop;
439 else if (loops != NULL)
440 loop = loops + i;
441 else
442 loop = &dummy_loop;
444 loop->v = gimple_omp_for_index (for_stmt, i);
445 gcc_assert (SSA_VAR_P (loop->v));
446 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
447 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
448 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
449 loop->n1 = gimple_omp_for_initial (for_stmt, i);
451 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
452 loop->n2 = gimple_omp_for_final (for_stmt, i);
453 switch (loop->cond_code)
455 case LT_EXPR:
456 case GT_EXPR:
457 break;
458 case NE_EXPR:
459 gcc_assert (gimple_omp_for_kind (for_stmt)
460 == GF_OMP_FOR_KIND_CILKSIMD
461 || (gimple_omp_for_kind (for_stmt)
462 == GF_OMP_FOR_KIND_CILKFOR));
463 break;
464 case LE_EXPR:
465 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
466 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
467 else
468 loop->n2 = fold_build2_loc (loc,
469 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
470 build_int_cst (TREE_TYPE (loop->n2), 1));
471 loop->cond_code = LT_EXPR;
472 break;
473 case GE_EXPR:
474 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
475 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
476 else
477 loop->n2 = fold_build2_loc (loc,
478 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
479 build_int_cst (TREE_TYPE (loop->n2), 1));
480 loop->cond_code = GT_EXPR;
481 break;
482 default:
483 gcc_unreachable ();
486 t = gimple_omp_for_incr (for_stmt, i);
487 gcc_assert (TREE_OPERAND (t, 0) == var);
488 switch (TREE_CODE (t))
490 case PLUS_EXPR:
491 loop->step = TREE_OPERAND (t, 1);
492 break;
493 case POINTER_PLUS_EXPR:
494 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
495 break;
496 case MINUS_EXPR:
497 loop->step = TREE_OPERAND (t, 1);
498 loop->step = fold_build1_loc (loc,
499 NEGATE_EXPR, TREE_TYPE (loop->step),
500 loop->step);
501 break;
502 default:
503 gcc_unreachable ();
506 if (simd
507 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
508 && !fd->have_ordered))
510 if (fd->collapse == 1)
511 iter_type = TREE_TYPE (loop->v);
512 else if (i == 0
513 || TYPE_PRECISION (iter_type)
514 < TYPE_PRECISION (TREE_TYPE (loop->v)))
515 iter_type
516 = build_nonstandard_integer_type
517 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
519 else if (iter_type != long_long_unsigned_type_node)
521 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
522 iter_type = long_long_unsigned_type_node;
523 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
524 && TYPE_PRECISION (TREE_TYPE (loop->v))
525 >= TYPE_PRECISION (iter_type))
527 tree n;
529 if (loop->cond_code == LT_EXPR)
530 n = fold_build2_loc (loc,
531 PLUS_EXPR, TREE_TYPE (loop->v),
532 loop->n2, loop->step);
533 else
534 n = loop->n1;
535 if (TREE_CODE (n) != INTEGER_CST
536 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
537 iter_type = long_long_unsigned_type_node;
539 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
540 > TYPE_PRECISION (iter_type))
542 tree n1, n2;
544 if (loop->cond_code == LT_EXPR)
546 n1 = loop->n1;
547 n2 = fold_build2_loc (loc,
548 PLUS_EXPR, TREE_TYPE (loop->v),
549 loop->n2, loop->step);
551 else
553 n1 = fold_build2_loc (loc,
554 MINUS_EXPR, TREE_TYPE (loop->v),
555 loop->n2, loop->step);
556 n2 = loop->n1;
558 if (TREE_CODE (n1) != INTEGER_CST
559 || TREE_CODE (n2) != INTEGER_CST
560 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
561 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
562 iter_type = long_long_unsigned_type_node;
566 if (collapse_count && *collapse_count == NULL)
568 t = fold_binary (loop->cond_code, boolean_type_node,
569 fold_convert (TREE_TYPE (loop->v), loop->n1),
570 fold_convert (TREE_TYPE (loop->v), loop->n2));
571 if (t && integer_zerop (t))
572 count = build_zero_cst (long_long_unsigned_type_node);
573 else if ((i == 0 || count != NULL_TREE)
574 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
575 && TREE_CONSTANT (loop->n1)
576 && TREE_CONSTANT (loop->n2)
577 && TREE_CODE (loop->step) == INTEGER_CST)
579 tree itype = TREE_TYPE (loop->v);
581 if (POINTER_TYPE_P (itype))
582 itype = signed_type_for (itype);
583 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
584 t = fold_build2_loc (loc,
585 PLUS_EXPR, itype,
586 fold_convert_loc (loc, itype, loop->step), t);
587 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
588 fold_convert_loc (loc, itype, loop->n2));
589 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
590 fold_convert_loc (loc, itype, loop->n1));
591 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
592 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
593 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
594 fold_build1_loc (loc, NEGATE_EXPR, itype,
595 fold_convert_loc (loc, itype,
596 loop->step)));
597 else
598 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
599 fold_convert_loc (loc, itype, loop->step));
600 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
601 if (count != NULL_TREE)
602 count = fold_build2_loc (loc,
603 MULT_EXPR, long_long_unsigned_type_node,
604 count, t);
605 else
606 count = t;
607 if (TREE_CODE (count) != INTEGER_CST)
608 count = NULL_TREE;
610 else if (count && !integer_zerop (count))
611 count = NULL_TREE;
615 if (count
616 && !simd
617 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
618 || fd->have_ordered))
620 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
621 iter_type = long_long_unsigned_type_node;
622 else
623 iter_type = long_integer_type_node;
625 else if (collapse_iter && *collapse_iter != NULL)
626 iter_type = TREE_TYPE (*collapse_iter);
627 fd->iter_type = iter_type;
628 if (collapse_iter && *collapse_iter == NULL)
629 *collapse_iter = create_tmp_var (iter_type, ".iter");
630 if (collapse_count && *collapse_count == NULL)
632 if (count)
633 *collapse_count = fold_convert_loc (loc, iter_type, count);
634 else
635 *collapse_count = create_tmp_var (iter_type, ".count");
638 if (fd->collapse > 1)
640 fd->loop.v = *collapse_iter;
641 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
642 fd->loop.n2 = *collapse_count;
643 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
644 fd->loop.cond_code = LT_EXPR;
647 //TODO
648 /* For OpenACC loops, force a chunk size of one, as this avoids the default
649 scheduling where several subsequent iterations are being executed by the
650 same thread. */
651 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
653 gcc_assert (fd->chunk_size == NULL_TREE);
654 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
659 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
660 is the immediate dominator of PAR_ENTRY_BB, return true if there
661 are no data dependencies that would prevent expanding the parallel
662 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
664 When expanding a combined parallel+workshare region, the call to
665 the child function may need additional arguments in the case of
666 GIMPLE_OMP_FOR regions. In some cases, these arguments are
667 computed out of variables passed in from the parent to the child
668 via 'struct .omp_data_s'. For instance:
670 #pragma omp parallel for schedule (guided, i * 4)
671 for (j ...)
673 Is lowered into:
675 # BLOCK 2 (PAR_ENTRY_BB)
676 .omp_data_o.i = i;
677 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
679 # BLOCK 3 (WS_ENTRY_BB)
680 .omp_data_i = &.omp_data_o;
681 D.1667 = .omp_data_i->i;
682 D.1598 = D.1667 * 4;
683 #pragma omp for schedule (guided, D.1598)
685 When we outline the parallel region, the call to the child function
686 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
687 that value is computed *after* the call site. So, in principle we
688 cannot do the transformation.
690 To see whether the code in WS_ENTRY_BB blocks the combined
691 parallel+workshare call, we collect all the variables used in the
692 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
693 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
694 call.
696 FIXME. If we had the SSA form built at this point, we could merely
697 hoist the code in block 3 into block 2 and be done with it. But at
698 this point we don't have dataflow information and though we could
699 hack something up here, it is really not worth the aggravation. */
701 static bool
702 workshare_safe_to_combine_p (basic_block ws_entry_bb)
704 struct omp_for_data fd;
705 gimple ws_stmt = last_stmt (ws_entry_bb);
707 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
708 return true;
710 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
712 extract_omp_for_data (ws_stmt, &fd, NULL);
714 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
715 return false;
716 if (fd.iter_type != long_integer_type_node)
717 return false;
719 /* FIXME. We give up too easily here. If any of these arguments
720 are not constants, they will likely involve variables that have
721 been mapped into fields of .omp_data_s for sharing with the child
722 function. With appropriate data flow, it would be possible to
723 see through this. */
724 if (!is_gimple_min_invariant (fd.loop.n1)
725 || !is_gimple_min_invariant (fd.loop.n2)
726 || !is_gimple_min_invariant (fd.loop.step)
727 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
728 return false;
730 return true;
734 /* Collect additional arguments needed to emit a combined
735 parallel+workshare call. WS_STMT is the workshare directive being
736 expanded. */
738 static vec<tree, va_gc> *
739 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
741 tree t;
742 location_t loc = gimple_location (ws_stmt);
743 vec<tree, va_gc> *ws_args;
745 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
747 struct omp_for_data fd;
748 tree n1, n2;
750 extract_omp_for_data (ws_stmt, &fd, NULL);
751 n1 = fd.loop.n1;
752 n2 = fd.loop.n2;
754 if (gimple_omp_for_combined_into_p (ws_stmt))
756 tree innerc
757 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
758 OMP_CLAUSE__LOOPTEMP_);
759 gcc_assert (innerc);
760 n1 = OMP_CLAUSE_DECL (innerc);
761 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
762 OMP_CLAUSE__LOOPTEMP_);
763 gcc_assert (innerc);
764 n2 = OMP_CLAUSE_DECL (innerc);
767 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
769 t = fold_convert_loc (loc, long_integer_type_node, n1);
770 ws_args->quick_push (t);
772 t = fold_convert_loc (loc, long_integer_type_node, n2);
773 ws_args->quick_push (t);
775 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
776 ws_args->quick_push (t);
778 if (fd.chunk_size)
780 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
781 ws_args->quick_push (t);
784 return ws_args;
786 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
788 /* Number of sections is equal to the number of edges from the
789 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
790 the exit of the sections region. */
791 basic_block bb = single_succ (gimple_bb (ws_stmt));
792 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
793 vec_alloc (ws_args, 1);
794 ws_args->quick_push (t);
795 return ws_args;
798 gcc_unreachable ();
802 /* Discover whether REGION is a combined parallel+workshare region. */
804 static void
805 determine_parallel_type (struct omp_region *region)
807 basic_block par_entry_bb, par_exit_bb;
808 basic_block ws_entry_bb, ws_exit_bb;
810 if (region == NULL || region->inner == NULL
811 || region->exit == NULL || region->inner->exit == NULL
812 || region->inner->cont == NULL)
813 return;
815 /* We only support parallel+for and parallel+sections. */
816 if (region->type != GIMPLE_OMP_PARALLEL
817 || (region->inner->type != GIMPLE_OMP_FOR
818 && region->inner->type != GIMPLE_OMP_SECTIONS))
819 return;
821 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
822 WS_EXIT_BB -> PAR_EXIT_BB. */
823 par_entry_bb = region->entry;
824 par_exit_bb = region->exit;
825 ws_entry_bb = region->inner->entry;
826 ws_exit_bb = region->inner->exit;
828 if (single_succ (par_entry_bb) == ws_entry_bb
829 && single_succ (ws_exit_bb) == par_exit_bb
830 && workshare_safe_to_combine_p (ws_entry_bb)
831 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
832 || (last_and_only_stmt (ws_entry_bb)
833 && last_and_only_stmt (par_exit_bb))))
835 gimple par_stmt = last_stmt (par_entry_bb);
836 gimple ws_stmt = last_stmt (ws_entry_bb);
838 if (region->inner->type == GIMPLE_OMP_FOR)
840 /* If this is a combined parallel loop, we need to determine
841 whether or not to use the combined library calls. There
842 are two cases where we do not apply the transformation:
843 static loops and any kind of ordered loop. In the first
844 case, we already open code the loop so there is no need
845 to do anything else. In the latter case, the combined
846 parallel loop call would still need extra synchronization
847 to implement ordered semantics, so there would not be any
848 gain in using the combined call. */
849 tree clauses = gimple_omp_for_clauses (ws_stmt);
850 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
851 if (c == NULL
852 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
853 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
855 region->is_combined_parallel = false;
856 region->inner->is_combined_parallel = false;
857 return;
861 region->is_combined_parallel = true;
862 region->inner->is_combined_parallel = true;
863 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
868 /* Return true if EXPR is variable sized. */
870 static inline bool
871 is_variable_sized (const_tree expr)
873 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
876 /* Return true if DECL is a reference type. */
878 static inline bool
879 is_reference (tree decl)
881 return lang_hooks.decls.omp_privatize_by_reference (decl);
884 /* Return the type of a decl. If the decl is reference type,
885 return its base type. */
886 static inline tree
887 get_base_type (tree decl)
889 tree type = TREE_TYPE (decl);
890 if (is_reference (decl))
891 type = TREE_TYPE (type);
892 return type;
895 /* Lookup variables in the decl or field splay trees. The "maybe" form
896 allows for the variable form to not have been entered, otherwise we
897 assert that the variable must have been entered. */
899 static inline tree
900 lookup_decl (tree var, omp_context *ctx)
902 tree *n = ctx->cb.decl_map->get (var);
903 return *n;
906 static inline tree
907 maybe_lookup_decl (const_tree var, omp_context *ctx)
909 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
910 return n ? *n : NULL_TREE;
913 static inline tree
914 lookup_field (tree var, omp_context *ctx)
916 splay_tree_node n;
917 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
918 return (tree) n->value;
921 static inline tree
922 lookup_sfield (tree var, omp_context *ctx)
924 splay_tree_node n;
925 n = splay_tree_lookup (ctx->sfield_map
926 ? ctx->sfield_map : ctx->field_map,
927 (splay_tree_key) var);
928 return (tree) n->value;
931 static inline tree
932 lookup_reduction (const char *id, omp_context *ctx)
934 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
936 splay_tree_node n;
937 n = splay_tree_lookup (ctx->reduction_map,
938 (splay_tree_key) id);
939 return (tree) n->value;
942 static inline tree
943 maybe_lookup_field (tree var, omp_context *ctx)
945 splay_tree_node n;
946 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
947 return n ? (tree) n->value : NULL_TREE;
950 static inline tree
951 maybe_lookup_reduction (tree var, omp_context *ctx)
953 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
955 splay_tree_node n;
956 n = splay_tree_lookup (ctx->reduction_map,
957 (splay_tree_key) var);
958 return n ?(tree) n->value : NULL_TREE;
961 /* Return true if DECL should be copied by pointer. SHARED_CTX is
962 the parallel context if DECL is to be shared. */
964 static bool
965 use_pointer_for_field (tree decl, omp_context *shared_ctx)
967 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
968 return true;
970 /* We can only use copy-in/copy-out semantics for shared variables
971 when we know the value is not accessible from an outer scope. */
972 if (shared_ctx)
974 gcc_assert (!is_gimple_omp_oacc_specifically (shared_ctx->stmt));
976 /* ??? Trivially accessible from anywhere. But why would we even
977 be passing an address in this case? Should we simply assert
978 this to be false, or should we have a cleanup pass that removes
979 these from the list of mappings? */
980 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
981 return true;
983 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
984 without analyzing the expression whether or not its location
985 is accessible to anyone else. In the case of nested parallel
986 regions it certainly may be. */
987 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
988 return true;
990 /* Do not use copy-in/copy-out for variables that have their
991 address taken. */
992 if (TREE_ADDRESSABLE (decl))
993 return true;
995 /* lower_send_shared_vars only uses copy-in, but not copy-out
996 for these. */
997 if (TREE_READONLY (decl)
998 || ((TREE_CODE (decl) == RESULT_DECL
999 || TREE_CODE (decl) == PARM_DECL)
1000 && DECL_BY_REFERENCE (decl)))
1001 return false;
1003 /* Disallow copy-in/out in nested parallel if
1004 decl is shared in outer parallel, otherwise
1005 each thread could store the shared variable
1006 in its own copy-in location, making the
1007 variable no longer really shared. */
1008 if (shared_ctx->is_nested)
1010 omp_context *up;
1012 for (up = shared_ctx->outer; up; up = up->outer)
1013 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1014 break;
1016 if (up)
1018 tree c;
1020 for (c = gimple_omp_taskreg_clauses (up->stmt);
1021 c; c = OMP_CLAUSE_CHAIN (c))
1022 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1023 && OMP_CLAUSE_DECL (c) == decl)
1024 break;
1026 if (c)
1027 goto maybe_mark_addressable_and_ret;
1031 /* For tasks avoid using copy-in/out. As tasks can be
1032 deferred or executed in different thread, when GOMP_task
1033 returns, the task hasn't necessarily terminated. */
1034 if (is_task_ctx (shared_ctx))
1036 tree outer;
1037 maybe_mark_addressable_and_ret:
1038 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1039 if (is_gimple_reg (outer))
1041 /* Taking address of OUTER in lower_send_shared_vars
1042 might need regimplification of everything that uses the
1043 variable. */
1044 if (!task_shared_vars)
1045 task_shared_vars = BITMAP_ALLOC (NULL);
1046 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1047 TREE_ADDRESSABLE (outer) = 1;
1049 return true;
1053 return false;
1056 /* Construct a new automatic decl similar to VAR. */
1058 static tree
1059 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1061 tree copy = copy_var_decl (var, name, type);
1063 DECL_CONTEXT (copy) = current_function_decl;
1064 DECL_CHAIN (copy) = ctx->block_vars;
1065 ctx->block_vars = copy;
1067 return copy;
1070 static tree
1071 omp_copy_decl_1 (tree var, omp_context *ctx)
1073 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1076 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1077 as appropriate. */
1078 static tree
1079 omp_build_component_ref (tree obj, tree field)
1081 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1082 if (TREE_THIS_VOLATILE (field))
1083 TREE_THIS_VOLATILE (ret) |= 1;
1084 if (TREE_READONLY (field))
1085 TREE_READONLY (ret) |= 1;
1086 return ret;
1089 /* Build tree nodes to access the field for VAR on the receiver side. */
1091 static tree
1092 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1094 tree x, field = lookup_field (var, ctx);
1096 /* If the receiver record type was remapped in the child function,
1097 remap the field into the new record type. */
1098 x = maybe_lookup_field (field, ctx);
1099 if (x != NULL)
1100 field = x;
1102 x = build_simple_mem_ref (ctx->receiver_decl);
1103 x = omp_build_component_ref (x, field);
1104 if (by_ref)
1105 x = build_simple_mem_ref (x);
1107 return x;
1110 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1111 of a parallel, this is a component reference; for workshare constructs
1112 this is some variable. */
1114 static tree
1115 build_outer_var_ref (tree var, omp_context *ctx)
1117 tree x;
1119 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1120 x = var;
1121 else if (is_variable_sized (var))
1123 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1124 x = build_outer_var_ref (x, ctx);
1125 x = build_simple_mem_ref (x);
1127 else if (is_taskreg_ctx (ctx))
1129 bool by_ref = use_pointer_for_field (var, NULL);
1130 x = build_receiver_ref (var, by_ref, ctx);
1132 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1133 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1135 /* #pragma omp simd isn't a worksharing construct, and can reference even
1136 private vars in its linear etc. clauses. */
1137 x = NULL_TREE;
1138 if (ctx->outer && is_taskreg_ctx (ctx))
1139 x = lookup_decl (var, ctx->outer);
1140 else if (ctx->outer)
1141 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1142 if (x == NULL_TREE)
1143 x = var;
1145 else if (ctx->outer)
1146 x = lookup_decl (var, ctx->outer);
1147 else if (is_reference (var))
1148 /* This can happen with orphaned constructs. If var is reference, it is
1149 possible it is shared and as such valid. */
1150 x = var;
1151 else
1152 gcc_unreachable ();
1154 if (is_reference (var))
1155 x = build_simple_mem_ref (x);
1157 return x;
1160 /* Build tree nodes to access the field for VAR on the sender side. */
1162 static tree
1163 build_sender_ref (tree var, omp_context *ctx)
1165 tree field = lookup_sfield (var, ctx);
1166 return omp_build_component_ref (ctx->sender_decl, field);
1169 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1171 static void
1172 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1174 tree field, type, sfield = NULL_TREE;
1176 gcc_assert ((mask & 1) == 0
1177 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1178 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1179 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1180 gcc_assert ((mask & 3) == 3
1181 || !is_gimple_omp_oacc_specifically (ctx->stmt));
1183 type = TREE_TYPE (var);
1184 if (mask & 4)
1186 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1187 type = build_pointer_type (build_pointer_type (type));
1189 else if (by_ref)
1190 type = build_pointer_type (type);
1191 else if ((mask & 3) == 1 && is_reference (var))
1192 type = TREE_TYPE (type);
1194 field = build_decl (DECL_SOURCE_LOCATION (var),
1195 FIELD_DECL, DECL_NAME (var), type);
1197 /* Remember what variable this field was created for. This does have a
1198 side effect of making dwarf2out ignore this member, so for helpful
1199 debugging we clear it later in delete_omp_context. */
1200 DECL_ABSTRACT_ORIGIN (field) = var;
1201 if (type == TREE_TYPE (var))
1203 DECL_ALIGN (field) = DECL_ALIGN (var);
1204 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1205 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1207 else
1208 DECL_ALIGN (field) = TYPE_ALIGN (type);
1210 if ((mask & 3) == 3)
1212 insert_field_into_struct (ctx->record_type, field);
1213 if (ctx->srecord_type)
1215 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1216 FIELD_DECL, DECL_NAME (var), type);
1217 DECL_ABSTRACT_ORIGIN (sfield) = var;
1218 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1219 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1220 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1221 insert_field_into_struct (ctx->srecord_type, sfield);
1224 else
1226 if (ctx->srecord_type == NULL_TREE)
1228 tree t;
1230 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1231 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1232 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1234 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1235 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1236 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1237 insert_field_into_struct (ctx->srecord_type, sfield);
1238 splay_tree_insert (ctx->sfield_map,
1239 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1240 (splay_tree_value) sfield);
1243 sfield = field;
1244 insert_field_into_struct ((mask & 1) ? ctx->record_type
1245 : ctx->srecord_type, field);
1248 if (mask & 1)
1249 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1250 (splay_tree_value) field);
1251 if ((mask & 2) && ctx->sfield_map)
1252 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1253 (splay_tree_value) sfield);
1256 static tree
1257 install_var_local (tree var, omp_context *ctx)
1259 tree new_var = omp_copy_decl_1 (var, ctx);
1260 insert_decl_map (&ctx->cb, var, new_var);
1261 return new_var;
1264 /* Adjust the replacement for DECL in CTX for the new context. This means
1265 copying the DECL_VALUE_EXPR, and fixing up the type. */
1267 static void
1268 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1270 tree new_decl, size;
1272 new_decl = lookup_decl (decl, ctx);
1274 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1276 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1277 && DECL_HAS_VALUE_EXPR_P (decl))
1279 tree ve = DECL_VALUE_EXPR (decl);
1280 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1281 SET_DECL_VALUE_EXPR (new_decl, ve);
1282 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1285 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1287 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1288 if (size == error_mark_node)
1289 size = TYPE_SIZE (TREE_TYPE (new_decl));
1290 DECL_SIZE (new_decl) = size;
1292 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1293 if (size == error_mark_node)
1294 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1295 DECL_SIZE_UNIT (new_decl) = size;
1299 /* The callback for remap_decl. Search all containing contexts for a
1300 mapping of the variable; this avoids having to duplicate the splay
1301 tree ahead of time. We know a mapping doesn't already exist in the
1302 given context. Create new mappings to implement default semantics. */
1304 static tree
1305 omp_copy_decl (tree var, copy_body_data *cb)
1307 omp_context *ctx = (omp_context *) cb;
1308 tree new_var;
1310 if (TREE_CODE (var) == LABEL_DECL)
1312 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1313 DECL_CONTEXT (new_var) = current_function_decl;
1314 insert_decl_map (&ctx->cb, var, new_var);
1315 return new_var;
1318 while (!is_taskreg_ctx (ctx))
1320 ctx = ctx->outer;
1321 if (ctx == NULL)
1322 return var;
1323 new_var = maybe_lookup_decl (var, ctx);
1324 if (new_var)
1325 return new_var;
1328 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1329 return var;
1331 return error_mark_node;
1335 /* Debugging dumps for parallel regions. */
1336 void dump_omp_region (FILE *, struct omp_region *, int);
1337 void debug_omp_region (struct omp_region *);
1338 void debug_all_omp_regions (void);
1340 /* Dump the parallel region tree rooted at REGION. */
1342 void
1343 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1345 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1346 gimple_code_name[region->type]);
1348 if (region->inner)
1349 dump_omp_region (file, region->inner, indent + 4);
1351 if (region->cont)
1353 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1354 region->cont->index);
1357 if (region->exit)
1358 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1359 region->exit->index);
1360 else
1361 fprintf (file, "%*s[no exit marker]\n", indent, "");
1363 if (region->next)
1364 dump_omp_region (file, region->next, indent);
1367 DEBUG_FUNCTION void
1368 debug_omp_region (struct omp_region *region)
1370 dump_omp_region (stderr, region, 0);
1373 DEBUG_FUNCTION void
1374 debug_all_omp_regions (void)
1376 dump_omp_region (stderr, root_omp_region, 0);
1380 /* Create a new parallel region starting at STMT inside region PARENT. */
1382 static struct omp_region *
1383 new_omp_region (basic_block bb, enum gimple_code type,
1384 struct omp_region *parent)
1386 struct omp_region *region = XCNEW (struct omp_region);
1388 region->outer = parent;
1389 region->entry = bb;
1390 region->type = type;
1392 if (parent)
1394 /* This is a nested region. Add it to the list of inner
1395 regions in PARENT. */
1396 region->next = parent->inner;
1397 parent->inner = region;
1399 else
1401 /* This is a toplevel region. Add it to the list of toplevel
1402 regions in ROOT_OMP_REGION. */
1403 region->next = root_omp_region;
1404 root_omp_region = region;
1407 return region;
1410 /* Release the memory associated with the region tree rooted at REGION. */
1412 static void
1413 free_omp_region_1 (struct omp_region *region)
1415 struct omp_region *i, *n;
1417 for (i = region->inner; i ; i = n)
1419 n = i->next;
1420 free_omp_region_1 (i);
1423 free (region);
1426 /* Release the memory for the entire omp region tree. */
1428 void
1429 free_omp_regions (void)
1431 struct omp_region *r, *n;
1432 for (r = root_omp_region; r ; r = n)
1434 n = r->next;
1435 free_omp_region_1 (r);
1437 root_omp_region = NULL;
1441 /* Create a new context, with OUTER_CTX being the surrounding context. */
1443 static omp_context *
1444 new_omp_context (gimple stmt, omp_context *outer_ctx)
1446 omp_context *ctx = XCNEW (omp_context);
1448 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1449 (splay_tree_value) ctx);
1450 ctx->stmt = stmt;
1452 if (outer_ctx)
1454 ctx->outer = outer_ctx;
1455 ctx->cb = outer_ctx->cb;
1456 ctx->cb.block = NULL;
1457 ctx->depth = outer_ctx->depth + 1;
1458 /* FIXME: handle reductions recursively. */
1459 ctx->reduction_map = outer_ctx->reduction_map;
1461 else
1463 ctx->cb.src_fn = current_function_decl;
1464 ctx->cb.dst_fn = current_function_decl;
1465 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1466 gcc_checking_assert (ctx->cb.src_node);
1467 ctx->cb.dst_node = ctx->cb.src_node;
1468 ctx->cb.src_cfun = cfun;
1469 ctx->cb.copy_decl = omp_copy_decl;
1470 ctx->cb.eh_lp_nr = 0;
1471 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1472 ctx->depth = 1;
1473 //TODO ctx->reduction_map = TODO;
1476 ctx->cb.decl_map = new hash_map<tree, tree>;
1478 return ctx;
1481 static gimple_seq maybe_catch_exception (gimple_seq);
1483 /* Finalize task copyfn. */
1485 static void
1486 finalize_task_copyfn (gimple task_stmt)
1488 struct function *child_cfun;
1489 tree child_fn;
1490 gimple_seq seq = NULL, new_seq;
1491 gimple bind;
1493 child_fn = gimple_omp_task_copy_fn (task_stmt);
1494 if (child_fn == NULL_TREE)
1495 return;
1497 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1498 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1500 push_cfun (child_cfun);
1501 bind = gimplify_body (child_fn, false);
1502 gimple_seq_add_stmt (&seq, bind);
1503 new_seq = maybe_catch_exception (seq);
1504 if (new_seq != seq)
1506 bind = gimple_build_bind (NULL, new_seq, NULL);
1507 seq = NULL;
1508 gimple_seq_add_stmt (&seq, bind);
1510 gimple_set_body (child_fn, seq);
1511 pop_cfun ();
1513 /* Inform the callgraph about the new function. */
1514 cgraph_node::add_new_function (child_fn, false);
1517 /* Destroy a omp_context data structures. Called through the splay tree
1518 value delete callback. */
1520 static void
1521 delete_omp_context (splay_tree_value value)
1523 omp_context *ctx = (omp_context *) value;
1525 delete ctx->cb.decl_map;
1527 if (ctx->field_map)
1528 splay_tree_delete (ctx->field_map);
1529 if (ctx->sfield_map)
1530 splay_tree_delete (ctx->sfield_map);
1532 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1533 it produces corrupt debug information. */
1534 if (ctx->record_type)
1536 tree t;
1537 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1538 DECL_ABSTRACT_ORIGIN (t) = NULL;
1540 if (ctx->srecord_type)
1542 tree t;
1543 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1544 DECL_ABSTRACT_ORIGIN (t) = NULL;
1547 if (is_task_ctx (ctx))
1548 finalize_task_copyfn (ctx->stmt);
1550 XDELETE (ctx);
1553 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1554 context. */
1556 static void
1557 fixup_child_record_type (omp_context *ctx)
1559 tree f, type = ctx->record_type;
1561 /* ??? It isn't sufficient to just call remap_type here, because
1562 variably_modified_type_p doesn't work the way we expect for
1563 record types. Testing each field for whether it needs remapping
1564 and creating a new record by hand works, however. */
1565 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1566 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1567 break;
1568 if (f)
1570 tree name, new_fields = NULL;
1572 type = lang_hooks.types.make_type (RECORD_TYPE);
1573 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1574 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1575 TYPE_DECL, name, type);
1576 TYPE_NAME (type) = name;
1578 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1580 tree new_f = copy_node (f);
1581 DECL_CONTEXT (new_f) = type;
1582 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1583 DECL_CHAIN (new_f) = new_fields;
1584 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1585 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1586 &ctx->cb, NULL);
1587 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1588 &ctx->cb, NULL);
1589 new_fields = new_f;
1591 /* Arrange to be able to look up the receiver field
1592 given the sender field. */
1593 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1594 (splay_tree_value) new_f);
1596 TYPE_FIELDS (type) = nreverse (new_fields);
1597 layout_type (type);
1600 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1603 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1604 specified by CLAUSES. */
1606 static void
1607 scan_sharing_clauses (tree clauses, omp_context *ctx)
1609 tree c, decl;
1610 bool scan_array_reductions = false;
1612 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1614 bool by_ref;
1616 switch (OMP_CLAUSE_CODE (c))
1618 case OMP_CLAUSE_PRIVATE:
1619 decl = OMP_CLAUSE_DECL (c);
1620 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1621 goto do_private;
1622 else if (!is_variable_sized (decl))
1623 install_var_local (decl, ctx);
1624 break;
1626 case OMP_CLAUSE_SHARED:
1627 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1628 decl = OMP_CLAUSE_DECL (c);
1629 /* Ignore shared directives in teams construct. */
1630 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1632 /* Global variables don't need to be copied,
1633 the receiver side will use them directly. */
1634 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1635 if (is_global_var (odecl))
1636 break;
1637 insert_decl_map (&ctx->cb, decl, odecl);
1638 break;
1640 gcc_assert (is_taskreg_ctx (ctx));
1641 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1642 || !is_variable_sized (decl));
1643 /* Global variables don't need to be copied,
1644 the receiver side will use them directly. */
1645 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1646 break;
1647 by_ref = use_pointer_for_field (decl, ctx);
1648 if (! TREE_READONLY (decl)
1649 || TREE_ADDRESSABLE (decl)
1650 || by_ref
1651 || is_reference (decl))
1653 install_var_field (decl, by_ref, 3, ctx);
1654 install_var_local (decl, ctx);
1655 break;
1657 /* We don't need to copy const scalar vars back. */
1658 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1659 goto do_private;
1661 case OMP_CLAUSE_LASTPRIVATE:
1662 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1663 /* Let the corresponding firstprivate clause create
1664 the variable. */
1665 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1666 break;
1667 /* FALLTHRU */
1669 case OMP_CLAUSE_FIRSTPRIVATE:
1670 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1672 sorry ("clause not supported yet");
1673 break;
1675 /* FALLTHRU */
1676 case OMP_CLAUSE_LINEAR:
1677 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1678 /* FALLTHRU */
1679 case OMP_CLAUSE_REDUCTION:
1680 decl = OMP_CLAUSE_DECL (c);
1681 do_private:
1682 if (is_variable_sized (decl))
1684 if (is_task_ctx (ctx))
1685 install_var_field (decl, false, 1, ctx);
1686 break;
1688 else if (is_taskreg_ctx (ctx))
1690 bool global
1691 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1692 by_ref = use_pointer_for_field (decl, NULL);
1694 if (is_task_ctx (ctx)
1695 && (global || by_ref || is_reference (decl)))
1697 install_var_field (decl, false, 1, ctx);
1698 if (!global)
1699 install_var_field (decl, by_ref, 2, ctx);
1701 else if (!global)
1702 install_var_field (decl, by_ref, 3, ctx);
1704 install_var_local (decl, ctx);
1705 //TODO
1706 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1708 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1710 /* Create a decl for the reduction array. */
1711 tree var = OMP_CLAUSE_DECL (c);
1712 tree type = get_base_type (var);
1713 tree ptype = build_pointer_type (type);
1714 tree array = create_tmp_var (ptype, omp_get_id (var));
1715 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1716 install_var_field (array, true, 3, c);
1717 install_var_local (array, c);
1719 /* Insert it into the current context. */
1720 splay_tree_insert (ctx->reduction_map,
1721 (splay_tree_key) omp_get_id(var),
1722 (splay_tree_value) array);
1723 splay_tree_insert (ctx->reduction_map,
1724 (splay_tree_key) array,
1725 (splay_tree_value) array);
1728 break;
1730 case OMP_CLAUSE__LOOPTEMP_:
1731 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1732 gcc_assert (is_parallel_ctx (ctx));
1733 decl = OMP_CLAUSE_DECL (c);
1734 install_var_field (decl, false, 3, ctx);
1735 install_var_local (decl, ctx);
1736 break;
1738 case OMP_CLAUSE_COPYPRIVATE:
1739 case OMP_CLAUSE_COPYIN:
1740 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1741 decl = OMP_CLAUSE_DECL (c);
1742 by_ref = use_pointer_for_field (decl, NULL);
1743 install_var_field (decl, by_ref, 3, ctx);
1744 break;
1746 case OMP_CLAUSE_DEFAULT:
1747 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1748 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1749 break;
1751 case OMP_CLAUSE_FINAL:
1752 case OMP_CLAUSE_NUM_THREADS:
1753 case OMP_CLAUSE_NUM_TEAMS:
1754 case OMP_CLAUSE_THREAD_LIMIT:
1755 case OMP_CLAUSE_DEVICE:
1756 case OMP_CLAUSE_SCHEDULE:
1757 case OMP_CLAUSE_DIST_SCHEDULE:
1758 case OMP_CLAUSE_DEPEND:
1759 case OMP_CLAUSE__CILK_FOR_COUNT_:
1760 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1761 /* FALLTHRU */
1762 case OMP_CLAUSE_IF:
1763 case OMP_CLAUSE_NUM_GANGS:
1764 case OMP_CLAUSE_NUM_WORKERS:
1765 case OMP_CLAUSE_VECTOR_LENGTH:
1766 if (ctx->outer)
1767 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1768 break;
1770 case OMP_CLAUSE_TO:
1771 case OMP_CLAUSE_FROM:
1772 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1773 /* FALLTHRU */
1774 case OMP_CLAUSE_MAP:
1775 switch (OMP_CLAUSE_CODE (c))
1777 case OMP_CLAUSE_TO:
1778 case OMP_CLAUSE_FROM:
1779 /* The to and from clauses are only ever seen with OpenMP target
1780 update constructs. */
1781 gcc_assert (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1782 && (gimple_omp_target_kind (ctx->stmt)
1783 == GF_OMP_TARGET_KIND_UPDATE));
1784 break;
1785 case OMP_CLAUSE_MAP:
1786 /* The map clause is never seen with OpenMP target update
1787 constructs. */
1788 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
1789 || (gimple_omp_target_kind (ctx->stmt)
1790 != GF_OMP_TARGET_KIND_UPDATE));
1791 break;
1792 default:
1793 gcc_unreachable ();
1795 if (ctx->outer)
1796 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1797 decl = OMP_CLAUSE_DECL (c);
1798 /* Global variables with "omp declare target" attribute
1799 don't need to be copied, the receiver side will use them
1800 directly. */
1801 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1802 && DECL_P (decl)
1803 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1804 && lookup_attribute ("omp declare target",
1805 DECL_ATTRIBUTES (decl)))
1807 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1808 break;
1810 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1811 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1813 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1814 target regions that are not offloaded; there is nothing to map for
1815 those. */
1816 if (!is_gimple_omp_offloaded (ctx->stmt)
1817 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1818 break;
1820 #if 0
1821 /* In target regions that are not offloaded, libgomp won't pay
1822 attention to OMP_CLAUSE_MAP_FORCE_DEVICEPTR -- but I think we need
1823 to handle it here anyway, in order to create a visible copy of the
1824 variable. */
1825 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1826 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
1828 if (!is_gimple_omp_offloaded (ctx->stmt))
1829 break;
1831 #endif
1832 if (DECL_P (decl))
1834 if (DECL_SIZE (decl)
1835 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1837 tree decl2 = DECL_VALUE_EXPR (decl);
1838 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1839 decl2 = TREE_OPERAND (decl2, 0);
1840 gcc_assert (DECL_P (decl2));
1841 install_var_field (decl2, true, 3, ctx);
1842 install_var_local (decl2, ctx);
1843 install_var_local (decl, ctx);
1845 else
1847 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
1848 || (OMP_CLAUSE_MAP_KIND (c)
1849 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
1850 || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE);
1851 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1852 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1853 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1854 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1855 install_var_field (decl, true, 7, ctx);
1856 else
1858 if (!is_gimple_omp_oacc_specifically (ctx->stmt))
1859 install_var_field (decl, true, 3, ctx);
1860 else
1862 /* decl goes heres. */
1863 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1864 install_var_field (decl, true, 3, c);
1867 if (is_gimple_omp_offloaded (ctx->stmt))
1868 install_var_local (decl, ctx);
1871 else
1873 tree base = get_base_address (decl);
1874 tree nc = OMP_CLAUSE_CHAIN (c);
1875 gcc_assert (nc == NULL_TREE
1876 || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP
1877 || (OMP_CLAUSE_MAP_KIND (nc)
1878 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR));
1879 if (DECL_P (base)
1880 && nc != NULL_TREE
1881 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1882 && OMP_CLAUSE_DECL (nc) == base
1883 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1884 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1886 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1887 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1889 else
1891 if (ctx->outer)
1893 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1894 decl = OMP_CLAUSE_DECL (c);
1896 gcc_assert (!splay_tree_lookup (ctx->field_map,
1897 (splay_tree_key) decl));
1898 tree field
1899 = build_decl (OMP_CLAUSE_LOCATION (c),
1900 FIELD_DECL, NULL_TREE, ptr_type_node);
1901 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1902 insert_field_into_struct (ctx->record_type, field);
1903 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1904 (splay_tree_value) field);
1907 break;
1909 case OMP_CLAUSE_NOWAIT:
1910 case OMP_CLAUSE_ORDERED:
1911 case OMP_CLAUSE_UNTIED:
1912 case OMP_CLAUSE_MERGEABLE:
1913 case OMP_CLAUSE_PROC_BIND:
1914 case OMP_CLAUSE_SAFELEN:
1915 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1917 sorry ("clause not supported yet");
1918 break;
1920 /* FALLTHRU */
1921 case OMP_CLAUSE_COLLAPSE:
1922 case OMP_CLAUSE_ASYNC:
1923 case OMP_CLAUSE_WAIT:
1924 break;
1926 case OMP_CLAUSE_ALIGNED:
1927 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1928 decl = OMP_CLAUSE_DECL (c);
1929 if (is_global_var (decl)
1930 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1931 install_var_local (decl, ctx);
1932 break;
1934 case OMP_CLAUSE_HOST:
1935 case OMP_CLAUSE_OACC_DEVICE:
1936 case OMP_CLAUSE_DEVICE_RESIDENT:
1937 case OMP_CLAUSE_USE_DEVICE:
1938 case OMP_CLAUSE_GANG:
1939 case OMP_NO_CLAUSE_CACHE:
1940 case OMP_CLAUSE_INDEPENDENT:
1941 case OMP_CLAUSE_WORKER:
1942 case OMP_CLAUSE_VECTOR:
1943 sorry ("Clause not supported yet");
1944 break;
1946 default:
1947 gcc_unreachable ();
1951 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1953 switch (OMP_CLAUSE_CODE (c))
1955 case OMP_CLAUSE_LASTPRIVATE:
1956 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1957 /* Let the corresponding firstprivate clause create
1958 the variable. */
1959 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1960 scan_array_reductions = true;
1961 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1962 break;
1963 /* FALLTHRU */
1965 case OMP_CLAUSE_FIRSTPRIVATE:
1966 if (is_gimple_omp_oacc_specifically (ctx->stmt))
1968 sorry ("clause not supported yet");
1969 break;
1971 /* FALLTHRU */
1972 case OMP_CLAUSE_LINEAR:
1973 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1974 /* FALLTHRU */
1975 case OMP_CLAUSE_REDUCTION:
1976 case OMP_CLAUSE_PRIVATE:
1977 decl = OMP_CLAUSE_DECL (c);
1978 if (is_variable_sized (decl))
1979 install_var_local (decl, ctx);
1980 fixup_remapped_decl (decl, ctx,
1981 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1982 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1983 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1984 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1985 scan_array_reductions = true;
1986 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1987 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1988 scan_array_reductions = true;
1989 break;
1991 case OMP_CLAUSE_SHARED:
1992 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
1993 /* Ignore shared directives in teams construct. */
1994 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1995 break;
1996 decl = OMP_CLAUSE_DECL (c);
1997 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1998 fixup_remapped_decl (decl, ctx, false);
1999 break;
2001 case OMP_CLAUSE_MAP:
2002 /* The map clause is never seen with OpenMP target update
2003 constructs. */
2004 gcc_assert (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2005 || (gimple_omp_target_kind (ctx->stmt)
2006 != GF_OMP_TARGET_KIND_UPDATE));
2007 if (!is_gimple_omp_offloaded (ctx->stmt))
2008 break;
2009 decl = OMP_CLAUSE_DECL (c);
2010 if (DECL_P (decl)
2011 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2012 && lookup_attribute ("omp declare target",
2013 DECL_ATTRIBUTES (decl)))
2015 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2016 break;
2018 if (DECL_P (decl))
2020 gcc_assert ((OMP_CLAUSE_MAP_KIND (c)
2021 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
2022 || TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE);
2023 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
2024 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2025 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2027 tree new_decl = lookup_decl (decl, ctx);
2028 TREE_TYPE (new_decl)
2029 = remap_type (TREE_TYPE (decl), &ctx->cb);
2031 else if (DECL_SIZE (decl)
2032 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2034 gcc_assert (OMP_CLAUSE_MAP_KIND (c)
2035 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR);
2037 tree decl2 = DECL_VALUE_EXPR (decl);
2038 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2039 decl2 = TREE_OPERAND (decl2, 0);
2040 gcc_assert (DECL_P (decl2));
2041 fixup_remapped_decl (decl2, ctx, false);
2042 fixup_remapped_decl (decl, ctx, true);
2044 else
2045 fixup_remapped_decl (decl, ctx, false);
2047 break;
2049 case OMP_CLAUSE_COPYPRIVATE:
2050 case OMP_CLAUSE_COPYIN:
2051 case OMP_CLAUSE_DEFAULT:
2052 case OMP_CLAUSE_NUM_THREADS:
2053 case OMP_CLAUSE_NUM_TEAMS:
2054 case OMP_CLAUSE_THREAD_LIMIT:
2055 case OMP_CLAUSE_DEVICE:
2056 case OMP_CLAUSE_SCHEDULE:
2057 case OMP_CLAUSE_DIST_SCHEDULE:
2058 case OMP_CLAUSE_NOWAIT:
2059 case OMP_CLAUSE_ORDERED:
2060 case OMP_CLAUSE_UNTIED:
2061 case OMP_CLAUSE_FINAL:
2062 case OMP_CLAUSE_MERGEABLE:
2063 case OMP_CLAUSE_PROC_BIND:
2064 case OMP_CLAUSE_SAFELEN:
2065 case OMP_CLAUSE_ALIGNED:
2066 case OMP_CLAUSE_DEPEND:
2067 case OMP_CLAUSE__LOOPTEMP_:
2068 case OMP_CLAUSE_TO:
2069 case OMP_CLAUSE_FROM:
2070 case OMP_CLAUSE__CILK_FOR_COUNT_:
2071 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2072 /* FALLTHRU */
2073 case OMP_CLAUSE_ASYNC:
2074 case OMP_CLAUSE_COLLAPSE:
2075 case OMP_CLAUSE_IF:
2076 case OMP_CLAUSE_NUM_GANGS:
2077 case OMP_CLAUSE_NUM_WORKERS:
2078 case OMP_CLAUSE_VECTOR_LENGTH:
2079 case OMP_CLAUSE_WAIT:
2080 break;
2082 case OMP_CLAUSE_HOST:
2083 case OMP_CLAUSE_OACC_DEVICE:
2084 case OMP_CLAUSE_DEVICE_RESIDENT:
2085 case OMP_CLAUSE_USE_DEVICE:
2086 case OMP_CLAUSE_GANG:
2087 case OMP_NO_CLAUSE_CACHE:
2088 case OMP_CLAUSE_INDEPENDENT:
2089 case OMP_CLAUSE_WORKER:
2090 case OMP_CLAUSE_VECTOR:
2091 sorry ("Clause not supported yet");
2092 break;
2094 default:
2095 gcc_unreachable ();
2099 if (scan_array_reductions)
2101 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
2102 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2103 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2104 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2106 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2107 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2109 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2110 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2111 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2112 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2113 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2114 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2118 /* Create a new name for omp child function. Returns an identifier. If
2119 IS_CILK_FOR is true then the suffix for the child function is
2120 "_cilk_for_fn." */
2122 static tree
2123 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2125 if (is_cilk_for)
2126 return clone_function_name (current_function_decl, "_cilk_for_fn");
2127 return clone_function_name (current_function_decl,
2128 task_copy ? "_omp_cpyfn" : "_omp_fn");
2131 /* Returns the type of the induction variable for the child function for
2132 _Cilk_for and the types for _high and _low variables based on TYPE. */
2134 static tree
2135 cilk_for_check_loop_diff_type (tree type)
2137 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2139 if (TYPE_UNSIGNED (type))
2140 return uint32_type_node;
2141 else
2142 return integer_type_node;
2144 else
2146 if (TYPE_UNSIGNED (type))
2147 return uint64_type_node;
2148 else
2149 return long_long_integer_type_node;
2153 /* Build a decl for the omp child function. It'll not contain a body
2154 yet, just the bare decl. */
2156 static void
2157 create_omp_child_function (omp_context *ctx, bool task_copy)
2159 tree decl, type, name, t;
2161 tree cilk_for_count
2162 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2163 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2164 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2165 tree cilk_var_type = NULL_TREE;
2167 name = create_omp_child_function_name (task_copy,
2168 cilk_for_count != NULL_TREE);
2169 if (task_copy)
2170 type = build_function_type_list (void_type_node, ptr_type_node,
2171 ptr_type_node, NULL_TREE);
2172 else if (cilk_for_count)
2174 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2175 cilk_var_type = cilk_for_check_loop_diff_type (type);
2176 type = build_function_type_list (void_type_node, ptr_type_node,
2177 cilk_var_type, cilk_var_type, NULL_TREE);
2179 else
2180 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2182 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2184 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt)
2185 || !task_copy);
2186 if (!task_copy)
2187 ctx->cb.dst_fn = decl;
2188 else
2189 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2191 TREE_STATIC (decl) = 1;
2192 TREE_USED (decl) = 1;
2193 DECL_ARTIFICIAL (decl) = 1;
2194 DECL_IGNORED_P (decl) = 0;
2195 TREE_PUBLIC (decl) = 0;
2196 DECL_UNINLINABLE (decl) = 1;
2197 DECL_EXTERNAL (decl) = 0;
2198 DECL_CONTEXT (decl) = NULL_TREE;
2199 DECL_INITIAL (decl) = make_node (BLOCK);
2200 bool target_p = false;
2201 if (lookup_attribute ("omp declare target",
2202 DECL_ATTRIBUTES (current_function_decl)))
2203 target_p = true;
2204 else
2206 omp_context *octx;
2207 for (octx = ctx; octx; octx = octx->outer)
2208 if (is_gimple_omp_offloaded (octx->stmt))
2210 target_p = true;
2211 break;
2214 if (target_p)
2215 DECL_ATTRIBUTES (decl)
2216 = tree_cons (get_identifier ("omp declare target"),
2217 NULL_TREE, DECL_ATTRIBUTES (decl));
2219 t = build_decl (DECL_SOURCE_LOCATION (decl),
2220 RESULT_DECL, NULL_TREE, void_type_node);
2221 DECL_ARTIFICIAL (t) = 1;
2222 DECL_IGNORED_P (t) = 1;
2223 DECL_CONTEXT (t) = decl;
2224 DECL_RESULT (decl) = t;
2226 /* _Cilk_for's child function requires two extra parameters called
2227 __low and __high that are set the by Cilk runtime when it calls this
2228 function. */
2229 if (cilk_for_count)
2231 t = build_decl (DECL_SOURCE_LOCATION (decl),
2232 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2233 DECL_ARTIFICIAL (t) = 1;
2234 DECL_NAMELESS (t) = 1;
2235 DECL_ARG_TYPE (t) = ptr_type_node;
2236 DECL_CONTEXT (t) = current_function_decl;
2237 TREE_USED (t) = 1;
2238 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2239 DECL_ARGUMENTS (decl) = t;
2241 t = build_decl (DECL_SOURCE_LOCATION (decl),
2242 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2243 DECL_ARTIFICIAL (t) = 1;
2244 DECL_NAMELESS (t) = 1;
2245 DECL_ARG_TYPE (t) = ptr_type_node;
2246 DECL_CONTEXT (t) = current_function_decl;
2247 TREE_USED (t) = 1;
2248 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2249 DECL_ARGUMENTS (decl) = t;
2252 tree data_name = get_identifier (".omp_data_i");
2253 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2254 ptr_type_node);
2255 DECL_ARTIFICIAL (t) = 1;
2256 DECL_NAMELESS (t) = 1;
2257 DECL_ARG_TYPE (t) = ptr_type_node;
2258 DECL_CONTEXT (t) = current_function_decl;
2259 TREE_USED (t) = 1;
2260 if (cilk_for_count)
2261 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2262 DECL_ARGUMENTS (decl) = t;
2263 if (!task_copy)
2264 ctx->receiver_decl = t;
2265 else
2267 t = build_decl (DECL_SOURCE_LOCATION (decl),
2268 PARM_DECL, get_identifier (".omp_data_o"),
2269 ptr_type_node);
2270 DECL_ARTIFICIAL (t) = 1;
2271 DECL_NAMELESS (t) = 1;
2272 DECL_ARG_TYPE (t) = ptr_type_node;
2273 DECL_CONTEXT (t) = current_function_decl;
2274 TREE_USED (t) = 1;
2275 TREE_ADDRESSABLE (t) = 1;
2276 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2277 DECL_ARGUMENTS (decl) = t;
2280 /* Allocate memory for the function structure. The call to
2281 allocate_struct_function clobbers CFUN, so we need to restore
2282 it afterward. */
2283 push_struct_function (decl);
2284 cfun->function_end_locus = gimple_location (ctx->stmt);
2285 pop_cfun ();
2288 /* Callback for walk_gimple_seq. Check if combined parallel
2289 contains gimple_omp_for_combined_into_p OMP_FOR. */
2291 static tree
2292 find_combined_for (gimple_stmt_iterator *gsi_p,
2293 bool *handled_ops_p,
2294 struct walk_stmt_info *wi)
2296 gimple stmt = gsi_stmt (*gsi_p);
2298 *handled_ops_p = true;
2299 switch (gimple_code (stmt))
2301 WALK_SUBSTMTS;
2303 case GIMPLE_OMP_FOR:
2304 if (gimple_omp_for_combined_into_p (stmt)
2305 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2307 wi->info = stmt;
2308 return integer_zero_node;
2310 break;
2311 default:
2312 break;
2314 return NULL;
2317 /* Scan an OpenACC offload directive. */
2319 static void
2320 scan_oacc_offload (gimple stmt, omp_context *outer_ctx)
2322 omp_context *ctx;
2323 tree name;
2324 void (*gimple_omp_set_child_fn) (gimple, tree);
2325 tree (*gimple_omp_clauses) (const_gimple);
2326 switch (gimple_code (stmt))
2328 case GIMPLE_OACC_KERNELS:
2329 gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
2330 gimple_omp_clauses = gimple_oacc_kernels_clauses;
2331 break;
2332 case GIMPLE_OACC_PARALLEL:
2333 gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
2334 gimple_omp_clauses = gimple_oacc_parallel_clauses;
2335 break;
2336 default:
2337 gcc_unreachable ();
2340 gcc_assert (taskreg_nesting_level == 0);
2341 gcc_assert (target_nesting_level == 0);
2343 ctx = new_omp_context (stmt, outer_ctx);
2344 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2345 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2346 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2347 name = create_tmp_var_name (".omp_data_t");
2348 name = build_decl (gimple_location (stmt),
2349 TYPE_DECL, name, ctx->record_type);
2350 DECL_ARTIFICIAL (name) = 1;
2351 DECL_NAMELESS (name) = 1;
2352 TYPE_NAME (ctx->record_type) = name;
2353 create_omp_child_function (ctx, false);
2354 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2356 gimple_omp_set_child_fn (stmt, ctx->cb.dst_fn);
2358 scan_sharing_clauses (gimple_omp_clauses (stmt), ctx);
2359 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2361 if (TYPE_FIELDS (ctx->record_type) == NULL)
2362 ctx->record_type = ctx->receiver_decl = NULL;
2363 else
2365 TYPE_FIELDS (ctx->record_type)
2366 = nreverse (TYPE_FIELDS (ctx->record_type));
2367 #ifdef ENABLE_CHECKING
2368 tree field;
2369 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2370 for (field = TYPE_FIELDS (ctx->record_type);
2371 field;
2372 field = DECL_CHAIN (field))
2373 gcc_assert (DECL_ALIGN (field) == align);
2374 #endif
2375 layout_type (ctx->record_type);
2376 fixup_child_record_type (ctx);
2380 /* Scan an OpenMP parallel directive. */
2382 static void
2383 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2385 omp_context *ctx;
2386 tree name;
2387 gimple stmt = gsi_stmt (*gsi);
2389 /* Ignore parallel directives with empty bodies, unless there
2390 are copyin clauses. */
2391 if (optimize > 0
2392 && empty_body_p (gimple_omp_body (stmt))
2393 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2394 OMP_CLAUSE_COPYIN) == NULL)
2396 gsi_replace (gsi, gimple_build_nop (), false);
2397 return;
2400 if (gimple_omp_parallel_combined_p (stmt))
2402 gimple for_stmt;
2403 struct walk_stmt_info wi;
2405 memset (&wi, 0, sizeof (wi));
2406 wi.val_only = true;
2407 walk_gimple_seq (gimple_omp_body (stmt),
2408 find_combined_for, NULL, &wi);
2409 for_stmt = (gimple) wi.info;
2410 if (for_stmt)
2412 struct omp_for_data fd;
2413 extract_omp_for_data (for_stmt, &fd, NULL);
2414 /* We need two temporaries with fd.loop.v type (istart/iend)
2415 and then (fd.collapse - 1) temporaries with the same
2416 type for count2 ... countN-1 vars if not constant. */
2417 size_t count = 2, i;
2418 tree type = fd.iter_type;
2419 if (fd.collapse > 1
2420 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2421 count += fd.collapse - 1;
2422 for (i = 0; i < count; i++)
2424 tree temp = create_tmp_var (type, NULL);
2425 tree c = build_omp_clause (UNKNOWN_LOCATION,
2426 OMP_CLAUSE__LOOPTEMP_);
2427 insert_decl_map (&outer_ctx->cb, temp, temp);
2428 OMP_CLAUSE_DECL (c) = temp;
2429 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2430 gimple_omp_parallel_set_clauses (stmt, c);
2435 ctx = new_omp_context (stmt, outer_ctx);
2436 taskreg_contexts.safe_push (ctx);
2437 if (taskreg_nesting_level > 1)
2438 ctx->is_nested = true;
2439 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2440 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2441 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2442 name = create_tmp_var_name (".omp_data_s");
2443 name = build_decl (gimple_location (stmt),
2444 TYPE_DECL, name, ctx->record_type);
2445 DECL_ARTIFICIAL (name) = 1;
2446 DECL_NAMELESS (name) = 1;
2447 TYPE_NAME (ctx->record_type) = name;
2448 create_omp_child_function (ctx, false);
2449 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2451 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2452 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2454 if (TYPE_FIELDS (ctx->record_type) == NULL)
2455 ctx->record_type = ctx->receiver_decl = NULL;
2458 /* Scan an OpenMP task directive. */
2460 static void
2461 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2463 omp_context *ctx;
2464 tree name, t;
2465 gimple stmt = gsi_stmt (*gsi);
2467 /* Ignore task directives with empty bodies. */
2468 if (optimize > 0
2469 && empty_body_p (gimple_omp_body (stmt)))
2471 gsi_replace (gsi, gimple_build_nop (), false);
2472 return;
2475 ctx = new_omp_context (stmt, outer_ctx);
2476 taskreg_contexts.safe_push (ctx);
2477 if (taskreg_nesting_level > 1)
2478 ctx->is_nested = true;
2479 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2480 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2481 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2482 name = create_tmp_var_name (".omp_data_s");
2483 name = build_decl (gimple_location (stmt),
2484 TYPE_DECL, name, ctx->record_type);
2485 DECL_ARTIFICIAL (name) = 1;
2486 DECL_NAMELESS (name) = 1;
2487 TYPE_NAME (ctx->record_type) = name;
2488 create_omp_child_function (ctx, false);
2489 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2491 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2493 if (ctx->srecord_type)
2495 name = create_tmp_var_name (".omp_data_a");
2496 name = build_decl (gimple_location (stmt),
2497 TYPE_DECL, name, ctx->srecord_type);
2498 DECL_ARTIFICIAL (name) = 1;
2499 DECL_NAMELESS (name) = 1;
2500 TYPE_NAME (ctx->srecord_type) = name;
2501 create_omp_child_function (ctx, true);
2504 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2506 if (TYPE_FIELDS (ctx->record_type) == NULL)
2508 ctx->record_type = ctx->receiver_decl = NULL;
2509 t = build_int_cst (long_integer_type_node, 0);
2510 gimple_omp_task_set_arg_size (stmt, t);
2511 t = build_int_cst (long_integer_type_node, 1);
2512 gimple_omp_task_set_arg_align (stmt, t);
2517 /* If any decls have been made addressable during scan_omp,
2518 adjust their fields if needed, and layout record types
2519 of parallel/task constructs. */
2521 static void
2522 finish_taskreg_scan (omp_context *ctx)
2524 if (ctx->record_type == NULL_TREE)
2525 return;
2527 /* If any task_shared_vars were needed, verify all
2528 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2529 statements if use_pointer_for_field hasn't changed
2530 because of that. If it did, update field types now. */
2531 if (task_shared_vars)
2533 tree c;
2535 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2536 c; c = OMP_CLAUSE_CHAIN (c))
2537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2539 tree decl = OMP_CLAUSE_DECL (c);
2541 /* Global variables don't need to be copied,
2542 the receiver side will use them directly. */
2543 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2544 continue;
2545 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2546 || !use_pointer_for_field (decl, ctx))
2547 continue;
2548 tree field = lookup_field (decl, ctx);
2549 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2550 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2551 continue;
2552 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2553 TREE_THIS_VOLATILE (field) = 0;
2554 DECL_USER_ALIGN (field) = 0;
2555 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2556 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2557 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2558 if (ctx->srecord_type)
2560 tree sfield = lookup_sfield (decl, ctx);
2561 TREE_TYPE (sfield) = TREE_TYPE (field);
2562 TREE_THIS_VOLATILE (sfield) = 0;
2563 DECL_USER_ALIGN (sfield) = 0;
2564 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2565 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2566 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2571 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2573 layout_type (ctx->record_type);
2574 fixup_child_record_type (ctx);
2576 else
2578 location_t loc = gimple_location (ctx->stmt);
2579 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2580 /* Move VLA fields to the end. */
2581 p = &TYPE_FIELDS (ctx->record_type);
2582 while (*p)
2583 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2584 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2586 *q = *p;
2587 *p = TREE_CHAIN (*p);
2588 TREE_CHAIN (*q) = NULL_TREE;
2589 q = &TREE_CHAIN (*q);
2591 else
2592 p = &DECL_CHAIN (*p);
2593 *p = vla_fields;
2594 layout_type (ctx->record_type);
2595 fixup_child_record_type (ctx);
2596 if (ctx->srecord_type)
2597 layout_type (ctx->srecord_type);
2598 tree t = fold_convert_loc (loc, long_integer_type_node,
2599 TYPE_SIZE_UNIT (ctx->record_type));
2600 gimple_omp_task_set_arg_size (ctx->stmt, t);
2601 t = build_int_cst (long_integer_type_node,
2602 TYPE_ALIGN_UNIT (ctx->record_type));
2603 gimple_omp_task_set_arg_align (ctx->stmt, t);
2608 /* Scan a GIMPLE_OMP_FOR. */
2610 static void
2611 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2613 omp_context *ctx;
2614 size_t i;
2616 ctx = new_omp_context (stmt, outer_ctx);
2618 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2620 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2621 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2623 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2624 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2625 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2626 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2628 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2631 /* Scan an OpenMP sections directive. */
2633 static void
2634 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2636 omp_context *ctx;
2638 ctx = new_omp_context (stmt, outer_ctx);
2639 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2640 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2643 /* Scan an OpenMP single directive. */
2645 static void
2646 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2648 omp_context *ctx;
2649 tree name;
2651 ctx = new_omp_context (stmt, outer_ctx);
2652 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2653 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2654 name = create_tmp_var_name (".omp_copy_s");
2655 name = build_decl (gimple_location (stmt),
2656 TYPE_DECL, name, ctx->record_type);
2657 TYPE_NAME (ctx->record_type) = name;
2659 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2660 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2662 if (TYPE_FIELDS (ctx->record_type) == NULL)
2663 ctx->record_type = NULL;
2664 else
2665 layout_type (ctx->record_type);
2668 /* Scan a GIMPLE_OMP_TARGET. */
2670 static void
2671 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2673 omp_context *ctx;
2674 tree name;
2675 int kind = gimple_omp_target_kind (stmt);
2677 if (kind == GF_OMP_TARGET_KIND_OACC_DATA
2678 || kind == GF_OMP_TARGET_KIND_OACC_UPDATE)
2680 gcc_assert (taskreg_nesting_level == 0);
2681 gcc_assert (target_nesting_level == 0);
2684 ctx = new_omp_context (stmt, outer_ctx);
2685 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2686 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2687 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2688 name = create_tmp_var_name (".omp_data_t");
2689 name = build_decl (gimple_location (stmt),
2690 TYPE_DECL, name, ctx->record_type);
2691 DECL_ARTIFICIAL (name) = 1;
2692 DECL_NAMELESS (name) = 1;
2693 TYPE_NAME (ctx->record_type) = name;
2694 if (kind == GF_OMP_TARGET_KIND_REGION)
2696 create_omp_child_function (ctx, false);
2697 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2700 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2701 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2703 if (TYPE_FIELDS (ctx->record_type) == NULL)
2704 ctx->record_type = ctx->receiver_decl = NULL;
2705 else
2707 TYPE_FIELDS (ctx->record_type)
2708 = nreverse (TYPE_FIELDS (ctx->record_type));
2709 #ifdef ENABLE_CHECKING
2710 tree field;
2711 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2712 for (field = TYPE_FIELDS (ctx->record_type);
2713 field;
2714 field = DECL_CHAIN (field))
2715 gcc_assert (DECL_ALIGN (field) == align);
2716 #endif
2717 layout_type (ctx->record_type);
2718 if (kind == GF_OMP_TARGET_KIND_REGION)
2719 fixup_child_record_type (ctx);
2723 /* Scan an OpenMP teams directive. */
2725 static void
2726 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2728 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2729 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2730 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2733 /* Check OpenMP nesting restrictions. */
2734 static bool
2735 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2737 /* TODO: While the OpenACC specification does allow for certain kinds of
2738 nesting, we don't support many of these yet. */
2739 if (is_gimple_omp (stmt)
2740 && is_gimple_omp_oacc_specifically (stmt))
2742 /* Regular handling of OpenACC loop constructs. */
2743 if (gimple_code (stmt) == GIMPLE_OMP_FOR
2744 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
2745 goto cont;
2746 /* No nesting of OpenACC STMT inside any OpenACC or OpenMP CTX different
2747 from an OpenACC data construct. */
2748 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2749 if (is_gimple_omp (ctx_->stmt)
2750 && !(gimple_code (ctx_->stmt) == GIMPLE_OMP_TARGET
2751 && (gimple_omp_target_kind (ctx_->stmt)
2752 == GF_OMP_TARGET_KIND_OACC_DATA)))
2754 error_at (gimple_location (stmt),
2755 "may not be nested");
2756 return false;
2759 else
2761 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP
2762 builtin) inside any OpenACC CTX. */
2763 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2764 if (is_gimple_omp (ctx_->stmt)
2765 && is_gimple_omp_oacc_specifically (ctx_->stmt))
2767 error_at (gimple_location (stmt),
2768 "may not be nested");
2769 return false;
2772 cont:
2774 if (ctx != NULL)
2776 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2777 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2779 error_at (gimple_location (stmt),
2780 "OpenMP constructs may not be nested inside simd region");
2781 return false;
2783 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2785 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2786 || (gimple_omp_for_kind (stmt)
2787 != GF_OMP_FOR_KIND_DISTRIBUTE))
2788 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2790 error_at (gimple_location (stmt),
2791 "only distribute or parallel constructs are allowed to "
2792 "be closely nested inside teams construct");
2793 return false;
2797 switch (gimple_code (stmt))
2799 case GIMPLE_OMP_FOR:
2800 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2801 return true;
2802 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2804 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2806 error_at (gimple_location (stmt),
2807 "distribute construct must be closely nested inside "
2808 "teams construct");
2809 return false;
2811 return true;
2813 /* FALLTHRU */
2814 case GIMPLE_CALL:
2815 if (is_gimple_call (stmt)
2816 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2817 == BUILT_IN_GOMP_CANCEL
2818 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2819 == BUILT_IN_GOMP_CANCELLATION_POINT))
2821 const char *bad = NULL;
2822 const char *kind = NULL;
2823 if (ctx == NULL)
2825 error_at (gimple_location (stmt), "orphaned %qs construct",
2826 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2827 == BUILT_IN_GOMP_CANCEL
2828 ? "#pragma omp cancel"
2829 : "#pragma omp cancellation point");
2830 return false;
2832 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2833 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2834 : 0)
2836 case 1:
2837 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2838 bad = "#pragma omp parallel";
2839 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2840 == BUILT_IN_GOMP_CANCEL
2841 && !integer_zerop (gimple_call_arg (stmt, 1)))
2842 ctx->cancellable = true;
2843 kind = "parallel";
2844 break;
2845 case 2:
2846 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2847 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2848 bad = "#pragma omp for";
2849 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2850 == BUILT_IN_GOMP_CANCEL
2851 && !integer_zerop (gimple_call_arg (stmt, 1)))
2853 ctx->cancellable = true;
2854 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2855 OMP_CLAUSE_NOWAIT))
2856 warning_at (gimple_location (stmt), 0,
2857 "%<#pragma omp cancel for%> inside "
2858 "%<nowait%> for construct");
2859 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2860 OMP_CLAUSE_ORDERED))
2861 warning_at (gimple_location (stmt), 0,
2862 "%<#pragma omp cancel for%> inside "
2863 "%<ordered%> for construct");
2865 kind = "for";
2866 break;
2867 case 4:
2868 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2869 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2870 bad = "#pragma omp sections";
2871 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2872 == BUILT_IN_GOMP_CANCEL
2873 && !integer_zerop (gimple_call_arg (stmt, 1)))
2875 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2877 ctx->cancellable = true;
2878 if (find_omp_clause (gimple_omp_sections_clauses
2879 (ctx->stmt),
2880 OMP_CLAUSE_NOWAIT))
2881 warning_at (gimple_location (stmt), 0,
2882 "%<#pragma omp cancel sections%> inside "
2883 "%<nowait%> sections construct");
2885 else
2887 gcc_assert (ctx->outer
2888 && gimple_code (ctx->outer->stmt)
2889 == GIMPLE_OMP_SECTIONS);
2890 ctx->outer->cancellable = true;
2891 if (find_omp_clause (gimple_omp_sections_clauses
2892 (ctx->outer->stmt),
2893 OMP_CLAUSE_NOWAIT))
2894 warning_at (gimple_location (stmt), 0,
2895 "%<#pragma omp cancel sections%> inside "
2896 "%<nowait%> sections construct");
2899 kind = "sections";
2900 break;
2901 case 8:
2902 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2903 bad = "#pragma omp task";
2904 else
2905 ctx->cancellable = true;
2906 kind = "taskgroup";
2907 break;
2908 default:
2909 error_at (gimple_location (stmt), "invalid arguments");
2910 return false;
2912 if (bad)
2914 error_at (gimple_location (stmt),
2915 "%<%s %s%> construct not closely nested inside of %qs",
2916 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2917 == BUILT_IN_GOMP_CANCEL
2918 ? "#pragma omp cancel"
2919 : "#pragma omp cancellation point", kind, bad);
2920 return false;
2923 /* FALLTHRU */
2924 case GIMPLE_OMP_SECTIONS:
2925 case GIMPLE_OMP_SINGLE:
2926 for (; ctx != NULL; ctx = ctx->outer)
2927 switch (gimple_code (ctx->stmt))
2929 case GIMPLE_OMP_FOR:
2930 case GIMPLE_OMP_SECTIONS:
2931 case GIMPLE_OMP_SINGLE:
2932 case GIMPLE_OMP_ORDERED:
2933 case GIMPLE_OMP_MASTER:
2934 case GIMPLE_OMP_TASK:
2935 case GIMPLE_OMP_CRITICAL:
2936 if (is_gimple_call (stmt))
2938 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2939 != BUILT_IN_GOMP_BARRIER)
2940 return true;
2941 error_at (gimple_location (stmt),
2942 "barrier region may not be closely nested inside "
2943 "of work-sharing, critical, ordered, master or "
2944 "explicit task region");
2945 return false;
2947 error_at (gimple_location (stmt),
2948 "work-sharing region may not be closely nested inside "
2949 "of work-sharing, critical, ordered, master or explicit "
2950 "task region");
2951 return false;
2952 case GIMPLE_OACC_KERNELS:
2953 case GIMPLE_OACC_PARALLEL:
2954 case GIMPLE_OMP_PARALLEL:
2955 return true;
2956 default:
2957 break;
2959 break;
2960 case GIMPLE_OMP_MASTER:
2961 for (; ctx != NULL; ctx = ctx->outer)
2962 switch (gimple_code (ctx->stmt))
2964 case GIMPLE_OMP_FOR:
2965 case GIMPLE_OMP_SECTIONS:
2966 case GIMPLE_OMP_SINGLE:
2967 case GIMPLE_OMP_TASK:
2968 error_at (gimple_location (stmt),
2969 "master region may not be closely nested inside "
2970 "of work-sharing or explicit task region");
2971 return false;
2972 case GIMPLE_OMP_PARALLEL:
2973 return true;
2974 default:
2975 break;
2977 break;
2978 case GIMPLE_OMP_ORDERED:
2979 for (; ctx != NULL; ctx = ctx->outer)
2980 switch (gimple_code (ctx->stmt))
2982 case GIMPLE_OMP_CRITICAL:
2983 case GIMPLE_OMP_TASK:
2984 error_at (gimple_location (stmt),
2985 "ordered region may not be closely nested inside "
2986 "of critical or explicit task region");
2987 return false;
2988 case GIMPLE_OMP_FOR:
2989 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2990 OMP_CLAUSE_ORDERED) == NULL)
2992 error_at (gimple_location (stmt),
2993 "ordered region must be closely nested inside "
2994 "a loop region with an ordered clause");
2995 return false;
2997 return true;
2998 case GIMPLE_OMP_PARALLEL:
2999 error_at (gimple_location (stmt),
3000 "ordered region must be closely nested inside "
3001 "a loop region with an ordered clause");
3002 return false;
3003 default:
3004 break;
3006 break;
3007 case GIMPLE_OMP_CRITICAL:
3008 for (; ctx != NULL; ctx = ctx->outer)
3009 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
3010 && (gimple_omp_critical_name (stmt)
3011 == gimple_omp_critical_name (ctx->stmt)))
3013 error_at (gimple_location (stmt),
3014 "critical region may not be nested inside a critical "
3015 "region with the same name");
3016 return false;
3018 break;
3019 case GIMPLE_OMP_TEAMS:
3020 if (ctx == NULL
3021 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3022 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3024 error_at (gimple_location (stmt),
3025 "teams construct not closely nested inside of target "
3026 "region");
3027 return false;
3029 break;
3030 case GIMPLE_OMP_TARGET:
3031 for (; ctx != NULL; ctx = ctx->outer)
3032 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
3033 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
3035 const char *name;
3036 switch (gimple_omp_target_kind (stmt))
3038 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
3039 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
3040 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
3041 default: gcc_unreachable ();
3043 warning_at (gimple_location (stmt), 0,
3044 "%s construct inside of target region", name);
3046 break;
3047 default:
3048 break;
3050 return true;
3054 /* Helper function scan_omp.
3056 Callback for walk_tree or operators in walk_gimple_stmt used to
3057 scan for OpenMP directives in TP. */
3059 static tree
3060 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3062 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3063 omp_context *ctx = (omp_context *) wi->info;
3064 tree t = *tp;
3066 switch (TREE_CODE (t))
3068 case VAR_DECL:
3069 case PARM_DECL:
3070 case LABEL_DECL:
3071 case RESULT_DECL:
3072 if (ctx)
3073 *tp = remap_decl (t, &ctx->cb);
3074 break;
3076 default:
3077 if (ctx && TYPE_P (t))
3078 *tp = remap_type (t, &ctx->cb);
3079 else if (!DECL_P (t))
3081 *walk_subtrees = 1;
3082 if (ctx)
3084 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3085 if (tem != TREE_TYPE (t))
3087 if (TREE_CODE (t) == INTEGER_CST)
3088 *tp = wide_int_to_tree (tem, t);
3089 else
3090 TREE_TYPE (t) = tem;
3094 break;
3097 return NULL_TREE;
3100 /* Return true if FNDECL is a setjmp or a longjmp. */
3102 static bool
3103 setjmp_or_longjmp_p (const_tree fndecl)
3105 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3106 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3107 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3108 return true;
3110 tree declname = DECL_NAME (fndecl);
3111 if (!declname)
3112 return false;
3113 const char *name = IDENTIFIER_POINTER (declname);
3114 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3118 /* Helper function for scan_omp.
3120 Callback for walk_gimple_stmt used to scan for OpenMP directives in
3121 the current statement in GSI. */
3123 static tree
3124 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3125 struct walk_stmt_info *wi)
3127 gimple stmt = gsi_stmt (*gsi);
3128 omp_context *ctx = (omp_context *) wi->info;
3130 if (gimple_has_location (stmt))
3131 input_location = gimple_location (stmt);
3133 /* Check the OpenMP nesting restrictions. */
3134 bool remove = false;
3135 if (is_gimple_omp (stmt))
3136 remove = !check_omp_nesting_restrictions (stmt, ctx);
3137 else if (is_gimple_call (stmt))
3139 tree fndecl = gimple_call_fndecl (stmt);
3140 if (fndecl)
3142 if (setjmp_or_longjmp_p (fndecl)
3143 && ctx
3144 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3145 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3147 remove = true;
3148 error_at (gimple_location (stmt),
3149 "setjmp/longjmp inside simd construct");
3151 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3152 switch (DECL_FUNCTION_CODE (fndecl))
3154 case BUILT_IN_GOMP_BARRIER:
3155 case BUILT_IN_GOMP_CANCEL:
3156 case BUILT_IN_GOMP_CANCELLATION_POINT:
3157 case BUILT_IN_GOMP_TASKYIELD:
3158 case BUILT_IN_GOMP_TASKWAIT:
3159 case BUILT_IN_GOMP_TASKGROUP_START:
3160 case BUILT_IN_GOMP_TASKGROUP_END:
3161 remove = !check_omp_nesting_restrictions (stmt, ctx);
3162 break;
3163 default:
3164 break;
3168 if (remove)
3170 stmt = gimple_build_nop ();
3171 gsi_replace (gsi, stmt, false);
3174 *handled_ops_p = true;
3176 switch (gimple_code (stmt))
3178 case GIMPLE_OACC_KERNELS:
3179 case GIMPLE_OACC_PARALLEL:
3180 scan_oacc_offload (stmt, ctx);
3181 break;
3183 case GIMPLE_OMP_PARALLEL:
3184 taskreg_nesting_level++;
3185 scan_omp_parallel (gsi, ctx);
3186 taskreg_nesting_level--;
3187 break;
3189 case GIMPLE_OMP_TASK:
3190 taskreg_nesting_level++;
3191 scan_omp_task (gsi, ctx);
3192 taskreg_nesting_level--;
3193 break;
3195 case GIMPLE_OMP_FOR:
3196 scan_omp_for (stmt, ctx);
3197 break;
3199 case GIMPLE_OMP_SECTIONS:
3200 scan_omp_sections (stmt, ctx);
3201 break;
3203 case GIMPLE_OMP_SINGLE:
3204 scan_omp_single (stmt, ctx);
3205 break;
3207 case GIMPLE_OMP_SECTION:
3208 case GIMPLE_OMP_MASTER:
3209 case GIMPLE_OMP_TASKGROUP:
3210 case GIMPLE_OMP_ORDERED:
3211 case GIMPLE_OMP_CRITICAL:
3212 ctx = new_omp_context (stmt, ctx);
3213 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3214 break;
3216 case GIMPLE_OMP_TARGET:
3217 scan_omp_target (stmt, ctx);
3218 break;
3220 case GIMPLE_OMP_TEAMS:
3221 scan_omp_teams (stmt, ctx);
3222 break;
3224 case GIMPLE_BIND:
3226 tree var;
3228 *handled_ops_p = false;
3229 if (ctx)
3230 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
3231 insert_decl_map (&ctx->cb, var, var);
3233 break;
3234 default:
3235 *handled_ops_p = false;
3236 break;
3239 return NULL_TREE;
3243 /* Scan all the statements starting at the current statement. CTX
3244 contains context information about the OpenMP directives and
3245 clauses found during the scan. */
3247 static void
3248 scan_omp (gimple_seq *body_p, omp_context *ctx)
3250 location_t saved_location;
3251 struct walk_stmt_info wi;
3253 memset (&wi, 0, sizeof (wi));
3254 wi.info = ctx;
3255 wi.want_locations = true;
3257 saved_location = input_location;
3258 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3259 input_location = saved_location;
3262 /* Re-gimplification and code generation routines. */
3264 /* Build a call to GOMP_barrier. */
3266 static gimple
3267 build_omp_barrier (tree lhs)
3269 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3270 : BUILT_IN_GOMP_BARRIER);
3271 gimple g = gimple_build_call (fndecl, 0);
3272 if (lhs)
3273 gimple_call_set_lhs (g, lhs);
3274 return g;
3277 /* If a context was created for STMT when it was scanned, return it. */
3279 static omp_context *
3280 maybe_lookup_ctx (gimple stmt)
3282 splay_tree_node n;
3283 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3284 return n ? (omp_context *) n->value : NULL;
3288 /* Find the mapping for DECL in CTX or the immediately enclosing
3289 context that has a mapping for DECL.
3291 If CTX is a nested parallel directive, we may have to use the decl
3292 mappings created in CTX's parent context. Suppose that we have the
3293 following parallel nesting (variable UIDs showed for clarity):
3295 iD.1562 = 0;
3296 #omp parallel shared(iD.1562) -> outer parallel
3297 iD.1562 = iD.1562 + 1;
3299 #omp parallel shared (iD.1562) -> inner parallel
3300 iD.1562 = iD.1562 - 1;
3302 Each parallel structure will create a distinct .omp_data_s structure
3303 for copying iD.1562 in/out of the directive:
3305 outer parallel .omp_data_s.1.i -> iD.1562
3306 inner parallel .omp_data_s.2.i -> iD.1562
3308 A shared variable mapping will produce a copy-out operation before
3309 the parallel directive and a copy-in operation after it. So, in
3310 this case we would have:
3312 iD.1562 = 0;
3313 .omp_data_o.1.i = iD.1562;
3314 #omp parallel shared(iD.1562) -> outer parallel
3315 .omp_data_i.1 = &.omp_data_o.1
3316 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3318 .omp_data_o.2.i = iD.1562; -> **
3319 #omp parallel shared(iD.1562) -> inner parallel
3320 .omp_data_i.2 = &.omp_data_o.2
3321 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3324 ** This is a problem. The symbol iD.1562 cannot be referenced
3325 inside the body of the outer parallel region. But since we are
3326 emitting this copy operation while expanding the inner parallel
3327 directive, we need to access the CTX structure of the outer
3328 parallel directive to get the correct mapping:
3330 .omp_data_o.2.i = .omp_data_i.1->i
3332 Since there may be other workshare or parallel directives enclosing
3333 the parallel directive, it may be necessary to walk up the context
3334 parent chain. This is not a problem in general because nested
3335 parallelism happens only rarely. */
3337 static tree
3338 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3340 tree t;
3341 omp_context *up;
3343 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3344 t = maybe_lookup_decl (decl, up);
3346 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3348 return t ? t : decl;
3352 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3353 in outer contexts. */
3355 static tree
3356 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3358 tree t = NULL;
3359 omp_context *up;
3361 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3362 t = maybe_lookup_decl (decl, up);
3364 return t ? t : decl;
3368 /* Construct the initialization value for reduction CLAUSE. */
3370 tree
3371 omp_reduction_init (tree clause, tree type)
3373 location_t loc = OMP_CLAUSE_LOCATION (clause);
3374 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3376 case PLUS_EXPR:
3377 case MINUS_EXPR:
3378 case BIT_IOR_EXPR:
3379 case BIT_XOR_EXPR:
3380 case TRUTH_OR_EXPR:
3381 case TRUTH_ORIF_EXPR:
3382 case TRUTH_XOR_EXPR:
3383 case NE_EXPR:
3384 return build_zero_cst (type);
3386 case MULT_EXPR:
3387 case TRUTH_AND_EXPR:
3388 case TRUTH_ANDIF_EXPR:
3389 case EQ_EXPR:
3390 return fold_convert_loc (loc, type, integer_one_node);
3392 case BIT_AND_EXPR:
3393 return fold_convert_loc (loc, type, integer_minus_one_node);
3395 case MAX_EXPR:
3396 if (SCALAR_FLOAT_TYPE_P (type))
3398 REAL_VALUE_TYPE max, min;
3399 if (HONOR_INFINITIES (TYPE_MODE (type)))
3401 real_inf (&max);
3402 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3404 else
3405 real_maxval (&min, 1, TYPE_MODE (type));
3406 return build_real (type, min);
3408 else
3410 gcc_assert (INTEGRAL_TYPE_P (type));
3411 return TYPE_MIN_VALUE (type);
3414 case MIN_EXPR:
3415 if (SCALAR_FLOAT_TYPE_P (type))
3417 REAL_VALUE_TYPE max;
3418 if (HONOR_INFINITIES (TYPE_MODE (type)))
3419 real_inf (&max);
3420 else
3421 real_maxval (&max, 0, TYPE_MODE (type));
3422 return build_real (type, max);
3424 else
3426 gcc_assert (INTEGRAL_TYPE_P (type));
3427 return TYPE_MAX_VALUE (type);
3430 default:
3431 gcc_unreachable ();
3435 /* Return alignment to be assumed for var in CLAUSE, which should be
3436 OMP_CLAUSE_ALIGNED. */
3438 static tree
3439 omp_clause_aligned_alignment (tree clause)
3441 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3442 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3444 /* Otherwise return implementation defined alignment. */
3445 unsigned int al = 1;
3446 machine_mode mode, vmode;
3447 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3448 if (vs)
3449 vs = 1 << floor_log2 (vs);
3450 static enum mode_class classes[]
3451 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3452 for (int i = 0; i < 4; i += 2)
3453 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3454 mode != VOIDmode;
3455 mode = GET_MODE_WIDER_MODE (mode))
3457 vmode = targetm.vectorize.preferred_simd_mode (mode);
3458 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3459 continue;
3460 while (vs
3461 && GET_MODE_SIZE (vmode) < vs
3462 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3463 vmode = GET_MODE_2XWIDER_MODE (vmode);
3465 tree type = lang_hooks.types.type_for_mode (mode, 1);
3466 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3467 continue;
3468 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3469 / GET_MODE_SIZE (mode));
3470 if (TYPE_MODE (type) != vmode)
3471 continue;
3472 if (TYPE_ALIGN_UNIT (type) > al)
3473 al = TYPE_ALIGN_UNIT (type);
3475 return build_int_cst (integer_type_node, al);
3478 /* Return maximum possible vectorization factor for the target. */
3480 static int
3481 omp_max_vf (void)
3483 if (!optimize
3484 || optimize_debug
3485 || !flag_tree_loop_optimize
3486 || (!flag_tree_loop_vectorize
3487 && (global_options_set.x_flag_tree_loop_vectorize
3488 || global_options_set.x_flag_tree_vectorize)))
3489 return 1;
3491 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3492 if (vs)
3494 vs = 1 << floor_log2 (vs);
3495 return vs;
3497 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3498 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3499 return GET_MODE_NUNITS (vqimode);
3500 return 1;
3503 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3504 privatization. */
3506 static bool
3507 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3508 tree &idx, tree &lane, tree &ivar, tree &lvar)
3510 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
3512 if (max_vf == 0)
3514 max_vf = omp_max_vf ();
3515 if (max_vf > 1)
3517 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3518 OMP_CLAUSE_SAFELEN);
3519 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3520 max_vf = 1;
3521 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3522 max_vf) == -1)
3523 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3525 if (max_vf > 1)
3527 idx = create_tmp_var (unsigned_type_node, NULL);
3528 lane = create_tmp_var (unsigned_type_node, NULL);
3531 if (max_vf == 1)
3532 return false;
3534 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3535 tree avar = create_tmp_var_raw (atype, NULL);
3536 if (TREE_ADDRESSABLE (new_var))
3537 TREE_ADDRESSABLE (avar) = 1;
3538 DECL_ATTRIBUTES (avar)
3539 = tree_cons (get_identifier ("omp simd array"), NULL,
3540 DECL_ATTRIBUTES (avar));
3541 gimple_add_tmp_var (avar);
3542 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3543 NULL_TREE, NULL_TREE);
3544 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3545 NULL_TREE, NULL_TREE);
3546 if (DECL_P (new_var))
3548 SET_DECL_VALUE_EXPR (new_var, lvar);
3549 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3551 return true;
3554 /* Helper function of lower_rec_input_clauses. For a reference
3555 in simd reduction, add an underlying variable it will reference. */
3557 static void
3558 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3560 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3561 if (TREE_CONSTANT (z))
3563 const char *name = NULL;
3564 if (DECL_NAME (new_vard))
3565 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3567 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3568 gimple_add_tmp_var (z);
3569 TREE_ADDRESSABLE (z) = 1;
3570 z = build_fold_addr_expr_loc (loc, z);
3571 gimplify_assign (new_vard, z, ilist);
3575 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3576 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3577 private variables. Initialization statements go in ILIST, while calls
3578 to destructors go in DLIST. */
3580 static void
3581 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3582 omp_context *ctx, struct omp_for_data *fd)
3584 tree c, dtor, copyin_seq, x, ptr;
3585 bool copyin_by_ref = false;
3586 bool lastprivate_firstprivate = false;
3587 bool reduction_omp_orig_ref = false;
3588 int pass;
3589 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3590 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3591 int max_vf = 0;
3592 tree lane = NULL_TREE, idx = NULL_TREE;
3593 tree ivar = NULL_TREE, lvar = NULL_TREE;
3594 gimple_seq llist[2] = { NULL, NULL };
3596 copyin_seq = NULL;
3598 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3599 with data sharing clauses referencing variable sized vars. That
3600 is unnecessarily hard to support and very unlikely to result in
3601 vectorized code anyway. */
3602 if (is_simd)
3603 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3604 switch (OMP_CLAUSE_CODE (c))
3606 case OMP_CLAUSE_LINEAR:
3607 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3608 max_vf = 1;
3609 /* FALLTHRU */
3610 case OMP_CLAUSE_REDUCTION:
3611 case OMP_CLAUSE_PRIVATE:
3612 case OMP_CLAUSE_FIRSTPRIVATE:
3613 case OMP_CLAUSE_LASTPRIVATE:
3614 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3615 max_vf = 1;
3616 break;
3617 default:
3618 continue;
3621 /* Do all the fixed sized types in the first pass, and the variable sized
3622 types in the second pass. This makes sure that the scalar arguments to
3623 the variable sized types are processed before we use them in the
3624 variable sized operations. */
3625 for (pass = 0; pass < 2; ++pass)
3627 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3629 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3630 tree var, new_var;
3631 bool by_ref;
3632 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3634 switch (c_kind)
3636 case OMP_CLAUSE_PRIVATE:
3637 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3638 continue;
3639 break;
3640 case OMP_CLAUSE_SHARED:
3641 /* Ignore shared directives in teams construct. */
3642 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3643 continue;
3644 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3646 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3647 continue;
3649 case OMP_CLAUSE_FIRSTPRIVATE:
3650 case OMP_CLAUSE_COPYIN:
3651 case OMP_CLAUSE_LINEAR:
3652 break;
3653 case OMP_CLAUSE_REDUCTION:
3654 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3655 reduction_omp_orig_ref = true;
3656 break;
3657 case OMP_CLAUSE__LOOPTEMP_:
3658 /* Handle _looptemp_ clauses only on parallel. */
3659 if (fd)
3660 continue;
3661 break;
3662 case OMP_CLAUSE_LASTPRIVATE:
3663 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3665 lastprivate_firstprivate = true;
3666 if (pass != 0)
3667 continue;
3669 /* Even without corresponding firstprivate, if
3670 decl is Fortran allocatable, it needs outer var
3671 reference. */
3672 else if (pass == 0
3673 && lang_hooks.decls.omp_private_outer_ref
3674 (OMP_CLAUSE_DECL (c)))
3675 lastprivate_firstprivate = true;
3676 break;
3677 case OMP_CLAUSE_ALIGNED:
3678 if (pass == 0)
3679 continue;
3680 var = OMP_CLAUSE_DECL (c);
3681 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3682 && !is_global_var (var))
3684 new_var = maybe_lookup_decl (var, ctx);
3685 if (new_var == NULL_TREE)
3686 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3687 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3688 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3689 omp_clause_aligned_alignment (c));
3690 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3691 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3692 gimplify_and_add (x, ilist);
3694 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3695 && is_global_var (var))
3697 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3698 new_var = lookup_decl (var, ctx);
3699 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3700 t = build_fold_addr_expr_loc (clause_loc, t);
3701 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3702 t = build_call_expr_loc (clause_loc, t2, 2, t,
3703 omp_clause_aligned_alignment (c));
3704 t = fold_convert_loc (clause_loc, ptype, t);
3705 x = create_tmp_var (ptype, NULL);
3706 t = build2 (MODIFY_EXPR, ptype, x, t);
3707 gimplify_and_add (t, ilist);
3708 t = build_simple_mem_ref_loc (clause_loc, x);
3709 SET_DECL_VALUE_EXPR (new_var, t);
3710 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3712 continue;
3713 default:
3714 continue;
3717 new_var = var = OMP_CLAUSE_DECL (c);
3718 if (c_kind != OMP_CLAUSE_COPYIN)
3719 new_var = lookup_decl (var, ctx);
3721 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3723 if (pass != 0)
3724 continue;
3726 else if (is_variable_sized (var))
3728 /* For variable sized types, we need to allocate the
3729 actual storage here. Call alloca and store the
3730 result in the pointer decl that we created elsewhere. */
3731 if (pass == 0)
3732 continue;
3734 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3736 gimple stmt;
3737 tree tmp, atmp;
3739 ptr = DECL_VALUE_EXPR (new_var);
3740 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3741 ptr = TREE_OPERAND (ptr, 0);
3742 gcc_assert (DECL_P (ptr));
3743 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3745 /* void *tmp = __builtin_alloca */
3746 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3747 stmt = gimple_build_call (atmp, 1, x);
3748 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3749 gimple_add_tmp_var (tmp);
3750 gimple_call_set_lhs (stmt, tmp);
3752 gimple_seq_add_stmt (ilist, stmt);
3754 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3755 gimplify_assign (ptr, x, ilist);
3758 else if (is_reference (var))
3760 /* For references that are being privatized for Fortran,
3761 allocate new backing storage for the new pointer
3762 variable. This allows us to avoid changing all the
3763 code that expects a pointer to something that expects
3764 a direct variable. */
3765 if (pass == 0)
3766 continue;
3768 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3769 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3771 x = build_receiver_ref (var, false, ctx);
3772 x = build_fold_addr_expr_loc (clause_loc, x);
3774 else if (TREE_CONSTANT (x))
3776 /* For reduction in SIMD loop, defer adding the
3777 initialization of the reference, because if we decide
3778 to use SIMD array for it, the initilization could cause
3779 expansion ICE. */
3780 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3781 x = NULL_TREE;
3782 else
3784 const char *name = NULL;
3785 if (DECL_NAME (var))
3786 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3788 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3789 name);
3790 gimple_add_tmp_var (x);
3791 TREE_ADDRESSABLE (x) = 1;
3792 x = build_fold_addr_expr_loc (clause_loc, x);
3795 else
3797 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3798 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3801 if (x)
3803 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3804 gimplify_assign (new_var, x, ilist);
3807 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3809 else if (c_kind == OMP_CLAUSE_REDUCTION
3810 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3812 if (pass == 0)
3813 continue;
3815 else if (pass != 0)
3816 continue;
3818 switch (OMP_CLAUSE_CODE (c))
3820 case OMP_CLAUSE_SHARED:
3821 /* Ignore shared directives in teams construct. */
3822 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3823 continue;
3824 /* Shared global vars are just accessed directly. */
3825 if (is_global_var (new_var))
3826 break;
3827 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3828 needs to be delayed until after fixup_child_record_type so
3829 that we get the correct type during the dereference. */
3830 by_ref = use_pointer_for_field (var, ctx);
3831 x = build_receiver_ref (var, by_ref, ctx);
3832 SET_DECL_VALUE_EXPR (new_var, x);
3833 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3835 /* ??? If VAR is not passed by reference, and the variable
3836 hasn't been initialized yet, then we'll get a warning for
3837 the store into the omp_data_s structure. Ideally, we'd be
3838 able to notice this and not store anything at all, but
3839 we're generating code too early. Suppress the warning. */
3840 if (!by_ref)
3841 TREE_NO_WARNING (var) = 1;
3842 break;
3844 case OMP_CLAUSE_LASTPRIVATE:
3845 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3846 break;
3847 /* FALLTHRU */
3849 case OMP_CLAUSE_PRIVATE:
3850 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3851 x = build_outer_var_ref (var, ctx);
3852 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3854 if (is_task_ctx (ctx))
3855 x = build_receiver_ref (var, false, ctx);
3856 else
3857 x = build_outer_var_ref (var, ctx);
3859 else
3860 x = NULL;
3861 do_private:
3862 tree nx;
3863 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3864 if (is_simd)
3866 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3867 if ((TREE_ADDRESSABLE (new_var) || nx || y
3868 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3869 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3870 idx, lane, ivar, lvar))
3872 if (nx)
3873 x = lang_hooks.decls.omp_clause_default_ctor
3874 (c, unshare_expr (ivar), x);
3875 if (nx && x)
3876 gimplify_and_add (x, &llist[0]);
3877 if (y)
3879 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3880 if (y)
3882 gimple_seq tseq = NULL;
3884 dtor = y;
3885 gimplify_stmt (&dtor, &tseq);
3886 gimple_seq_add_seq (&llist[1], tseq);
3889 break;
3892 if (nx)
3893 gimplify_and_add (nx, ilist);
3894 /* FALLTHRU */
3896 do_dtor:
3897 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3898 if (x)
3900 gimple_seq tseq = NULL;
3902 dtor = x;
3903 gimplify_stmt (&dtor, &tseq);
3904 gimple_seq_add_seq (dlist, tseq);
3906 break;
3908 case OMP_CLAUSE_LINEAR:
3909 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3910 goto do_firstprivate;
3911 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3912 x = NULL;
3913 else
3914 x = build_outer_var_ref (var, ctx);
3915 goto do_private;
3917 case OMP_CLAUSE_FIRSTPRIVATE:
3918 if (is_task_ctx (ctx))
3920 if (is_reference (var) || is_variable_sized (var))
3921 goto do_dtor;
3922 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3923 ctx))
3924 || use_pointer_for_field (var, NULL))
3926 x = build_receiver_ref (var, false, ctx);
3927 SET_DECL_VALUE_EXPR (new_var, x);
3928 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3929 goto do_dtor;
3932 do_firstprivate:
3933 x = build_outer_var_ref (var, ctx);
3934 if (is_simd)
3936 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3937 && gimple_omp_for_combined_into_p (ctx->stmt))
3939 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3940 tree stept = TREE_TYPE (t);
3941 tree ct = find_omp_clause (clauses,
3942 OMP_CLAUSE__LOOPTEMP_);
3943 gcc_assert (ct);
3944 tree l = OMP_CLAUSE_DECL (ct);
3945 tree n1 = fd->loop.n1;
3946 tree step = fd->loop.step;
3947 tree itype = TREE_TYPE (l);
3948 if (POINTER_TYPE_P (itype))
3949 itype = signed_type_for (itype);
3950 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3951 if (TYPE_UNSIGNED (itype)
3952 && fd->loop.cond_code == GT_EXPR)
3953 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3954 fold_build1 (NEGATE_EXPR, itype, l),
3955 fold_build1 (NEGATE_EXPR,
3956 itype, step));
3957 else
3958 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3959 t = fold_build2 (MULT_EXPR, stept,
3960 fold_convert (stept, l), t);
3962 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3964 x = lang_hooks.decls.omp_clause_linear_ctor
3965 (c, new_var, x, t);
3966 gimplify_and_add (x, ilist);
3967 goto do_dtor;
3970 if (POINTER_TYPE_P (TREE_TYPE (x)))
3971 x = fold_build2 (POINTER_PLUS_EXPR,
3972 TREE_TYPE (x), x, t);
3973 else
3974 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3977 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3978 || TREE_ADDRESSABLE (new_var))
3979 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3980 idx, lane, ivar, lvar))
3982 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3984 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3985 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3986 gimplify_and_add (x, ilist);
3987 gimple_stmt_iterator gsi
3988 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3989 gimple g
3990 = gimple_build_assign (unshare_expr (lvar), iv);
3991 gsi_insert_before_without_update (&gsi, g,
3992 GSI_SAME_STMT);
3993 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3994 enum tree_code code = PLUS_EXPR;
3995 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3996 code = POINTER_PLUS_EXPR;
3997 g = gimple_build_assign_with_ops (code, iv, iv, t);
3998 gsi_insert_before_without_update (&gsi, g,
3999 GSI_SAME_STMT);
4000 break;
4002 x = lang_hooks.decls.omp_clause_copy_ctor
4003 (c, unshare_expr (ivar), x);
4004 gimplify_and_add (x, &llist[0]);
4005 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4006 if (x)
4008 gimple_seq tseq = NULL;
4010 dtor = x;
4011 gimplify_stmt (&dtor, &tseq);
4012 gimple_seq_add_seq (&llist[1], tseq);
4014 break;
4017 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4018 gimplify_and_add (x, ilist);
4019 goto do_dtor;
4021 case OMP_CLAUSE__LOOPTEMP_:
4022 gcc_assert (is_parallel_ctx (ctx));
4023 x = build_outer_var_ref (var, ctx);
4024 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4025 gimplify_and_add (x, ilist);
4026 break;
4028 case OMP_CLAUSE_COPYIN:
4029 by_ref = use_pointer_for_field (var, NULL);
4030 x = build_receiver_ref (var, by_ref, ctx);
4031 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4032 append_to_statement_list (x, &copyin_seq);
4033 copyin_by_ref |= by_ref;
4034 break;
4036 case OMP_CLAUSE_REDUCTION:
4037 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4039 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4040 gimple tseq;
4041 x = build_outer_var_ref (var, ctx);
4043 if (is_reference (var)
4044 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4045 TREE_TYPE (x)))
4046 x = build_fold_addr_expr_loc (clause_loc, x);
4047 SET_DECL_VALUE_EXPR (placeholder, x);
4048 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4049 tree new_vard = new_var;
4050 if (is_reference (var))
4052 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4053 new_vard = TREE_OPERAND (new_var, 0);
4054 gcc_assert (DECL_P (new_vard));
4056 if (is_simd
4057 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4058 idx, lane, ivar, lvar))
4060 if (new_vard == new_var)
4062 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4063 SET_DECL_VALUE_EXPR (new_var, ivar);
4065 else
4067 SET_DECL_VALUE_EXPR (new_vard,
4068 build_fold_addr_expr (ivar));
4069 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4071 x = lang_hooks.decls.omp_clause_default_ctor
4072 (c, unshare_expr (ivar),
4073 build_outer_var_ref (var, ctx));
4074 if (x)
4075 gimplify_and_add (x, &llist[0]);
4076 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4078 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4079 lower_omp (&tseq, ctx);
4080 gimple_seq_add_seq (&llist[0], tseq);
4082 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4083 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4084 lower_omp (&tseq, ctx);
4085 gimple_seq_add_seq (&llist[1], tseq);
4086 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4087 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4088 if (new_vard == new_var)
4089 SET_DECL_VALUE_EXPR (new_var, lvar);
4090 else
4091 SET_DECL_VALUE_EXPR (new_vard,
4092 build_fold_addr_expr (lvar));
4093 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4094 if (x)
4096 tseq = NULL;
4097 dtor = x;
4098 gimplify_stmt (&dtor, &tseq);
4099 gimple_seq_add_seq (&llist[1], tseq);
4101 break;
4103 /* If this is a reference to constant size reduction var
4104 with placeholder, we haven't emitted the initializer
4105 for it because it is undesirable if SIMD arrays are used.
4106 But if they aren't used, we need to emit the deferred
4107 initialization now. */
4108 else if (is_reference (var) && is_simd)
4109 handle_simd_reference (clause_loc, new_vard, ilist);
4110 x = lang_hooks.decls.omp_clause_default_ctor
4111 (c, unshare_expr (new_var),
4112 build_outer_var_ref (var, ctx));
4113 if (x)
4114 gimplify_and_add (x, ilist);
4115 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4117 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4118 lower_omp (&tseq, ctx);
4119 gimple_seq_add_seq (ilist, tseq);
4121 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4122 if (is_simd)
4124 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4125 lower_omp (&tseq, ctx);
4126 gimple_seq_add_seq (dlist, tseq);
4127 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4129 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4130 goto do_dtor;
4132 else
4134 x = omp_reduction_init (c, TREE_TYPE (new_var));
4135 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4136 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4138 /* reduction(-:var) sums up the partial results, so it
4139 acts identically to reduction(+:var). */
4140 if (code == MINUS_EXPR)
4141 code = PLUS_EXPR;
4143 tree new_vard = new_var;
4144 if (is_simd && is_reference (var))
4146 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4147 new_vard = TREE_OPERAND (new_var, 0);
4148 gcc_assert (DECL_P (new_vard));
4150 if (is_simd
4151 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4152 idx, lane, ivar, lvar))
4154 tree ref = build_outer_var_ref (var, ctx);
4156 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4158 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4159 ref = build_outer_var_ref (var, ctx);
4160 gimplify_assign (ref, x, &llist[1]);
4162 if (new_vard != new_var)
4164 SET_DECL_VALUE_EXPR (new_vard,
4165 build_fold_addr_expr (lvar));
4166 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4169 else
4171 if (is_reference (var) && is_simd)
4172 handle_simd_reference (clause_loc, new_vard, ilist);
4173 gimplify_assign (new_var, x, ilist);
4174 if (is_simd)
4176 tree ref = build_outer_var_ref (var, ctx);
4178 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4179 ref = build_outer_var_ref (var, ctx);
4180 gimplify_assign (ref, x, dlist);
4184 break;
4186 default:
4187 gcc_unreachable ();
4192 if (lane)
4194 tree uid = create_tmp_var (ptr_type_node, "simduid");
4195 /* Don't want uninit warnings on simduid, it is always uninitialized,
4196 but we use it not for the value, but for the DECL_UID only. */
4197 TREE_NO_WARNING (uid) = 1;
4198 gimple g
4199 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4200 gimple_call_set_lhs (g, lane);
4201 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4202 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4203 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4204 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4205 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4206 gimple_omp_for_set_clauses (ctx->stmt, c);
4207 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
4208 build_int_cst (unsigned_type_node, 0),
4209 NULL_TREE);
4210 gimple_seq_add_stmt (ilist, g);
4211 for (int i = 0; i < 2; i++)
4212 if (llist[i])
4214 tree vf = create_tmp_var (unsigned_type_node, NULL);
4215 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4216 gimple_call_set_lhs (g, vf);
4217 gimple_seq *seq = i == 0 ? ilist : dlist;
4218 gimple_seq_add_stmt (seq, g);
4219 tree t = build_int_cst (unsigned_type_node, 0);
4220 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
4221 gimple_seq_add_stmt (seq, g);
4222 tree body = create_artificial_label (UNKNOWN_LOCATION);
4223 tree header = create_artificial_label (UNKNOWN_LOCATION);
4224 tree end = create_artificial_label (UNKNOWN_LOCATION);
4225 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4226 gimple_seq_add_stmt (seq, gimple_build_label (body));
4227 gimple_seq_add_seq (seq, llist[i]);
4228 t = build_int_cst (unsigned_type_node, 1);
4229 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
4230 gimple_seq_add_stmt (seq, g);
4231 gimple_seq_add_stmt (seq, gimple_build_label (header));
4232 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4233 gimple_seq_add_stmt (seq, g);
4234 gimple_seq_add_stmt (seq, gimple_build_label (end));
4238 /* The copyin sequence is not to be executed by the main thread, since
4239 that would result in self-copies. Perhaps not visible to scalars,
4240 but it certainly is to C++ operator=. */
4241 if (copyin_seq)
4243 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4245 x = build2 (NE_EXPR, boolean_type_node, x,
4246 build_int_cst (TREE_TYPE (x), 0));
4247 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4248 gimplify_and_add (x, ilist);
4251 /* If any copyin variable is passed by reference, we must ensure the
4252 master thread doesn't modify it before it is copied over in all
4253 threads. Similarly for variables in both firstprivate and
4254 lastprivate clauses we need to ensure the lastprivate copying
4255 happens after firstprivate copying in all threads. And similarly
4256 for UDRs if initializer expression refers to omp_orig. */
4257 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4259 /* Don't add any barrier for #pragma omp simd or
4260 #pragma omp distribute. */
4261 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4262 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4263 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4266 /* If max_vf is non-zero, then we can use only a vectorization factor
4267 up to the max_vf we chose. So stick it into the safelen clause. */
4268 if (max_vf)
4270 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4271 OMP_CLAUSE_SAFELEN);
4272 if (c == NULL_TREE
4273 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4274 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4275 max_vf) == 1))
4277 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4278 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4279 max_vf);
4280 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4281 gimple_omp_for_set_clauses (ctx->stmt, c);
4287 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4288 both parallel and workshare constructs. PREDICATE may be NULL if it's
4289 always true. */
4291 static void
4292 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4293 omp_context *ctx)
4295 tree x, c, label = NULL, orig_clauses = clauses;
4296 bool par_clauses = false;
4297 tree simduid = NULL, lastlane = NULL;
4299 /* Early exit if there are no lastprivate or linear clauses. */
4300 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4301 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4302 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4303 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4304 break;
4305 if (clauses == NULL)
4307 /* If this was a workshare clause, see if it had been combined
4308 with its parallel. In that case, look for the clauses on the
4309 parallel statement itself. */
4310 if (is_parallel_ctx (ctx))
4311 return;
4313 ctx = ctx->outer;
4314 if (ctx == NULL || !is_parallel_ctx (ctx))
4315 return;
4317 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4318 OMP_CLAUSE_LASTPRIVATE);
4319 if (clauses == NULL)
4320 return;
4321 par_clauses = true;
4324 if (predicate)
4326 gimple stmt;
4327 tree label_true, arm1, arm2;
4329 label = create_artificial_label (UNKNOWN_LOCATION);
4330 label_true = create_artificial_label (UNKNOWN_LOCATION);
4331 arm1 = TREE_OPERAND (predicate, 0);
4332 arm2 = TREE_OPERAND (predicate, 1);
4333 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4334 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4335 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4336 label_true, label);
4337 gimple_seq_add_stmt (stmt_list, stmt);
4338 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4341 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4342 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4344 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4345 if (simduid)
4346 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4349 for (c = clauses; c ;)
4351 tree var, new_var;
4352 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4354 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4355 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4356 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4358 var = OMP_CLAUSE_DECL (c);
4359 new_var = lookup_decl (var, ctx);
4361 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4363 tree val = DECL_VALUE_EXPR (new_var);
4364 if (TREE_CODE (val) == ARRAY_REF
4365 && VAR_P (TREE_OPERAND (val, 0))
4366 && lookup_attribute ("omp simd array",
4367 DECL_ATTRIBUTES (TREE_OPERAND (val,
4368 0))))
4370 if (lastlane == NULL)
4372 lastlane = create_tmp_var (unsigned_type_node, NULL);
4373 gimple g
4374 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4375 2, simduid,
4376 TREE_OPERAND (val, 1));
4377 gimple_call_set_lhs (g, lastlane);
4378 gimple_seq_add_stmt (stmt_list, g);
4380 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4381 TREE_OPERAND (val, 0), lastlane,
4382 NULL_TREE, NULL_TREE);
4386 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4387 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4389 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4390 gimple_seq_add_seq (stmt_list,
4391 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4392 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4394 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4395 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4397 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4398 gimple_seq_add_seq (stmt_list,
4399 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4400 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4403 x = build_outer_var_ref (var, ctx);
4404 if (is_reference (var))
4405 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4406 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4407 gimplify_and_add (x, stmt_list);
4409 c = OMP_CLAUSE_CHAIN (c);
4410 if (c == NULL && !par_clauses)
4412 /* If this was a workshare clause, see if it had been combined
4413 with its parallel. In that case, continue looking for the
4414 clauses also on the parallel statement itself. */
4415 if (is_parallel_ctx (ctx))
4416 break;
4418 ctx = ctx->outer;
4419 if (ctx == NULL || !is_parallel_ctx (ctx))
4420 break;
4422 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4423 OMP_CLAUSE_LASTPRIVATE);
4424 par_clauses = true;
4428 if (label)
4429 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4433 /* Generate code to implement the REDUCTION clauses. */
4435 static void
4436 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4438 gimple_seq sub_seq = NULL;
4439 gimple stmt;
4440 tree x, c;
4441 int count = 0;
4443 /* SIMD reductions are handled in lower_rec_input_clauses. */
4444 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4445 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4446 return;
4448 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4449 update in that case, otherwise use a lock. */
4450 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4451 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4453 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4455 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4456 count = -1;
4457 break;
4459 count++;
4462 if (count == 0)
4463 return;
4465 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4467 tree var, ref, new_var;
4468 enum tree_code code;
4469 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4471 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4472 continue;
4474 var = OMP_CLAUSE_DECL (c);
4475 new_var = lookup_decl (var, ctx);
4476 if (is_reference (var))
4477 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4478 ref = build_outer_var_ref (var, ctx);
4479 code = OMP_CLAUSE_REDUCTION_CODE (c);
4481 /* reduction(-:var) sums up the partial results, so it acts
4482 identically to reduction(+:var). */
4483 if (code == MINUS_EXPR)
4484 code = PLUS_EXPR;
4486 if (count == 1)
4488 if (!is_gimple_omp_oacc_specifically (ctx->stmt))
4490 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4492 addr = save_expr (addr);
4493 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4494 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4495 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4496 gimplify_and_add (x, stmt_seqp);
4497 return;
4499 else
4501 /* The atomic add at the end of the sum creates unnecessary
4502 write contention on accelerators. To work around this,
4503 create an array to store the partial reductions. Later, in
4504 lower_omp_for (for openacc), the values of array will be
4505 combined. */
4507 tree t = NULL_TREE, array, nthreads;
4508 tree type = get_base_type (var);
4510 /* First ensure that the current tid is less than vector_length. */
4511 tree exit_label = create_artificial_label (UNKNOWN_LOCATION);
4512 tree reduction_label = create_artificial_label (UNKNOWN_LOCATION);
4514 /* Get the current thread id. */
4515 tree call = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4516 gimple stmt = gimple_build_call (call, 1, integer_zero_node);
4517 tree fntype = gimple_call_fntype (stmt);
4518 tree tid = create_tmp_var (TREE_TYPE (fntype), NULL);
4519 gimple_call_set_lhs (stmt, tid);
4520 gimple_seq_add_stmt (stmt_seqp, stmt);
4522 /* Find the total number of threads. A reduction clause
4523 only appears inside a loop construction or a combined
4524 parallel and loop construct. */
4525 tree c;
4527 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
4528 c = gimple_oacc_parallel_clauses (ctx->outer->stmt);
4529 else
4530 c = gimple_oacc_parallel_clauses (ctx->stmt);
4532 t = find_omp_clause (c, OMP_CLAUSE_VECTOR_LENGTH);
4534 if (t)
4536 t = fold_convert_loc (OMP_CLAUSE_LOCATION (t),
4537 integer_type_node,
4538 OMP_CLAUSE_VECTOR_LENGTH_EXPR (t));
4541 if (!t)
4542 t = integer_one_node;
4544 /* Extract the number of threads. */
4545 nthreads = create_tmp_var (sizetype, NULL);
4546 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype, t),
4547 stmt_seqp);
4548 stmt = gimple_build_assign_with_ops (MINUS_EXPR, nthreads, nthreads,
4549 fold_build1 (NOP_EXPR, sizetype,
4550 integer_one_node));
4551 gimple_seq_add_stmt (stmt_seqp, stmt);
4553 /* If tid >= nthreads, goto exit_label. */
4554 t = create_tmp_var (sizetype, NULL);
4555 gimplify_assign (t, fold_build1 (NOP_EXPR, sizetype, tid),
4556 stmt_seqp);
4557 stmt = gimple_build_cond (GT_EXPR, t, nthreads, exit_label,
4558 reduction_label);
4559 gimple_seq_add_stmt (stmt_seqp, stmt);
4561 /* Place the reduction_label here. */
4563 gimple_seq_add_stmt (stmt_seqp,
4564 gimple_build_label (reduction_label));
4566 /* Now insert the partial reductions into the array. */
4568 /* Find the reduction array. */
4570 tree ptype = build_pointer_type (type);
4572 t = lookup_reduction (omp_get_id (var), ctx);
4573 t = build_receiver_ref (t, false, ctx->outer);
4575 array = create_tmp_var (ptype, NULL);
4576 gimplify_assign (array, t, stmt_seqp);
4578 tree ptr = create_tmp_var (TREE_TYPE (array), NULL);
4580 /* Find the reduction array. */
4582 /* testing a unary conversion. */
4583 tree offset = create_tmp_var (sizetype, NULL);
4584 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4585 stmt_seqp);
4586 t = create_tmp_var (sizetype, NULL);
4587 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype,
4588 tid)),
4589 stmt_seqp);
4590 stmt = gimple_build_assign_with_ops (MULT_EXPR, offset, offset, t);
4591 gimple_seq_add_stmt (stmt_seqp, stmt);
4593 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4594 of adding sizeof(var) to the array? */
4595 ptr = create_tmp_var (ptype, NULL);
4596 stmt = gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
4597 unshare_expr(ptr),
4598 array, offset);
4599 gimple_seq_add_stmt (stmt_seqp, stmt);
4601 /* Move the local sum to gfc$sum[i]. */
4602 x = unshare_expr (build_simple_mem_ref (ptr));
4603 stmt = gimplify_assign (x, new_var, stmt_seqp);
4605 /* Place exit label here. */
4606 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (exit_label));
4608 return;
4612 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4614 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4616 if (is_reference (var)
4617 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4618 TREE_TYPE (ref)))
4619 ref = build_fold_addr_expr_loc (clause_loc, ref);
4620 SET_DECL_VALUE_EXPR (placeholder, ref);
4621 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4622 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4623 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4624 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4625 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4627 else
4629 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4630 ref = build_outer_var_ref (var, ctx);
4631 gimplify_assign (ref, x, &sub_seq);
4635 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4637 gimple_seq_add_stmt (stmt_seqp, stmt);
4639 gimple_seq_add_seq (stmt_seqp, sub_seq);
4641 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4643 gimple_seq_add_stmt (stmt_seqp, stmt);
4647 /* Generate code to implement the COPYPRIVATE clauses. */
4649 static void
4650 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4651 omp_context *ctx)
4653 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4655 tree c;
4657 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4659 tree var, new_var, ref, x;
4660 bool by_ref;
4661 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4663 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4664 continue;
4666 var = OMP_CLAUSE_DECL (c);
4667 by_ref = use_pointer_for_field (var, NULL);
4669 ref = build_sender_ref (var, ctx);
4670 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4671 if (by_ref)
4673 x = build_fold_addr_expr_loc (clause_loc, new_var);
4674 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4676 gimplify_assign (ref, x, slist);
4678 ref = build_receiver_ref (var, false, ctx);
4679 if (by_ref)
4681 ref = fold_convert_loc (clause_loc,
4682 build_pointer_type (TREE_TYPE (new_var)),
4683 ref);
4684 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4686 if (is_reference (var))
4688 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4689 ref = build_simple_mem_ref_loc (clause_loc, ref);
4690 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4692 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4693 gimplify_and_add (x, rlist);
4698 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4699 and REDUCTION from the sender (aka parent) side. */
4701 static void
4702 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4703 omp_context *ctx)
4705 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4707 tree c;
4709 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4711 tree val, ref, x, var;
4712 bool by_ref, do_in = false, do_out = false;
4713 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4715 switch (OMP_CLAUSE_CODE (c))
4717 case OMP_CLAUSE_PRIVATE:
4718 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4719 break;
4720 continue;
4721 case OMP_CLAUSE_FIRSTPRIVATE:
4722 case OMP_CLAUSE_COPYIN:
4723 case OMP_CLAUSE_LASTPRIVATE:
4724 case OMP_CLAUSE_REDUCTION:
4725 case OMP_CLAUSE__LOOPTEMP_:
4726 break;
4727 default:
4728 continue;
4731 val = OMP_CLAUSE_DECL (c);
4732 var = lookup_decl_in_outer_ctx (val, ctx);
4734 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4735 && is_global_var (var))
4736 continue;
4737 if (is_variable_sized (val))
4738 continue;
4739 by_ref = use_pointer_for_field (val, NULL);
4741 switch (OMP_CLAUSE_CODE (c))
4743 case OMP_CLAUSE_PRIVATE:
4744 case OMP_CLAUSE_FIRSTPRIVATE:
4745 case OMP_CLAUSE_COPYIN:
4746 case OMP_CLAUSE__LOOPTEMP_:
4747 do_in = true;
4748 break;
4750 case OMP_CLAUSE_LASTPRIVATE:
4751 if (by_ref || is_reference (val))
4753 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4754 continue;
4755 do_in = true;
4757 else
4759 do_out = true;
4760 if (lang_hooks.decls.omp_private_outer_ref (val))
4761 do_in = true;
4763 break;
4765 case OMP_CLAUSE_REDUCTION:
4766 do_in = true;
4767 do_out = !(by_ref || is_reference (val));
4768 break;
4770 default:
4771 gcc_unreachable ();
4774 if (do_in)
4776 ref = build_sender_ref (val, ctx);
4777 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4778 gimplify_assign (ref, x, ilist);
4779 if (is_task_ctx (ctx))
4780 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4783 if (do_out)
4785 ref = build_sender_ref (val, ctx);
4786 gimplify_assign (var, ref, olist);
4791 /* Generate code to implement SHARED from the sender (aka parent)
4792 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4793 list things that got automatically shared. */
4795 static void
4796 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4798 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
4800 tree var, ovar, nvar, f, x, record_type;
4802 if (ctx->record_type == NULL)
4803 return;
4805 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4806 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4808 ovar = DECL_ABSTRACT_ORIGIN (f);
4809 nvar = maybe_lookup_decl (ovar, ctx);
4810 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4811 continue;
4813 /* If CTX is a nested parallel directive. Find the immediately
4814 enclosing parallel or workshare construct that contains a
4815 mapping for OVAR. */
4816 var = lookup_decl_in_outer_ctx (ovar, ctx);
4818 if (use_pointer_for_field (ovar, ctx))
4820 x = build_sender_ref (ovar, ctx);
4821 var = build_fold_addr_expr (var);
4822 gimplify_assign (x, var, ilist);
4824 else
4826 x = build_sender_ref (ovar, ctx);
4827 gimplify_assign (x, var, ilist);
4829 if (!TREE_READONLY (var)
4830 /* We don't need to receive a new reference to a result
4831 or parm decl. In fact we may not store to it as we will
4832 invalidate any pending RSO and generate wrong gimple
4833 during inlining. */
4834 && !((TREE_CODE (var) == RESULT_DECL
4835 || TREE_CODE (var) == PARM_DECL)
4836 && DECL_BY_REFERENCE (var)))
4838 x = build_sender_ref (ovar, ctx);
4839 gimplify_assign (var, x, olist);
4846 /* A convenience function to build an empty GIMPLE_COND with just the
4847 condition. */
4849 static gimple
4850 gimple_build_cond_empty (tree cond)
4852 enum tree_code pred_code;
4853 tree lhs, rhs;
4855 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4856 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4860 /* Build the function calls to GOMP_parallel_start etc to actually
4861 generate the parallel operation. REGION is the parallel region
4862 being expanded. BB is the block where to insert the code. WS_ARGS
4863 will be set if this is a call to a combined parallel+workshare
4864 construct, it contains the list of additional arguments needed by
4865 the workshare construct. */
4867 static void
4868 expand_parallel_call (struct omp_region *region, basic_block bb,
4869 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4871 tree t, t1, t2, val, cond, c, clauses, flags;
4872 gimple_stmt_iterator gsi;
4873 gimple stmt;
4874 enum built_in_function start_ix;
4875 int start_ix2;
4876 location_t clause_loc;
4877 vec<tree, va_gc> *args;
4879 clauses = gimple_omp_parallel_clauses (entry_stmt);
4881 /* Determine what flavor of GOMP_parallel we will be
4882 emitting. */
4883 start_ix = BUILT_IN_GOMP_PARALLEL;
4884 if (is_combined_parallel (region))
4886 switch (region->inner->type)
4888 case GIMPLE_OMP_FOR:
4889 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4890 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4891 + (region->inner->sched_kind
4892 == OMP_CLAUSE_SCHEDULE_RUNTIME
4893 ? 3 : region->inner->sched_kind));
4894 start_ix = (enum built_in_function)start_ix2;
4895 break;
4896 case GIMPLE_OMP_SECTIONS:
4897 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4898 break;
4899 default:
4900 gcc_unreachable ();
4904 /* By default, the value of NUM_THREADS is zero (selected at run time)
4905 and there is no conditional. */
4906 cond = NULL_TREE;
4907 val = build_int_cst (unsigned_type_node, 0);
4908 flags = build_int_cst (unsigned_type_node, 0);
4910 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4911 if (c)
4912 cond = OMP_CLAUSE_IF_EXPR (c);
4914 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4915 if (c)
4917 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4918 clause_loc = OMP_CLAUSE_LOCATION (c);
4920 else
4921 clause_loc = gimple_location (entry_stmt);
4923 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4924 if (c)
4925 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4927 /* Ensure 'val' is of the correct type. */
4928 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4930 /* If we found the clause 'if (cond)', build either
4931 (cond != 0) or (cond ? val : 1u). */
4932 if (cond)
4934 cond = gimple_boolify (cond);
4936 if (integer_zerop (val))
4937 val = fold_build2_loc (clause_loc,
4938 EQ_EXPR, unsigned_type_node, cond,
4939 build_int_cst (TREE_TYPE (cond), 0));
4940 else
4942 basic_block cond_bb, then_bb, else_bb;
4943 edge e, e_then, e_else;
4944 tree tmp_then, tmp_else, tmp_join, tmp_var;
4946 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4947 if (gimple_in_ssa_p (cfun))
4949 tmp_then = make_ssa_name (tmp_var, NULL);
4950 tmp_else = make_ssa_name (tmp_var, NULL);
4951 tmp_join = make_ssa_name (tmp_var, NULL);
4953 else
4955 tmp_then = tmp_var;
4956 tmp_else = tmp_var;
4957 tmp_join = tmp_var;
4960 e = split_block (bb, NULL);
4961 cond_bb = e->src;
4962 bb = e->dest;
4963 remove_edge (e);
4965 then_bb = create_empty_bb (cond_bb);
4966 else_bb = create_empty_bb (then_bb);
4967 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4968 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4970 stmt = gimple_build_cond_empty (cond);
4971 gsi = gsi_start_bb (cond_bb);
4972 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4974 gsi = gsi_start_bb (then_bb);
4975 stmt = gimple_build_assign (tmp_then, val);
4976 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4978 gsi = gsi_start_bb (else_bb);
4979 stmt = gimple_build_assign
4980 (tmp_else, build_int_cst (unsigned_type_node, 1));
4981 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4983 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4984 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4985 add_bb_to_loop (then_bb, cond_bb->loop_father);
4986 add_bb_to_loop (else_bb, cond_bb->loop_father);
4987 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4988 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4990 if (gimple_in_ssa_p (cfun))
4992 gimple phi = create_phi_node (tmp_join, bb);
4993 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4994 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4997 val = tmp_join;
5000 gsi = gsi_start_bb (bb);
5001 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
5002 false, GSI_CONTINUE_LINKING);
5005 gsi = gsi_last_bb (bb);
5006 t = gimple_omp_parallel_data_arg (entry_stmt);
5007 if (t == NULL)
5008 t1 = null_pointer_node;
5009 else
5010 t1 = build_fold_addr_expr (t);
5011 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5013 vec_alloc (args, 4 + vec_safe_length (ws_args));
5014 args->quick_push (t2);
5015 args->quick_push (t1);
5016 args->quick_push (val);
5017 if (ws_args)
5018 args->splice (*ws_args);
5019 args->quick_push (flags);
5021 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5022 builtin_decl_explicit (start_ix), args);
5024 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5025 false, GSI_CONTINUE_LINKING);
5028 /* Insert a function call whose name is FUNC_NAME with the information from
5029 ENTRY_STMT into the basic_block BB. */
5031 static void
5032 expand_cilk_for_call (basic_block bb, gimple entry_stmt,
5033 vec <tree, va_gc> *ws_args)
5035 tree t, t1, t2;
5036 gimple_stmt_iterator gsi;
5037 vec <tree, va_gc> *args;
5039 gcc_assert (vec_safe_length (ws_args) == 2);
5040 tree func_name = (*ws_args)[0];
5041 tree grain = (*ws_args)[1];
5043 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5044 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5045 gcc_assert (count != NULL_TREE);
5046 count = OMP_CLAUSE_OPERAND (count, 0);
5048 gsi = gsi_last_bb (bb);
5049 t = gimple_omp_parallel_data_arg (entry_stmt);
5050 if (t == NULL)
5051 t1 = null_pointer_node;
5052 else
5053 t1 = build_fold_addr_expr (t);
5054 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5056 vec_alloc (args, 4);
5057 args->quick_push (t2);
5058 args->quick_push (t1);
5059 args->quick_push (count);
5060 args->quick_push (grain);
5061 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5063 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5064 GSI_CONTINUE_LINKING);
5067 /* Build the function call to GOMP_task to actually
5068 generate the task operation. BB is the block where to insert the code. */
5070 static void
5071 expand_task_call (basic_block bb, gimple entry_stmt)
5073 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5074 gimple_stmt_iterator gsi;
5075 location_t loc = gimple_location (entry_stmt);
5077 clauses = gimple_omp_task_clauses (entry_stmt);
5079 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5080 if (c)
5081 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5082 else
5083 cond = boolean_true_node;
5085 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5086 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5087 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5088 flags = build_int_cst (unsigned_type_node,
5089 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5091 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5092 if (c)
5094 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5095 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5096 build_int_cst (unsigned_type_node, 2),
5097 build_int_cst (unsigned_type_node, 0));
5098 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5100 if (depend)
5101 depend = OMP_CLAUSE_DECL (depend);
5102 else
5103 depend = build_int_cst (ptr_type_node, 0);
5105 gsi = gsi_last_bb (bb);
5106 t = gimple_omp_task_data_arg (entry_stmt);
5107 if (t == NULL)
5108 t2 = null_pointer_node;
5109 else
5110 t2 = build_fold_addr_expr_loc (loc, t);
5111 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5112 t = gimple_omp_task_copy_fn (entry_stmt);
5113 if (t == NULL)
5114 t3 = null_pointer_node;
5115 else
5116 t3 = build_fold_addr_expr_loc (loc, t);
5118 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5119 8, t1, t2, t3,
5120 gimple_omp_task_arg_size (entry_stmt),
5121 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5122 depend);
5124 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5125 false, GSI_CONTINUE_LINKING);
5129 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5130 catch handler and return it. This prevents programs from violating the
5131 structured block semantics with throws. */
5133 static gimple_seq
5134 maybe_catch_exception (gimple_seq body)
5136 gimple g;
5137 tree decl;
5139 if (!flag_exceptions)
5140 return body;
5142 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5143 decl = lang_hooks.eh_protect_cleanup_actions ();
5144 else
5145 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5147 g = gimple_build_eh_must_not_throw (decl);
5148 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5149 GIMPLE_TRY_CATCH);
5151 return gimple_seq_alloc_with_stmt (g);
5154 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5156 static tree
5157 vec2chain (vec<tree, va_gc> *v)
5159 tree chain = NULL_TREE, t;
5160 unsigned ix;
5162 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5164 DECL_CHAIN (t) = chain;
5165 chain = t;
5168 return chain;
5172 /* Remove barriers in REGION->EXIT's block. Note that this is only
5173 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5174 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5175 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5176 removed. */
5178 static void
5179 remove_exit_barrier (struct omp_region *region)
5181 gimple_stmt_iterator gsi;
5182 basic_block exit_bb;
5183 edge_iterator ei;
5184 edge e;
5185 gimple stmt;
5186 int any_addressable_vars = -1;
5188 exit_bb = region->exit;
5190 /* If the parallel region doesn't return, we don't have REGION->EXIT
5191 block at all. */
5192 if (! exit_bb)
5193 return;
5195 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5196 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5197 statements that can appear in between are extremely limited -- no
5198 memory operations at all. Here, we allow nothing at all, so the
5199 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5200 gsi = gsi_last_bb (exit_bb);
5201 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5202 gsi_prev (&gsi);
5203 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5204 return;
5206 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5208 gsi = gsi_last_bb (e->src);
5209 if (gsi_end_p (gsi))
5210 continue;
5211 stmt = gsi_stmt (gsi);
5212 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5213 && !gimple_omp_return_nowait_p (stmt))
5215 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5216 in many cases. If there could be tasks queued, the barrier
5217 might be needed to let the tasks run before some local
5218 variable of the parallel that the task uses as shared
5219 runs out of scope. The task can be spawned either
5220 from within current function (this would be easy to check)
5221 or from some function it calls and gets passed an address
5222 of such a variable. */
5223 if (any_addressable_vars < 0)
5225 gimple parallel_stmt = last_stmt (region->entry);
5226 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5227 tree local_decls, block, decl;
5228 unsigned ix;
5230 any_addressable_vars = 0;
5231 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5232 if (TREE_ADDRESSABLE (decl))
5234 any_addressable_vars = 1;
5235 break;
5237 for (block = gimple_block (stmt);
5238 !any_addressable_vars
5239 && block
5240 && TREE_CODE (block) == BLOCK;
5241 block = BLOCK_SUPERCONTEXT (block))
5243 for (local_decls = BLOCK_VARS (block);
5244 local_decls;
5245 local_decls = DECL_CHAIN (local_decls))
5246 if (TREE_ADDRESSABLE (local_decls))
5248 any_addressable_vars = 1;
5249 break;
5251 if (block == gimple_block (parallel_stmt))
5252 break;
5255 if (!any_addressable_vars)
5256 gimple_omp_return_set_nowait (stmt);
5261 static void
5262 remove_exit_barriers (struct omp_region *region)
5264 if (region->type == GIMPLE_OMP_PARALLEL)
5265 remove_exit_barrier (region);
5267 if (region->inner)
5269 region = region->inner;
5270 remove_exit_barriers (region);
5271 while (region->next)
5273 region = region->next;
5274 remove_exit_barriers (region);
5279 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5280 calls. These can't be declared as const functions, but
5281 within one parallel body they are constant, so they can be
5282 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5283 which are declared const. Similarly for task body, except
5284 that in untied task omp_get_thread_num () can change at any task
5285 scheduling point. */
5287 static void
5288 optimize_omp_library_calls (gimple entry_stmt)
5290 basic_block bb;
5291 gimple_stmt_iterator gsi;
5292 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5293 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5294 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5295 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5296 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5297 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5298 OMP_CLAUSE_UNTIED) != NULL);
5300 FOR_EACH_BB_FN (bb, cfun)
5301 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5303 gimple call = gsi_stmt (gsi);
5304 tree decl;
5306 if (is_gimple_call (call)
5307 && (decl = gimple_call_fndecl (call))
5308 && DECL_EXTERNAL (decl)
5309 && TREE_PUBLIC (decl)
5310 && DECL_INITIAL (decl) == NULL)
5312 tree built_in;
5314 if (DECL_NAME (decl) == thr_num_id)
5316 /* In #pragma omp task untied omp_get_thread_num () can change
5317 during the execution of the task region. */
5318 if (untied_task)
5319 continue;
5320 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5322 else if (DECL_NAME (decl) == num_thr_id)
5323 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5324 else
5325 continue;
5327 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5328 || gimple_call_num_args (call) != 0)
5329 continue;
5331 if (flag_exceptions && !TREE_NOTHROW (decl))
5332 continue;
5334 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5335 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5336 TREE_TYPE (TREE_TYPE (built_in))))
5337 continue;
5339 gimple_call_set_fndecl (call, built_in);
5344 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5345 regimplified. */
5347 static tree
5348 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5350 tree t = *tp;
5352 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5353 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5354 return t;
5356 if (TREE_CODE (t) == ADDR_EXPR)
5357 recompute_tree_invariant_for_addr_expr (t);
5359 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5360 return NULL_TREE;
5363 /* Prepend TO = FROM assignment before *GSI_P. */
5365 static void
5366 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5368 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5369 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5370 true, GSI_SAME_STMT);
5371 gimple stmt = gimple_build_assign (to, from);
5372 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5373 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5374 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5376 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5377 gimple_regimplify_operands (stmt, &gsi);
5381 /* Expand the OpenACC offload directive starting at REGION. */
5383 static void
5384 expand_oacc_offload (struct omp_region *region)
5386 basic_block entry_bb, exit_bb, new_bb;
5387 struct function *child_cfun;
5388 tree child_fn, block, t;
5389 gimple_stmt_iterator gsi;
5390 gimple entry_stmt, stmt;
5391 edge e;
5392 tree (*gimple_omp_child_fn) (const_gimple);
5393 tree (*gimple_omp_data_arg) (const_gimple);
5394 switch (region->type)
5396 case GIMPLE_OACC_KERNELS:
5397 gimple_omp_child_fn = gimple_oacc_kernels_child_fn;
5398 gimple_omp_data_arg = gimple_oacc_kernels_data_arg;
5399 break;
5400 case GIMPLE_OACC_PARALLEL:
5401 gimple_omp_child_fn = gimple_oacc_parallel_child_fn;
5402 gimple_omp_data_arg = gimple_oacc_parallel_data_arg;
5403 break;
5404 default:
5405 gcc_unreachable ();
5408 entry_stmt = last_stmt (region->entry);
5409 child_fn = gimple_omp_child_fn (entry_stmt);
5410 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5412 /* Supported by expand_omp_taskreg, but not here. */
5413 gcc_assert (!child_cfun->cfg);
5414 gcc_assert (!gimple_in_ssa_p (cfun));
5416 entry_bb = region->entry;
5417 exit_bb = region->exit;
5419 /* Preserve indentation of expand_omp_target and expand_omp_taskreg. */
5420 if (1)
5422 unsigned srcidx, dstidx, num;
5424 /* If the parallel region needs data sent from the parent
5425 function, then the very first statement (except possible
5426 tree profile counter updates) of the parallel body
5427 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5428 &.OMP_DATA_O is passed as an argument to the child function,
5429 we need to replace it with the argument as seen by the child
5430 function.
5432 In most cases, this will end up being the identity assignment
5433 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5434 a function call that has been inlined, the original PARM_DECL
5435 .OMP_DATA_I may have been converted into a different local
5436 variable. In which case, we need to keep the assignment. */
5437 if (gimple_omp_data_arg (entry_stmt))
5439 basic_block entry_succ_bb = single_succ (entry_bb);
5440 gimple_stmt_iterator gsi;
5441 tree arg;
5442 gimple parcopy_stmt = NULL;
5443 tree sender = TREE_VEC_ELT (gimple_omp_data_arg (entry_stmt), 0);
5445 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5447 gcc_assert (!gsi_end_p (gsi));
5448 stmt = gsi_stmt (gsi);
5449 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5450 continue;
5452 if (gimple_num_ops (stmt) == 2)
5454 tree arg = gimple_assign_rhs1 (stmt);
5456 /* We're ignore the subcode because we're
5457 effectively doing a STRIP_NOPS. */
5459 if (TREE_CODE (arg) == ADDR_EXPR
5460 && TREE_OPERAND (arg, 0) == sender)
5462 parcopy_stmt = stmt;
5463 break;
5468 gcc_assert (parcopy_stmt != NULL);
5469 arg = DECL_ARGUMENTS (child_fn);
5471 gcc_assert (gimple_assign_lhs (parcopy_stmt) == arg);
5472 gsi_remove (&gsi, true);
5475 /* Declare local variables needed in CHILD_CFUN. */
5476 block = DECL_INITIAL (child_fn);
5477 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5478 /* The gimplifier could record temporaries in the block
5479 rather than in containing function's local_decls chain,
5480 which would mean cgraph missed finalizing them. Do it now. */
5481 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5482 if (TREE_CODE (t) == VAR_DECL
5483 && TREE_STATIC (t)
5484 && !DECL_EXTERNAL (t))
5485 varpool_node::finalize_decl (t);
5486 DECL_SAVED_TREE (child_fn) = NULL;
5487 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5488 gimple_set_body (child_fn, NULL);
5489 TREE_USED (block) = 1;
5491 /* Reset DECL_CONTEXT on function arguments. */
5492 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5493 DECL_CONTEXT (t) = child_fn;
5495 /* Split ENTRY_BB at GIMPLE_OACC_PARALLEL,
5496 so that it can be moved to the child function. */
5497 gsi = gsi_last_bb (entry_bb);
5498 stmt = gsi_stmt (gsi);
5499 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OACC_KERNELS
5500 || gimple_code (stmt) == GIMPLE_OACC_PARALLEL));
5501 gsi_remove (&gsi, true);
5502 e = split_block (entry_bb, stmt);
5503 entry_bb = e->dest;
5504 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5506 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5507 if (exit_bb)
5509 gsi = gsi_last_bb (exit_bb);
5510 gcc_assert (!gsi_end_p (gsi)
5511 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5512 stmt = gimple_build_return (NULL);
5513 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5514 gsi_remove (&gsi, true);
5517 /* Move the region into CHILD_CFUN. */
5519 block = gimple_block (entry_stmt);
5521 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5522 if (exit_bb)
5523 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5524 /* When the expansion process cannot guarantee an up-to-date
5525 loop tree arrange for the child function to fixup loops. */
5526 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5527 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5529 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5530 num = vec_safe_length (child_cfun->local_decls);
5531 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5533 t = (*child_cfun->local_decls)[srcidx];
5534 if (DECL_CONTEXT (t) == cfun->decl)
5535 continue;
5536 if (srcidx != dstidx)
5537 (*child_cfun->local_decls)[dstidx] = t;
5538 dstidx++;
5540 if (dstidx != num)
5541 vec_safe_truncate (child_cfun->local_decls, dstidx);
5543 /* Inform the callgraph about the new function. */
5544 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5545 cgraph_node::add_new_function (child_fn, true);
5547 /* Add the new function to the offload table. */
5548 vec_safe_push (offload_funcs, child_fn);
5550 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5551 fixed in a following pass. */
5552 push_cfun (child_cfun);
5553 cgraph_edge::rebuild_edges ();
5555 /* Some EH regions might become dead, see PR34608. If
5556 pass_cleanup_cfg isn't the first pass to happen with the
5557 new child, these dead EH edges might cause problems.
5558 Clean them up now. */
5559 if (flag_exceptions)
5561 basic_block bb;
5562 bool changed = false;
5564 FOR_EACH_BB_FN (bb, cfun)
5565 changed |= gimple_purge_dead_eh_edges (bb);
5566 if (changed)
5567 cleanup_tree_cfg ();
5569 pop_cfun ();
5572 /* Emit a library call to launch CHILD_FN. */
5573 tree t1, t2, t3, t4,
5574 t_num_gangs, t_num_workers, t_vector_length, t_async,
5575 device, cond, c, clauses;
5576 enum built_in_function start_ix;
5577 location_t clause_loc;
5578 tree (*gimple_omp_clauses) (const_gimple);
5579 switch (region->type)
5581 case GIMPLE_OACC_KERNELS:
5582 gimple_omp_clauses = gimple_oacc_kernels_clauses;
5583 start_ix = BUILT_IN_GOACC_KERNELS;
5584 break;
5585 case GIMPLE_OACC_PARALLEL:
5586 gimple_omp_clauses = gimple_oacc_parallel_clauses;
5587 start_ix = BUILT_IN_GOACC_PARALLEL;
5588 break;
5589 default:
5590 gcc_unreachable ();
5593 clauses = gimple_omp_clauses (entry_stmt);
5595 /* Default values for NUM_GANGS, NUM_WORKERS, and VECTOR_LENGTH. */
5596 t_num_gangs = t_num_workers = t_vector_length
5597 = fold_convert_loc (gimple_location (entry_stmt),
5598 integer_type_node, integer_one_node);
5599 /* TODO: XXX FIX -2. */
5600 t_async = fold_convert_loc (gimple_location (entry_stmt),
5601 integer_type_node, build_int_cst (integer_type_node, -2));
5602 switch (region->type)
5604 case GIMPLE_OACC_PARALLEL:
5605 /* ..., but if present, use the values specified by the respective
5606 clauses, making sure these are of the correct type. */
5607 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
5608 if (c)
5609 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5610 integer_type_node,
5611 OMP_CLAUSE_NUM_GANGS_EXPR (c));
5612 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
5613 if (c)
5614 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5615 integer_type_node,
5616 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
5617 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
5618 if (c)
5619 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5620 integer_type_node,
5621 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
5622 /* FALL THROUGH. */
5623 case GIMPLE_OACC_KERNELS:
5624 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
5625 if (c)
5626 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
5627 integer_type_node,
5628 OMP_CLAUSE_ASYNC_EXPR (c));
5629 break;
5631 default:
5632 break;
5635 /* By default, the value of DEVICE is -1 (let runtime library choose)
5636 and there is no conditional. */
5637 cond = NULL_TREE;
5638 device = build_int_cst (integer_type_node, -1);
5640 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5641 if (c)
5642 cond = OMP_CLAUSE_IF_EXPR (c);
5644 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
5645 gcc_assert (c == NULL);
5646 if (c)
5648 device = OMP_CLAUSE_DEVICE_ID (c);
5649 clause_loc = OMP_CLAUSE_LOCATION (c);
5651 else
5652 clause_loc = gimple_location (entry_stmt);
5654 /* Ensure 'device' is of the correct type. */
5655 device = fold_convert_loc (clause_loc, integer_type_node, device);
5657 /* If we found the clause 'if (cond)', build
5658 (cond ? device : -2). */
5659 if (cond)
5661 cond = gimple_boolify (cond);
5663 basic_block cond_bb, then_bb, else_bb;
5664 edge e;
5665 tree tmp_var;
5667 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
5668 /* Preserve indentation of expand_omp_target. */
5669 if (0)
5671 gsi = gsi_last_bb (new_bb);
5672 gsi_prev (&gsi);
5673 e = split_block (new_bb, gsi_stmt (gsi));
5675 else
5676 e = split_block (new_bb, NULL);
5677 cond_bb = e->src;
5678 new_bb = e->dest;
5679 remove_edge (e);
5681 then_bb = create_empty_bb (cond_bb);
5682 else_bb = create_empty_bb (then_bb);
5683 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
5684 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
5686 stmt = gimple_build_cond_empty (cond);
5687 gsi = gsi_last_bb (cond_bb);
5688 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5690 gsi = gsi_start_bb (then_bb);
5691 stmt = gimple_build_assign (tmp_var, device);
5692 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5694 gsi = gsi_start_bb (else_bb);
5695 stmt = gimple_build_assign (tmp_var,
5696 build_int_cst (integer_type_node, -2));
5697 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5699 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
5700 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
5701 add_bb_to_loop (then_bb, cond_bb->loop_father);
5702 add_bb_to_loop (else_bb, cond_bb->loop_father);
5703 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
5704 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
5706 device = tmp_var;
5709 gsi = gsi_last_bb (new_bb);
5710 t = gimple_omp_data_arg (entry_stmt);
5711 if (t == NULL)
5713 t1 = size_zero_node;
5714 t2 = build_zero_cst (ptr_type_node);
5715 t3 = t2;
5716 t4 = t2;
5718 else
5720 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
5721 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
5722 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
5723 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
5724 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
5727 gimple g;
5728 tree openmp_target = get_offload_symbol_decl ();
5729 tree fnaddr = build_fold_addr_expr (child_fn);
5731 vec<tree> *args;
5732 int idx;
5733 unsigned int argcnt = 12;
5735 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
5736 if (c)
5738 for (t = c; t; t = OMP_CLAUSE_CHAIN (t))
5740 if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_WAIT)
5741 argcnt++;
5745 vec_alloc (args, argcnt);
5746 args->quick_push (device);
5747 args->quick_push (fnaddr);
5748 args->quick_push (build_fold_addr_expr (openmp_target));
5749 args->quick_push (t1);
5750 args->quick_push (t2);
5751 args->quick_push (t3);
5752 args->quick_push (t4);
5753 args->quick_push (t_num_gangs);
5754 args->quick_push (t_num_workers);
5755 args->quick_push (t_vector_length);
5756 args->quick_push (t_async);
5757 idx = args->length ();
5758 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
5759 integer_type_node, integer_minus_one_node));
5760 if (c)
5762 int n = 0;
5764 for (t = c; t; t = OMP_CLAUSE_CHAIN (t))
5766 if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_WAIT)
5768 args->quick_push (fold_convert (integer_type_node,
5769 OMP_CLAUSE_WAIT_EXPR (t)));
5770 n++;
5774 args->ordered_remove (idx);
5775 args->quick_insert (idx, fold_convert_loc (gimple_location (entry_stmt),
5776 integer_type_node,
5777 build_int_cst (integer_type_node, n)));
5780 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
5781 args->release ();
5782 gimple_set_location (g, gimple_location (entry_stmt));
5783 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
5786 /* Expand the OpenMP parallel or task directive starting at REGION. */
5788 static void
5789 expand_omp_taskreg (struct omp_region *region)
5791 basic_block entry_bb, exit_bb, new_bb;
5792 struct function *child_cfun;
5793 tree child_fn, block, t;
5794 gimple_stmt_iterator gsi;
5795 gimple entry_stmt, stmt;
5796 edge e;
5797 vec<tree, va_gc> *ws_args;
5799 entry_stmt = last_stmt (region->entry);
5800 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5801 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5803 entry_bb = region->entry;
5804 exit_bb = region->exit;
5806 bool is_cilk_for
5807 = (flag_cilkplus
5808 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5809 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5810 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5812 if (is_cilk_for)
5813 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5814 and the inner statement contains the name of the built-in function
5815 and grain. */
5816 ws_args = region->inner->ws_args;
5817 else if (is_combined_parallel (region))
5818 ws_args = region->ws_args;
5819 else
5820 ws_args = NULL;
5822 if (child_cfun->cfg)
5824 /* Due to inlining, it may happen that we have already outlined
5825 the region, in which case all we need to do is make the
5826 sub-graph unreachable and emit the parallel call. */
5827 edge entry_succ_e, exit_succ_e;
5829 entry_succ_e = single_succ_edge (entry_bb);
5831 gsi = gsi_last_bb (entry_bb);
5832 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5833 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5834 gsi_remove (&gsi, true);
5836 new_bb = entry_bb;
5837 if (exit_bb)
5839 exit_succ_e = single_succ_edge (exit_bb);
5840 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5842 remove_edge_and_dominated_blocks (entry_succ_e);
5844 else
5846 unsigned srcidx, dstidx, num;
5848 /* If the parallel region needs data sent from the parent
5849 function, then the very first statement (except possible
5850 tree profile counter updates) of the parallel body
5851 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5852 &.OMP_DATA_O is passed as an argument to the child function,
5853 we need to replace it with the argument as seen by the child
5854 function.
5856 In most cases, this will end up being the identity assignment
5857 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5858 a function call that has been inlined, the original PARM_DECL
5859 .OMP_DATA_I may have been converted into a different local
5860 variable. In which case, we need to keep the assignment. */
5861 if (gimple_omp_taskreg_data_arg (entry_stmt))
5863 basic_block entry_succ_bb = single_succ (entry_bb);
5864 tree arg, narg;
5865 gimple parcopy_stmt = NULL;
5867 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5869 gimple stmt;
5871 gcc_assert (!gsi_end_p (gsi));
5872 stmt = gsi_stmt (gsi);
5873 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5874 continue;
5876 if (gimple_num_ops (stmt) == 2)
5878 tree arg = gimple_assign_rhs1 (stmt);
5880 /* We're ignore the subcode because we're
5881 effectively doing a STRIP_NOPS. */
5883 if (TREE_CODE (arg) == ADDR_EXPR
5884 && TREE_OPERAND (arg, 0)
5885 == gimple_omp_taskreg_data_arg (entry_stmt))
5887 parcopy_stmt = stmt;
5888 break;
5893 gcc_assert (parcopy_stmt != NULL);
5894 arg = DECL_ARGUMENTS (child_fn);
5896 if (!gimple_in_ssa_p (cfun))
5898 if (gimple_assign_lhs (parcopy_stmt) == arg)
5899 gsi_remove (&gsi, true);
5900 else
5902 /* ?? Is setting the subcode really necessary ?? */
5903 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5904 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5907 else
5909 /* If we are in ssa form, we must load the value from the default
5910 definition of the argument. That should not be defined now,
5911 since the argument is not used uninitialized. */
5912 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5913 narg = make_ssa_name (arg, gimple_build_nop ());
5914 set_ssa_default_def (cfun, arg, narg);
5915 /* ?? Is setting the subcode really necessary ?? */
5916 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5917 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5918 update_stmt (parcopy_stmt);
5922 /* Declare local variables needed in CHILD_CFUN. */
5923 block = DECL_INITIAL (child_fn);
5924 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5925 /* The gimplifier could record temporaries in parallel/task block
5926 rather than in containing function's local_decls chain,
5927 which would mean cgraph missed finalizing them. Do it now. */
5928 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5929 if (TREE_CODE (t) == VAR_DECL
5930 && TREE_STATIC (t)
5931 && !DECL_EXTERNAL (t))
5932 varpool_node::finalize_decl (t);
5933 DECL_SAVED_TREE (child_fn) = NULL;
5934 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5935 gimple_set_body (child_fn, NULL);
5936 TREE_USED (block) = 1;
5938 /* Reset DECL_CONTEXT on function arguments. */
5939 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5940 DECL_CONTEXT (t) = child_fn;
5942 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5943 so that it can be moved to the child function. */
5944 gsi = gsi_last_bb (entry_bb);
5945 stmt = gsi_stmt (gsi);
5946 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5947 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5948 gsi_remove (&gsi, true);
5949 e = split_block (entry_bb, stmt);
5950 entry_bb = e->dest;
5951 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5953 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5954 if (exit_bb)
5956 gsi = gsi_last_bb (exit_bb);
5957 gcc_assert (!gsi_end_p (gsi)
5958 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5959 stmt = gimple_build_return (NULL);
5960 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5961 gsi_remove (&gsi, true);
5964 /* Move the parallel region into CHILD_CFUN. */
5966 if (gimple_in_ssa_p (cfun))
5968 init_tree_ssa (child_cfun);
5969 init_ssa_operands (child_cfun);
5970 child_cfun->gimple_df->in_ssa_p = true;
5971 block = NULL_TREE;
5973 else
5974 block = gimple_block (entry_stmt);
5976 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5977 if (exit_bb)
5978 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5979 /* When the OMP expansion process cannot guarantee an up-to-date
5980 loop tree arrange for the child function to fixup loops. */
5981 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5982 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5984 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5985 num = vec_safe_length (child_cfun->local_decls);
5986 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5988 t = (*child_cfun->local_decls)[srcidx];
5989 if (DECL_CONTEXT (t) == cfun->decl)
5990 continue;
5991 if (srcidx != dstidx)
5992 (*child_cfun->local_decls)[dstidx] = t;
5993 dstidx++;
5995 if (dstidx != num)
5996 vec_safe_truncate (child_cfun->local_decls, dstidx);
5998 /* Inform the callgraph about the new function. */
5999 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
6000 cgraph_node::add_new_function (child_fn, true);
6002 /* Fix the callgraph edges for child_cfun. Those for cfun will be
6003 fixed in a following pass. */
6004 push_cfun (child_cfun);
6005 if (optimize)
6006 optimize_omp_library_calls (entry_stmt);
6007 cgraph_edge::rebuild_edges ();
6009 /* Some EH regions might become dead, see PR34608. If
6010 pass_cleanup_cfg isn't the first pass to happen with the
6011 new child, these dead EH edges might cause problems.
6012 Clean them up now. */
6013 if (flag_exceptions)
6015 basic_block bb;
6016 bool changed = false;
6018 FOR_EACH_BB_FN (bb, cfun)
6019 changed |= gimple_purge_dead_eh_edges (bb);
6020 if (changed)
6021 cleanup_tree_cfg ();
6023 if (gimple_in_ssa_p (cfun))
6024 update_ssa (TODO_update_ssa);
6025 pop_cfun ();
6028 /* Emit a library call to launch the children threads. */
6029 if (is_cilk_for)
6030 expand_cilk_for_call (new_bb, entry_stmt, ws_args);
6031 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6032 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
6033 else
6034 expand_task_call (new_bb, entry_stmt);
6035 if (gimple_in_ssa_p (cfun))
6036 update_ssa (TODO_update_ssa_only_virtuals);
6040 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
6041 of the combined collapse > 1 loop constructs, generate code like:
6042 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
6043 if (cond3 is <)
6044 adj = STEP3 - 1;
6045 else
6046 adj = STEP3 + 1;
6047 count3 = (adj + N32 - N31) / STEP3;
6048 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
6049 if (cond2 is <)
6050 adj = STEP2 - 1;
6051 else
6052 adj = STEP2 + 1;
6053 count2 = (adj + N22 - N21) / STEP2;
6054 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
6055 if (cond1 is <)
6056 adj = STEP1 - 1;
6057 else
6058 adj = STEP1 + 1;
6059 count1 = (adj + N12 - N11) / STEP1;
6060 count = count1 * count2 * count3;
6061 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
6062 count = 0;
6063 and set ZERO_ITER_BB to that bb. If this isn't the outermost
6064 of the combined loop constructs, just initialize COUNTS array
6065 from the _looptemp_ clauses. */
6067 /* NOTE: It *could* be better to moosh all of the BBs together,
6068 creating one larger BB with all the computation and the unexpected
6069 jump at the end. I.e.
6071 bool zero3, zero2, zero1, zero;
6073 zero3 = N32 c3 N31;
6074 count3 = (N32 - N31) /[cl] STEP3;
6075 zero2 = N22 c2 N21;
6076 count2 = (N22 - N21) /[cl] STEP2;
6077 zero1 = N12 c1 N11;
6078 count1 = (N12 - N11) /[cl] STEP1;
6079 zero = zero3 || zero2 || zero1;
6080 count = count1 * count2 * count3;
6081 if (__builtin_expect(zero, false)) goto zero_iter_bb;
6083 After all, we expect the zero=false, and thus we expect to have to
6084 evaluate all of the comparison expressions, so short-circuiting
6085 oughtn't be a win. Since the condition isn't protecting a
6086 denominator, we're not concerned about divide-by-zero, so we can
6087 fully evaluate count even if a numerator turned out to be wrong.
6089 It seems like putting this all together would create much better
6090 scheduling opportunities, and less pressure on the chip's branch
6091 predictor. */
6093 static void
6094 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
6095 basic_block &entry_bb, tree *counts,
6096 basic_block &zero_iter_bb, int &first_zero_iter,
6097 basic_block &l2_dom_bb)
6099 tree t, type = TREE_TYPE (fd->loop.v);
6100 gimple stmt;
6101 edge e, ne;
6102 int i;
6104 /* Collapsed loops need work for expansion into SSA form. */
6105 gcc_assert (!gimple_in_ssa_p (cfun));
6107 if (gimple_omp_for_combined_into_p (fd->for_stmt)
6108 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
6110 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6111 isn't supposed to be handled, as the inner loop doesn't
6112 use it. */
6113 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6114 OMP_CLAUSE__LOOPTEMP_);
6115 gcc_assert (innerc);
6116 for (i = 0; i < fd->collapse; i++)
6118 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6119 OMP_CLAUSE__LOOPTEMP_);
6120 gcc_assert (innerc);
6121 if (i)
6122 counts[i] = OMP_CLAUSE_DECL (innerc);
6123 else
6124 counts[0] = NULL_TREE;
6126 return;
6129 for (i = 0; i < fd->collapse; i++)
6131 tree itype = TREE_TYPE (fd->loops[i].v);
6133 if (SSA_VAR_P (fd->loop.n2)
6134 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
6135 fold_convert (itype, fd->loops[i].n1),
6136 fold_convert (itype, fd->loops[i].n2)))
6137 == NULL_TREE || !integer_onep (t)))
6139 tree n1, n2;
6140 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
6141 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
6142 true, GSI_SAME_STMT);
6143 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
6144 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
6145 true, GSI_SAME_STMT);
6146 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
6147 NULL_TREE, NULL_TREE);
6148 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
6149 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6150 expand_omp_regimplify_p, NULL, NULL)
6151 || walk_tree (gimple_cond_rhs_ptr (stmt),
6152 expand_omp_regimplify_p, NULL, NULL))
6154 *gsi = gsi_for_stmt (stmt);
6155 gimple_regimplify_operands (stmt, gsi);
6157 e = split_block (entry_bb, stmt);
6158 if (zero_iter_bb == NULL)
6160 first_zero_iter = i;
6161 zero_iter_bb = create_empty_bb (entry_bb);
6162 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
6163 *gsi = gsi_after_labels (zero_iter_bb);
6164 stmt = gimple_build_assign (fd->loop.n2,
6165 build_zero_cst (type));
6166 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
6167 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
6168 entry_bb);
6170 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
6171 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
6172 e->flags = EDGE_TRUE_VALUE;
6173 e->probability = REG_BR_PROB_BASE - ne->probability;
6174 if (l2_dom_bb == NULL)
6175 l2_dom_bb = entry_bb;
6176 entry_bb = e->dest;
6177 *gsi = gsi_last_bb (entry_bb);
6180 if (POINTER_TYPE_P (itype))
6181 itype = signed_type_for (itype);
6182 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
6183 ? -1 : 1));
6184 t = fold_build2 (PLUS_EXPR, itype,
6185 fold_convert (itype, fd->loops[i].step), t);
6186 t = fold_build2 (PLUS_EXPR, itype, t,
6187 fold_convert (itype, fd->loops[i].n2));
6188 t = fold_build2 (MINUS_EXPR, itype, t,
6189 fold_convert (itype, fd->loops[i].n1));
6190 /* ?? We could probably use CEIL_DIV_EXPR instead of
6191 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
6192 generate the same code in the end because generically we
6193 don't know that the values involved must be negative for
6194 GT?? */
6195 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
6196 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6197 fold_build1 (NEGATE_EXPR, itype, t),
6198 fold_build1 (NEGATE_EXPR, itype,
6199 fold_convert (itype,
6200 fd->loops[i].step)));
6201 else
6202 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
6203 fold_convert (itype, fd->loops[i].step));
6204 t = fold_convert (type, t);
6205 if (TREE_CODE (t) == INTEGER_CST)
6206 counts[i] = t;
6207 else
6209 counts[i] = create_tmp_reg (type, ".count");
6210 expand_omp_build_assign (gsi, counts[i], t);
6212 if (SSA_VAR_P (fd->loop.n2))
6214 if (i == 0)
6215 t = counts[0];
6216 else
6217 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
6218 expand_omp_build_assign (gsi, fd->loop.n2, t);
6224 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
6225 T = V;
6226 V3 = N31 + (T % count3) * STEP3;
6227 T = T / count3;
6228 V2 = N21 + (T % count2) * STEP2;
6229 T = T / count2;
6230 V1 = N11 + T * STEP1;
6231 if this loop doesn't have an inner loop construct combined with it.
6232 If it does have an inner loop construct combined with it and the
6233 iteration count isn't known constant, store values from counts array
6234 into its _looptemp_ temporaries instead. */
6236 static void
6237 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
6238 tree *counts, gimple inner_stmt, tree startvar)
6240 int i;
6241 if (gimple_omp_for_combined_p (fd->for_stmt))
6243 /* If fd->loop.n2 is constant, then no propagation of the counts
6244 is needed, they are constant. */
6245 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
6246 return;
6248 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6249 ? gimple_omp_parallel_clauses (inner_stmt)
6250 : gimple_omp_for_clauses (inner_stmt);
6251 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6252 isn't supposed to be handled, as the inner loop doesn't
6253 use it. */
6254 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6255 gcc_assert (innerc);
6256 for (i = 0; i < fd->collapse; i++)
6258 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6259 OMP_CLAUSE__LOOPTEMP_);
6260 gcc_assert (innerc);
6261 if (i)
6263 tree tem = OMP_CLAUSE_DECL (innerc);
6264 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
6265 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
6266 false, GSI_CONTINUE_LINKING);
6267 gimple stmt = gimple_build_assign (tem, t);
6268 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6271 return;
6274 tree type = TREE_TYPE (fd->loop.v);
6275 tree tem = create_tmp_reg (type, ".tem");
6276 gimple stmt = gimple_build_assign (tem, startvar);
6277 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6279 for (i = fd->collapse - 1; i >= 0; i--)
6281 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
6282 itype = vtype;
6283 if (POINTER_TYPE_P (vtype))
6284 itype = signed_type_for (vtype);
6285 if (i != 0)
6286 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
6287 else
6288 t = tem;
6289 t = fold_convert (itype, t);
6290 t = fold_build2 (MULT_EXPR, itype, t,
6291 fold_convert (itype, fd->loops[i].step));
6292 if (POINTER_TYPE_P (vtype))
6293 t = fold_build_pointer_plus (fd->loops[i].n1, t);
6294 else
6295 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
6296 t = force_gimple_operand_gsi (gsi, t,
6297 DECL_P (fd->loops[i].v)
6298 && TREE_ADDRESSABLE (fd->loops[i].v),
6299 NULL_TREE, false,
6300 GSI_CONTINUE_LINKING);
6301 stmt = gimple_build_assign (fd->loops[i].v, t);
6302 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6303 if (i != 0)
6305 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
6306 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
6307 false, GSI_CONTINUE_LINKING);
6308 stmt = gimple_build_assign (tem, t);
6309 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6315 /* Helper function for expand_omp_for_*. Generate code like:
6316 L10:
6317 V3 += STEP3;
6318 if (V3 cond3 N32) goto BODY_BB; else goto L11;
6319 L11:
6320 V3 = N31;
6321 V2 += STEP2;
6322 if (V2 cond2 N22) goto BODY_BB; else goto L12;
6323 L12:
6324 V2 = N21;
6325 V1 += STEP1;
6326 goto BODY_BB; */
6328 static basic_block
6329 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
6330 basic_block body_bb)
6332 basic_block last_bb, bb, collapse_bb = NULL;
6333 int i;
6334 gimple_stmt_iterator gsi;
6335 edge e;
6336 tree t;
6337 gimple stmt;
6339 last_bb = cont_bb;
6340 for (i = fd->collapse - 1; i >= 0; i--)
6342 tree vtype = TREE_TYPE (fd->loops[i].v);
6344 bb = create_empty_bb (last_bb);
6345 add_bb_to_loop (bb, last_bb->loop_father);
6346 gsi = gsi_start_bb (bb);
6348 if (i < fd->collapse - 1)
6350 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
6351 e->probability = REG_BR_PROB_BASE / 8;
6353 t = fd->loops[i + 1].n1;
6354 t = force_gimple_operand_gsi (&gsi, t,
6355 DECL_P (fd->loops[i + 1].v)
6356 && TREE_ADDRESSABLE (fd->loops[i
6357 + 1].v),
6358 NULL_TREE, false,
6359 GSI_CONTINUE_LINKING);
6360 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
6361 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6363 else
6364 collapse_bb = bb;
6366 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
6368 if (POINTER_TYPE_P (vtype))
6369 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
6370 else
6371 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
6372 t = force_gimple_operand_gsi (&gsi, t,
6373 DECL_P (fd->loops[i].v)
6374 && TREE_ADDRESSABLE (fd->loops[i].v),
6375 NULL_TREE, false, GSI_CONTINUE_LINKING);
6376 stmt = gimple_build_assign (fd->loops[i].v, t);
6377 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6379 if (i > 0)
6381 t = fd->loops[i].n2;
6382 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6383 false, GSI_CONTINUE_LINKING);
6384 tree v = fd->loops[i].v;
6385 if (DECL_P (v) && TREE_ADDRESSABLE (v))
6386 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
6387 false, GSI_CONTINUE_LINKING);
6388 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
6389 stmt = gimple_build_cond_empty (t);
6390 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6391 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
6392 e->probability = REG_BR_PROB_BASE * 7 / 8;
6394 else
6395 make_edge (bb, body_bb, EDGE_FALLTHRU);
6396 last_bb = bb;
6399 return collapse_bb;
6403 /* A subroutine of expand_omp_for. Generate code for a parallel
6404 loop with any schedule. Given parameters:
6406 for (V = N1; V cond N2; V += STEP) BODY;
6408 where COND is "<" or ">", we generate pseudocode
6410 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6411 if (more) goto L0; else goto L3;
6413 V = istart0;
6414 iend = iend0;
6416 BODY;
6417 V += STEP;
6418 if (V cond iend) goto L1; else goto L2;
6420 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6423 If this is a combined omp parallel loop, instead of the call to
6424 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6425 If this is gimple_omp_for_combined_p loop, then instead of assigning
6426 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6427 inner GIMPLE_OMP_FOR and V += STEP; and
6428 if (V cond iend) goto L1; else goto L2; are removed.
6430 For collapsed loops, given parameters:
6431 collapse(3)
6432 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6433 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6434 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6435 BODY;
6437 we generate pseudocode
6439 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6440 if (cond3 is <)
6441 adj = STEP3 - 1;
6442 else
6443 adj = STEP3 + 1;
6444 count3 = (adj + N32 - N31) / STEP3;
6445 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6446 if (cond2 is <)
6447 adj = STEP2 - 1;
6448 else
6449 adj = STEP2 + 1;
6450 count2 = (adj + N22 - N21) / STEP2;
6451 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6452 if (cond1 is <)
6453 adj = STEP1 - 1;
6454 else
6455 adj = STEP1 + 1;
6456 count1 = (adj + N12 - N11) / STEP1;
6457 count = count1 * count2 * count3;
6458 goto Z1;
6460 count = 0;
6462 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6463 if (more) goto L0; else goto L3;
6465 V = istart0;
6466 T = V;
6467 V3 = N31 + (T % count3) * STEP3;
6468 T = T / count3;
6469 V2 = N21 + (T % count2) * STEP2;
6470 T = T / count2;
6471 V1 = N11 + T * STEP1;
6472 iend = iend0;
6474 BODY;
6475 V += 1;
6476 if (V < iend) goto L10; else goto L2;
6477 L10:
6478 V3 += STEP3;
6479 if (V3 cond3 N32) goto L1; else goto L11;
6480 L11:
6481 V3 = N31;
6482 V2 += STEP2;
6483 if (V2 cond2 N22) goto L1; else goto L12;
6484 L12:
6485 V2 = N21;
6486 V1 += STEP1;
6487 goto L1;
6489 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6494 static void
6495 expand_omp_for_generic (struct omp_region *region,
6496 struct omp_for_data *fd,
6497 enum built_in_function start_fn,
6498 enum built_in_function next_fn,
6499 gimple inner_stmt)
6501 gcc_assert (gimple_omp_for_kind (fd->for_stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
6503 tree type, istart0, iend0, iend;
6504 tree t, vmain, vback, bias = NULL_TREE;
6505 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6506 basic_block l2_bb = NULL, l3_bb = NULL;
6507 gimple_stmt_iterator gsi;
6508 gimple stmt;
6509 bool in_combined_parallel = is_combined_parallel (region);
6510 bool broken_loop = region->cont == NULL;
6511 edge e, ne;
6512 tree *counts = NULL;
6513 int i;
6515 gcc_assert (!broken_loop || !in_combined_parallel);
6516 gcc_assert (fd->iter_type == long_integer_type_node
6517 || !in_combined_parallel);
6519 type = TREE_TYPE (fd->loop.v);
6520 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6521 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6522 TREE_ADDRESSABLE (istart0) = 1;
6523 TREE_ADDRESSABLE (iend0) = 1;
6525 /* See if we need to bias by LLONG_MIN. */
6526 if (fd->iter_type == long_long_unsigned_type_node
6527 && TREE_CODE (type) == INTEGER_TYPE
6528 && !TYPE_UNSIGNED (type))
6530 tree n1, n2;
6532 if (fd->loop.cond_code == LT_EXPR)
6534 n1 = fd->loop.n1;
6535 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6537 else
6539 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6540 n2 = fd->loop.n1;
6542 if (TREE_CODE (n1) != INTEGER_CST
6543 || TREE_CODE (n2) != INTEGER_CST
6544 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6545 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6548 entry_bb = region->entry;
6549 cont_bb = region->cont;
6550 collapse_bb = NULL;
6551 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6552 gcc_assert (broken_loop
6553 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6554 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6555 l1_bb = single_succ (l0_bb);
6556 if (!broken_loop)
6558 l2_bb = create_empty_bb (cont_bb);
6559 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6560 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6562 else
6563 l2_bb = NULL;
6564 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6565 exit_bb = region->exit;
6567 gsi = gsi_last_bb (entry_bb);
6569 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6570 if (fd->collapse > 1)
6572 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6573 != GF_OMP_FOR_KIND_OACC_LOOP);
6575 int first_zero_iter = -1;
6576 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6578 counts = XALLOCAVEC (tree, fd->collapse);
6579 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6580 zero_iter_bb, first_zero_iter,
6581 l2_dom_bb);
6583 if (zero_iter_bb)
6585 /* Some counts[i] vars might be uninitialized if
6586 some loop has zero iterations. But the body shouldn't
6587 be executed in that case, so just avoid uninit warnings. */
6588 for (i = first_zero_iter; i < fd->collapse; i++)
6589 if (SSA_VAR_P (counts[i]))
6590 TREE_NO_WARNING (counts[i]) = 1;
6591 gsi_prev (&gsi);
6592 e = split_block (entry_bb, gsi_stmt (gsi));
6593 entry_bb = e->dest;
6594 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6595 gsi = gsi_last_bb (entry_bb);
6596 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6597 get_immediate_dominator (CDI_DOMINATORS,
6598 zero_iter_bb));
6601 if (in_combined_parallel)
6603 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6604 != GF_OMP_FOR_KIND_OACC_LOOP);
6606 /* In a combined parallel loop, emit a call to
6607 GOMP_loop_foo_next. */
6608 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6609 build_fold_addr_expr (istart0),
6610 build_fold_addr_expr (iend0));
6612 else
6614 tree t0, t1, t2, t3, t4;
6615 /* If this is not a combined parallel loop, emit a call to
6616 GOMP_loop_foo_start in ENTRY_BB. */
6617 t4 = build_fold_addr_expr (iend0);
6618 t3 = build_fold_addr_expr (istart0);
6619 t2 = fold_convert (fd->iter_type, fd->loop.step);
6620 t1 = fd->loop.n2;
6621 t0 = fd->loop.n1;
6622 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6624 gcc_assert (gimple_omp_for_kind (gsi_stmt (gsi))
6625 != GF_OMP_FOR_KIND_OACC_LOOP);
6627 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6628 OMP_CLAUSE__LOOPTEMP_);
6629 gcc_assert (innerc);
6630 t0 = OMP_CLAUSE_DECL (innerc);
6631 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6632 OMP_CLAUSE__LOOPTEMP_);
6633 gcc_assert (innerc);
6634 t1 = OMP_CLAUSE_DECL (innerc);
6636 if (POINTER_TYPE_P (TREE_TYPE (t0))
6637 && TYPE_PRECISION (TREE_TYPE (t0))
6638 != TYPE_PRECISION (fd->iter_type))
6640 /* Avoid casting pointers to integer of a different size. */
6641 tree itype = signed_type_for (type);
6642 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6643 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6645 else
6647 t1 = fold_convert (fd->iter_type, t1);
6648 t0 = fold_convert (fd->iter_type, t0);
6650 if (bias)
6652 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6653 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6655 if (fd->iter_type == long_integer_type_node)
6657 if (fd->chunk_size)
6659 t = fold_convert (fd->iter_type, fd->chunk_size);
6660 t = build_call_expr (builtin_decl_explicit (start_fn),
6661 6, t0, t1, t2, t, t3, t4);
6663 else
6664 t = build_call_expr (builtin_decl_explicit (start_fn),
6665 5, t0, t1, t2, t3, t4);
6667 else
6669 tree t5;
6670 tree c_bool_type;
6671 tree bfn_decl;
6673 /* The GOMP_loop_ull_*start functions have additional boolean
6674 argument, true for < loops and false for > loops.
6675 In Fortran, the C bool type can be different from
6676 boolean_type_node. */
6677 bfn_decl = builtin_decl_explicit (start_fn);
6678 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6679 t5 = build_int_cst (c_bool_type,
6680 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6681 if (fd->chunk_size)
6683 tree bfn_decl = builtin_decl_explicit (start_fn);
6684 t = fold_convert (fd->iter_type, fd->chunk_size);
6685 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6687 else
6688 t = build_call_expr (builtin_decl_explicit (start_fn),
6689 6, t5, t0, t1, t2, t3, t4);
6692 if (TREE_TYPE (t) != boolean_type_node)
6693 t = fold_build2 (NE_EXPR, boolean_type_node,
6694 t, build_int_cst (TREE_TYPE (t), 0));
6695 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6696 true, GSI_SAME_STMT);
6697 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6699 /* Remove the GIMPLE_OMP_FOR statement. */
6700 gsi_remove (&gsi, true);
6702 /* Iteration setup for sequential loop goes in L0_BB. */
6703 tree startvar = fd->loop.v;
6704 tree endvar = NULL_TREE;
6706 if (gimple_omp_for_combined_p (fd->for_stmt))
6708 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6709 && gimple_omp_for_kind (inner_stmt)
6710 == GF_OMP_FOR_KIND_SIMD);
6711 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6712 OMP_CLAUSE__LOOPTEMP_);
6713 gcc_assert (innerc);
6714 startvar = OMP_CLAUSE_DECL (innerc);
6715 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6716 OMP_CLAUSE__LOOPTEMP_);
6717 gcc_assert (innerc);
6718 endvar = OMP_CLAUSE_DECL (innerc);
6721 gsi = gsi_start_bb (l0_bb);
6722 t = istart0;
6723 if (bias)
6724 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6725 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6726 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6727 t = fold_convert (TREE_TYPE (startvar), t);
6728 t = force_gimple_operand_gsi (&gsi, t,
6729 DECL_P (startvar)
6730 && TREE_ADDRESSABLE (startvar),
6731 NULL_TREE, false, GSI_CONTINUE_LINKING);
6732 stmt = gimple_build_assign (startvar, t);
6733 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6735 t = iend0;
6736 if (bias)
6737 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6738 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6739 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6740 t = fold_convert (TREE_TYPE (startvar), t);
6741 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6742 false, GSI_CONTINUE_LINKING);
6743 if (endvar)
6745 stmt = gimple_build_assign (endvar, iend);
6746 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6747 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6748 stmt = gimple_build_assign (fd->loop.v, iend);
6749 else
6750 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
6751 NULL_TREE);
6752 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6754 if (fd->collapse > 1)
6755 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6757 if (!broken_loop)
6759 /* Code to control the increment and predicate for the sequential
6760 loop goes in the CONT_BB. */
6761 gsi = gsi_last_bb (cont_bb);
6762 stmt = gsi_stmt (gsi);
6763 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6764 vmain = gimple_omp_continue_control_use (stmt);
6765 vback = gimple_omp_continue_control_def (stmt);
6767 if (!gimple_omp_for_combined_p (fd->for_stmt))
6769 if (POINTER_TYPE_P (type))
6770 t = fold_build_pointer_plus (vmain, fd->loop.step);
6771 else
6772 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6773 t = force_gimple_operand_gsi (&gsi, t,
6774 DECL_P (vback)
6775 && TREE_ADDRESSABLE (vback),
6776 NULL_TREE, true, GSI_SAME_STMT);
6777 stmt = gimple_build_assign (vback, t);
6778 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6780 t = build2 (fd->loop.cond_code, boolean_type_node,
6781 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6782 iend);
6783 stmt = gimple_build_cond_empty (t);
6784 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6787 /* Remove GIMPLE_OMP_CONTINUE. */
6788 gsi_remove (&gsi, true);
6790 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6791 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6793 /* Emit code to get the next parallel iteration in L2_BB. */
6794 gsi = gsi_start_bb (l2_bb);
6796 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6797 build_fold_addr_expr (istart0),
6798 build_fold_addr_expr (iend0));
6799 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6800 false, GSI_CONTINUE_LINKING);
6801 if (TREE_TYPE (t) != boolean_type_node)
6802 t = fold_build2 (NE_EXPR, boolean_type_node,
6803 t, build_int_cst (TREE_TYPE (t), 0));
6804 stmt = gimple_build_cond_empty (t);
6805 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6808 /* Add the loop cleanup function. */
6809 gsi = gsi_last_bb (exit_bb);
6810 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6811 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6812 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6813 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6814 else
6815 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6816 stmt = gimple_build_call (t, 0);
6817 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6818 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6819 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6820 gsi_remove (&gsi, true);
6822 /* Connect the new blocks. */
6823 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6824 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6826 if (!broken_loop)
6828 gimple_seq phis;
6830 e = find_edge (cont_bb, l3_bb);
6831 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6833 phis = phi_nodes (l3_bb);
6834 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6836 gimple phi = gsi_stmt (gsi);
6837 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6838 PHI_ARG_DEF_FROM_EDGE (phi, e));
6840 remove_edge (e);
6842 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6843 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6844 e = find_edge (cont_bb, l1_bb);
6845 if (gimple_omp_for_combined_p (fd->for_stmt))
6847 remove_edge (e);
6848 e = NULL;
6850 else if (fd->collapse > 1)
6852 remove_edge (e);
6853 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6855 else
6856 e->flags = EDGE_TRUE_VALUE;
6857 if (e)
6859 e->probability = REG_BR_PROB_BASE * 7 / 8;
6860 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6862 else
6864 e = find_edge (cont_bb, l2_bb);
6865 e->flags = EDGE_FALLTHRU;
6867 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6869 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6870 recompute_dominator (CDI_DOMINATORS, l2_bb));
6871 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6872 recompute_dominator (CDI_DOMINATORS, l3_bb));
6873 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6874 recompute_dominator (CDI_DOMINATORS, l0_bb));
6875 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6876 recompute_dominator (CDI_DOMINATORS, l1_bb));
6878 struct loop *outer_loop = alloc_loop ();
6879 outer_loop->header = l0_bb;
6880 outer_loop->latch = l2_bb;
6881 add_loop (outer_loop, l0_bb->loop_father);
6883 if (!gimple_omp_for_combined_p (fd->for_stmt))
6885 struct loop *loop = alloc_loop ();
6886 loop->header = l1_bb;
6887 /* The loop may have multiple latches. */
6888 add_loop (loop, outer_loop);
6894 /* A subroutine of expand_omp_for. Generate code for a parallel
6895 loop with static schedule and no specified chunk size. Given
6896 parameters:
6898 for (V = N1; V cond N2; V += STEP) BODY;
6900 where COND is "<" or ">", we generate pseudocode
6902 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6903 if (cond is <)
6904 adj = STEP - 1;
6905 else
6906 adj = STEP + 1;
6907 if ((__typeof (V)) -1 > 0 && cond is >)
6908 n = -(adj + N2 - N1) / -STEP;
6909 else
6910 n = (adj + N2 - N1) / STEP;
6911 q = n / nthreads;
6912 tt = n % nthreads;
6913 if (threadid < tt) goto L3; else goto L4;
6915 tt = 0;
6916 q = q + 1;
6918 s0 = q * threadid + tt;
6919 e0 = s0 + q;
6920 V = s0 * STEP + N1;
6921 if (s0 >= e0) goto L2; else goto L0;
6923 e = e0 * STEP + N1;
6925 BODY;
6926 V += STEP;
6927 if (V cond e) goto L1;
6931 static void
6932 expand_omp_for_static_nochunk (struct omp_region *region,
6933 struct omp_for_data *fd,
6934 gimple inner_stmt)
6936 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6937 tree type, itype, vmain, vback;
6938 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6939 basic_block body_bb, cont_bb, collapse_bb = NULL;
6940 basic_block fin_bb;
6941 gimple_stmt_iterator gsi;
6942 gimple stmt;
6943 edge ep;
6944 bool broken_loop = region->cont == NULL;
6945 tree *counts = NULL;
6946 tree n1, n2, step;
6948 gcc_assert ((gimple_omp_for_kind (fd->for_stmt)
6949 != GF_OMP_FOR_KIND_OACC_LOOP)
6950 || !inner_stmt);
6952 itype = type = TREE_TYPE (fd->loop.v);
6953 if (POINTER_TYPE_P (type))
6954 itype = signed_type_for (type);
6956 entry_bb = region->entry;
6957 cont_bb = region->cont;
6958 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6959 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6960 gcc_assert (broken_loop
6961 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6962 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6963 body_bb = single_succ (seq_start_bb);
6964 if (!broken_loop)
6966 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6967 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6969 exit_bb = region->exit;
6971 /* Iteration space partitioning goes in ENTRY_BB. */
6972 gsi = gsi_last_bb (entry_bb);
6973 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6975 if (fd->collapse > 1)
6977 int first_zero_iter = -1;
6978 basic_block l2_dom_bb = NULL;
6980 counts = XALLOCAVEC (tree, fd->collapse);
6981 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6982 fin_bb, first_zero_iter,
6983 l2_dom_bb);
6984 t = NULL_TREE;
6986 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6987 t = integer_one_node;
6988 else
6989 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6990 fold_convert (type, fd->loop.n1),
6991 fold_convert (type, fd->loop.n2));
6992 if (fd->collapse == 1
6993 && TYPE_UNSIGNED (type)
6994 && (t == NULL_TREE || !integer_onep (t)))
6996 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6997 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6998 true, GSI_SAME_STMT);
6999 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7000 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7001 true, GSI_SAME_STMT);
7002 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7003 NULL_TREE, NULL_TREE);
7004 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7005 if (walk_tree (gimple_cond_lhs_ptr (stmt),
7006 expand_omp_regimplify_p, NULL, NULL)
7007 || walk_tree (gimple_cond_rhs_ptr (stmt),
7008 expand_omp_regimplify_p, NULL, NULL))
7010 gsi = gsi_for_stmt (stmt);
7011 gimple_regimplify_operands (stmt, &gsi);
7013 ep = split_block (entry_bb, stmt);
7014 ep->flags = EDGE_TRUE_VALUE;
7015 entry_bb = ep->dest;
7016 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7017 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
7018 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
7019 if (gimple_in_ssa_p (cfun))
7021 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7022 for (gsi = gsi_start_phis (fin_bb);
7023 !gsi_end_p (gsi); gsi_next (&gsi))
7025 gimple phi = gsi_stmt (gsi);
7026 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7027 ep, UNKNOWN_LOCATION);
7030 gsi = gsi_last_bb (entry_bb);
7033 switch (gimple_omp_for_kind (fd->for_stmt))
7035 case GF_OMP_FOR_KIND_FOR:
7036 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7037 nthreads = build_call_expr (nthreads, 0);
7038 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7039 threadid = build_call_expr (threadid, 0);
7040 break;
7041 case GF_OMP_FOR_KIND_DISTRIBUTE:
7042 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7043 nthreads = build_call_expr (nthreads, 0);
7044 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7045 threadid = build_call_expr (threadid, 0);
7046 break;
7047 case GF_OMP_FOR_KIND_OACC_LOOP:
7048 nthreads = integer_one_node;
7049 threadid = integer_zero_node;
7050 break;
7051 default:
7052 gcc_unreachable ();
7054 nthreads = fold_convert (itype, nthreads);
7055 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7056 true, GSI_SAME_STMT);
7057 threadid = fold_convert (itype, threadid);
7058 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7059 true, GSI_SAME_STMT);
7061 n1 = fd->loop.n1;
7062 n2 = fd->loop.n2;
7063 step = fd->loop.step;
7064 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7066 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7067 != GF_OMP_FOR_KIND_OACC_LOOP);
7069 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7070 OMP_CLAUSE__LOOPTEMP_);
7071 gcc_assert (innerc);
7072 n1 = OMP_CLAUSE_DECL (innerc);
7073 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7074 OMP_CLAUSE__LOOPTEMP_);
7075 gcc_assert (innerc);
7076 n2 = OMP_CLAUSE_DECL (innerc);
7078 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7079 true, NULL_TREE, true, GSI_SAME_STMT);
7080 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7081 true, NULL_TREE, true, GSI_SAME_STMT);
7082 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7083 true, NULL_TREE, true, GSI_SAME_STMT);
7085 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7086 t = fold_build2 (PLUS_EXPR, itype, step, t);
7087 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7088 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7089 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7090 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7091 fold_build1 (NEGATE_EXPR, itype, t),
7092 fold_build1 (NEGATE_EXPR, itype, step));
7093 else
7094 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7095 t = fold_convert (itype, t);
7096 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
7098 q = create_tmp_reg (itype, "q");
7099 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
7100 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
7101 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
7103 tt = create_tmp_reg (itype, "tt");
7104 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
7105 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
7106 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
7108 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
7109 stmt = gimple_build_cond_empty (t);
7110 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7112 second_bb = split_block (entry_bb, stmt)->dest;
7113 gsi = gsi_last_bb (second_bb);
7114 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7116 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
7117 GSI_SAME_STMT);
7118 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
7119 build_int_cst (itype, 1));
7120 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7122 third_bb = split_block (second_bb, stmt)->dest;
7123 gsi = gsi_last_bb (third_bb);
7124 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7126 t = build2 (MULT_EXPR, itype, q, threadid);
7127 t = build2 (PLUS_EXPR, itype, t, tt);
7128 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
7130 t = fold_build2 (PLUS_EXPR, itype, s0, q);
7131 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
7133 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
7134 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7136 /* Remove the GIMPLE_OMP_FOR statement. */
7137 gsi_remove (&gsi, true);
7139 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7140 gsi = gsi_start_bb (seq_start_bb);
7142 tree startvar = fd->loop.v;
7143 tree endvar = NULL_TREE;
7145 if (gimple_omp_for_combined_p (fd->for_stmt))
7147 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7148 ? gimple_omp_parallel_clauses (inner_stmt)
7149 : gimple_omp_for_clauses (inner_stmt);
7150 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7151 gcc_assert (innerc);
7152 startvar = OMP_CLAUSE_DECL (innerc);
7153 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7154 OMP_CLAUSE__LOOPTEMP_);
7155 gcc_assert (innerc);
7156 endvar = OMP_CLAUSE_DECL (innerc);
7158 t = fold_convert (itype, s0);
7159 t = fold_build2 (MULT_EXPR, itype, t, step);
7160 if (POINTER_TYPE_P (type))
7161 t = fold_build_pointer_plus (n1, t);
7162 else
7163 t = fold_build2 (PLUS_EXPR, type, t, n1);
7164 t = fold_convert (TREE_TYPE (startvar), t);
7165 t = force_gimple_operand_gsi (&gsi, t,
7166 DECL_P (startvar)
7167 && TREE_ADDRESSABLE (startvar),
7168 NULL_TREE, false, GSI_CONTINUE_LINKING);
7169 stmt = gimple_build_assign (startvar, t);
7170 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7172 t = fold_convert (itype, e0);
7173 t = fold_build2 (MULT_EXPR, itype, t, step);
7174 if (POINTER_TYPE_P (type))
7175 t = fold_build_pointer_plus (n1, t);
7176 else
7177 t = fold_build2 (PLUS_EXPR, type, t, n1);
7178 t = fold_convert (TREE_TYPE (startvar), t);
7179 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7180 false, GSI_CONTINUE_LINKING);
7181 if (endvar)
7183 stmt = gimple_build_assign (endvar, e);
7184 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7185 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7186 stmt = gimple_build_assign (fd->loop.v, e);
7187 else
7188 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
7189 NULL_TREE);
7190 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7192 if (fd->collapse > 1)
7193 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7195 if (!broken_loop)
7197 /* The code controlling the sequential loop replaces the
7198 GIMPLE_OMP_CONTINUE. */
7199 gsi = gsi_last_bb (cont_bb);
7200 stmt = gsi_stmt (gsi);
7201 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7202 vmain = gimple_omp_continue_control_use (stmt);
7203 vback = gimple_omp_continue_control_def (stmt);
7205 if (!gimple_omp_for_combined_p (fd->for_stmt))
7207 if (POINTER_TYPE_P (type))
7208 t = fold_build_pointer_plus (vmain, step);
7209 else
7210 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7211 t = force_gimple_operand_gsi (&gsi, t,
7212 DECL_P (vback)
7213 && TREE_ADDRESSABLE (vback),
7214 NULL_TREE, true, GSI_SAME_STMT);
7215 stmt = gimple_build_assign (vback, t);
7216 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7218 t = build2 (fd->loop.cond_code, boolean_type_node,
7219 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7220 ? t : vback, e);
7221 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7224 /* Remove the GIMPLE_OMP_CONTINUE statement. */
7225 gsi_remove (&gsi, true);
7227 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7228 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7231 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7232 gsi = gsi_last_bb (exit_bb);
7233 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7235 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7236 != GF_OMP_FOR_KIND_OACC_LOOP);
7238 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7239 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7241 gsi_remove (&gsi, true);
7243 /* Connect all the blocks. */
7244 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
7245 ep->probability = REG_BR_PROB_BASE / 4 * 3;
7246 ep = find_edge (entry_bb, second_bb);
7247 ep->flags = EDGE_TRUE_VALUE;
7248 ep->probability = REG_BR_PROB_BASE / 4;
7249 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
7250 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
7252 if (!broken_loop)
7254 ep = find_edge (cont_bb, body_bb);
7255 if (gimple_omp_for_combined_p (fd->for_stmt))
7257 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7258 != GF_OMP_FOR_KIND_OACC_LOOP);
7260 remove_edge (ep);
7261 ep = NULL;
7263 else if (fd->collapse > 1)
7265 remove_edge (ep);
7266 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7268 else
7269 ep->flags = EDGE_TRUE_VALUE;
7270 find_edge (cont_bb, fin_bb)->flags
7271 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7274 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
7275 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
7276 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
7278 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7279 recompute_dominator (CDI_DOMINATORS, body_bb));
7280 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7281 recompute_dominator (CDI_DOMINATORS, fin_bb));
7283 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
7285 struct loop *loop = alloc_loop ();
7286 loop->header = body_bb;
7287 if (collapse_bb == NULL)
7288 loop->latch = cont_bb;
7289 add_loop (loop, body_bb->loop_father);
7294 /* A subroutine of expand_omp_for. Generate code for a parallel
7295 loop with static schedule and a specified chunk size. Given
7296 parameters:
7298 for (V = N1; V cond N2; V += STEP) BODY;
7300 where COND is "<" or ">", we generate pseudocode
7302 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
7303 if (cond is <)
7304 adj = STEP - 1;
7305 else
7306 adj = STEP + 1;
7307 if ((__typeof (V)) -1 > 0 && cond is >)
7308 n = -(adj + N2 - N1) / -STEP;
7309 else
7310 n = (adj + N2 - N1) / STEP;
7311 trip = 0;
7312 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
7313 here so that V is defined
7314 if the loop is not entered
7316 s0 = (trip * nthreads + threadid) * CHUNK;
7317 e0 = min(s0 + CHUNK, n);
7318 if (s0 < n) goto L1; else goto L4;
7320 V = s0 * STEP + N1;
7321 e = e0 * STEP + N1;
7323 BODY;
7324 V += STEP;
7325 if (V cond e) goto L2; else goto L3;
7327 trip += 1;
7328 goto L0;
7332 static void
7333 expand_omp_for_static_chunk (struct omp_region *region,
7334 struct omp_for_data *fd, gimple inner_stmt)
7336 tree n, s0, e0, e, t;
7337 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
7338 tree type, itype, vmain, vback, vextra;
7339 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
7340 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
7341 gimple_stmt_iterator gsi;
7342 gimple stmt;
7343 edge se;
7344 bool broken_loop = region->cont == NULL;
7345 tree *counts = NULL;
7346 tree n1, n2, step;
7348 gcc_assert ((gimple_omp_for_kind (fd->for_stmt)
7349 != GF_OMP_FOR_KIND_OACC_LOOP)
7350 || !inner_stmt);
7352 itype = type = TREE_TYPE (fd->loop.v);
7353 if (POINTER_TYPE_P (type))
7354 itype = signed_type_for (type);
7356 entry_bb = region->entry;
7357 se = split_block (entry_bb, last_stmt (entry_bb));
7358 entry_bb = se->src;
7359 iter_part_bb = se->dest;
7360 cont_bb = region->cont;
7361 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
7362 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
7363 gcc_assert (broken_loop
7364 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
7365 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
7366 body_bb = single_succ (seq_start_bb);
7367 if (!broken_loop)
7369 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
7370 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7371 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
7373 exit_bb = region->exit;
7375 /* Trip and adjustment setup goes in ENTRY_BB. */
7376 gsi = gsi_last_bb (entry_bb);
7377 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7379 if (fd->collapse > 1)
7381 int first_zero_iter = -1;
7382 basic_block l2_dom_bb = NULL;
7384 counts = XALLOCAVEC (tree, fd->collapse);
7385 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7386 fin_bb, first_zero_iter,
7387 l2_dom_bb);
7388 t = NULL_TREE;
7390 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7391 t = integer_one_node;
7392 else
7393 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7394 fold_convert (type, fd->loop.n1),
7395 fold_convert (type, fd->loop.n2));
7396 if (fd->collapse == 1
7397 && TYPE_UNSIGNED (type)
7398 && (t == NULL_TREE || !integer_onep (t)))
7400 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
7401 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
7402 true, GSI_SAME_STMT);
7403 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7404 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7405 true, GSI_SAME_STMT);
7406 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7407 NULL_TREE, NULL_TREE);
7408 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7409 if (walk_tree (gimple_cond_lhs_ptr (stmt),
7410 expand_omp_regimplify_p, NULL, NULL)
7411 || walk_tree (gimple_cond_rhs_ptr (stmt),
7412 expand_omp_regimplify_p, NULL, NULL))
7414 gsi = gsi_for_stmt (stmt);
7415 gimple_regimplify_operands (stmt, &gsi);
7417 se = split_block (entry_bb, stmt);
7418 se->flags = EDGE_TRUE_VALUE;
7419 entry_bb = se->dest;
7420 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7421 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7422 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7423 if (gimple_in_ssa_p (cfun))
7425 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7426 for (gsi = gsi_start_phis (fin_bb);
7427 !gsi_end_p (gsi); gsi_next (&gsi))
7429 gimple phi = gsi_stmt (gsi);
7430 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7431 se, UNKNOWN_LOCATION);
7434 gsi = gsi_last_bb (entry_bb);
7437 switch (gimple_omp_for_kind (fd->for_stmt))
7439 case GF_OMP_FOR_KIND_FOR:
7440 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7441 nthreads = build_call_expr (nthreads, 0);
7442 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7443 threadid = build_call_expr (threadid, 0);
7444 break;
7445 case GF_OMP_FOR_KIND_DISTRIBUTE:
7446 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7447 nthreads = build_call_expr (nthreads, 0);
7448 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7449 threadid = build_call_expr (threadid, 0);
7450 break;
7451 case GF_OMP_FOR_KIND_OACC_LOOP:
7452 nthreads = integer_one_node;
7453 threadid = integer_zero_node;
7454 break;
7455 default:
7456 gcc_unreachable ();
7458 nthreads = fold_convert (itype, nthreads);
7459 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7460 true, GSI_SAME_STMT);
7461 threadid = fold_convert (itype, threadid);
7462 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7463 true, GSI_SAME_STMT);
7465 n1 = fd->loop.n1;
7466 n2 = fd->loop.n2;
7467 step = fd->loop.step;
7468 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7470 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7471 != GF_OMP_FOR_KIND_OACC_LOOP);
7473 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7474 OMP_CLAUSE__LOOPTEMP_);
7475 gcc_assert (innerc);
7476 n1 = OMP_CLAUSE_DECL (innerc);
7477 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7478 OMP_CLAUSE__LOOPTEMP_);
7479 gcc_assert (innerc);
7480 n2 = OMP_CLAUSE_DECL (innerc);
7482 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7483 true, NULL_TREE, true, GSI_SAME_STMT);
7484 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7485 true, NULL_TREE, true, GSI_SAME_STMT);
7486 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7487 true, NULL_TREE, true, GSI_SAME_STMT);
7488 fd->chunk_size
7489 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7490 true, NULL_TREE, true, GSI_SAME_STMT);
7492 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7493 t = fold_build2 (PLUS_EXPR, itype, step, t);
7494 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7495 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7496 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7497 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7498 fold_build1 (NEGATE_EXPR, itype, t),
7499 fold_build1 (NEGATE_EXPR, itype, step));
7500 else
7501 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7502 t = fold_convert (itype, t);
7503 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7504 true, GSI_SAME_STMT);
7506 trip_var = create_tmp_reg (itype, ".trip");
7507 if (gimple_in_ssa_p (cfun))
7509 trip_init = make_ssa_name (trip_var, NULL);
7510 trip_main = make_ssa_name (trip_var, NULL);
7511 trip_back = make_ssa_name (trip_var, NULL);
7513 else
7515 trip_init = trip_var;
7516 trip_main = trip_var;
7517 trip_back = trip_var;
7520 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7521 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7523 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7524 t = fold_build2 (MULT_EXPR, itype, t, step);
7525 if (POINTER_TYPE_P (type))
7526 t = fold_build_pointer_plus (n1, t);
7527 else
7528 t = fold_build2 (PLUS_EXPR, type, t, n1);
7529 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7530 true, GSI_SAME_STMT);
7532 /* Remove the GIMPLE_OMP_FOR. */
7533 gsi_remove (&gsi, true);
7535 /* Iteration space partitioning goes in ITER_PART_BB. */
7536 gsi = gsi_last_bb (iter_part_bb);
7538 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7539 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7540 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7541 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7542 false, GSI_CONTINUE_LINKING);
7544 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7545 t = fold_build2 (MIN_EXPR, itype, t, n);
7546 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7547 false, GSI_CONTINUE_LINKING);
7549 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7550 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7552 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7553 gsi = gsi_start_bb (seq_start_bb);
7555 tree startvar = fd->loop.v;
7556 tree endvar = NULL_TREE;
7558 if (gimple_omp_for_combined_p (fd->for_stmt))
7560 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7561 ? gimple_omp_parallel_clauses (inner_stmt)
7562 : gimple_omp_for_clauses (inner_stmt);
7563 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7564 gcc_assert (innerc);
7565 startvar = OMP_CLAUSE_DECL (innerc);
7566 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7567 OMP_CLAUSE__LOOPTEMP_);
7568 gcc_assert (innerc);
7569 endvar = OMP_CLAUSE_DECL (innerc);
7572 t = fold_convert (itype, s0);
7573 t = fold_build2 (MULT_EXPR, itype, t, step);
7574 if (POINTER_TYPE_P (type))
7575 t = fold_build_pointer_plus (n1, t);
7576 else
7577 t = fold_build2 (PLUS_EXPR, type, t, n1);
7578 t = fold_convert (TREE_TYPE (startvar), t);
7579 t = force_gimple_operand_gsi (&gsi, t,
7580 DECL_P (startvar)
7581 && TREE_ADDRESSABLE (startvar),
7582 NULL_TREE, false, GSI_CONTINUE_LINKING);
7583 stmt = gimple_build_assign (startvar, t);
7584 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7586 t = fold_convert (itype, e0);
7587 t = fold_build2 (MULT_EXPR, itype, t, step);
7588 if (POINTER_TYPE_P (type))
7589 t = fold_build_pointer_plus (n1, t);
7590 else
7591 t = fold_build2 (PLUS_EXPR, type, t, n1);
7592 t = fold_convert (TREE_TYPE (startvar), t);
7593 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7594 false, GSI_CONTINUE_LINKING);
7595 if (endvar)
7597 stmt = gimple_build_assign (endvar, e);
7598 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7599 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7600 stmt = gimple_build_assign (fd->loop.v, e);
7601 else
7602 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
7603 NULL_TREE);
7604 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7606 if (fd->collapse > 1)
7607 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7609 if (!broken_loop)
7611 /* The code controlling the sequential loop goes in CONT_BB,
7612 replacing the GIMPLE_OMP_CONTINUE. */
7613 gsi = gsi_last_bb (cont_bb);
7614 stmt = gsi_stmt (gsi);
7615 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7616 vmain = gimple_omp_continue_control_use (stmt);
7617 vback = gimple_omp_continue_control_def (stmt);
7619 if (!gimple_omp_for_combined_p (fd->for_stmt))
7621 if (POINTER_TYPE_P (type))
7622 t = fold_build_pointer_plus (vmain, step);
7623 else
7624 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7625 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7626 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7627 true, GSI_SAME_STMT);
7628 stmt = gimple_build_assign (vback, t);
7629 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7631 t = build2 (fd->loop.cond_code, boolean_type_node,
7632 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7633 ? t : vback, e);
7634 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7637 /* Remove GIMPLE_OMP_CONTINUE. */
7638 gsi_remove (&gsi, true);
7640 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7641 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7643 /* Trip update code goes into TRIP_UPDATE_BB. */
7644 gsi = gsi_start_bb (trip_update_bb);
7646 t = build_int_cst (itype, 1);
7647 t = build2 (PLUS_EXPR, itype, trip_main, t);
7648 stmt = gimple_build_assign (trip_back, t);
7649 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7652 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7653 gsi = gsi_last_bb (exit_bb);
7654 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7656 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7657 != GF_OMP_FOR_KIND_OACC_LOOP);
7659 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7660 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7662 gsi_remove (&gsi, true);
7664 /* Connect the new blocks. */
7665 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7666 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7668 if (!broken_loop)
7670 se = find_edge (cont_bb, body_bb);
7671 if (gimple_omp_for_combined_p (fd->for_stmt))
7673 gcc_assert (gimple_omp_for_kind (fd->for_stmt)
7674 != GF_OMP_FOR_KIND_OACC_LOOP);
7676 remove_edge (se);
7677 se = NULL;
7679 else if (fd->collapse > 1)
7681 remove_edge (se);
7682 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7684 else
7685 se->flags = EDGE_TRUE_VALUE;
7686 find_edge (cont_bb, trip_update_bb)->flags
7687 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7689 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7692 if (gimple_in_ssa_p (cfun))
7694 gimple_stmt_iterator psi;
7695 gimple phi;
7696 edge re, ene;
7697 edge_var_map *vm;
7698 size_t i;
7700 gcc_assert (fd->collapse == 1 && !broken_loop);
7702 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7703 remove arguments of the phi nodes in fin_bb. We need to create
7704 appropriate phi nodes in iter_part_bb instead. */
7705 se = single_pred_edge (fin_bb);
7706 re = single_succ_edge (trip_update_bb);
7707 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7708 ene = single_succ_edge (entry_bb);
7710 psi = gsi_start_phis (fin_bb);
7711 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7712 gsi_next (&psi), ++i)
7714 gimple nphi;
7715 source_location locus;
7717 phi = gsi_stmt (psi);
7718 t = gimple_phi_result (phi);
7719 gcc_assert (t == redirect_edge_var_map_result (vm));
7720 nphi = create_phi_node (t, iter_part_bb);
7722 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7723 locus = gimple_phi_arg_location_from_edge (phi, se);
7725 /* A special case -- fd->loop.v is not yet computed in
7726 iter_part_bb, we need to use vextra instead. */
7727 if (t == fd->loop.v)
7728 t = vextra;
7729 add_phi_arg (nphi, t, ene, locus);
7730 locus = redirect_edge_var_map_location (vm);
7731 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7733 gcc_assert (!gsi_end_p (psi) && i == head->length ());
7734 redirect_edge_var_map_clear (re);
7735 while (1)
7737 psi = gsi_start_phis (fin_bb);
7738 if (gsi_end_p (psi))
7739 break;
7740 remove_phi_node (&psi, false);
7743 /* Make phi node for trip. */
7744 phi = create_phi_node (trip_main, iter_part_bb);
7745 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7746 UNKNOWN_LOCATION);
7747 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7748 UNKNOWN_LOCATION);
7751 if (!broken_loop)
7752 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7753 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7754 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7755 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7756 recompute_dominator (CDI_DOMINATORS, fin_bb));
7757 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7758 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7759 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7760 recompute_dominator (CDI_DOMINATORS, body_bb));
7762 if (!broken_loop)
7764 struct loop *trip_loop = alloc_loop ();
7765 trip_loop->header = iter_part_bb;
7766 trip_loop->latch = trip_update_bb;
7767 add_loop (trip_loop, iter_part_bb->loop_father);
7769 if (!gimple_omp_for_combined_p (fd->for_stmt))
7771 struct loop *loop = alloc_loop ();
7772 loop->header = body_bb;
7773 if (collapse_bb == NULL)
7774 loop->latch = cont_bb;
7775 add_loop (loop, trip_loop);
7780 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7781 Given parameters:
7782 for (V = N1; V cond N2; V += STEP) BODY;
7784 where COND is "<" or ">" or "!=", we generate pseudocode
7786 for (ind_var = low; ind_var < high; ind_var++)
7788 V = n1 + (ind_var * STEP)
7790 <BODY>
7793 In the above pseudocode, low and high are function parameters of the
7794 child function. In the function below, we are inserting a temp.
7795 variable that will be making a call to two OMP functions that will not be
7796 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7797 with _Cilk_for). These functions are replaced with low and high
7798 by the function that handles taskreg. */
7801 static void
7802 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7804 bool broken_loop = region->cont == NULL;
7805 basic_block entry_bb = region->entry;
7806 basic_block cont_bb = region->cont;
7808 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7809 gcc_assert (broken_loop
7810 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7811 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7812 basic_block l1_bb, l2_bb;
7814 if (!broken_loop)
7816 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7817 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7818 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7819 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7821 else
7823 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7824 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7825 l2_bb = single_succ (l1_bb);
7827 basic_block exit_bb = region->exit;
7828 basic_block l2_dom_bb = NULL;
7830 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7832 /* Below statements until the "tree high_val = ..." are pseudo statements
7833 used to pass information to be used by expand_omp_taskreg.
7834 low_val and high_val will be replaced by the __low and __high
7835 parameter from the child function.
7837 The call_exprs part is a place-holder, it is mainly used
7838 to distinctly identify to the top-level part that this is
7839 where we should put low and high (reasoning given in header
7840 comment). */
7842 tree child_fndecl
7843 = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
7844 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7845 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7847 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7848 high_val = t;
7849 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7850 low_val = t;
7852 gcc_assert (low_val && high_val);
7854 tree type = TREE_TYPE (low_val);
7855 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7856 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7858 /* Not needed in SSA form right now. */
7859 gcc_assert (!gimple_in_ssa_p (cfun));
7860 if (l2_dom_bb == NULL)
7861 l2_dom_bb = l1_bb;
7863 tree n1 = low_val;
7864 tree n2 = high_val;
7866 gimple stmt = gimple_build_assign (ind_var, n1);
7868 /* Replace the GIMPLE_OMP_FOR statement. */
7869 gsi_replace (&gsi, stmt, true);
7871 if (!broken_loop)
7873 /* Code to control the increment goes in the CONT_BB. */
7874 gsi = gsi_last_bb (cont_bb);
7875 stmt = gsi_stmt (gsi);
7876 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7877 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
7878 build_one_cst (type));
7880 /* Replace GIMPLE_OMP_CONTINUE. */
7881 gsi_replace (&gsi, stmt, true);
7884 /* Emit the condition in L1_BB. */
7885 gsi = gsi_after_labels (l1_bb);
7886 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7887 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7888 fd->loop.step);
7889 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7890 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7891 fd->loop.n1, fold_convert (sizetype, t));
7892 else
7893 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7894 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7895 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7896 expand_omp_build_assign (&gsi, fd->loop.v, t);
7898 /* The condition is always '<' since the runtime will fill in the low
7899 and high values. */
7900 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7901 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7903 /* Remove GIMPLE_OMP_RETURN. */
7904 gsi = gsi_last_bb (exit_bb);
7905 gsi_remove (&gsi, true);
7907 /* Connect the new blocks. */
7908 remove_edge (FALLTHRU_EDGE (entry_bb));
7910 edge e, ne;
7911 if (!broken_loop)
7913 remove_edge (BRANCH_EDGE (entry_bb));
7914 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7916 e = BRANCH_EDGE (l1_bb);
7917 ne = FALLTHRU_EDGE (l1_bb);
7918 e->flags = EDGE_TRUE_VALUE;
7920 else
7922 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7924 ne = single_succ_edge (l1_bb);
7925 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7928 ne->flags = EDGE_FALSE_VALUE;
7929 e->probability = REG_BR_PROB_BASE * 7 / 8;
7930 ne->probability = REG_BR_PROB_BASE / 8;
7932 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7933 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7934 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7936 if (!broken_loop)
7938 struct loop *loop = alloc_loop ();
7939 loop->header = l1_bb;
7940 loop->latch = cont_bb;
7941 add_loop (loop, l1_bb->loop_father);
7942 loop->safelen = INT_MAX;
7945 /* Pick the correct library function based on the precision of the
7946 induction variable type. */
7947 tree lib_fun = NULL_TREE;
7948 if (TYPE_PRECISION (type) == 32)
7949 lib_fun = cilk_for_32_fndecl;
7950 else if (TYPE_PRECISION (type) == 64)
7951 lib_fun = cilk_for_64_fndecl;
7952 else
7953 gcc_unreachable ();
7955 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7957 /* WS_ARGS contains the library function flavor to call:
7958 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7959 user-defined grain value. If the user does not define one, then zero
7960 is passed in by the parser. */
7961 vec_alloc (region->ws_args, 2);
7962 region->ws_args->quick_push (lib_fun);
7963 region->ws_args->quick_push (fd->chunk_size);
7966 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7967 loop. Given parameters:
7969 for (V = N1; V cond N2; V += STEP) BODY;
7971 where COND is "<" or ">", we generate pseudocode
7973 V = N1;
7974 goto L1;
7976 BODY;
7977 V += STEP;
7979 if (V cond N2) goto L0; else goto L2;
7982 For collapsed loops, given parameters:
7983 collapse(3)
7984 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7985 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7986 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7987 BODY;
7989 we generate pseudocode
7991 if (cond3 is <)
7992 adj = STEP3 - 1;
7993 else
7994 adj = STEP3 + 1;
7995 count3 = (adj + N32 - N31) / STEP3;
7996 if (cond2 is <)
7997 adj = STEP2 - 1;
7998 else
7999 adj = STEP2 + 1;
8000 count2 = (adj + N22 - N21) / STEP2;
8001 if (cond1 is <)
8002 adj = STEP1 - 1;
8003 else
8004 adj = STEP1 + 1;
8005 count1 = (adj + N12 - N11) / STEP1;
8006 count = count1 * count2 * count3;
8007 V = 0;
8008 V1 = N11;
8009 V2 = N21;
8010 V3 = N31;
8011 goto L1;
8013 BODY;
8014 V += 1;
8015 V3 += STEP3;
8016 V2 += (V3 cond3 N32) ? 0 : STEP2;
8017 V3 = (V3 cond3 N32) ? V3 : N31;
8018 V1 += (V2 cond2 N22) ? 0 : STEP1;
8019 V2 = (V2 cond2 N22) ? V2 : N21;
8021 if (V < count) goto L0; else goto L2;
8026 static void
8027 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
8029 tree type, t;
8030 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
8031 gimple_stmt_iterator gsi;
8032 gimple stmt;
8033 bool broken_loop = region->cont == NULL;
8034 edge e, ne;
8035 tree *counts = NULL;
8036 int i;
8037 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8038 OMP_CLAUSE_SAFELEN);
8039 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8040 OMP_CLAUSE__SIMDUID_);
8041 tree n1, n2;
8043 type = TREE_TYPE (fd->loop.v);
8044 entry_bb = region->entry;
8045 cont_bb = region->cont;
8046 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8047 gcc_assert (broken_loop
8048 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8049 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
8050 if (!broken_loop)
8052 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
8053 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8054 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
8055 l2_bb = BRANCH_EDGE (entry_bb)->dest;
8057 else
8059 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
8060 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
8061 l2_bb = single_succ (l1_bb);
8063 exit_bb = region->exit;
8064 l2_dom_bb = NULL;
8066 gsi = gsi_last_bb (entry_bb);
8068 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8069 /* Not needed in SSA form right now. */
8070 gcc_assert (!gimple_in_ssa_p (cfun));
8071 if (fd->collapse > 1)
8073 int first_zero_iter = -1;
8074 basic_block zero_iter_bb = l2_bb;
8076 counts = XALLOCAVEC (tree, fd->collapse);
8077 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8078 zero_iter_bb, first_zero_iter,
8079 l2_dom_bb);
8081 if (l2_dom_bb == NULL)
8082 l2_dom_bb = l1_bb;
8084 n1 = fd->loop.n1;
8085 n2 = fd->loop.n2;
8086 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8088 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8089 OMP_CLAUSE__LOOPTEMP_);
8090 gcc_assert (innerc);
8091 n1 = OMP_CLAUSE_DECL (innerc);
8092 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8093 OMP_CLAUSE__LOOPTEMP_);
8094 gcc_assert (innerc);
8095 n2 = OMP_CLAUSE_DECL (innerc);
8096 expand_omp_build_assign (&gsi, fd->loop.v,
8097 fold_convert (type, n1));
8098 if (fd->collapse > 1)
8100 gsi_prev (&gsi);
8101 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
8102 gsi_next (&gsi);
8105 else
8107 expand_omp_build_assign (&gsi, fd->loop.v,
8108 fold_convert (type, fd->loop.n1));
8109 if (fd->collapse > 1)
8110 for (i = 0; i < fd->collapse; i++)
8112 tree itype = TREE_TYPE (fd->loops[i].v);
8113 if (POINTER_TYPE_P (itype))
8114 itype = signed_type_for (itype);
8115 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
8116 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8120 /* Remove the GIMPLE_OMP_FOR statement. */
8121 gsi_remove (&gsi, true);
8123 if (!broken_loop)
8125 /* Code to control the increment goes in the CONT_BB. */
8126 gsi = gsi_last_bb (cont_bb);
8127 stmt = gsi_stmt (gsi);
8128 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
8130 if (POINTER_TYPE_P (type))
8131 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
8132 else
8133 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
8134 expand_omp_build_assign (&gsi, fd->loop.v, t);
8136 if (fd->collapse > 1)
8138 i = fd->collapse - 1;
8139 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8141 t = fold_convert (sizetype, fd->loops[i].step);
8142 t = fold_build_pointer_plus (fd->loops[i].v, t);
8144 else
8146 t = fold_convert (TREE_TYPE (fd->loops[i].v),
8147 fd->loops[i].step);
8148 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8149 fd->loops[i].v, t);
8151 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8153 for (i = fd->collapse - 1; i > 0; i--)
8155 tree itype = TREE_TYPE (fd->loops[i].v);
8156 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
8157 if (POINTER_TYPE_P (itype2))
8158 itype2 = signed_type_for (itype2);
8159 t = build3 (COND_EXPR, itype2,
8160 build2 (fd->loops[i].cond_code, boolean_type_node,
8161 fd->loops[i].v,
8162 fold_convert (itype, fd->loops[i].n2)),
8163 build_int_cst (itype2, 0),
8164 fold_convert (itype2, fd->loops[i - 1].step));
8165 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
8166 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
8167 else
8168 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
8169 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
8171 t = build3 (COND_EXPR, itype,
8172 build2 (fd->loops[i].cond_code, boolean_type_node,
8173 fd->loops[i].v,
8174 fold_convert (itype, fd->loops[i].n2)),
8175 fd->loops[i].v,
8176 fold_convert (itype, fd->loops[i].n1));
8177 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8181 /* Remove GIMPLE_OMP_CONTINUE. */
8182 gsi_remove (&gsi, true);
8185 /* Emit the condition in L1_BB. */
8186 gsi = gsi_start_bb (l1_bb);
8188 t = fold_convert (type, n2);
8189 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8190 false, GSI_CONTINUE_LINKING);
8191 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
8192 stmt = gimple_build_cond_empty (t);
8193 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8194 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
8195 NULL, NULL)
8196 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
8197 NULL, NULL))
8199 gsi = gsi_for_stmt (stmt);
8200 gimple_regimplify_operands (stmt, &gsi);
8203 /* Remove GIMPLE_OMP_RETURN. */
8204 gsi = gsi_last_bb (exit_bb);
8205 gsi_remove (&gsi, true);
8207 /* Connect the new blocks. */
8208 remove_edge (FALLTHRU_EDGE (entry_bb));
8210 if (!broken_loop)
8212 remove_edge (BRANCH_EDGE (entry_bb));
8213 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
8215 e = BRANCH_EDGE (l1_bb);
8216 ne = FALLTHRU_EDGE (l1_bb);
8217 e->flags = EDGE_TRUE_VALUE;
8219 else
8221 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8223 ne = single_succ_edge (l1_bb);
8224 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
8227 ne->flags = EDGE_FALSE_VALUE;
8228 e->probability = REG_BR_PROB_BASE * 7 / 8;
8229 ne->probability = REG_BR_PROB_BASE / 8;
8231 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
8232 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
8233 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
8235 if (!broken_loop)
8237 struct loop *loop = alloc_loop ();
8238 loop->header = l1_bb;
8239 loop->latch = cont_bb;
8240 add_loop (loop, l1_bb->loop_father);
8241 if (safelen == NULL_TREE)
8242 loop->safelen = INT_MAX;
8243 else
8245 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
8246 if (TREE_CODE (safelen) != INTEGER_CST)
8247 loop->safelen = 0;
8248 else if (!tree_fits_uhwi_p (safelen)
8249 || tree_to_uhwi (safelen) > INT_MAX)
8250 loop->safelen = INT_MAX;
8251 else
8252 loop->safelen = tree_to_uhwi (safelen);
8253 if (loop->safelen == 1)
8254 loop->safelen = 0;
8256 if (simduid)
8258 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
8259 cfun->has_simduid_loops = true;
8261 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
8262 the loop. */
8263 if ((flag_tree_loop_vectorize
8264 || (!global_options_set.x_flag_tree_loop_vectorize
8265 && !global_options_set.x_flag_tree_vectorize))
8266 && flag_tree_loop_optimize
8267 && loop->safelen > 1)
8269 loop->force_vectorize = true;
8270 cfun->has_force_vectorize_loops = true;
8276 /* Expand the OpenMP loop defined by REGION. */
8278 static void
8279 expand_omp_for (struct omp_region *region, gimple inner_stmt)
8281 struct omp_for_data fd;
8282 struct omp_for_data_loop *loops;
8284 loops
8285 = (struct omp_for_data_loop *)
8286 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
8287 * sizeof (struct omp_for_data_loop));
8288 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
8289 region->sched_kind = fd.sched_kind;
8291 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
8292 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8293 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8294 if (region->cont)
8296 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
8297 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8298 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8300 else
8301 /* If there isn't a continue then this is a degerate case where
8302 the introduction of abnormal edges during lowering will prevent
8303 original loops from being detected. Fix that up. */
8304 loops_state_set (LOOPS_NEED_FIXUP);
8306 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
8307 expand_omp_simd (region, &fd);
8308 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
8309 expand_cilk_for (region, &fd);
8310 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
8311 && !fd.have_ordered)
8313 if (fd.chunk_size == NULL)
8314 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
8315 else
8316 expand_omp_for_static_chunk (region, &fd, inner_stmt);
8318 else
8320 int fn_index, start_ix, next_ix;
8322 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
8323 == GF_OMP_FOR_KIND_FOR);
8324 if (fd.chunk_size == NULL
8325 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
8326 fd.chunk_size = integer_zero_node;
8327 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
8328 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
8329 ? 3 : fd.sched_kind;
8330 fn_index += fd.have_ordered * 4;
8331 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
8332 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
8333 if (fd.iter_type == long_long_unsigned_type_node)
8335 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
8336 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
8337 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
8338 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
8340 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
8341 (enum built_in_function) next_ix, inner_stmt);
8344 if (gimple_in_ssa_p (cfun))
8345 update_ssa (TODO_update_ssa_only_virtuals);
8349 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8351 v = GOMP_sections_start (n);
8353 switch (v)
8355 case 0:
8356 goto L2;
8357 case 1:
8358 section 1;
8359 goto L1;
8360 case 2:
8362 case n:
8364 default:
8365 abort ();
8368 v = GOMP_sections_next ();
8369 goto L0;
8371 reduction;
8373 If this is a combined parallel sections, replace the call to
8374 GOMP_sections_start with call to GOMP_sections_next. */
8376 static void
8377 expand_omp_sections (struct omp_region *region)
8379 tree t, u, vin = NULL, vmain, vnext, l2;
8380 unsigned len;
8381 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8382 gimple_stmt_iterator si, switch_si;
8383 gimple sections_stmt, stmt, cont;
8384 edge_iterator ei;
8385 edge e;
8386 struct omp_region *inner;
8387 unsigned i, casei;
8388 bool exit_reachable = region->cont != NULL;
8390 gcc_assert (region->exit != NULL);
8391 entry_bb = region->entry;
8392 l0_bb = single_succ (entry_bb);
8393 l1_bb = region->cont;
8394 l2_bb = region->exit;
8395 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8396 l2 = gimple_block_label (l2_bb);
8397 else
8399 /* This can happen if there are reductions. */
8400 len = EDGE_COUNT (l0_bb->succs);
8401 gcc_assert (len > 0);
8402 e = EDGE_SUCC (l0_bb, len - 1);
8403 si = gsi_last_bb (e->dest);
8404 l2 = NULL_TREE;
8405 if (gsi_end_p (si)
8406 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8407 l2 = gimple_block_label (e->dest);
8408 else
8409 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8411 si = gsi_last_bb (e->dest);
8412 if (gsi_end_p (si)
8413 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8415 l2 = gimple_block_label (e->dest);
8416 break;
8420 if (exit_reachable)
8421 default_bb = create_empty_bb (l1_bb->prev_bb);
8422 else
8423 default_bb = create_empty_bb (l0_bb);
8425 /* We will build a switch() with enough cases for all the
8426 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8427 and a default case to abort if something goes wrong. */
8428 len = EDGE_COUNT (l0_bb->succs);
8430 /* Use vec::quick_push on label_vec throughout, since we know the size
8431 in advance. */
8432 auto_vec<tree> label_vec (len);
8434 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8435 GIMPLE_OMP_SECTIONS statement. */
8436 si = gsi_last_bb (entry_bb);
8437 sections_stmt = gsi_stmt (si);
8438 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8439 vin = gimple_omp_sections_control (sections_stmt);
8440 if (!is_combined_parallel (region))
8442 /* If we are not inside a combined parallel+sections region,
8443 call GOMP_sections_start. */
8444 t = build_int_cst (unsigned_type_node, len - 1);
8445 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8446 stmt = gimple_build_call (u, 1, t);
8448 else
8450 /* Otherwise, call GOMP_sections_next. */
8451 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8452 stmt = gimple_build_call (u, 0);
8454 gimple_call_set_lhs (stmt, vin);
8455 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8456 gsi_remove (&si, true);
8458 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8459 L0_BB. */
8460 switch_si = gsi_last_bb (l0_bb);
8461 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8462 if (exit_reachable)
8464 cont = last_stmt (l1_bb);
8465 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8466 vmain = gimple_omp_continue_control_use (cont);
8467 vnext = gimple_omp_continue_control_def (cont);
8469 else
8471 vmain = vin;
8472 vnext = NULL_TREE;
8475 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8476 label_vec.quick_push (t);
8477 i = 1;
8479 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8480 for (inner = region->inner, casei = 1;
8481 inner;
8482 inner = inner->next, i++, casei++)
8484 basic_block s_entry_bb, s_exit_bb;
8486 /* Skip optional reduction region. */
8487 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8489 --i;
8490 --casei;
8491 continue;
8494 s_entry_bb = inner->entry;
8495 s_exit_bb = inner->exit;
8497 t = gimple_block_label (s_entry_bb);
8498 u = build_int_cst (unsigned_type_node, casei);
8499 u = build_case_label (u, NULL, t);
8500 label_vec.quick_push (u);
8502 si = gsi_last_bb (s_entry_bb);
8503 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8504 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8505 gsi_remove (&si, true);
8506 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8508 if (s_exit_bb == NULL)
8509 continue;
8511 si = gsi_last_bb (s_exit_bb);
8512 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8513 gsi_remove (&si, true);
8515 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8518 /* Error handling code goes in DEFAULT_BB. */
8519 t = gimple_block_label (default_bb);
8520 u = build_case_label (NULL, NULL, t);
8521 make_edge (l0_bb, default_bb, 0);
8522 add_bb_to_loop (default_bb, current_loops->tree_root);
8524 stmt = gimple_build_switch (vmain, u, label_vec);
8525 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8526 gsi_remove (&switch_si, true);
8528 si = gsi_start_bb (default_bb);
8529 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8530 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8532 if (exit_reachable)
8534 tree bfn_decl;
8536 /* Code to get the next section goes in L1_BB. */
8537 si = gsi_last_bb (l1_bb);
8538 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8540 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8541 stmt = gimple_build_call (bfn_decl, 0);
8542 gimple_call_set_lhs (stmt, vnext);
8543 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8544 gsi_remove (&si, true);
8546 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8549 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8550 si = gsi_last_bb (l2_bb);
8551 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8552 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8553 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8554 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8555 else
8556 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8557 stmt = gimple_build_call (t, 0);
8558 if (gimple_omp_return_lhs (gsi_stmt (si)))
8559 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8560 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8561 gsi_remove (&si, true);
8563 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8567 /* Expand code for an OpenMP single directive. We've already expanded
8568 much of the code, here we simply place the GOMP_barrier call. */
8570 static void
8571 expand_omp_single (struct omp_region *region)
8573 basic_block entry_bb, exit_bb;
8574 gimple_stmt_iterator si;
8576 entry_bb = region->entry;
8577 exit_bb = region->exit;
8579 si = gsi_last_bb (entry_bb);
8580 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8581 gsi_remove (&si, true);
8582 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8584 si = gsi_last_bb (exit_bb);
8585 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8587 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8588 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8590 gsi_remove (&si, true);
8591 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8595 /* Generic expansion for OpenMP synchronization directives: master,
8596 ordered and critical. All we need to do here is remove the entry
8597 and exit markers for REGION. */
8599 static void
8600 expand_omp_synch (struct omp_region *region)
8602 basic_block entry_bb, exit_bb;
8603 gimple_stmt_iterator si;
8605 entry_bb = region->entry;
8606 exit_bb = region->exit;
8608 si = gsi_last_bb (entry_bb);
8609 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8610 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8611 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8612 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8613 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8614 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8615 gsi_remove (&si, true);
8616 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8618 if (exit_bb)
8620 si = gsi_last_bb (exit_bb);
8621 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8622 gsi_remove (&si, true);
8623 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8627 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8628 operation as a normal volatile load. */
8630 static bool
8631 expand_omp_atomic_load (basic_block load_bb, tree addr,
8632 tree loaded_val, int index)
8634 enum built_in_function tmpbase;
8635 gimple_stmt_iterator gsi;
8636 basic_block store_bb;
8637 location_t loc;
8638 gimple stmt;
8639 tree decl, call, type, itype;
8641 gsi = gsi_last_bb (load_bb);
8642 stmt = gsi_stmt (gsi);
8643 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8644 loc = gimple_location (stmt);
8646 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8647 is smaller than word size, then expand_atomic_load assumes that the load
8648 is atomic. We could avoid the builtin entirely in this case. */
8650 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8651 decl = builtin_decl_explicit (tmpbase);
8652 if (decl == NULL_TREE)
8653 return false;
8655 type = TREE_TYPE (loaded_val);
8656 itype = TREE_TYPE (TREE_TYPE (decl));
8658 call = build_call_expr_loc (loc, decl, 2, addr,
8659 build_int_cst (NULL,
8660 gimple_omp_atomic_seq_cst_p (stmt)
8661 ? MEMMODEL_SEQ_CST
8662 : MEMMODEL_RELAXED));
8663 if (!useless_type_conversion_p (type, itype))
8664 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8665 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8667 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8668 gsi_remove (&gsi, true);
8670 store_bb = single_succ (load_bb);
8671 gsi = gsi_last_bb (store_bb);
8672 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8673 gsi_remove (&gsi, true);
8675 if (gimple_in_ssa_p (cfun))
8676 update_ssa (TODO_update_ssa_no_phi);
8678 return true;
8681 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8682 operation as a normal volatile store. */
8684 static bool
8685 expand_omp_atomic_store (basic_block load_bb, tree addr,
8686 tree loaded_val, tree stored_val, int index)
8688 enum built_in_function tmpbase;
8689 gimple_stmt_iterator gsi;
8690 basic_block store_bb = single_succ (load_bb);
8691 location_t loc;
8692 gimple stmt;
8693 tree decl, call, type, itype;
8694 machine_mode imode;
8695 bool exchange;
8697 gsi = gsi_last_bb (load_bb);
8698 stmt = gsi_stmt (gsi);
8699 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8701 /* If the load value is needed, then this isn't a store but an exchange. */
8702 exchange = gimple_omp_atomic_need_value_p (stmt);
8704 gsi = gsi_last_bb (store_bb);
8705 stmt = gsi_stmt (gsi);
8706 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8707 loc = gimple_location (stmt);
8709 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8710 is smaller than word size, then expand_atomic_store assumes that the store
8711 is atomic. We could avoid the builtin entirely in this case. */
8713 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8714 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8715 decl = builtin_decl_explicit (tmpbase);
8716 if (decl == NULL_TREE)
8717 return false;
8719 type = TREE_TYPE (stored_val);
8721 /* Dig out the type of the function's second argument. */
8722 itype = TREE_TYPE (decl);
8723 itype = TYPE_ARG_TYPES (itype);
8724 itype = TREE_CHAIN (itype);
8725 itype = TREE_VALUE (itype);
8726 imode = TYPE_MODE (itype);
8728 if (exchange && !can_atomic_exchange_p (imode, true))
8729 return false;
8731 if (!useless_type_conversion_p (itype, type))
8732 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8733 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8734 build_int_cst (NULL,
8735 gimple_omp_atomic_seq_cst_p (stmt)
8736 ? MEMMODEL_SEQ_CST
8737 : MEMMODEL_RELAXED));
8738 if (exchange)
8740 if (!useless_type_conversion_p (type, itype))
8741 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8742 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8745 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8746 gsi_remove (&gsi, true);
8748 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8749 gsi = gsi_last_bb (load_bb);
8750 gsi_remove (&gsi, true);
8752 if (gimple_in_ssa_p (cfun))
8753 update_ssa (TODO_update_ssa_no_phi);
8755 return true;
8758 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8759 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8760 size of the data type, and thus usable to find the index of the builtin
8761 decl. Returns false if the expression is not of the proper form. */
8763 static bool
8764 expand_omp_atomic_fetch_op (basic_block load_bb,
8765 tree addr, tree loaded_val,
8766 tree stored_val, int index)
8768 enum built_in_function oldbase, newbase, tmpbase;
8769 tree decl, itype, call;
8770 tree lhs, rhs;
8771 basic_block store_bb = single_succ (load_bb);
8772 gimple_stmt_iterator gsi;
8773 gimple stmt;
8774 location_t loc;
8775 enum tree_code code;
8776 bool need_old, need_new;
8777 machine_mode imode;
8778 bool seq_cst;
8780 /* We expect to find the following sequences:
8782 load_bb:
8783 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8785 store_bb:
8786 val = tmp OP something; (or: something OP tmp)
8787 GIMPLE_OMP_STORE (val)
8789 ???FIXME: Allow a more flexible sequence.
8790 Perhaps use data flow to pick the statements.
8794 gsi = gsi_after_labels (store_bb);
8795 stmt = gsi_stmt (gsi);
8796 loc = gimple_location (stmt);
8797 if (!is_gimple_assign (stmt))
8798 return false;
8799 gsi_next (&gsi);
8800 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8801 return false;
8802 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8803 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8804 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8805 gcc_checking_assert (!need_old || !need_new);
8807 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8808 return false;
8810 /* Check for one of the supported fetch-op operations. */
8811 code = gimple_assign_rhs_code (stmt);
8812 switch (code)
8814 case PLUS_EXPR:
8815 case POINTER_PLUS_EXPR:
8816 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8817 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8818 break;
8819 case MINUS_EXPR:
8820 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8821 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8822 break;
8823 case BIT_AND_EXPR:
8824 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8825 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8826 break;
8827 case BIT_IOR_EXPR:
8828 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8829 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8830 break;
8831 case BIT_XOR_EXPR:
8832 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8833 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8834 break;
8835 default:
8836 return false;
8839 /* Make sure the expression is of the proper form. */
8840 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8841 rhs = gimple_assign_rhs2 (stmt);
8842 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8843 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8844 rhs = gimple_assign_rhs1 (stmt);
8845 else
8846 return false;
8848 tmpbase = ((enum built_in_function)
8849 ((need_new ? newbase : oldbase) + index + 1));
8850 decl = builtin_decl_explicit (tmpbase);
8851 if (decl == NULL_TREE)
8852 return false;
8853 itype = TREE_TYPE (TREE_TYPE (decl));
8854 imode = TYPE_MODE (itype);
8856 /* We could test all of the various optabs involved, but the fact of the
8857 matter is that (with the exception of i486 vs i586 and xadd) all targets
8858 that support any atomic operaton optab also implements compare-and-swap.
8859 Let optabs.c take care of expanding any compare-and-swap loop. */
8860 if (!can_compare_and_swap_p (imode, true))
8861 return false;
8863 gsi = gsi_last_bb (load_bb);
8864 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8866 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8867 It only requires that the operation happen atomically. Thus we can
8868 use the RELAXED memory model. */
8869 call = build_call_expr_loc (loc, decl, 3, addr,
8870 fold_convert_loc (loc, itype, rhs),
8871 build_int_cst (NULL,
8872 seq_cst ? MEMMODEL_SEQ_CST
8873 : MEMMODEL_RELAXED));
8875 if (need_old || need_new)
8877 lhs = need_old ? loaded_val : stored_val;
8878 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8879 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8881 else
8882 call = fold_convert_loc (loc, void_type_node, call);
8883 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8884 gsi_remove (&gsi, true);
8886 gsi = gsi_last_bb (store_bb);
8887 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8888 gsi_remove (&gsi, true);
8889 gsi = gsi_last_bb (store_bb);
8890 gsi_remove (&gsi, true);
8892 if (gimple_in_ssa_p (cfun))
8893 update_ssa (TODO_update_ssa_no_phi);
8895 return true;
8898 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8900 oldval = *addr;
8901 repeat:
8902 newval = rhs; // with oldval replacing *addr in rhs
8903 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8904 if (oldval != newval)
8905 goto repeat;
8907 INDEX is log2 of the size of the data type, and thus usable to find the
8908 index of the builtin decl. */
8910 static bool
8911 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8912 tree addr, tree loaded_val, tree stored_val,
8913 int index)
8915 tree loadedi, storedi, initial, new_storedi, old_vali;
8916 tree type, itype, cmpxchg, iaddr;
8917 gimple_stmt_iterator si;
8918 basic_block loop_header = single_succ (load_bb);
8919 gimple phi, stmt;
8920 edge e;
8921 enum built_in_function fncode;
8923 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8924 order to use the RELAXED memory model effectively. */
8925 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8926 + index + 1);
8927 cmpxchg = builtin_decl_explicit (fncode);
8928 if (cmpxchg == NULL_TREE)
8929 return false;
8930 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8931 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8933 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8934 return false;
8936 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8937 si = gsi_last_bb (load_bb);
8938 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8940 /* For floating-point values, we'll need to view-convert them to integers
8941 so that we can perform the atomic compare and swap. Simplify the
8942 following code by always setting up the "i"ntegral variables. */
8943 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8945 tree iaddr_val;
8947 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8948 true), NULL);
8949 iaddr_val
8950 = force_gimple_operand_gsi (&si,
8951 fold_convert (TREE_TYPE (iaddr), addr),
8952 false, NULL_TREE, true, GSI_SAME_STMT);
8953 stmt = gimple_build_assign (iaddr, iaddr_val);
8954 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8955 loadedi = create_tmp_var (itype, NULL);
8956 if (gimple_in_ssa_p (cfun))
8957 loadedi = make_ssa_name (loadedi, NULL);
8959 else
8961 iaddr = addr;
8962 loadedi = loaded_val;
8965 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8966 tree loaddecl = builtin_decl_explicit (fncode);
8967 if (loaddecl)
8968 initial
8969 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8970 build_call_expr (loaddecl, 2, iaddr,
8971 build_int_cst (NULL_TREE,
8972 MEMMODEL_RELAXED)));
8973 else
8974 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8975 build_int_cst (TREE_TYPE (iaddr), 0));
8977 initial
8978 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8979 GSI_SAME_STMT);
8981 /* Move the value to the LOADEDI temporary. */
8982 if (gimple_in_ssa_p (cfun))
8984 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8985 phi = create_phi_node (loadedi, loop_header);
8986 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8987 initial);
8989 else
8990 gsi_insert_before (&si,
8991 gimple_build_assign (loadedi, initial),
8992 GSI_SAME_STMT);
8993 if (loadedi != loaded_val)
8995 gimple_stmt_iterator gsi2;
8996 tree x;
8998 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8999 gsi2 = gsi_start_bb (loop_header);
9000 if (gimple_in_ssa_p (cfun))
9002 gimple stmt;
9003 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
9004 true, GSI_SAME_STMT);
9005 stmt = gimple_build_assign (loaded_val, x);
9006 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
9008 else
9010 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
9011 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
9012 true, GSI_SAME_STMT);
9015 gsi_remove (&si, true);
9017 si = gsi_last_bb (store_bb);
9018 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
9020 if (iaddr == addr)
9021 storedi = stored_val;
9022 else
9023 storedi =
9024 force_gimple_operand_gsi (&si,
9025 build1 (VIEW_CONVERT_EXPR, itype,
9026 stored_val), true, NULL_TREE, true,
9027 GSI_SAME_STMT);
9029 /* Build the compare&swap statement. */
9030 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
9031 new_storedi = force_gimple_operand_gsi (&si,
9032 fold_convert (TREE_TYPE (loadedi),
9033 new_storedi),
9034 true, NULL_TREE,
9035 true, GSI_SAME_STMT);
9037 if (gimple_in_ssa_p (cfun))
9038 old_vali = loadedi;
9039 else
9041 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
9042 stmt = gimple_build_assign (old_vali, loadedi);
9043 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9045 stmt = gimple_build_assign (loadedi, new_storedi);
9046 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9049 /* Note that we always perform the comparison as an integer, even for
9050 floating point. This allows the atomic operation to properly
9051 succeed even with NaNs and -0.0. */
9052 stmt = gimple_build_cond_empty
9053 (build2 (NE_EXPR, boolean_type_node,
9054 new_storedi, old_vali));
9055 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9057 /* Update cfg. */
9058 e = single_succ_edge (store_bb);
9059 e->flags &= ~EDGE_FALLTHRU;
9060 e->flags |= EDGE_FALSE_VALUE;
9062 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
9064 /* Copy the new value to loadedi (we already did that before the condition
9065 if we are not in SSA). */
9066 if (gimple_in_ssa_p (cfun))
9068 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
9069 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
9072 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
9073 gsi_remove (&si, true);
9075 struct loop *loop = alloc_loop ();
9076 loop->header = loop_header;
9077 loop->latch = store_bb;
9078 add_loop (loop, loop_header->loop_father);
9080 if (gimple_in_ssa_p (cfun))
9081 update_ssa (TODO_update_ssa_no_phi);
9083 return true;
9086 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
9088 GOMP_atomic_start ();
9089 *addr = rhs;
9090 GOMP_atomic_end ();
9092 The result is not globally atomic, but works so long as all parallel
9093 references are within #pragma omp atomic directives. According to
9094 responses received from omp@openmp.org, appears to be within spec.
9095 Which makes sense, since that's how several other compilers handle
9096 this situation as well.
9097 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
9098 expanding. STORED_VAL is the operand of the matching
9099 GIMPLE_OMP_ATOMIC_STORE.
9101 We replace
9102 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
9103 loaded_val = *addr;
9105 and replace
9106 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
9107 *addr = stored_val;
9110 static bool
9111 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
9112 tree addr, tree loaded_val, tree stored_val)
9114 gimple_stmt_iterator si;
9115 gimple stmt;
9116 tree t;
9118 si = gsi_last_bb (load_bb);
9119 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
9121 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
9122 t = build_call_expr (t, 0);
9123 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
9125 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
9126 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9127 gsi_remove (&si, true);
9129 si = gsi_last_bb (store_bb);
9130 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
9132 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
9133 stored_val);
9134 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
9136 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
9137 t = build_call_expr (t, 0);
9138 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
9139 gsi_remove (&si, true);
9141 if (gimple_in_ssa_p (cfun))
9142 update_ssa (TODO_update_ssa_no_phi);
9143 return true;
9146 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
9147 using expand_omp_atomic_fetch_op. If it failed, we try to
9148 call expand_omp_atomic_pipeline, and if it fails too, the
9149 ultimate fallback is wrapping the operation in a mutex
9150 (expand_omp_atomic_mutex). REGION is the atomic region built
9151 by build_omp_regions_1(). */
9153 static void
9154 expand_omp_atomic (struct omp_region *region)
9156 basic_block load_bb = region->entry, store_bb = region->exit;
9157 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
9158 tree loaded_val = gimple_omp_atomic_load_lhs (load);
9159 tree addr = gimple_omp_atomic_load_rhs (load);
9160 tree stored_val = gimple_omp_atomic_store_val (store);
9161 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
9162 HOST_WIDE_INT index;
9164 /* Make sure the type is one of the supported sizes. */
9165 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
9166 index = exact_log2 (index);
9167 if (index >= 0 && index <= 4)
9169 unsigned int align = TYPE_ALIGN_UNIT (type);
9171 /* __sync builtins require strict data alignment. */
9172 if (exact_log2 (align) >= index)
9174 /* Atomic load. */
9175 if (loaded_val == stored_val
9176 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
9177 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
9178 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
9179 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
9180 return;
9182 /* Atomic store. */
9183 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
9184 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
9185 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
9186 && store_bb == single_succ (load_bb)
9187 && first_stmt (store_bb) == store
9188 && expand_omp_atomic_store (load_bb, addr, loaded_val,
9189 stored_val, index))
9190 return;
9192 /* When possible, use specialized atomic update functions. */
9193 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
9194 && store_bb == single_succ (load_bb)
9195 && expand_omp_atomic_fetch_op (load_bb, addr,
9196 loaded_val, stored_val, index))
9197 return;
9199 /* If we don't have specialized __sync builtins, try and implement
9200 as a compare and swap loop. */
9201 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
9202 loaded_val, stored_val, index))
9203 return;
9207 /* The ultimate fallback is wrapping the operation in a mutex. */
9208 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
9212 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
9214 static void
9215 expand_omp_target (struct omp_region *region)
9217 basic_block entry_bb, exit_bb, new_bb;
9218 struct function *child_cfun = NULL;
9219 tree child_fn = NULL_TREE, block, t;
9220 gimple_stmt_iterator gsi;
9221 gimple entry_stmt, stmt;
9222 edge e;
9224 entry_stmt = last_stmt (region->entry);
9225 new_bb = region->entry;
9226 int kind = gimple_omp_target_kind (entry_stmt);
9227 if (kind == GF_OMP_TARGET_KIND_REGION)
9229 child_fn = gimple_omp_target_child_fn (entry_stmt);
9230 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9233 entry_bb = region->entry;
9234 exit_bb = region->exit;
9236 if (kind == GF_OMP_TARGET_KIND_REGION)
9238 unsigned srcidx, dstidx, num;
9240 /* If the target region needs data sent from the parent
9241 function, then the very first statement (except possible
9242 tree profile counter updates) of the parallel body
9243 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
9244 &.OMP_DATA_O is passed as an argument to the child function,
9245 we need to replace it with the argument as seen by the child
9246 function.
9248 In most cases, this will end up being the identity assignment
9249 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
9250 a function call that has been inlined, the original PARM_DECL
9251 .OMP_DATA_I may have been converted into a different local
9252 variable. In which case, we need to keep the assignment. */
9253 if (gimple_omp_target_data_arg (entry_stmt))
9255 basic_block entry_succ_bb = single_succ (entry_bb);
9256 gimple_stmt_iterator gsi;
9257 tree arg;
9258 gimple tgtcopy_stmt = NULL;
9259 tree sender
9260 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
9262 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
9264 gcc_assert (!gsi_end_p (gsi));
9265 stmt = gsi_stmt (gsi);
9266 if (gimple_code (stmt) != GIMPLE_ASSIGN)
9267 continue;
9269 if (gimple_num_ops (stmt) == 2)
9271 tree arg = gimple_assign_rhs1 (stmt);
9273 /* We're ignoring the subcode because we're
9274 effectively doing a STRIP_NOPS. */
9276 if (TREE_CODE (arg) == ADDR_EXPR
9277 && TREE_OPERAND (arg, 0) == sender)
9279 tgtcopy_stmt = stmt;
9280 break;
9285 gcc_assert (tgtcopy_stmt != NULL);
9286 arg = DECL_ARGUMENTS (child_fn);
9288 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
9289 gsi_remove (&gsi, true);
9292 /* Declare local variables needed in CHILD_CFUN. */
9293 block = DECL_INITIAL (child_fn);
9294 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
9295 /* The gimplifier could record temporaries in target block
9296 rather than in containing function's local_decls chain,
9297 which would mean cgraph missed finalizing them. Do it now. */
9298 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
9299 if (TREE_CODE (t) == VAR_DECL
9300 && TREE_STATIC (t)
9301 && !DECL_EXTERNAL (t))
9302 varpool_node::finalize_decl (t);
9303 DECL_SAVED_TREE (child_fn) = NULL;
9304 /* We'll create a CFG for child_fn, so no gimple body is needed. */
9305 gimple_set_body (child_fn, NULL);
9306 TREE_USED (block) = 1;
9308 /* Reset DECL_CONTEXT on function arguments. */
9309 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9310 DECL_CONTEXT (t) = child_fn;
9312 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
9313 so that it can be moved to the child function. */
9314 gsi = gsi_last_bb (entry_bb);
9315 stmt = gsi_stmt (gsi);
9316 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
9317 && gimple_omp_target_kind (stmt)
9318 == GF_OMP_TARGET_KIND_REGION);
9319 gsi_remove (&gsi, true);
9320 e = split_block (entry_bb, stmt);
9321 entry_bb = e->dest;
9322 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9324 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9325 if (exit_bb)
9327 gsi = gsi_last_bb (exit_bb);
9328 gcc_assert (!gsi_end_p (gsi)
9329 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9330 stmt = gimple_build_return (NULL);
9331 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9332 gsi_remove (&gsi, true);
9335 /* Move the target region into CHILD_CFUN. */
9337 block = gimple_block (entry_stmt);
9339 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9340 if (exit_bb)
9341 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9342 /* When the OMP expansion process cannot guarantee an up-to-date
9343 loop tree arrange for the child function to fixup loops. */
9344 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9345 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9347 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9348 num = vec_safe_length (child_cfun->local_decls);
9349 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9351 t = (*child_cfun->local_decls)[srcidx];
9352 if (DECL_CONTEXT (t) == cfun->decl)
9353 continue;
9354 if (srcidx != dstidx)
9355 (*child_cfun->local_decls)[dstidx] = t;
9356 dstidx++;
9358 if (dstidx != num)
9359 vec_safe_truncate (child_cfun->local_decls, dstidx);
9361 /* Inform the callgraph about the new function. */
9362 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
9363 cgraph_node::add_new_function (child_fn, true);
9365 /* Add the new function to the offload table. */
9366 vec_safe_push (offload_funcs, child_fn);
9368 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9369 fixed in a following pass. */
9370 push_cfun (child_cfun);
9371 cgraph_edge::rebuild_edges ();
9373 /* Some EH regions might become dead, see PR34608. If
9374 pass_cleanup_cfg isn't the first pass to happen with the
9375 new child, these dead EH edges might cause problems.
9376 Clean them up now. */
9377 if (flag_exceptions)
9379 basic_block bb;
9380 bool changed = false;
9382 FOR_EACH_BB_FN (bb, cfun)
9383 changed |= gimple_purge_dead_eh_edges (bb);
9384 if (changed)
9385 cleanup_tree_cfg ();
9387 pop_cfun ();
9390 /* Emit a library call to launch the target region, or do data
9391 transfers. */
9392 tree t1, t2, t3, t4, device, cond, c, clauses;
9393 enum built_in_function start_ix;
9394 location_t clause_loc;
9396 clauses = gimple_omp_target_clauses (entry_stmt);
9398 switch (kind)
9400 case GF_OMP_TARGET_KIND_REGION:
9401 start_ix = BUILT_IN_GOMP_TARGET;
9402 break;
9403 case GF_OMP_TARGET_KIND_DATA:
9404 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9405 break;
9406 case GF_OMP_TARGET_KIND_UPDATE:
9407 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9408 break;
9409 case GF_OMP_TARGET_KIND_OACC_DATA:
9410 start_ix = BUILT_IN_GOACC_DATA_START;
9411 break;
9412 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9413 start_ix = BUILT_IN_GOACC_UPDATE;
9414 break;
9415 default:
9416 gcc_unreachable ();
9419 /* By default, the value of DEVICE is -1 (let runtime library choose)
9420 and there is no conditional. */
9421 cond = NULL_TREE;
9422 device = build_int_cst (integer_type_node, -1);
9424 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9425 if (c)
9426 cond = OMP_CLAUSE_IF_EXPR (c);
9428 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9429 if (c)
9431 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA
9432 && kind != GF_OMP_TARGET_KIND_OACC_UPDATE);
9434 device = OMP_CLAUSE_DEVICE_ID (c);
9435 clause_loc = OMP_CLAUSE_LOCATION (c);
9437 else
9438 clause_loc = gimple_location (entry_stmt);
9440 /* Ensure 'device' is of the correct type. */
9441 device = fold_convert_loc (clause_loc, integer_type_node, device);
9443 /* If we found the clause 'if (cond)', build
9444 (cond ? device : -2). */
9445 if (cond)
9447 cond = gimple_boolify (cond);
9449 basic_block cond_bb, then_bb, else_bb;
9450 edge e;
9451 tree tmp_var;
9453 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
9454 if (kind != GF_OMP_TARGET_KIND_REGION)
9456 gsi = gsi_last_bb (new_bb);
9457 gsi_prev (&gsi);
9458 e = split_block (new_bb, gsi_stmt (gsi));
9460 else
9461 e = split_block (new_bb, NULL);
9462 cond_bb = e->src;
9463 new_bb = e->dest;
9464 remove_edge (e);
9466 then_bb = create_empty_bb (cond_bb);
9467 else_bb = create_empty_bb (then_bb);
9468 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9469 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9471 stmt = gimple_build_cond_empty (cond);
9472 gsi = gsi_last_bb (cond_bb);
9473 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9475 gsi = gsi_start_bb (then_bb);
9476 stmt = gimple_build_assign (tmp_var, device);
9477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9479 gsi = gsi_start_bb (else_bb);
9480 stmt = gimple_build_assign (tmp_var,
9481 build_int_cst (integer_type_node, -2));
9482 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9484 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9485 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9486 add_bb_to_loop (then_bb, cond_bb->loop_father);
9487 add_bb_to_loop (else_bb, cond_bb->loop_father);
9488 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9489 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9491 device = tmp_var;
9494 gsi = gsi_last_bb (new_bb);
9495 t = gimple_omp_target_data_arg (entry_stmt);
9496 if (t == NULL)
9498 t1 = size_zero_node;
9499 t2 = build_zero_cst (ptr_type_node);
9500 t3 = t2;
9501 t4 = t2;
9503 else
9505 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9506 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9507 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9508 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9509 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9512 gimple g;
9513 tree openmp_target = get_offload_symbol_decl ();
9514 vec<tree> *args;
9515 unsigned int argcnt = 6;
9517 if (kind == GF_OMP_TARGET_KIND_REGION)
9518 argcnt++;
9519 else if (kind == GF_OMP_TARGET_KIND_OACC_DATA
9520 || kind == GF_OMP_TARGET_KIND_OACC_UPDATE)
9521 argcnt += 2;
9523 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9524 if (c)
9526 for (t = c; t; t = OMP_CLAUSE_CHAIN (t))
9528 if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_WAIT)
9529 argcnt++;
9533 vec_alloc (args, argcnt);
9534 args->quick_push (device);
9536 if (kind == GF_OMP_TARGET_KIND_REGION)
9537 args->quick_push (build_fold_addr_expr (child_fn));
9539 args->quick_push (build_fold_addr_expr (openmp_target));
9540 args->quick_push (t1);
9541 args->quick_push (t2);
9542 args->quick_push (t3);
9543 args->quick_push (t4);
9545 if (kind == GF_OMP_TARGET_KIND_OACC_DATA
9546 || kind == GF_OMP_TARGET_KIND_OACC_UPDATE)
9548 int idx;
9550 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9551 if (c)
9552 t1 = fold_convert_loc (OMP_CLAUSE_LOCATION (c), integer_type_node,
9553 OMP_CLAUSE_ASYNC_EXPR (c));
9554 else /* TODO: XXX FIX -2. */
9555 t1 = fold_convert_loc (gimple_location (entry_stmt),
9556 integer_type_node, build_int_cst (integer_type_node, -2));
9558 args->quick_push (t1);
9559 idx = args->length ();
9560 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9561 integer_type_node, integer_minus_one_node));
9563 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9564 if (c)
9566 int n = 0;
9568 for (t = c; t; t = OMP_CLAUSE_CHAIN (t))
9570 if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_WAIT)
9572 args->quick_push (fold_convert (integer_type_node,
9573 OMP_CLAUSE_WAIT_EXPR (t)));
9574 n++;
9578 args->ordered_remove (idx);
9579 args->quick_insert (idx,
9580 fold_convert_loc (gimple_location (entry_stmt),
9581 integer_type_node,
9582 build_int_cst (integer_type_node, n)));
9586 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9587 args->release ();
9588 gimple_set_location (g, gimple_location (entry_stmt));
9589 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9590 if (kind != GF_OMP_TARGET_KIND_REGION)
9592 g = gsi_stmt (gsi);
9593 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9594 gsi_remove (&gsi, true);
9596 if ((kind == GF_OMP_TARGET_KIND_DATA
9597 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
9598 && region->exit)
9600 gsi = gsi_last_bb (region->exit);
9601 g = gsi_stmt (gsi);
9602 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9603 gsi_remove (&gsi, true);
9608 /* Expand the parallel region tree rooted at REGION. Expansion
9609 proceeds in depth-first order. Innermost regions are expanded
9610 first. This way, parallel regions that require a new function to
9611 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9612 internal dependencies in their body. */
9614 static void
9615 expand_omp (struct omp_region *region)
9617 while (region)
9619 location_t saved_location;
9620 gimple inner_stmt = NULL;
9622 /* First, determine whether this is a combined parallel+workshare
9623 region. */
9624 if (region->type == GIMPLE_OMP_PARALLEL)
9625 determine_parallel_type (region);
9627 if (region->type == GIMPLE_OMP_FOR
9628 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9629 inner_stmt = last_stmt (region->inner->entry);
9631 if (region->inner)
9632 expand_omp (region->inner);
9634 saved_location = input_location;
9635 if (gimple_has_location (last_stmt (region->entry)))
9636 input_location = gimple_location (last_stmt (region->entry));
9638 switch (region->type)
9640 case GIMPLE_OACC_KERNELS:
9641 case GIMPLE_OACC_PARALLEL:
9642 expand_oacc_offload (region);
9643 break;
9645 case GIMPLE_OMP_PARALLEL:
9646 case GIMPLE_OMP_TASK:
9647 expand_omp_taskreg (region);
9648 break;
9650 case GIMPLE_OMP_FOR:
9651 expand_omp_for (region, inner_stmt);
9652 break;
9654 case GIMPLE_OMP_SECTIONS:
9655 expand_omp_sections (region);
9656 break;
9658 case GIMPLE_OMP_SECTION:
9659 /* Individual omp sections are handled together with their
9660 parent GIMPLE_OMP_SECTIONS region. */
9661 break;
9663 case GIMPLE_OMP_SINGLE:
9664 expand_omp_single (region);
9665 break;
9667 case GIMPLE_OMP_MASTER:
9668 case GIMPLE_OMP_TASKGROUP:
9669 case GIMPLE_OMP_ORDERED:
9670 case GIMPLE_OMP_CRITICAL:
9671 case GIMPLE_OMP_TEAMS:
9672 expand_omp_synch (region);
9673 break;
9675 case GIMPLE_OMP_ATOMIC_LOAD:
9676 expand_omp_atomic (region);
9677 break;
9679 case GIMPLE_OMP_TARGET:
9680 expand_omp_target (region);
9681 break;
9683 default:
9684 gcc_unreachable ();
9687 input_location = saved_location;
9688 region = region->next;
9693 /* Helper for build_omp_regions. Scan the dominator tree starting at
9694 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9695 true, the function ends once a single tree is built (otherwise, whole
9696 forest of OMP constructs may be built). */
9698 static void
9699 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9700 bool single_tree)
9702 gimple_stmt_iterator gsi;
9703 gimple stmt;
9704 basic_block son;
9706 gsi = gsi_last_bb (bb);
9707 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9709 struct omp_region *region;
9710 enum gimple_code code;
9712 stmt = gsi_stmt (gsi);
9713 code = gimple_code (stmt);
9714 if (code == GIMPLE_OMP_RETURN)
9716 /* STMT is the return point out of region PARENT. Mark it
9717 as the exit point and make PARENT the immediately
9718 enclosing region. */
9719 gcc_assert (parent);
9720 region = parent;
9721 region->exit = bb;
9722 parent = parent->outer;
9724 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9726 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9727 GIMPLE_OMP_RETURN, but matches with
9728 GIMPLE_OMP_ATOMIC_LOAD. */
9729 gcc_assert (parent);
9730 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9731 region = parent;
9732 region->exit = bb;
9733 parent = parent->outer;
9736 else if (code == GIMPLE_OMP_CONTINUE)
9738 gcc_assert (parent);
9739 parent->cont = bb;
9741 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9743 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9744 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9747 else if (code == GIMPLE_OMP_TARGET
9748 && (gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE
9749 || (gimple_omp_target_kind (stmt)
9750 == GF_OMP_TARGET_KIND_OACC_UPDATE)))
9751 new_omp_region (bb, code, parent);
9752 else
9754 /* Otherwise, this directive becomes the parent for a new
9755 region. */
9756 region = new_omp_region (bb, code, parent);
9757 parent = region;
9761 if (single_tree && !parent)
9762 return;
9764 for (son = first_dom_son (CDI_DOMINATORS, bb);
9765 son;
9766 son = next_dom_son (CDI_DOMINATORS, son))
9767 build_omp_regions_1 (son, parent, single_tree);
9770 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9771 root_omp_region. */
9773 static void
9774 build_omp_regions_root (basic_block root)
9776 gcc_assert (root_omp_region == NULL);
9777 build_omp_regions_1 (root, NULL, true);
9778 gcc_assert (root_omp_region != NULL);
9781 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9783 void
9784 omp_expand_local (basic_block head)
9786 build_omp_regions_root (head);
9787 if (dump_file && (dump_flags & TDF_DETAILS))
9789 fprintf (dump_file, "\nOMP region tree\n\n");
9790 dump_omp_region (dump_file, root_omp_region, 0);
9791 fprintf (dump_file, "\n");
9794 remove_exit_barriers (root_omp_region);
9795 expand_omp (root_omp_region);
9797 free_omp_regions ();
9800 /* Scan the CFG and build a tree of OMP regions. Return the root of
9801 the OMP region tree. */
9803 static void
9804 build_omp_regions (void)
9806 gcc_assert (root_omp_region == NULL);
9807 calculate_dominance_info (CDI_DOMINATORS);
9808 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9811 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9813 static unsigned int
9814 execute_expand_omp (void)
9816 build_omp_regions ();
9818 if (!root_omp_region)
9819 return 0;
9821 if (dump_file)
9823 fprintf (dump_file, "\nOMP region tree\n\n");
9824 dump_omp_region (dump_file, root_omp_region, 0);
9825 fprintf (dump_file, "\n");
9828 remove_exit_barriers (root_omp_region);
9830 expand_omp (root_omp_region);
9832 cleanup_tree_cfg ();
9834 free_omp_regions ();
9836 return 0;
9839 /* OMP expansion -- the default pass, run before creation of SSA form. */
9841 namespace {
9843 const pass_data pass_data_expand_omp =
9845 GIMPLE_PASS, /* type */
9846 "ompexp", /* name */
9847 OPTGROUP_NONE, /* optinfo_flags */
9848 TV_NONE, /* tv_id */
9849 PROP_gimple_any, /* properties_required */
9850 0, /* properties_provided */
9851 0, /* properties_destroyed */
9852 0, /* todo_flags_start */
9853 0, /* todo_flags_finish */
9856 class pass_expand_omp : public gimple_opt_pass
9858 public:
9859 pass_expand_omp (gcc::context *ctxt)
9860 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9863 /* opt_pass methods: */
9864 virtual bool gate (function *)
9866 return ((flag_openacc != 0 || flag_openmp != 0 || flag_openmp_simd != 0
9867 || flag_cilkplus != 0) && !seen_error ());
9870 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9872 }; // class pass_expand_omp
9874 } // anon namespace
9876 gimple_opt_pass *
9877 make_pass_expand_omp (gcc::context *ctxt)
9879 return new pass_expand_omp (ctxt);
9882 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9883 convert it to gimple. */
9884 static void
9885 omp_gimple_assign_with_ops (tree_code op, tree dest, tree src, gimple_seq *seq)
9887 gimple stmt;
9889 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9891 stmt = gimple_build_assign_with_ops (op, dest, dest, src);
9892 gimple_seq_add_stmt (seq, stmt);
9893 return;
9896 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9897 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9898 gimplify_assign (t, rdest, seq);
9899 rdest = t;
9901 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9902 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9903 gimplify_assign (t, idest, seq);
9904 idest = t;
9906 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)), NULL);
9907 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9908 gimplify_assign (t, rsrc, seq);
9909 rsrc = t;
9911 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)), NULL);
9912 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9913 gimplify_assign (t, isrc, seq);
9914 isrc = t;
9916 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9917 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9918 tree result;
9920 gcc_assert (op == PLUS_EXPR || op == MULT_EXPR);
9922 if (op == PLUS_EXPR)
9924 stmt = gimple_build_assign_with_ops (op, r, rdest, rsrc);
9925 gimple_seq_add_stmt (seq, stmt);
9927 stmt = gimple_build_assign_with_ops (op, i, idest, isrc);
9928 gimple_seq_add_stmt (seq, stmt);
9930 else if (op == MULT_EXPR)
9932 /* Let x = a + ib = dest, y = c + id = src.
9933 x * y = (ac - bd) + i(ad + bc) */
9934 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9935 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9936 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9937 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)), NULL);
9939 stmt = gimple_build_assign_with_ops (MULT_EXPR, ac, rdest, rsrc);
9940 gimple_seq_add_stmt (seq, stmt);
9942 stmt = gimple_build_assign_with_ops (MULT_EXPR, bd, idest, isrc);
9943 gimple_seq_add_stmt (seq, stmt);
9945 stmt = gimple_build_assign_with_ops (MINUS_EXPR, r, ac, bd);
9946 gimple_seq_add_stmt (seq, stmt);
9948 stmt = gimple_build_assign_with_ops (MULT_EXPR, ad, rdest, isrc);
9949 gimple_seq_add_stmt (seq, stmt);
9951 stmt = gimple_build_assign_with_ops (MULT_EXPR, bd, idest, rsrc);
9952 gimple_seq_add_stmt (seq, stmt);
9954 stmt = gimple_build_assign_with_ops (PLUS_EXPR, i, ad, bc);
9955 gimple_seq_add_stmt (seq, stmt);
9958 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9959 gimplify_assign (dest, result, seq);
9962 /* Helper function to initialize local data for the reduction arrays.
9963 The reduction arrays need to be placed inside the calling function
9964 for accelerators, or else the host won't be able to preform the final
9965 reduction. FIXME: This function assumes that there are
9966 vector_length threads in total. */
9968 static void
9969 initialize_reduction_data (tree clauses, tree nthreads, gimple_seq *stmt_seqp,
9970 omp_context *ctx)
9972 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
9974 tree c, t, oc;
9975 gimple stmt;
9976 omp_context *octx;
9977 tree (*gimple_omp_clauses) (const_gimple);
9978 void (*gimple_omp_set_clauses) (gimple, tree);
9980 /* Find the innermost PARALLEL openmp context. FIXME: OpenACC kernels
9981 may require extra care unless they are converted to openmp for loops. */
9983 if (gimple_code (ctx->stmt) == GIMPLE_OACC_PARALLEL)
9984 octx = ctx;
9985 else
9986 octx = ctx->outer;
9988 gimple_omp_clauses = gimple_oacc_parallel_clauses;
9989 gimple_omp_set_clauses = gimple_oacc_parallel_set_clauses;
9991 /* Extract the clauses. */
9992 oc = gimple_omp_clauses (octx->stmt);
9994 /* Find the last outer clause. */
9995 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9998 /* Allocate arrays for each reduction variable. */
9999 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10001 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
10002 continue;
10004 tree var = OMP_CLAUSE_DECL (c);
10005 tree type = get_base_type (var);
10006 tree array = lookup_reduction (omp_get_id (var), ctx);
10007 tree size, call;
10009 /* Calculate size of the reduction array. */
10010 t = create_tmp_var (TREE_TYPE (nthreads), NULL);
10011 stmt = gimple_build_assign_with_ops (MULT_EXPR, t, nthreads,
10012 fold_convert (TREE_TYPE (nthreads),
10013 TYPE_SIZE_UNIT (type)));
10014 gimple_seq_add_stmt (stmt_seqp, stmt);
10016 size = create_tmp_var (sizetype, NULL);
10017 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
10019 /* Now allocate memory for it. FIXME: Allocating memory for the
10020 reduction array may be unnecessary once the final reduction is able
10021 to be preformed on the accelerator. Instead of allocating memory on
10022 the host side, it could just be allocated on the accelerator. */
10023 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
10024 stmt = gimple_build_call (call, 1, size);
10025 gimple_call_set_lhs (stmt, array);
10026 gimple_seq_add_stmt (stmt_seqp, stmt);
10028 /* Map this array into the accelerator. */
10030 /* Add the reduction array to the list of clauses. */
10031 /* FIXME: Currently, these variables must be placed in the outer
10032 most clause so that copy-out works. */
10033 tree x = array;
10034 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
10035 OMP_CLAUSE_MAP_KIND (t) = OMP_CLAUSE_MAP_FORCE_FROM;
10036 OMP_CLAUSE_DECL (t) = x;
10037 OMP_CLAUSE_CHAIN (t) = NULL;
10038 if (oc)
10039 OMP_CLAUSE_CHAIN (oc) = t;
10040 else
10041 gimple_omp_set_clauses (octx->stmt, t);
10042 OMP_CLAUSE_SIZE (t) = size;
10043 oc = t;
10047 /* Helper function to finalize local data for the reduction arrays. The
10048 reduction array needs to be reduced to the original reduction variable.
10049 FIXME: This function assumes that there are vector_length threads in
10050 total. Also, it assumes that there are at least vector_length iterations
10051 in the for loop. */
10053 static void
10054 finalize_reduction_data (tree clauses, tree nthreads, gimple_seq *stmt_seqp,
10055 omp_context *ctx)
10057 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
10059 tree c, var, array, loop_header, loop_body, loop_exit, type;
10060 gimple stmt;
10062 /* Create for loop.
10064 let var = the original reduction variable
10065 let array = reduction variable array
10067 for (i = 0; i < nthreads; i++)
10068 var op= array[i]
10071 loop_header = create_artificial_label (UNKNOWN_LOCATION);
10072 loop_body = create_artificial_label (UNKNOWN_LOCATION);
10073 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
10075 /* Create and initialize an index variable. */
10076 tree ix = create_tmp_var (sizetype, NULL);
10077 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
10078 stmt_seqp);
10080 /* Insert the loop header label here. */
10081 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
10083 /* Loop if ix >= nthreads. */
10084 tree x = create_tmp_var (sizetype, NULL);
10085 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
10086 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
10087 gimple_seq_add_stmt (stmt_seqp, stmt);
10089 /* Insert the loop body label here. */
10090 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
10092 /* Collapse each reduction array, one element at a time. */
10093 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10095 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
10096 continue;
10098 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
10100 /* reduction(-:var) sums up the partial results, so it acts
10101 identically to reduction(+:var). */
10102 if (reduction_code == MINUS_EXPR)
10103 reduction_code = PLUS_EXPR;
10105 /* Set up reduction variable var. */
10106 var = OMP_CLAUSE_DECL (c);
10107 type = get_base_type (var);
10108 array = lookup_reduction (omp_get_id (OMP_CLAUSE_DECL (c)), ctx);
10110 /* Calculate the array offset. */
10111 tree offset = create_tmp_var (sizetype, NULL);
10112 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
10113 stmt = gimple_build_assign_with_ops (MULT_EXPR, offset, offset, ix);
10114 gimple_seq_add_stmt (stmt_seqp, stmt);
10116 tree ptr = create_tmp_var (TREE_TYPE (array), NULL);
10117 stmt = gimple_build_assign_with_ops (POINTER_PLUS_EXPR, ptr, array,
10118 offset);
10119 gimple_seq_add_stmt (stmt_seqp, stmt);
10121 /* Extract array[ix] into mem. */
10122 tree mem = create_tmp_var (type, NULL);
10123 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
10125 /* Find the original reduction variable. */
10126 tree x = build_outer_var_ref (var, ctx);
10127 if (is_reference (var))
10128 var = build_simple_mem_ref (var);
10130 tree t = create_tmp_var (type, NULL);
10132 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
10133 gimplify_and_add (unshare_expr(x), stmt_seqp);
10135 /* var = var op mem */
10136 switch (OMP_CLAUSE_REDUCTION_CODE (c))
10138 case TRUTH_ANDIF_EXPR:
10139 case TRUTH_ORIF_EXPR:
10140 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
10141 t, mem);
10142 gimplify_and_add (t, stmt_seqp);
10143 break;
10144 default:
10145 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
10146 omp_gimple_assign_with_ops (OMP_CLAUSE_REDUCTION_CODE (c),
10147 t, mem, stmt_seqp);
10150 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
10151 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
10152 gimplify_and_add (unshare_expr(x), stmt_seqp);
10155 /* Increment the induction variable. */
10156 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
10157 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ix, ix, one);
10158 gimple_seq_add_stmt (stmt_seqp, stmt);
10160 /* Go back to the top of the loop. */
10161 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
10163 /* Place the loop exit label here. */
10164 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
10167 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
10168 scan that for reductions. */
10170 static void
10171 process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
10172 gimple_seq *out_stmt_seqp, omp_context *ctx)
10174 gcc_assert (is_gimple_omp_oacc_specifically (ctx->stmt));
10176 gimple_stmt_iterator gsi;
10177 gimple_seq inner = NULL;
10178 gimple stmt;
10180 /* A collapse clause may have inserted a new bind block. */
10181 gsi = gsi_start (*body);
10182 while (!gsi_end_p (gsi))
10184 stmt = gsi_stmt (gsi);
10185 if (gimple_code (stmt) == GIMPLE_BIND)
10187 inner = gimple_bind_body (stmt);
10188 body = &inner;
10189 gsi = gsi_start (*body);
10191 else if (gimple_code (stmt) == GIMPLE_OMP_FOR)
10192 break;
10193 else
10194 gsi_next (&gsi);
10197 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10199 tree call;
10200 tree clauses, nthreads, t, c;
10201 bool reduction_found = false;
10203 stmt = gsi_stmt (gsi);
10205 switch (gimple_code (stmt))
10207 case GIMPLE_OMP_FOR:
10208 clauses = gimple_omp_for_clauses (stmt);
10210 /* Search for a reduction clause. */
10211 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10212 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10214 reduction_found = true;
10215 break;
10218 if (!reduction_found)
10219 break;
10221 ctx = maybe_lookup_ctx (stmt);
10222 t = NULL_TREE;
10224 /* The reduction clause may be nested inside a loop directive.
10225 Scan for the innermost vector_length clause. */
10226 for (omp_context *oc = ctx; oc; oc = oc->outer)
10228 switch (gimple_code (oc->stmt))
10230 case GIMPLE_OACC_PARALLEL:
10231 c = gimple_oacc_parallel_clauses (oc->stmt);
10232 break;
10233 case GIMPLE_OMP_FOR:
10234 c = gimple_omp_for_clauses (oc->stmt);
10235 break;
10236 default:
10237 c = NULL_TREE;
10238 break;
10241 if (c && gimple_code (oc->stmt) == GIMPLE_OACC_PARALLEL)
10243 t = find_omp_clause (c, OMP_CLAUSE_VECTOR_LENGTH);
10244 if (t)
10245 t = fold_convert_loc (OMP_CLAUSE_LOCATION (t),
10246 integer_type_node,
10247 OMP_CLAUSE_VECTOR_LENGTH_EXPR (t));
10248 break;
10252 if (!t)
10253 t = integer_one_node;
10255 /* Extract the number of threads. */
10256 nthreads = create_tmp_var (TREE_TYPE (t), NULL);
10257 gimplify_assign (nthreads, t, in_stmt_seqp);
10259 /* Ensure nthreads >= 1. */
10260 stmt = gimple_build_assign_with_ops (MAX_EXPR, nthreads, nthreads,
10261 fold_convert(TREE_TYPE (nthreads),
10262 integer_one_node));
10263 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10265 /* Set the number of threads. */
10266 /* FIXME: This needs to handle accelerators */
10267 call = builtin_decl_explicit (BUILT_IN_OMP_SET_NUM_THREADS);
10268 stmt = gimple_build_call (call, 1, nthreads);
10269 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10271 initialize_reduction_data (clauses, nthreads, in_stmt_seqp, ctx);
10272 finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10273 break;
10274 default:
10275 // Scan for other directives which support reduction here.
10276 break;
10281 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
10283 /* Lower the OpenACC offload directive in the current statement
10284 in GSI_P. CTX holds context information for the directive. */
10286 static void
10287 lower_oacc_offload (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10289 tree clauses;
10290 tree child_fn, t, c;
10291 gimple stmt = gsi_stmt (*gsi_p);
10292 gimple par_bind, bind;
10293 gimple_seq par_body, olist, ilist, orlist, irlist, new_body;
10294 location_t loc = gimple_location (stmt);
10295 unsigned int map_cnt = 0;
10296 tree (*gimple_omp_clauses) (const_gimple);
10297 void (*gimple_omp_set_data_arg) (gimple, tree);
10298 switch (gimple_code (stmt))
10300 case GIMPLE_OACC_KERNELS:
10301 gimple_omp_clauses = gimple_oacc_kernels_clauses;
10302 gimple_omp_set_data_arg = gimple_oacc_kernels_set_data_arg;
10303 break;
10304 case GIMPLE_OACC_PARALLEL:
10305 gimple_omp_clauses = gimple_oacc_parallel_clauses;
10306 gimple_omp_set_data_arg = gimple_oacc_parallel_set_data_arg;
10307 break;
10308 default:
10309 gcc_unreachable ();
10312 clauses = gimple_omp_clauses (stmt);
10313 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10314 par_body = gimple_bind_body (par_bind);
10315 child_fn = ctx->cb.dst_fn;
10317 push_gimplify_context ();
10319 irlist = NULL;
10320 orlist = NULL;
10321 process_reduction_data (&par_body, &irlist, &orlist, ctx);
10323 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10324 switch (OMP_CLAUSE_CODE (c))
10326 tree var, x;
10328 default:
10329 break;
10330 case OMP_CLAUSE_MAP:
10331 var = OMP_CLAUSE_DECL (c);
10332 if (!DECL_P (var))
10334 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10335 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10336 map_cnt++;
10337 continue;
10340 if (DECL_SIZE (var)
10341 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10343 tree var2 = DECL_VALUE_EXPR (var);
10344 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10345 var2 = TREE_OPERAND (var2, 0);
10346 gcc_assert (DECL_P (var2));
10347 var = var2;
10350 if (!maybe_lookup_field (var, ctx))
10351 continue;
10353 /* Preserve indentation of lower_omp_target. */
10354 if (1)
10356 x = build_receiver_ref (var, true, ctx);
10357 tree new_var = lookup_decl (var, ctx);
10358 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10359 || (OMP_CLAUSE_MAP_KIND (c)
10360 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
10361 || TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE);
10362 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10363 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10364 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10365 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10366 x = build_simple_mem_ref (x);
10367 SET_DECL_VALUE_EXPR (new_var, x);
10368 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10370 map_cnt++;
10373 target_nesting_level++;
10374 lower_omp (&par_body, ctx);
10375 target_nesting_level--;
10377 /* Declare all the variables created by mapping and the variables
10378 declared in the scope of the body. */
10379 record_vars_into (ctx->block_vars, child_fn);
10380 record_vars_into (gimple_bind_vars (par_bind), child_fn);
10382 olist = NULL;
10383 ilist = NULL;
10384 if (ctx->record_type)
10386 ctx->sender_decl
10387 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10388 DECL_NAMELESS (ctx->sender_decl) = 1;
10389 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10390 t = make_tree_vec (3);
10391 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10392 TREE_VEC_ELT (t, 1)
10393 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10394 ".omp_data_sizes");
10395 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10396 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10397 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10398 TREE_VEC_ELT (t, 2)
10399 = create_tmp_var (build_array_type_nelts (short_unsigned_type_node,
10400 map_cnt),
10401 ".omp_data_kinds");
10402 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10403 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10404 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10405 gimple_omp_set_data_arg (stmt, t);
10407 vec<constructor_elt, va_gc> *vsize;
10408 vec<constructor_elt, va_gc> *vkind;
10409 vec_alloc (vsize, map_cnt);
10410 vec_alloc (vkind, map_cnt);
10411 unsigned int map_idx = 0;
10413 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10414 switch (OMP_CLAUSE_CODE (c))
10416 tree ovar, nc;
10418 default:
10419 break;
10420 case OMP_CLAUSE_MAP:
10421 nc = c;
10422 ovar = OMP_CLAUSE_DECL (c);
10423 if (!DECL_P (ovar))
10425 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10426 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10428 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10429 == get_base_address (ovar));
10430 nc = OMP_CLAUSE_CHAIN (c);
10431 ovar = OMP_CLAUSE_DECL (nc);
10433 else
10435 tree x = build_sender_ref (ovar, ctx);
10436 tree v
10437 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10438 gimplify_assign (x, v, &ilist);
10439 nc = NULL_TREE;
10442 else
10444 if (DECL_SIZE (ovar)
10445 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10447 tree ovar2 = DECL_VALUE_EXPR (ovar);
10448 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10449 ovar2 = TREE_OPERAND (ovar2, 0);
10450 gcc_assert (DECL_P (ovar2));
10451 ovar = ovar2;
10453 if (!maybe_lookup_field (ovar, ctx))
10454 continue;
10457 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10458 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10459 talign = DECL_ALIGN_UNIT (ovar);
10460 if (nc)
10462 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10463 tree x = build_sender_ref (ovar, ctx);
10464 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10465 || (OMP_CLAUSE_MAP_KIND (c)
10466 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
10467 || TREE_CODE (TREE_TYPE (ovar)) != ARRAY_TYPE);
10468 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10469 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10470 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10471 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10473 tree avar
10474 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10475 mark_addressable (avar);
10476 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10477 talign = DECL_ALIGN_UNIT (avar);
10478 avar = build_fold_addr_expr (avar);
10479 gimplify_assign (x, avar, &ilist);
10481 else if (is_gimple_reg (var)
10482 && !maybe_lookup_reduction (var, ctx))
10484 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10485 mark_addressable (avar);
10486 enum omp_clause_map_kind map_kind
10487 = OMP_CLAUSE_MAP_KIND (c);
10488 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10489 && (map_kind & OMP_CLAUSE_MAP_TO))
10490 || map_kind == OMP_CLAUSE_MAP_POINTER
10491 || map_kind == OMP_CLAUSE_MAP_TO_PSET
10492 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
10493 gimplify_assign (avar, var, &ilist);
10494 avar = build_fold_addr_expr (avar);
10495 gimplify_assign (x, avar, &ilist);
10496 if (((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
10497 && (map_kind & OMP_CLAUSE_MAP_FROM))
10498 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
10499 && !TYPE_READONLY (TREE_TYPE (var)))
10501 x = build_sender_ref (ovar, ctx);
10502 x = build_simple_mem_ref (x);
10503 gimplify_assign (var, x, &olist);
10506 else
10508 if (!maybe_lookup_reduction (var, ctx))
10509 var = build_fold_addr_expr (var);
10510 gimplify_assign (x, var, &ilist);
10513 tree s = OMP_CLAUSE_SIZE (c);
10514 if (s == NULL_TREE)
10515 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10516 s = fold_convert (size_type_node, s);
10517 tree purpose = size_int (map_idx++);
10518 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10519 if (TREE_CODE (s) != INTEGER_CST)
10520 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10522 unsigned short tkind = 0;
10523 switch (OMP_CLAUSE_CODE (c))
10525 case OMP_CLAUSE_MAP:
10526 tkind = OMP_CLAUSE_MAP_KIND (c);
10527 break;
10528 default:
10529 gcc_unreachable ();
10531 talign = ceil_log2 (talign);
10532 tkind |= talign << 8;
10533 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10534 build_int_cst (short_unsigned_type_node,
10535 tkind));
10536 if (nc && nc != c)
10537 c = nc;
10540 gcc_assert (map_idx == map_cnt);
10542 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10543 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10544 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10545 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10546 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10548 gimple_seq initlist = NULL;
10549 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10550 TREE_VEC_ELT (t, 1)),
10551 &initlist, true, NULL_TREE);
10552 gimple_seq_add_seq (&ilist, initlist);
10554 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10555 NULL);
10556 TREE_THIS_VOLATILE (clobber) = 1;
10557 gimple_seq_add_stmt (&olist,
10558 gimple_build_assign (TREE_VEC_ELT (t, 1),
10559 clobber));
10562 tree clobber = build_constructor (ctx->record_type, NULL);
10563 TREE_THIS_VOLATILE (clobber) = 1;
10564 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10565 clobber));
10568 /* Once all the expansions are done, sequence all the different
10569 fragments inside gimple_omp_body. */
10571 new_body = NULL;
10573 if (ctx->record_type)
10575 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10576 /* fixup_child_record_type might have changed receiver_decl's type. */
10577 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10578 gimple_seq_add_stmt (&new_body,
10579 gimple_build_assign (ctx->receiver_decl, t));
10582 gimple_seq_add_seq (&new_body, par_body);
10583 gcc_assert (!ctx->cancellable);
10584 new_body = maybe_catch_exception (new_body);
10585 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10586 gimple_omp_set_body (stmt, new_body);
10588 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10589 gsi_replace (gsi_p, bind, true);
10590 gimple_bind_add_seq (bind, irlist);
10591 gimple_bind_add_seq (bind, ilist);
10592 gimple_bind_add_stmt (bind, stmt);
10593 gimple_bind_add_seq (bind, olist);
10594 gimple_bind_add_seq (bind, orlist);
10596 pop_gimplify_context (NULL);
10599 /* If ctx is a worksharing context inside of a cancellable parallel
10600 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10601 and conditional branch to parallel's cancel_label to handle
10602 cancellation in the implicit barrier. */
10604 static void
10605 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10607 gimple omp_return = gimple_seq_last_stmt (*body);
10608 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10609 if (gimple_omp_return_nowait_p (omp_return))
10610 return;
10611 if (ctx->outer
10612 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10613 && ctx->outer->cancellable)
10615 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10616 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10617 tree lhs = create_tmp_var (c_bool_type, NULL);
10618 gimple_omp_return_set_lhs (omp_return, lhs);
10619 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10620 gimple g = gimple_build_cond (NE_EXPR, lhs,
10621 fold_convert (c_bool_type,
10622 boolean_false_node),
10623 ctx->outer->cancel_label, fallthru_label);
10624 gimple_seq_add_stmt (body, g);
10625 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10629 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10630 CTX is the enclosing OMP context for the current statement. */
10632 static void
10633 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10635 tree block, control;
10636 gimple_stmt_iterator tgsi;
10637 gimple stmt, new_stmt, bind, t;
10638 gimple_seq ilist, dlist, olist, new_body;
10640 stmt = gsi_stmt (*gsi_p);
10642 push_gimplify_context ();
10644 dlist = NULL;
10645 ilist = NULL;
10646 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10647 &ilist, &dlist, ctx, NULL);
10649 new_body = gimple_omp_body (stmt);
10650 gimple_omp_set_body (stmt, NULL);
10651 tgsi = gsi_start (new_body);
10652 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10654 omp_context *sctx;
10655 gimple sec_start;
10657 sec_start = gsi_stmt (tgsi);
10658 sctx = maybe_lookup_ctx (sec_start);
10659 gcc_assert (sctx);
10661 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10662 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10663 GSI_CONTINUE_LINKING);
10664 gimple_omp_set_body (sec_start, NULL);
10666 if (gsi_one_before_end_p (tgsi))
10668 gimple_seq l = NULL;
10669 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10670 &l, ctx);
10671 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10672 gimple_omp_section_set_last (sec_start);
10675 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10676 GSI_CONTINUE_LINKING);
10679 block = make_node (BLOCK);
10680 bind = gimple_build_bind (NULL, new_body, block);
10682 olist = NULL;
10683 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10685 block = make_node (BLOCK);
10686 new_stmt = gimple_build_bind (NULL, NULL, block);
10687 gsi_replace (gsi_p, new_stmt, true);
10689 pop_gimplify_context (new_stmt);
10690 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10691 BLOCK_VARS (block) = gimple_bind_vars (bind);
10692 if (BLOCK_VARS (block))
10693 TREE_USED (block) = 1;
10695 new_body = NULL;
10696 gimple_seq_add_seq (&new_body, ilist);
10697 gimple_seq_add_stmt (&new_body, stmt);
10698 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10699 gimple_seq_add_stmt (&new_body, bind);
10701 control = create_tmp_var (unsigned_type_node, ".section");
10702 t = gimple_build_omp_continue (control, control);
10703 gimple_omp_sections_set_control (stmt, control);
10704 gimple_seq_add_stmt (&new_body, t);
10706 gimple_seq_add_seq (&new_body, olist);
10707 if (ctx->cancellable)
10708 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10709 gimple_seq_add_seq (&new_body, dlist);
10711 new_body = maybe_catch_exception (new_body);
10713 t = gimple_build_omp_return
10714 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10715 OMP_CLAUSE_NOWAIT));
10716 gimple_seq_add_stmt (&new_body, t);
10717 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10719 gimple_bind_set_body (new_stmt, new_body);
10723 /* A subroutine of lower_omp_single. Expand the simple form of
10724 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10726 if (GOMP_single_start ())
10727 BODY;
10728 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10730 FIXME. It may be better to delay expanding the logic of this until
10731 pass_expand_omp. The expanded logic may make the job more difficult
10732 to a synchronization analysis pass. */
10734 static void
10735 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
10737 location_t loc = gimple_location (single_stmt);
10738 tree tlabel = create_artificial_label (loc);
10739 tree flabel = create_artificial_label (loc);
10740 gimple call, cond;
10741 tree lhs, decl;
10743 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10744 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
10745 call = gimple_build_call (decl, 0);
10746 gimple_call_set_lhs (call, lhs);
10747 gimple_seq_add_stmt (pre_p, call);
10749 cond = gimple_build_cond (EQ_EXPR, lhs,
10750 fold_convert_loc (loc, TREE_TYPE (lhs),
10751 boolean_true_node),
10752 tlabel, flabel);
10753 gimple_seq_add_stmt (pre_p, cond);
10754 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10755 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10756 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10760 /* A subroutine of lower_omp_single. Expand the simple form of
10761 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10763 #pragma omp single copyprivate (a, b, c)
10765 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10768 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10770 BODY;
10771 copyout.a = a;
10772 copyout.b = b;
10773 copyout.c = c;
10774 GOMP_single_copy_end (&copyout);
10776 else
10778 a = copyout_p->a;
10779 b = copyout_p->b;
10780 c = copyout_p->c;
10782 GOMP_barrier ();
10785 FIXME. It may be better to delay expanding the logic of this until
10786 pass_expand_omp. The expanded logic may make the job more difficult
10787 to a synchronization analysis pass. */
10789 static void
10790 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
10792 tree ptr_type, t, l0, l1, l2, bfn_decl;
10793 gimple_seq copyin_seq;
10794 location_t loc = gimple_location (single_stmt);
10796 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10798 ptr_type = build_pointer_type (ctx->record_type);
10799 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10801 l0 = create_artificial_label (loc);
10802 l1 = create_artificial_label (loc);
10803 l2 = create_artificial_label (loc);
10805 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10806 t = build_call_expr_loc (loc, bfn_decl, 0);
10807 t = fold_convert_loc (loc, ptr_type, t);
10808 gimplify_assign (ctx->receiver_decl, t, pre_p);
10810 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10811 build_int_cst (ptr_type, 0));
10812 t = build3 (COND_EXPR, void_type_node, t,
10813 build_and_jump (&l0), build_and_jump (&l1));
10814 gimplify_and_add (t, pre_p);
10816 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10818 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10820 copyin_seq = NULL;
10821 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10822 &copyin_seq, ctx);
10824 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10825 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10826 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10827 gimplify_and_add (t, pre_p);
10829 t = build_and_jump (&l2);
10830 gimplify_and_add (t, pre_p);
10832 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10834 gimple_seq_add_seq (pre_p, copyin_seq);
10836 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10840 /* Expand code for an OpenMP single directive. */
10842 static void
10843 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10845 tree block;
10846 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
10847 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10849 push_gimplify_context ();
10851 block = make_node (BLOCK);
10852 bind = gimple_build_bind (NULL, NULL, block);
10853 gsi_replace (gsi_p, bind, true);
10854 bind_body = NULL;
10855 dlist = NULL;
10856 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10857 &bind_body, &dlist, ctx, NULL);
10858 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10860 gimple_seq_add_stmt (&bind_body, single_stmt);
10862 if (ctx->record_type)
10863 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10864 else
10865 lower_omp_single_simple (single_stmt, &bind_body);
10867 gimple_omp_set_body (single_stmt, NULL);
10869 gimple_seq_add_seq (&bind_body, dlist);
10871 bind_body = maybe_catch_exception (bind_body);
10873 t = gimple_build_omp_return
10874 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10875 OMP_CLAUSE_NOWAIT));
10876 gimple_seq_add_stmt (&bind_body_tail, t);
10877 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10878 if (ctx->record_type)
10880 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10881 tree clobber = build_constructor (ctx->record_type, NULL);
10882 TREE_THIS_VOLATILE (clobber) = 1;
10883 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10884 clobber), GSI_SAME_STMT);
10886 gimple_seq_add_seq (&bind_body, bind_body_tail);
10887 gimple_bind_set_body (bind, bind_body);
10889 pop_gimplify_context (bind);
10891 gimple_bind_append_vars (bind, ctx->block_vars);
10892 BLOCK_VARS (block) = ctx->block_vars;
10893 if (BLOCK_VARS (block))
10894 TREE_USED (block) = 1;
10898 /* Expand code for an OpenMP master directive. */
10900 static void
10901 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10903 tree block, lab = NULL, x, bfn_decl;
10904 gimple stmt = gsi_stmt (*gsi_p), bind;
10905 location_t loc = gimple_location (stmt);
10906 gimple_seq tseq;
10908 push_gimplify_context ();
10910 block = make_node (BLOCK);
10911 bind = gimple_build_bind (NULL, NULL, block);
10912 gsi_replace (gsi_p, bind, true);
10913 gimple_bind_add_stmt (bind, stmt);
10915 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10916 x = build_call_expr_loc (loc, bfn_decl, 0);
10917 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10918 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10919 tseq = NULL;
10920 gimplify_and_add (x, &tseq);
10921 gimple_bind_add_seq (bind, tseq);
10923 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10924 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10925 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10926 gimple_omp_set_body (stmt, NULL);
10928 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10930 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10932 pop_gimplify_context (bind);
10934 gimple_bind_append_vars (bind, ctx->block_vars);
10935 BLOCK_VARS (block) = ctx->block_vars;
10939 /* Expand code for an OpenMP taskgroup directive. */
10941 static void
10942 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10944 gimple stmt = gsi_stmt (*gsi_p), bind, x;
10945 tree block = make_node (BLOCK);
10947 bind = gimple_build_bind (NULL, NULL, block);
10948 gsi_replace (gsi_p, bind, true);
10949 gimple_bind_add_stmt (bind, stmt);
10951 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10953 gimple_bind_add_stmt (bind, x);
10955 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10956 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10957 gimple_omp_set_body (stmt, NULL);
10959 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10961 gimple_bind_append_vars (bind, ctx->block_vars);
10962 BLOCK_VARS (block) = ctx->block_vars;
10966 /* Expand code for an OpenMP ordered directive. */
10968 static void
10969 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10971 tree block;
10972 gimple stmt = gsi_stmt (*gsi_p), bind, x;
10974 push_gimplify_context ();
10976 block = make_node (BLOCK);
10977 bind = gimple_build_bind (NULL, NULL, block);
10978 gsi_replace (gsi_p, bind, true);
10979 gimple_bind_add_stmt (bind, stmt);
10981 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10983 gimple_bind_add_stmt (bind, x);
10985 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10986 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10987 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10988 gimple_omp_set_body (stmt, NULL);
10990 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10991 gimple_bind_add_stmt (bind, x);
10993 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10995 pop_gimplify_context (bind);
10997 gimple_bind_append_vars (bind, ctx->block_vars);
10998 BLOCK_VARS (block) = gimple_bind_vars (bind);
11002 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
11003 substitution of a couple of function calls. But in the NAMED case,
11004 requires that languages coordinate a symbol name. It is therefore
11005 best put here in common code. */
11007 static GTY((param1_is (tree), param2_is (tree)))
11008 splay_tree critical_name_mutexes;
11010 static void
11011 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11013 tree block;
11014 tree name, lock, unlock;
11015 gimple stmt = gsi_stmt (*gsi_p), bind;
11016 location_t loc = gimple_location (stmt);
11017 gimple_seq tbody;
11019 name = gimple_omp_critical_name (stmt);
11020 if (name)
11022 tree decl;
11023 splay_tree_node n;
11025 if (!critical_name_mutexes)
11026 critical_name_mutexes
11027 = splay_tree_new_ggc (splay_tree_compare_pointers,
11028 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
11029 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
11031 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
11032 if (n == NULL)
11034 char *new_str;
11036 decl = create_tmp_var_raw (ptr_type_node, NULL);
11038 new_str = ACONCAT ((".gomp_critical_user_",
11039 IDENTIFIER_POINTER (name), NULL));
11040 DECL_NAME (decl) = get_identifier (new_str);
11041 TREE_PUBLIC (decl) = 1;
11042 TREE_STATIC (decl) = 1;
11043 DECL_COMMON (decl) = 1;
11044 DECL_ARTIFICIAL (decl) = 1;
11045 DECL_IGNORED_P (decl) = 1;
11046 varpool_node::finalize_decl (decl);
11048 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
11049 (splay_tree_value) decl);
11051 else
11052 decl = (tree) n->value;
11054 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
11055 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
11057 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
11058 unlock = build_call_expr_loc (loc, unlock, 1,
11059 build_fold_addr_expr_loc (loc, decl));
11061 else
11063 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
11064 lock = build_call_expr_loc (loc, lock, 0);
11066 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
11067 unlock = build_call_expr_loc (loc, unlock, 0);
11070 push_gimplify_context ();
11072 block = make_node (BLOCK);
11073 bind = gimple_build_bind (NULL, NULL, block);
11074 gsi_replace (gsi_p, bind, true);
11075 gimple_bind_add_stmt (bind, stmt);
11077 tbody = gimple_bind_body (bind);
11078 gimplify_and_add (lock, &tbody);
11079 gimple_bind_set_body (bind, tbody);
11081 lower_omp (gimple_omp_body_ptr (stmt), ctx);
11082 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
11083 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
11084 gimple_omp_set_body (stmt, NULL);
11086 tbody = gimple_bind_body (bind);
11087 gimplify_and_add (unlock, &tbody);
11088 gimple_bind_set_body (bind, tbody);
11090 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
11092 pop_gimplify_context (bind);
11093 gimple_bind_append_vars (bind, ctx->block_vars);
11094 BLOCK_VARS (block) = gimple_bind_vars (bind);
11098 /* A subroutine of lower_omp_for. Generate code to emit the predicate
11099 for a lastprivate clause. Given a loop control predicate of (V
11100 cond N2), we gate the clause on (!(V cond N2)). The lowered form
11101 is appended to *DLIST, iterator initialization is appended to
11102 *BODY_P. */
11104 static void
11105 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
11106 gimple_seq *dlist, struct omp_context *ctx)
11108 tree clauses, cond, vinit;
11109 enum tree_code cond_code;
11110 gimple_seq stmts;
11112 cond_code = fd->loop.cond_code;
11113 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
11115 /* When possible, use a strict equality expression. This can let VRP
11116 type optimizations deduce the value and remove a copy. */
11117 if (tree_fits_shwi_p (fd->loop.step))
11119 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
11120 if (step == 1 || step == -1)
11121 cond_code = EQ_EXPR;
11124 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
11126 clauses = gimple_omp_for_clauses (fd->for_stmt);
11127 stmts = NULL;
11128 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
11129 if (!gimple_seq_empty_p (stmts))
11131 gimple_seq_add_seq (&stmts, *dlist);
11132 *dlist = stmts;
11134 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
11135 vinit = fd->loop.n1;
11136 if (cond_code == EQ_EXPR
11137 && tree_fits_shwi_p (fd->loop.n2)
11138 && ! integer_zerop (fd->loop.n2))
11139 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
11140 else
11141 vinit = unshare_expr (vinit);
11143 /* Initialize the iterator variable, so that threads that don't execute
11144 any iterations don't execute the lastprivate clauses by accident. */
11145 gimplify_assign (fd->loop.v, vinit, body_p);
11150 /* Lower code for an OpenMP loop directive. */
11152 static void
11153 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11155 tree *rhs_p, block;
11156 struct omp_for_data fd, *fdp = NULL;
11157 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
11158 gimple_seq omp_for_body, body, dlist;
11159 size_t i;
11161 push_gimplify_context ();
11163 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
11165 block = make_node (BLOCK);
11166 new_stmt = gimple_build_bind (NULL, NULL, block);
11167 /* Replace at gsi right away, so that 'stmt' is no member
11168 of a sequence anymore as we're going to add to to a different
11169 one below. */
11170 gsi_replace (gsi_p, new_stmt, true);
11172 /* Move declaration of temporaries in the loop body before we make
11173 it go away. */
11174 omp_for_body = gimple_omp_body (stmt);
11175 if (!gimple_seq_empty_p (omp_for_body)
11176 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
11178 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
11179 tree vars = gimple_bind_vars (inner_bind);
11180 gimple_bind_append_vars (new_stmt, vars);
11181 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
11182 keep them on the inner_bind and it's block. */
11183 gimple_bind_set_vars (inner_bind, NULL_TREE);
11184 if (gimple_bind_block (inner_bind))
11185 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
11188 if (gimple_omp_for_combined_into_p (stmt))
11190 gcc_assert (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_OACC_LOOP);
11192 extract_omp_for_data (stmt, &fd, NULL);
11193 fdp = &fd;
11195 /* We need two temporaries with fd.loop.v type (istart/iend)
11196 and then (fd.collapse - 1) temporaries with the same
11197 type for count2 ... countN-1 vars if not constant. */
11198 size_t count = 2;
11199 tree type = fd.iter_type;
11200 if (fd.collapse > 1
11201 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11202 count += fd.collapse - 1;
11203 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
11204 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
11205 tree clauses = *pc;
11206 if (parallel_for)
11207 outerc
11208 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
11209 OMP_CLAUSE__LOOPTEMP_);
11210 for (i = 0; i < count; i++)
11212 tree temp;
11213 if (parallel_for)
11215 gcc_assert (outerc);
11216 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
11217 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
11218 OMP_CLAUSE__LOOPTEMP_);
11220 else
11222 temp = create_tmp_var (type, NULL);
11223 insert_decl_map (&ctx->outer->cb, temp, temp);
11225 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
11226 OMP_CLAUSE_DECL (*pc) = temp;
11227 pc = &OMP_CLAUSE_CHAIN (*pc);
11229 *pc = clauses;
11232 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
11233 dlist = NULL;
11234 body = NULL;
11235 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
11236 fdp);
11237 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
11239 lower_omp (gimple_omp_body_ptr (stmt), ctx);
11241 /* Lower the header expressions. At this point, we can assume that
11242 the header is of the form:
11244 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
11246 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
11247 using the .omp_data_s mapping, if needed. */
11248 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
11250 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
11251 if (!is_gimple_min_invariant (*rhs_p))
11252 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
11254 rhs_p = gimple_omp_for_final_ptr (stmt, i);
11255 if (!is_gimple_min_invariant (*rhs_p))
11256 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
11258 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
11259 if (!is_gimple_min_invariant (*rhs_p))
11260 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
11263 /* Once lowered, extract the bounds and clauses. */
11264 extract_omp_for_data (stmt, &fd, NULL);
11266 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
11268 gimple_seq_add_stmt (&body, stmt);
11269 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
11271 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
11272 fd.loop.v));
11274 /* After the loop, add exit clauses. */
11275 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
11277 if (ctx->cancellable)
11278 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
11280 gimple_seq_add_seq (&body, dlist);
11282 body = maybe_catch_exception (body);
11284 /* Region exit marker goes at the end of the loop body. */
11285 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
11286 maybe_add_implicit_barrier_cancel (ctx, &body);
11287 pop_gimplify_context (new_stmt);
11289 gimple_bind_append_vars (new_stmt, ctx->block_vars);
11290 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
11291 if (BLOCK_VARS (block))
11292 TREE_USED (block) = 1;
11294 gimple_bind_set_body (new_stmt, body);
11295 gimple_omp_set_body (stmt, NULL);
11296 gimple_omp_for_set_pre_body (stmt, NULL);
11299 /* Callback for walk_stmts. Check if the current statement only contains
11300 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
11302 static tree
11303 check_combined_parallel (gimple_stmt_iterator *gsi_p,
11304 bool *handled_ops_p,
11305 struct walk_stmt_info *wi)
11307 int *info = (int *) wi->info;
11308 gimple stmt = gsi_stmt (*gsi_p);
11310 *handled_ops_p = true;
11311 switch (gimple_code (stmt))
11313 WALK_SUBSTMTS;
11315 case GIMPLE_OMP_FOR:
11316 case GIMPLE_OMP_SECTIONS:
11317 *info = *info == 0 ? 1 : -1;
11318 break;
11319 default:
11320 *info = -1;
11321 break;
11323 return NULL;
11326 struct omp_taskcopy_context
11328 /* This field must be at the beginning, as we do "inheritance": Some
11329 callback functions for tree-inline.c (e.g., omp_copy_decl)
11330 receive a copy_body_data pointer that is up-casted to an
11331 omp_context pointer. */
11332 copy_body_data cb;
11333 omp_context *ctx;
11336 static tree
11337 task_copyfn_copy_decl (tree var, copy_body_data *cb)
11339 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
11341 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
11342 return create_tmp_var (TREE_TYPE (var), NULL);
11344 return var;
11347 static tree
11348 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
11350 tree name, new_fields = NULL, type, f;
11352 type = lang_hooks.types.make_type (RECORD_TYPE);
11353 name = DECL_NAME (TYPE_NAME (orig_type));
11354 name = build_decl (gimple_location (tcctx->ctx->stmt),
11355 TYPE_DECL, name, type);
11356 TYPE_NAME (type) = name;
11358 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
11360 tree new_f = copy_node (f);
11361 DECL_CONTEXT (new_f) = type;
11362 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
11363 TREE_CHAIN (new_f) = new_fields;
11364 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11365 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11366 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
11367 &tcctx->cb, NULL);
11368 new_fields = new_f;
11369 tcctx->cb.decl_map->put (f, new_f);
11371 TYPE_FIELDS (type) = nreverse (new_fields);
11372 layout_type (type);
11373 return type;
11376 /* Create task copyfn. */
11378 static void
11379 create_task_copyfn (gimple task_stmt, omp_context *ctx)
11381 gcc_assert (!is_gimple_omp_oacc_specifically (ctx->stmt));
11383 struct function *child_cfun;
11384 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
11385 tree record_type, srecord_type, bind, list;
11386 bool record_needs_remap = false, srecord_needs_remap = false;
11387 splay_tree_node n;
11388 struct omp_taskcopy_context tcctx;
11389 location_t loc = gimple_location (task_stmt);
11391 child_fn = gimple_omp_task_copy_fn (task_stmt);
11392 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
11393 gcc_assert (child_cfun->cfg == NULL);
11394 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
11396 /* Reset DECL_CONTEXT on function arguments. */
11397 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
11398 DECL_CONTEXT (t) = child_fn;
11400 /* Populate the function. */
11401 push_gimplify_context ();
11402 push_cfun (child_cfun);
11404 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
11405 TREE_SIDE_EFFECTS (bind) = 1;
11406 list = NULL;
11407 DECL_SAVED_TREE (child_fn) = bind;
11408 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
11410 /* Remap src and dst argument types if needed. */
11411 record_type = ctx->record_type;
11412 srecord_type = ctx->srecord_type;
11413 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
11414 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11416 record_needs_remap = true;
11417 break;
11419 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
11420 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11422 srecord_needs_remap = true;
11423 break;
11426 if (record_needs_remap || srecord_needs_remap)
11428 memset (&tcctx, '\0', sizeof (tcctx));
11429 tcctx.cb.src_fn = ctx->cb.src_fn;
11430 tcctx.cb.dst_fn = child_fn;
11431 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
11432 gcc_checking_assert (tcctx.cb.src_node);
11433 tcctx.cb.dst_node = tcctx.cb.src_node;
11434 tcctx.cb.src_cfun = ctx->cb.src_cfun;
11435 tcctx.cb.copy_decl = task_copyfn_copy_decl;
11436 tcctx.cb.eh_lp_nr = 0;
11437 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
11438 tcctx.cb.decl_map = new hash_map<tree, tree>;
11439 tcctx.ctx = ctx;
11441 if (record_needs_remap)
11442 record_type = task_copyfn_remap_type (&tcctx, record_type);
11443 if (srecord_needs_remap)
11444 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
11446 else
11447 tcctx.cb.decl_map = NULL;
11449 arg = DECL_ARGUMENTS (child_fn);
11450 TREE_TYPE (arg) = build_pointer_type (record_type);
11451 sarg = DECL_CHAIN (arg);
11452 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
11454 /* First pass: initialize temporaries used in record_type and srecord_type
11455 sizes and field offsets. */
11456 if (tcctx.cb.decl_map)
11457 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11458 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11460 tree *p;
11462 decl = OMP_CLAUSE_DECL (c);
11463 p = tcctx.cb.decl_map->get (decl);
11464 if (p == NULL)
11465 continue;
11466 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11467 sf = (tree) n->value;
11468 sf = *tcctx.cb.decl_map->get (sf);
11469 src = build_simple_mem_ref_loc (loc, sarg);
11470 src = omp_build_component_ref (src, sf);
11471 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
11472 append_to_statement_list (t, &list);
11475 /* Second pass: copy shared var pointers and copy construct non-VLA
11476 firstprivate vars. */
11477 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11478 switch (OMP_CLAUSE_CODE (c))
11480 case OMP_CLAUSE_SHARED:
11481 decl = OMP_CLAUSE_DECL (c);
11482 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11483 if (n == NULL)
11484 break;
11485 f = (tree) n->value;
11486 if (tcctx.cb.decl_map)
11487 f = *tcctx.cb.decl_map->get (f);
11488 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11489 sf = (tree) n->value;
11490 if (tcctx.cb.decl_map)
11491 sf = *tcctx.cb.decl_map->get (sf);
11492 src = build_simple_mem_ref_loc (loc, sarg);
11493 src = omp_build_component_ref (src, sf);
11494 dst = build_simple_mem_ref_loc (loc, arg);
11495 dst = omp_build_component_ref (dst, f);
11496 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11497 append_to_statement_list (t, &list);
11498 break;
11499 case OMP_CLAUSE_FIRSTPRIVATE:
11500 decl = OMP_CLAUSE_DECL (c);
11501 if (is_variable_sized (decl))
11502 break;
11503 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11504 if (n == NULL)
11505 break;
11506 f = (tree) n->value;
11507 if (tcctx.cb.decl_map)
11508 f = *tcctx.cb.decl_map->get (f);
11509 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11510 if (n != NULL)
11512 sf = (tree) n->value;
11513 if (tcctx.cb.decl_map)
11514 sf = *tcctx.cb.decl_map->get (sf);
11515 src = build_simple_mem_ref_loc (loc, sarg);
11516 src = omp_build_component_ref (src, sf);
11517 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
11518 src = build_simple_mem_ref_loc (loc, src);
11520 else
11521 src = decl;
11522 dst = build_simple_mem_ref_loc (loc, arg);
11523 dst = omp_build_component_ref (dst, f);
11524 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11525 append_to_statement_list (t, &list);
11526 break;
11527 case OMP_CLAUSE_PRIVATE:
11528 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11529 break;
11530 decl = OMP_CLAUSE_DECL (c);
11531 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11532 f = (tree) n->value;
11533 if (tcctx.cb.decl_map)
11534 f = *tcctx.cb.decl_map->get (f);
11535 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11536 if (n != NULL)
11538 sf = (tree) n->value;
11539 if (tcctx.cb.decl_map)
11540 sf = *tcctx.cb.decl_map->get (sf);
11541 src = build_simple_mem_ref_loc (loc, sarg);
11542 src = omp_build_component_ref (src, sf);
11543 if (use_pointer_for_field (decl, NULL))
11544 src = build_simple_mem_ref_loc (loc, src);
11546 else
11547 src = decl;
11548 dst = build_simple_mem_ref_loc (loc, arg);
11549 dst = omp_build_component_ref (dst, f);
11550 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11551 append_to_statement_list (t, &list);
11552 break;
11553 default:
11554 break;
11557 /* Last pass: handle VLA firstprivates. */
11558 if (tcctx.cb.decl_map)
11559 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11560 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11562 tree ind, ptr, df;
11564 decl = OMP_CLAUSE_DECL (c);
11565 if (!is_variable_sized (decl))
11566 continue;
11567 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11568 if (n == NULL)
11569 continue;
11570 f = (tree) n->value;
11571 f = *tcctx.cb.decl_map->get (f);
11572 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11573 ind = DECL_VALUE_EXPR (decl);
11574 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11575 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11576 n = splay_tree_lookup (ctx->sfield_map,
11577 (splay_tree_key) TREE_OPERAND (ind, 0));
11578 sf = (tree) n->value;
11579 sf = *tcctx.cb.decl_map->get (sf);
11580 src = build_simple_mem_ref_loc (loc, sarg);
11581 src = omp_build_component_ref (src, sf);
11582 src = build_simple_mem_ref_loc (loc, src);
11583 dst = build_simple_mem_ref_loc (loc, arg);
11584 dst = omp_build_component_ref (dst, f);
11585 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11586 append_to_statement_list (t, &list);
11587 n = splay_tree_lookup (ctx->field_map,
11588 (splay_tree_key) TREE_OPERAND (ind, 0));
11589 df = (tree) n->value;
11590 df = *tcctx.cb.decl_map->get (df);
11591 ptr = build_simple_mem_ref_loc (loc, arg);
11592 ptr = omp_build_component_ref (ptr, df);
11593 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11594 build_fold_addr_expr_loc (loc, dst));
11595 append_to_statement_list (t, &list);
11598 t = build1 (RETURN_EXPR, void_type_node, NULL);
11599 append_to_statement_list (t, &list);
11601 if (tcctx.cb.decl_map)
11602 delete tcctx.cb.decl_map;
11603 pop_gimplify_context (NULL);
11604 BIND_EXPR_BODY (bind) = list;
11605 pop_cfun ();
11608 static void
11609 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11611 tree c, clauses;
11612 gimple g;
11613 size_t n_in = 0, n_out = 0, idx = 2, i;
11615 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11616 OMP_CLAUSE_DEPEND);
11617 gcc_assert (clauses);
11618 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11619 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11620 switch (OMP_CLAUSE_DEPEND_KIND (c))
11622 case OMP_CLAUSE_DEPEND_IN:
11623 n_in++;
11624 break;
11625 case OMP_CLAUSE_DEPEND_OUT:
11626 case OMP_CLAUSE_DEPEND_INOUT:
11627 n_out++;
11628 break;
11629 default:
11630 gcc_unreachable ();
11632 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11633 tree array = create_tmp_var (type, NULL);
11634 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11635 NULL_TREE);
11636 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11637 gimple_seq_add_stmt (iseq, g);
11638 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11639 NULL_TREE);
11640 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11641 gimple_seq_add_stmt (iseq, g);
11642 for (i = 0; i < 2; i++)
11644 if ((i ? n_in : n_out) == 0)
11645 continue;
11646 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11647 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11648 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11650 tree t = OMP_CLAUSE_DECL (c);
11651 t = fold_convert (ptr_type_node, t);
11652 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11653 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11654 NULL_TREE, NULL_TREE);
11655 g = gimple_build_assign (r, t);
11656 gimple_seq_add_stmt (iseq, g);
11659 tree *p = gimple_omp_task_clauses_ptr (stmt);
11660 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11661 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11662 OMP_CLAUSE_CHAIN (c) = *p;
11663 *p = c;
11664 tree clobber = build_constructor (type, NULL);
11665 TREE_THIS_VOLATILE (clobber) = 1;
11666 g = gimple_build_assign (array, clobber);
11667 gimple_seq_add_stmt (oseq, g);
11670 /* Lower the OpenMP parallel or task directive in the current statement
11671 in GSI_P. CTX holds context information for the directive. */
11673 static void
11674 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11676 tree clauses;
11677 tree child_fn, t;
11678 gimple stmt = gsi_stmt (*gsi_p);
11679 gimple par_bind, bind, dep_bind = NULL;
11680 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11681 location_t loc = gimple_location (stmt);
11683 clauses = gimple_omp_taskreg_clauses (stmt);
11684 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
11685 par_body = gimple_bind_body (par_bind);
11686 child_fn = ctx->cb.dst_fn;
11687 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11688 && !gimple_omp_parallel_combined_p (stmt))
11690 struct walk_stmt_info wi;
11691 int ws_num = 0;
11693 memset (&wi, 0, sizeof (wi));
11694 wi.info = &ws_num;
11695 wi.val_only = true;
11696 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11697 if (ws_num == 1)
11698 gimple_omp_parallel_set_combined_p (stmt, true);
11700 gimple_seq dep_ilist = NULL;
11701 gimple_seq dep_olist = NULL;
11702 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11703 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11705 push_gimplify_context ();
11706 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11707 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11710 if (ctx->srecord_type)
11711 create_task_copyfn (stmt, ctx);
11713 push_gimplify_context ();
11715 par_olist = NULL;
11716 par_ilist = NULL;
11717 par_rlist = NULL;
11718 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11719 lower_omp (&par_body, ctx);
11720 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11721 lower_reduction_clauses (clauses, &par_rlist, ctx);
11723 /* Declare all the variables created by mapping and the variables
11724 declared in the scope of the parallel body. */
11725 record_vars_into (ctx->block_vars, child_fn);
11726 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11728 if (ctx->record_type)
11730 ctx->sender_decl
11731 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11732 : ctx->record_type, ".omp_data_o");
11733 DECL_NAMELESS (ctx->sender_decl) = 1;
11734 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11735 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11738 olist = NULL;
11739 ilist = NULL;
11740 lower_send_clauses (clauses, &ilist, &olist, ctx);
11741 lower_send_shared_vars (&ilist, &olist, ctx);
11743 if (ctx->record_type)
11745 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11746 TREE_THIS_VOLATILE (clobber) = 1;
11747 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11748 clobber));
11751 /* Once all the expansions are done, sequence all the different
11752 fragments inside gimple_omp_body. */
11754 new_body = NULL;
11756 if (ctx->record_type)
11758 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11759 /* fixup_child_record_type might have changed receiver_decl's type. */
11760 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11761 gimple_seq_add_stmt (&new_body,
11762 gimple_build_assign (ctx->receiver_decl, t));
11765 gimple_seq_add_seq (&new_body, par_ilist);
11766 gimple_seq_add_seq (&new_body, par_body);
11767 gimple_seq_add_seq (&new_body, par_rlist);
11768 if (ctx->cancellable)
11769 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11770 gimple_seq_add_seq (&new_body, par_olist);
11771 new_body = maybe_catch_exception (new_body);
11772 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11773 gimple_omp_set_body (stmt, new_body);
11775 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11776 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11777 gimple_bind_add_seq (bind, ilist);
11778 gimple_bind_add_stmt (bind, stmt);
11779 gimple_bind_add_seq (bind, olist);
11781 pop_gimplify_context (NULL);
11783 if (dep_bind)
11785 gimple_bind_add_seq (dep_bind, dep_ilist);
11786 gimple_bind_add_stmt (dep_bind, bind);
11787 gimple_bind_add_seq (dep_bind, dep_olist);
11788 pop_gimplify_context (dep_bind);
11792 /* Lower the GIMPLE_OMP_TARGET in the current statement
11793 in GSI_P. CTX holds context information for the directive. */
11795 static void
11796 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11798 tree clauses;
11799 tree child_fn, t, c;
11800 gimple stmt = gsi_stmt (*gsi_p);
11801 gimple tgt_bind = NULL, bind;
11802 gimple_seq tgt_body = NULL, olist, ilist, new_body;
11803 location_t loc = gimple_location (stmt);
11804 int kind = gimple_omp_target_kind (stmt);
11805 unsigned int map_cnt = 0;
11807 clauses = gimple_omp_target_clauses (stmt);
11808 if (kind == GF_OMP_TARGET_KIND_REGION)
11810 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
11811 tgt_body = gimple_bind_body (tgt_bind);
11813 else if (kind == GF_OMP_TARGET_KIND_DATA
11814 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
11815 tgt_body = gimple_omp_body (stmt);
11816 child_fn = ctx->cb.dst_fn;
11818 push_gimplify_context ();
11820 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11821 switch (OMP_CLAUSE_CODE (c))
11823 tree var, x;
11825 default:
11826 break;
11827 case OMP_CLAUSE_MAP:
11828 #ifdef ENABLE_CHECKING
11829 /* First check what we're prepared to handle in the following. */
11830 switch (OMP_CLAUSE_MAP_KIND (c))
11832 case OMP_CLAUSE_MAP_ALLOC:
11833 case OMP_CLAUSE_MAP_TO:
11834 case OMP_CLAUSE_MAP_FROM:
11835 case OMP_CLAUSE_MAP_TOFROM:
11836 case OMP_CLAUSE_MAP_POINTER:
11837 case OMP_CLAUSE_MAP_TO_PSET:
11838 break;
11839 case OMP_CLAUSE_MAP_FORCE_ALLOC:
11840 case OMP_CLAUSE_MAP_FORCE_TO:
11841 case OMP_CLAUSE_MAP_FORCE_FROM:
11842 case OMP_CLAUSE_MAP_FORCE_TOFROM:
11843 case OMP_CLAUSE_MAP_FORCE_PRESENT:
11844 case OMP_CLAUSE_MAP_FORCE_DEALLOC:
11845 case OMP_CLAUSE_MAP_FORCE_DEVICEPTR:
11846 gcc_assert (kind == GF_OMP_TARGET_KIND_OACC_DATA
11847 || kind == GF_OMP_TARGET_KIND_OACC_UPDATE);
11848 break;
11849 default:
11850 gcc_unreachable ();
11852 #endif
11853 /* FALLTHRU */
11855 case OMP_CLAUSE_TO:
11856 case OMP_CLAUSE_FROM:
11857 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
11858 gcc_assert (kind != GF_OMP_TARGET_KIND_OACC_DATA
11859 && kind != GF_OMP_TARGET_KIND_OACC_UPDATE);
11860 var = OMP_CLAUSE_DECL (c);
11861 if (!DECL_P (var))
11863 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11864 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11865 map_cnt++;
11866 continue;
11869 if (DECL_SIZE (var)
11870 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11872 tree var2 = DECL_VALUE_EXPR (var);
11873 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11874 var2 = TREE_OPERAND (var2, 0);
11875 gcc_assert (DECL_P (var2));
11876 var = var2;
11879 if (!maybe_lookup_field (var, ctx))
11880 continue;
11882 if (kind == GF_OMP_TARGET_KIND_REGION)
11884 x = build_receiver_ref (var, true, ctx);
11885 tree new_var = lookup_decl (var, ctx);
11886 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11887 || (OMP_CLAUSE_MAP_KIND (c)
11888 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11889 || TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE);
11890 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11891 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
11892 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11893 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11894 x = build_simple_mem_ref (x);
11895 SET_DECL_VALUE_EXPR (new_var, x);
11896 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11898 map_cnt++;
11901 if (kind == GF_OMP_TARGET_KIND_REGION)
11903 target_nesting_level++;
11904 lower_omp (&tgt_body, ctx);
11905 target_nesting_level--;
11907 else if (kind == GF_OMP_TARGET_KIND_DATA
11908 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
11909 lower_omp (&tgt_body, ctx);
11911 if (kind == GF_OMP_TARGET_KIND_REGION)
11913 /* Declare all the variables created by mapping and the variables
11914 declared in the scope of the target body. */
11915 record_vars_into (ctx->block_vars, child_fn);
11916 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11919 olist = NULL;
11920 ilist = NULL;
11921 if (ctx->record_type)
11923 ctx->sender_decl
11924 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11925 DECL_NAMELESS (ctx->sender_decl) = 1;
11926 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11927 t = make_tree_vec (3);
11928 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11929 TREE_VEC_ELT (t, 1)
11930 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11931 ".omp_data_sizes");
11932 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11933 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11934 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11935 tree tkind_type;
11936 int talign_shift;
11937 switch (kind)
11939 case GF_OMP_TARGET_KIND_REGION:
11940 case GF_OMP_TARGET_KIND_DATA:
11941 case GF_OMP_TARGET_KIND_UPDATE:
11942 tkind_type = unsigned_char_type_node;
11943 talign_shift = 3;
11944 break;
11945 case GF_OMP_TARGET_KIND_OACC_DATA:
11946 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11947 tkind_type = short_unsigned_type_node;
11948 talign_shift = 8;
11949 break;
11950 default:
11951 gcc_unreachable ();
11953 TREE_VEC_ELT (t, 2)
11954 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11955 ".omp_data_kinds");
11956 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11957 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11958 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11959 gimple_omp_target_set_data_arg (stmt, t);
11961 vec<constructor_elt, va_gc> *vsize;
11962 vec<constructor_elt, va_gc> *vkind;
11963 vec_alloc (vsize, map_cnt);
11964 vec_alloc (vkind, map_cnt);
11965 unsigned int map_idx = 0;
11967 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11968 switch (OMP_CLAUSE_CODE (c))
11970 tree ovar, nc;
11972 default:
11973 break;
11974 case OMP_CLAUSE_MAP:
11975 case OMP_CLAUSE_TO:
11976 case OMP_CLAUSE_FROM:
11977 nc = c;
11978 ovar = OMP_CLAUSE_DECL (c);
11979 if (!DECL_P (ovar))
11981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11982 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11984 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11985 == get_base_address (ovar));
11986 nc = OMP_CLAUSE_CHAIN (c);
11987 ovar = OMP_CLAUSE_DECL (nc);
11989 else
11991 tree x = build_sender_ref (ovar, ctx);
11992 tree v
11993 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11994 gimplify_assign (x, v, &ilist);
11995 nc = NULL_TREE;
11998 else
12000 if (DECL_SIZE (ovar)
12001 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
12003 tree ovar2 = DECL_VALUE_EXPR (ovar);
12004 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
12005 ovar2 = TREE_OPERAND (ovar2, 0);
12006 gcc_assert (DECL_P (ovar2));
12007 ovar = ovar2;
12009 if (!maybe_lookup_field (ovar, ctx))
12010 continue;
12013 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
12014 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
12015 talign = DECL_ALIGN_UNIT (ovar);
12016 if (nc)
12018 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
12019 tree x = build_sender_ref (ovar, ctx);
12020 gcc_assert (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
12021 || (OMP_CLAUSE_MAP_KIND (c)
12022 != OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
12023 || TREE_CODE (TREE_TYPE (ovar)) != ARRAY_TYPE);
12024 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12025 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
12026 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
12027 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
12029 tree avar
12030 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
12031 mark_addressable (avar);
12032 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
12033 talign = DECL_ALIGN_UNIT (avar);
12034 avar = build_fold_addr_expr (avar);
12035 gimplify_assign (x, avar, &ilist);
12037 else if (is_gimple_reg (var))
12039 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
12040 mark_addressable (avar);
12041 enum omp_clause_map_kind map_kind
12042 = OMP_CLAUSE_MAP_KIND (c);
12043 if ((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
12044 && (map_kind & OMP_CLAUSE_MAP_TO))
12045 || map_kind == OMP_CLAUSE_MAP_POINTER
12046 || map_kind == OMP_CLAUSE_MAP_TO_PSET
12047 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
12048 gimplify_assign (avar, var, &ilist);
12049 avar = build_fold_addr_expr (avar);
12050 gimplify_assign (x, avar, &ilist);
12051 if (((!(map_kind & OMP_CLAUSE_MAP_SPECIAL)
12052 && (map_kind & OMP_CLAUSE_MAP_FROM))
12053 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
12054 && !TYPE_READONLY (TREE_TYPE (var)))
12056 x = build_sender_ref (ovar, ctx);
12057 x = build_simple_mem_ref (x);
12058 gimplify_assign (var, x, &olist);
12061 else
12063 var = build_fold_addr_expr (var);
12064 gimplify_assign (x, var, &ilist);
12067 tree s = OMP_CLAUSE_SIZE (c);
12068 if (s == NULL_TREE)
12069 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
12070 s = fold_convert (size_type_node, s);
12071 tree purpose = size_int (map_idx++);
12072 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
12073 if (TREE_CODE (s) != INTEGER_CST)
12074 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
12076 unsigned HOST_WIDE_INT tkind;
12077 switch (OMP_CLAUSE_CODE (c))
12079 case OMP_CLAUSE_MAP:
12080 tkind = OMP_CLAUSE_MAP_KIND (c);
12081 break;
12082 case OMP_CLAUSE_TO:
12083 tkind = OMP_CLAUSE_MAP_TO;
12084 break;
12085 case OMP_CLAUSE_FROM:
12086 tkind = OMP_CLAUSE_MAP_FROM;
12087 break;
12088 default:
12089 gcc_unreachable ();
12091 gcc_assert (tkind < (HOST_WIDE_INT_C (1U) << talign_shift));
12092 talign = ceil_log2 (talign);
12093 tkind |= talign << talign_shift;
12094 gcc_assert (tkind <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
12095 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
12096 build_int_cstu (tkind_type, tkind));
12097 if (nc && nc != c)
12098 c = nc;
12101 gcc_assert (map_idx == map_cnt);
12103 DECL_INITIAL (TREE_VEC_ELT (t, 1))
12104 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
12105 DECL_INITIAL (TREE_VEC_ELT (t, 2))
12106 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
12107 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
12109 gimple_seq initlist = NULL;
12110 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
12111 TREE_VEC_ELT (t, 1)),
12112 &initlist, true, NULL_TREE);
12113 gimple_seq_add_seq (&ilist, initlist);
12115 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
12116 NULL);
12117 TREE_THIS_VOLATILE (clobber) = 1;
12118 gimple_seq_add_stmt (&olist,
12119 gimple_build_assign (TREE_VEC_ELT (t, 1),
12120 clobber));
12123 tree clobber = build_constructor (ctx->record_type, NULL);
12124 TREE_THIS_VOLATILE (clobber) = 1;
12125 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
12126 clobber));
12129 /* Once all the expansions are done, sequence all the different
12130 fragments inside gimple_omp_body. */
12132 new_body = NULL;
12134 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
12136 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
12137 /* fixup_child_record_type might have changed receiver_decl's type. */
12138 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
12139 gimple_seq_add_stmt (&new_body,
12140 gimple_build_assign (ctx->receiver_decl, t));
12143 if (kind == GF_OMP_TARGET_KIND_REGION)
12145 gimple_seq_add_seq (&new_body, tgt_body);
12146 new_body = maybe_catch_exception (new_body);
12148 else if (kind == GF_OMP_TARGET_KIND_DATA
12149 || kind == GF_OMP_TARGET_KIND_OACC_DATA)
12150 new_body = tgt_body;
12151 if (kind != GF_OMP_TARGET_KIND_UPDATE
12152 && kind != GF_OMP_TARGET_KIND_OACC_UPDATE)
12154 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
12155 gimple_omp_set_body (stmt, new_body);
12158 bind = gimple_build_bind (NULL, NULL,
12159 tgt_bind ? gimple_bind_block (tgt_bind)
12160 : NULL_TREE);
12161 gsi_replace (gsi_p, bind, true);
12162 gimple_bind_add_seq (bind, ilist);
12163 gimple_bind_add_stmt (bind, stmt);
12164 gimple_bind_add_seq (bind, olist);
12166 pop_gimplify_context (NULL);
12169 /* Expand code for an OpenMP teams directive. */
12171 static void
12172 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12174 gimple teams_stmt = gsi_stmt (*gsi_p);
12175 push_gimplify_context ();
12177 tree block = make_node (BLOCK);
12178 gimple bind = gimple_build_bind (NULL, NULL, block);
12179 gsi_replace (gsi_p, bind, true);
12180 gimple_seq bind_body = NULL;
12181 gimple_seq dlist = NULL;
12182 gimple_seq olist = NULL;
12184 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
12185 OMP_CLAUSE_NUM_TEAMS);
12186 if (num_teams == NULL_TREE)
12187 num_teams = build_int_cst (unsigned_type_node, 0);
12188 else
12190 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
12191 num_teams = fold_convert (unsigned_type_node, num_teams);
12192 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
12194 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
12195 OMP_CLAUSE_THREAD_LIMIT);
12196 if (thread_limit == NULL_TREE)
12197 thread_limit = build_int_cst (unsigned_type_node, 0);
12198 else
12200 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
12201 thread_limit = fold_convert (unsigned_type_node, thread_limit);
12202 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
12203 fb_rvalue);
12206 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
12207 &bind_body, &dlist, ctx, NULL);
12208 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
12209 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
12210 gimple_seq_add_stmt (&bind_body, teams_stmt);
12212 location_t loc = gimple_location (teams_stmt);
12213 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
12214 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
12215 gimple_set_location (call, loc);
12216 gimple_seq_add_stmt (&bind_body, call);
12218 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
12219 gimple_omp_set_body (teams_stmt, NULL);
12220 gimple_seq_add_seq (&bind_body, olist);
12221 gimple_seq_add_seq (&bind_body, dlist);
12222 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
12223 gimple_bind_set_body (bind, bind_body);
12225 pop_gimplify_context (bind);
12227 gimple_bind_append_vars (bind, ctx->block_vars);
12228 BLOCK_VARS (block) = ctx->block_vars;
12229 if (BLOCK_VARS (block))
12230 TREE_USED (block) = 1;
12234 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
12235 regimplified. If DATA is non-NULL, lower_omp_1 is outside
12236 of OpenMP context, but with task_shared_vars set. */
12238 static tree
12239 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
12240 void *data)
12242 tree t = *tp;
12244 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
12245 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
12246 return t;
12248 if (task_shared_vars
12249 && DECL_P (t)
12250 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
12251 return t;
12253 /* If a global variable has been privatized, TREE_CONSTANT on
12254 ADDR_EXPR might be wrong. */
12255 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
12256 recompute_tree_invariant_for_addr_expr (t);
12258 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
12259 return NULL_TREE;
12262 static void
12263 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12265 gimple stmt = gsi_stmt (*gsi_p);
12266 struct walk_stmt_info wi;
12268 if (gimple_has_location (stmt))
12269 input_location = gimple_location (stmt);
12271 if (task_shared_vars)
12272 memset (&wi, '\0', sizeof (wi));
12274 /* If we have issued syntax errors, avoid doing any heavy lifting.
12275 Just replace the OpenMP directives with a NOP to avoid
12276 confusing RTL expansion. */
12277 if (seen_error () && is_gimple_omp (stmt))
12279 gsi_replace (gsi_p, gimple_build_nop (), true);
12280 return;
12283 switch (gimple_code (stmt))
12285 case GIMPLE_COND:
12286 if ((ctx || task_shared_vars)
12287 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
12288 ctx ? NULL : &wi, NULL)
12289 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
12290 ctx ? NULL : &wi, NULL)))
12291 gimple_regimplify_operands (stmt, gsi_p);
12292 break;
12293 case GIMPLE_CATCH:
12294 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
12295 break;
12296 case GIMPLE_EH_FILTER:
12297 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
12298 break;
12299 case GIMPLE_TRY:
12300 lower_omp (gimple_try_eval_ptr (stmt), ctx);
12301 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
12302 break;
12303 case GIMPLE_TRANSACTION:
12304 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
12305 break;
12306 case GIMPLE_BIND:
12307 lower_omp (gimple_bind_body_ptr (stmt), ctx);
12308 break;
12309 case GIMPLE_OACC_KERNELS:
12310 case GIMPLE_OACC_PARALLEL:
12311 ctx = maybe_lookup_ctx (stmt);
12312 gcc_assert (ctx);
12313 gcc_assert (!ctx->cancellable);
12314 lower_oacc_offload (gsi_p, ctx);
12315 break;
12316 case GIMPLE_OMP_PARALLEL:
12317 case GIMPLE_OMP_TASK:
12318 ctx = maybe_lookup_ctx (stmt);
12319 gcc_assert (ctx);
12320 if (ctx->cancellable)
12321 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12322 lower_omp_taskreg (gsi_p, ctx);
12323 break;
12324 case GIMPLE_OMP_FOR:
12325 ctx = maybe_lookup_ctx (stmt);
12326 gcc_assert (ctx);
12327 if (ctx->cancellable)
12328 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12329 lower_omp_for (gsi_p, ctx);
12330 break;
12331 case GIMPLE_OMP_SECTIONS:
12332 ctx = maybe_lookup_ctx (stmt);
12333 gcc_assert (ctx);
12334 if (ctx->cancellable)
12335 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12336 lower_omp_sections (gsi_p, ctx);
12337 break;
12338 case GIMPLE_OMP_SINGLE:
12339 ctx = maybe_lookup_ctx (stmt);
12340 gcc_assert (ctx);
12341 lower_omp_single (gsi_p, ctx);
12342 break;
12343 case GIMPLE_OMP_MASTER:
12344 ctx = maybe_lookup_ctx (stmt);
12345 gcc_assert (ctx);
12346 lower_omp_master (gsi_p, ctx);
12347 break;
12348 case GIMPLE_OMP_TASKGROUP:
12349 ctx = maybe_lookup_ctx (stmt);
12350 gcc_assert (ctx);
12351 lower_omp_taskgroup (gsi_p, ctx);
12352 break;
12353 case GIMPLE_OMP_ORDERED:
12354 ctx = maybe_lookup_ctx (stmt);
12355 gcc_assert (ctx);
12356 lower_omp_ordered (gsi_p, ctx);
12357 break;
12358 case GIMPLE_OMP_CRITICAL:
12359 ctx = maybe_lookup_ctx (stmt);
12360 gcc_assert (ctx);
12361 lower_omp_critical (gsi_p, ctx);
12362 break;
12363 case GIMPLE_OMP_ATOMIC_LOAD:
12364 if ((ctx || task_shared_vars)
12365 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
12366 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
12367 gimple_regimplify_operands (stmt, gsi_p);
12368 break;
12369 case GIMPLE_OMP_TARGET:
12370 ctx = maybe_lookup_ctx (stmt);
12371 gcc_assert (ctx);
12372 if (gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_DATA
12373 || gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_UPDATE)
12374 gcc_assert (!ctx->cancellable);
12375 lower_omp_target (gsi_p, ctx);
12376 break;
12377 case GIMPLE_OMP_TEAMS:
12378 ctx = maybe_lookup_ctx (stmt);
12379 gcc_assert (ctx);
12380 lower_omp_teams (gsi_p, ctx);
12381 break;
12382 case GIMPLE_CALL:
12383 tree fndecl;
12384 fndecl = gimple_call_fndecl (stmt);
12385 if (fndecl
12386 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
12387 switch (DECL_FUNCTION_CODE (fndecl))
12389 case BUILT_IN_GOMP_BARRIER:
12390 if (ctx == NULL)
12391 break;
12392 /* FALLTHRU */
12393 case BUILT_IN_GOMP_CANCEL:
12394 case BUILT_IN_GOMP_CANCELLATION_POINT:
12395 omp_context *cctx;
12396 cctx = ctx;
12397 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
12398 cctx = cctx->outer;
12399 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
12400 if (!cctx->cancellable)
12402 if (DECL_FUNCTION_CODE (fndecl)
12403 == BUILT_IN_GOMP_CANCELLATION_POINT)
12405 stmt = gimple_build_nop ();
12406 gsi_replace (gsi_p, stmt, false);
12408 break;
12410 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
12412 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
12413 gimple_call_set_fndecl (stmt, fndecl);
12414 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
12416 tree lhs;
12417 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
12418 gimple_call_set_lhs (stmt, lhs);
12419 tree fallthru_label;
12420 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
12421 gimple g;
12422 g = gimple_build_label (fallthru_label);
12423 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12424 g = gimple_build_cond (NE_EXPR, lhs,
12425 fold_convert (TREE_TYPE (lhs),
12426 boolean_false_node),
12427 cctx->cancel_label, fallthru_label);
12428 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12429 break;
12430 default:
12431 break;
12433 /* FALLTHRU */
12434 default:
12435 if ((ctx || task_shared_vars)
12436 && walk_gimple_op (stmt, lower_omp_regimplify_p,
12437 ctx ? NULL : &wi))
12439 /* Just remove clobbers, this should happen only if we have
12440 "privatized" local addressable variables in SIMD regions,
12441 the clobber isn't needed in that case and gimplifying address
12442 of the ARRAY_REF into a pointer and creating MEM_REF based
12443 clobber would create worse code than we get with the clobber
12444 dropped. */
12445 if (gimple_clobber_p (stmt))
12447 gsi_replace (gsi_p, gimple_build_nop (), true);
12448 break;
12450 gimple_regimplify_operands (stmt, gsi_p);
12452 break;
12456 static void
12457 lower_omp (gimple_seq *body, omp_context *ctx)
12459 location_t saved_location = input_location;
12460 gimple_stmt_iterator gsi;
12461 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12462 lower_omp_1 (&gsi, ctx);
12463 /* During gimplification, we haven't folded statments inside offloading
12464 regions (gimplify.c:maybe_fold_stmt); do that now. */
12465 if (target_nesting_level)
12466 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12467 fold_stmt (&gsi);
12468 input_location = saved_location;
12471 /* Main entry point. */
12473 static unsigned int
12474 execute_lower_omp (void)
12476 gimple_seq body;
12477 int i;
12478 omp_context *ctx;
12480 /* This pass always runs, to provide PROP_gimple_lomp.
12481 But often, there is nothing to do. */
12482 if (flag_openacc == 0 && flag_openmp == 0 && flag_openmp_simd == 0
12483 && flag_cilkplus == 0)
12484 return 0;
12486 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
12487 delete_omp_context);
12489 body = gimple_body (current_function_decl);
12490 scan_omp (&body, NULL);
12491 gcc_assert (taskreg_nesting_level == 0);
12492 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12493 finish_taskreg_scan (ctx);
12494 taskreg_contexts.release ();
12496 if (all_contexts->root)
12498 if (task_shared_vars)
12499 push_gimplify_context ();
12500 lower_omp (&body, NULL);
12501 if (task_shared_vars)
12502 pop_gimplify_context (NULL);
12505 if (all_contexts)
12507 splay_tree_delete (all_contexts);
12508 all_contexts = NULL;
12510 BITMAP_FREE (task_shared_vars);
12511 return 0;
12514 namespace {
12516 const pass_data pass_data_lower_omp =
12518 GIMPLE_PASS, /* type */
12519 "omplower", /* name */
12520 OPTGROUP_NONE, /* optinfo_flags */
12521 TV_NONE, /* tv_id */
12522 PROP_gimple_any, /* properties_required */
12523 PROP_gimple_lomp, /* properties_provided */
12524 0, /* properties_destroyed */
12525 0, /* todo_flags_start */
12526 0, /* todo_flags_finish */
12529 class pass_lower_omp : public gimple_opt_pass
12531 public:
12532 pass_lower_omp (gcc::context *ctxt)
12533 : gimple_opt_pass (pass_data_lower_omp, ctxt)
12536 /* opt_pass methods: */
12537 virtual unsigned int execute (function *) { return execute_lower_omp (); }
12539 }; // class pass_lower_omp
12541 } // anon namespace
12543 gimple_opt_pass *
12544 make_pass_lower_omp (gcc::context *ctxt)
12546 return new pass_lower_omp (ctxt);
12549 /* The following is a utility to diagnose structured block violations.
12550 It is not part of the "omplower" pass, as that's invoked too late. It
12551 should be invoked by the respective front ends after gimplification. */
12553 static splay_tree all_labels;
12555 /* Check for mismatched contexts and generate an error if needed. Return
12556 true if an error is detected. */
12558 static bool
12559 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12560 gimple branch_ctx, gimple label_ctx)
12562 gcc_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12563 gcc_assert (!label_ctx || is_gimple_omp (label_ctx));
12565 if (label_ctx == branch_ctx)
12566 return false;
12568 const char* kind = NULL;
12570 if (flag_cilkplus)
12572 if ((branch_ctx
12573 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12574 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12575 || (label_ctx
12576 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12577 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12578 kind = "Cilk Plus";
12580 if (flag_openacc)
12582 if ((branch_ctx && is_gimple_omp_oacc_specifically (branch_ctx))
12583 || (label_ctx && is_gimple_omp_oacc_specifically (label_ctx)))
12585 gcc_assert (kind == NULL);
12586 kind = "OpenACC";
12589 if (kind == NULL)
12591 gcc_assert (flag_openmp);
12592 kind = "OpenMP";
12596 Previously we kept track of the label's entire context in diagnose_sb_[12]
12597 so we could traverse it and issue a correct "exit" or "enter" error
12598 message upon a structured block violation.
12600 We built the context by building a list with tree_cons'ing, but there is
12601 no easy counterpart in gimple tuples. It seems like far too much work
12602 for issuing exit/enter error messages. If someone really misses the
12603 distinct error message... patches welcome.
12606 #if 0
12607 /* Try to avoid confusing the user by producing and error message
12608 with correct "exit" or "enter" verbiage. We prefer "exit"
12609 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12610 if (branch_ctx == NULL)
12611 exit_p = false;
12612 else
12614 while (label_ctx)
12616 if (TREE_VALUE (label_ctx) == branch_ctx)
12618 exit_p = false;
12619 break;
12621 label_ctx = TREE_CHAIN (label_ctx);
12625 if (exit_p)
12626 error ("invalid exit from %s structured block", kind);
12627 else
12628 error ("invalid entry to %s structured block", kind);
12629 #endif
12631 /* If it's obvious we have an invalid entry, be specific about the error. */
12632 if (branch_ctx == NULL)
12633 error ("invalid entry to %s structured block", kind);
12634 else
12636 /* Otherwise, be vague and lazy, but efficient. */
12637 error ("invalid branch to/from %s structured block", kind);
12640 gsi_replace (gsi_p, gimple_build_nop (), false);
12641 return true;
12644 /* Pass 1: Create a minimal tree of structured blocks, and record
12645 where each label is found. */
12647 static tree
12648 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12649 struct walk_stmt_info *wi)
12651 gimple context = (gimple) wi->info;
12652 gimple inner_context;
12653 gimple stmt = gsi_stmt (*gsi_p);
12655 *handled_ops_p = true;
12657 switch (gimple_code (stmt))
12659 WALK_SUBSTMTS;
12661 case GIMPLE_OACC_KERNELS:
12662 case GIMPLE_OACC_PARALLEL:
12663 case GIMPLE_OMP_PARALLEL:
12664 case GIMPLE_OMP_TASK:
12665 case GIMPLE_OMP_SECTIONS:
12666 case GIMPLE_OMP_SINGLE:
12667 case GIMPLE_OMP_SECTION:
12668 case GIMPLE_OMP_MASTER:
12669 case GIMPLE_OMP_ORDERED:
12670 case GIMPLE_OMP_CRITICAL:
12671 case GIMPLE_OMP_TARGET:
12672 case GIMPLE_OMP_TEAMS:
12673 case GIMPLE_OMP_TASKGROUP:
12674 /* The minimal context here is just the current construct. */
12675 inner_context = stmt;
12676 wi->info = inner_context;
12677 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12678 wi->info = context;
12679 break;
12681 case GIMPLE_OMP_FOR:
12682 inner_context = stmt;
12683 wi->info = inner_context;
12684 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12685 walk them. */
12686 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12687 diagnose_sb_1, NULL, wi);
12688 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12689 wi->info = context;
12690 break;
12692 case GIMPLE_LABEL:
12693 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
12694 (splay_tree_value) context);
12695 break;
12697 default:
12698 break;
12701 return NULL_TREE;
12704 /* Pass 2: Check each branch and see if its context differs from that of
12705 the destination label's context. */
12707 static tree
12708 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12709 struct walk_stmt_info *wi)
12711 gimple context = (gimple) wi->info;
12712 splay_tree_node n;
12713 gimple stmt = gsi_stmt (*gsi_p);
12715 *handled_ops_p = true;
12717 switch (gimple_code (stmt))
12719 WALK_SUBSTMTS;
12721 case GIMPLE_OACC_KERNELS:
12722 case GIMPLE_OACC_PARALLEL:
12723 case GIMPLE_OMP_PARALLEL:
12724 case GIMPLE_OMP_TASK:
12725 case GIMPLE_OMP_SECTIONS:
12726 case GIMPLE_OMP_SINGLE:
12727 case GIMPLE_OMP_SECTION:
12728 case GIMPLE_OMP_MASTER:
12729 case GIMPLE_OMP_ORDERED:
12730 case GIMPLE_OMP_CRITICAL:
12731 case GIMPLE_OMP_TARGET:
12732 case GIMPLE_OMP_TEAMS:
12733 case GIMPLE_OMP_TASKGROUP:
12734 wi->info = stmt;
12735 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12736 wi->info = context;
12737 break;
12739 case GIMPLE_OMP_FOR:
12740 wi->info = stmt;
12741 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12742 walk them. */
12743 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12744 diagnose_sb_2, NULL, wi);
12745 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12746 wi->info = context;
12747 break;
12749 case GIMPLE_COND:
12751 tree lab = gimple_cond_true_label (stmt);
12752 if (lab)
12754 n = splay_tree_lookup (all_labels,
12755 (splay_tree_key) lab);
12756 diagnose_sb_0 (gsi_p, context,
12757 n ? (gimple) n->value : NULL);
12759 lab = gimple_cond_false_label (stmt);
12760 if (lab)
12762 n = splay_tree_lookup (all_labels,
12763 (splay_tree_key) lab);
12764 diagnose_sb_0 (gsi_p, context,
12765 n ? (gimple) n->value : NULL);
12768 break;
12770 case GIMPLE_GOTO:
12772 tree lab = gimple_goto_dest (stmt);
12773 if (TREE_CODE (lab) != LABEL_DECL)
12774 break;
12776 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12777 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12779 break;
12781 case GIMPLE_SWITCH:
12783 unsigned int i;
12784 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
12786 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
12787 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12788 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12789 break;
12792 break;
12794 case GIMPLE_RETURN:
12795 diagnose_sb_0 (gsi_p, context, NULL);
12796 break;
12798 default:
12799 break;
12802 return NULL_TREE;
12805 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12806 GIMPLE codes. */
12807 bool
12808 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12809 int *region_idx)
12811 gimple last = last_stmt (bb);
12812 enum gimple_code code = gimple_code (last);
12813 struct omp_region *cur_region = *region;
12814 bool fallthru = false;
12816 switch (code)
12818 case GIMPLE_OACC_KERNELS:
12819 case GIMPLE_OACC_PARALLEL:
12820 case GIMPLE_OMP_PARALLEL:
12821 case GIMPLE_OMP_TASK:
12822 case GIMPLE_OMP_FOR:
12823 case GIMPLE_OMP_SINGLE:
12824 case GIMPLE_OMP_TEAMS:
12825 case GIMPLE_OMP_MASTER:
12826 case GIMPLE_OMP_TASKGROUP:
12827 case GIMPLE_OMP_ORDERED:
12828 case GIMPLE_OMP_CRITICAL:
12829 case GIMPLE_OMP_SECTION:
12830 cur_region = new_omp_region (bb, code, cur_region);
12831 fallthru = true;
12832 break;
12834 case GIMPLE_OMP_TARGET:
12835 cur_region = new_omp_region (bb, code, cur_region);
12836 fallthru = true;
12837 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE
12838 || gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_OACC_UPDATE)
12839 cur_region = cur_region->outer;
12840 break;
12842 case GIMPLE_OMP_SECTIONS:
12843 cur_region = new_omp_region (bb, code, cur_region);
12844 fallthru = true;
12845 break;
12847 case GIMPLE_OMP_SECTIONS_SWITCH:
12848 fallthru = false;
12849 break;
12851 case GIMPLE_OMP_ATOMIC_LOAD:
12852 case GIMPLE_OMP_ATOMIC_STORE:
12853 fallthru = true;
12854 break;
12856 case GIMPLE_OMP_RETURN:
12857 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12858 somewhere other than the next block. This will be
12859 created later. */
12860 cur_region->exit = bb;
12861 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12862 cur_region = cur_region->outer;
12863 break;
12865 case GIMPLE_OMP_CONTINUE:
12866 cur_region->cont = bb;
12867 switch (cur_region->type)
12869 case GIMPLE_OMP_FOR:
12870 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12871 succs edges as abnormal to prevent splitting
12872 them. */
12873 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12874 /* Make the loopback edge. */
12875 make_edge (bb, single_succ (cur_region->entry),
12876 EDGE_ABNORMAL);
12878 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12879 corresponds to the case that the body of the loop
12880 is not executed at all. */
12881 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12882 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12883 fallthru = false;
12884 break;
12886 case GIMPLE_OMP_SECTIONS:
12887 /* Wire up the edges into and out of the nested sections. */
12889 basic_block switch_bb = single_succ (cur_region->entry);
12891 struct omp_region *i;
12892 for (i = cur_region->inner; i ; i = i->next)
12894 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12895 make_edge (switch_bb, i->entry, 0);
12896 make_edge (i->exit, bb, EDGE_FALLTHRU);
12899 /* Make the loopback edge to the block with
12900 GIMPLE_OMP_SECTIONS_SWITCH. */
12901 make_edge (bb, switch_bb, 0);
12903 /* Make the edge from the switch to exit. */
12904 make_edge (switch_bb, bb->next_bb, 0);
12905 fallthru = false;
12907 break;
12909 default:
12910 gcc_unreachable ();
12912 break;
12914 default:
12915 gcc_unreachable ();
12918 if (*region != cur_region)
12920 *region = cur_region;
12921 if (cur_region)
12922 *region_idx = cur_region->entry->index;
12923 else
12924 *region_idx = 0;
12927 return fallthru;
12930 static unsigned int
12931 diagnose_omp_structured_block_errors (void)
12933 struct walk_stmt_info wi;
12934 gimple_seq body = gimple_body (current_function_decl);
12936 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12938 memset (&wi, 0, sizeof (wi));
12939 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12941 memset (&wi, 0, sizeof (wi));
12942 wi.want_locations = true;
12943 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12945 gimple_set_body (current_function_decl, body);
12947 splay_tree_delete (all_labels);
12948 all_labels = NULL;
12950 return 0;
12953 namespace {
12955 const pass_data pass_data_diagnose_omp_blocks =
12957 GIMPLE_PASS, /* type */
12958 "*diagnose_omp_blocks", /* name */
12959 OPTGROUP_NONE, /* optinfo_flags */
12960 TV_NONE, /* tv_id */
12961 PROP_gimple_any, /* properties_required */
12962 0, /* properties_provided */
12963 0, /* properties_destroyed */
12964 0, /* todo_flags_start */
12965 0, /* todo_flags_finish */
12968 class pass_diagnose_omp_blocks : public gimple_opt_pass
12970 public:
12971 pass_diagnose_omp_blocks (gcc::context *ctxt)
12972 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12975 /* opt_pass methods: */
12976 virtual bool gate (function *)
12978 return flag_openacc || flag_openmp || flag_cilkplus;
12980 virtual unsigned int execute (function *)
12982 return diagnose_omp_structured_block_errors ();
12985 }; // class pass_diagnose_omp_blocks
12987 } // anon namespace
12989 gimple_opt_pass *
12990 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12992 return new pass_diagnose_omp_blocks (ctxt);
12995 /* SIMD clone supporting code. */
12997 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12998 of arguments to reserve space for. */
13000 static struct cgraph_simd_clone *
13001 simd_clone_struct_alloc (int nargs)
13003 struct cgraph_simd_clone *clone_info;
13004 size_t len = (sizeof (struct cgraph_simd_clone)
13005 + nargs * sizeof (struct cgraph_simd_clone_arg));
13006 clone_info = (struct cgraph_simd_clone *)
13007 ggc_internal_cleared_alloc (len);
13008 return clone_info;
13011 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
13013 static inline void
13014 simd_clone_struct_copy (struct cgraph_simd_clone *to,
13015 struct cgraph_simd_clone *from)
13017 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
13018 + ((from->nargs - from->inbranch)
13019 * sizeof (struct cgraph_simd_clone_arg))));
13022 /* Return vector of parameter types of function FNDECL. This uses
13023 TYPE_ARG_TYPES if available, otherwise falls back to types of
13024 DECL_ARGUMENTS types. */
13026 vec<tree>
13027 simd_clone_vector_of_formal_parm_types (tree fndecl)
13029 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
13030 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
13031 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
13032 unsigned int i;
13033 tree arg;
13034 FOR_EACH_VEC_ELT (args, i, arg)
13035 args[i] = TREE_TYPE (args[i]);
13036 return args;
13039 /* Given a simd function in NODE, extract the simd specific
13040 information from the OMP clauses passed in CLAUSES, and return
13041 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
13042 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
13043 otherwise set to FALSE. */
13045 static struct cgraph_simd_clone *
13046 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
13047 bool *inbranch_specified)
13049 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
13050 tree t;
13051 int n;
13052 *inbranch_specified = false;
13054 n = args.length ();
13055 if (n > 0 && args.last () == void_type_node)
13056 n--;
13058 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
13059 be cloned have a distinctive artificial label in addition to "omp
13060 declare simd". */
13061 bool cilk_clone
13062 = (flag_cilkplus
13063 && lookup_attribute ("cilk simd function",
13064 DECL_ATTRIBUTES (node->decl)));
13066 /* Allocate one more than needed just in case this is an in-branch
13067 clone which will require a mask argument. */
13068 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
13069 clone_info->nargs = n;
13070 clone_info->cilk_elemental = cilk_clone;
13072 if (!clauses)
13074 args.release ();
13075 return clone_info;
13077 clauses = TREE_VALUE (clauses);
13078 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
13079 return clone_info;
13081 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
13083 switch (OMP_CLAUSE_CODE (t))
13085 case OMP_CLAUSE_INBRANCH:
13086 clone_info->inbranch = 1;
13087 *inbranch_specified = true;
13088 break;
13089 case OMP_CLAUSE_NOTINBRANCH:
13090 clone_info->inbranch = 0;
13091 *inbranch_specified = true;
13092 break;
13093 case OMP_CLAUSE_SIMDLEN:
13094 clone_info->simdlen
13095 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
13096 break;
13097 case OMP_CLAUSE_LINEAR:
13099 tree decl = OMP_CLAUSE_DECL (t);
13100 tree step = OMP_CLAUSE_LINEAR_STEP (t);
13101 int argno = TREE_INT_CST_LOW (decl);
13102 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
13104 clone_info->args[argno].arg_type
13105 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
13106 clone_info->args[argno].linear_step = tree_to_shwi (step);
13107 gcc_assert (clone_info->args[argno].linear_step >= 0
13108 && clone_info->args[argno].linear_step < n);
13110 else
13112 if (POINTER_TYPE_P (args[argno]))
13113 step = fold_convert (ssizetype, step);
13114 if (!tree_fits_shwi_p (step))
13116 warning_at (OMP_CLAUSE_LOCATION (t), 0,
13117 "ignoring large linear step");
13118 args.release ();
13119 return NULL;
13121 else if (integer_zerop (step))
13123 warning_at (OMP_CLAUSE_LOCATION (t), 0,
13124 "ignoring zero linear step");
13125 args.release ();
13126 return NULL;
13128 else
13130 clone_info->args[argno].arg_type
13131 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
13132 clone_info->args[argno].linear_step = tree_to_shwi (step);
13135 break;
13137 case OMP_CLAUSE_UNIFORM:
13139 tree decl = OMP_CLAUSE_DECL (t);
13140 int argno = tree_to_uhwi (decl);
13141 clone_info->args[argno].arg_type
13142 = SIMD_CLONE_ARG_TYPE_UNIFORM;
13143 break;
13145 case OMP_CLAUSE_ALIGNED:
13147 tree decl = OMP_CLAUSE_DECL (t);
13148 int argno = tree_to_uhwi (decl);
13149 clone_info->args[argno].alignment
13150 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
13151 break;
13153 default:
13154 break;
13157 args.release ();
13158 return clone_info;
13161 /* Given a SIMD clone in NODE, calculate the characteristic data
13162 type and return the coresponding type. The characteristic data
13163 type is computed as described in the Intel Vector ABI. */
13165 static tree
13166 simd_clone_compute_base_data_type (struct cgraph_node *node,
13167 struct cgraph_simd_clone *clone_info)
13169 tree type = integer_type_node;
13170 tree fndecl = node->decl;
13172 /* a) For non-void function, the characteristic data type is the
13173 return type. */
13174 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
13175 type = TREE_TYPE (TREE_TYPE (fndecl));
13177 /* b) If the function has any non-uniform, non-linear parameters,
13178 then the characteristic data type is the type of the first
13179 such parameter. */
13180 else
13182 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
13183 for (unsigned int i = 0; i < clone_info->nargs; ++i)
13184 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
13186 type = map[i];
13187 break;
13189 map.release ();
13192 /* c) If the characteristic data type determined by a) or b) above
13193 is struct, union, or class type which is pass-by-value (except
13194 for the type that maps to the built-in complex data type), the
13195 characteristic data type is int. */
13196 if (RECORD_OR_UNION_TYPE_P (type)
13197 && !aggregate_value_p (type, NULL)
13198 && TREE_CODE (type) != COMPLEX_TYPE)
13199 return integer_type_node;
13201 /* d) If none of the above three classes is applicable, the
13202 characteristic data type is int. */
13204 return type;
13206 /* e) For Intel Xeon Phi native and offload compilation, if the
13207 resulting characteristic data type is 8-bit or 16-bit integer
13208 data type, the characteristic data type is int. */
13209 /* Well, we don't handle Xeon Phi yet. */
13212 static tree
13213 simd_clone_mangle (struct cgraph_node *node,
13214 struct cgraph_simd_clone *clone_info)
13216 char vecsize_mangle = clone_info->vecsize_mangle;
13217 char mask = clone_info->inbranch ? 'M' : 'N';
13218 unsigned int simdlen = clone_info->simdlen;
13219 unsigned int n;
13220 pretty_printer pp;
13222 gcc_assert (vecsize_mangle && simdlen);
13224 pp_string (&pp, "_ZGV");
13225 pp_character (&pp, vecsize_mangle);
13226 pp_character (&pp, mask);
13227 pp_decimal_int (&pp, simdlen);
13229 for (n = 0; n < clone_info->nargs; ++n)
13231 struct cgraph_simd_clone_arg arg = clone_info->args[n];
13233 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
13234 pp_character (&pp, 'u');
13235 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13237 gcc_assert (arg.linear_step != 0);
13238 pp_character (&pp, 'l');
13239 if (arg.linear_step > 1)
13240 pp_unsigned_wide_integer (&pp, arg.linear_step);
13241 else if (arg.linear_step < 0)
13243 pp_character (&pp, 'n');
13244 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
13245 arg.linear_step));
13248 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
13250 pp_character (&pp, 's');
13251 pp_unsigned_wide_integer (&pp, arg.linear_step);
13253 else
13254 pp_character (&pp, 'v');
13255 if (arg.alignment)
13257 pp_character (&pp, 'a');
13258 pp_decimal_int (&pp, arg.alignment);
13262 pp_underscore (&pp);
13263 pp_string (&pp,
13264 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
13265 const char *str = pp_formatted_text (&pp);
13267 /* If there already is a SIMD clone with the same mangled name, don't
13268 add another one. This can happen e.g. for
13269 #pragma omp declare simd
13270 #pragma omp declare simd simdlen(8)
13271 int foo (int, int);
13272 if the simdlen is assumed to be 8 for the first one, etc. */
13273 for (struct cgraph_node *clone = node->simd_clones; clone;
13274 clone = clone->simdclone->next_clone)
13275 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
13276 str) == 0)
13277 return NULL_TREE;
13279 return get_identifier (str);
13282 /* Create a simd clone of OLD_NODE and return it. */
13284 static struct cgraph_node *
13285 simd_clone_create (struct cgraph_node *old_node)
13287 struct cgraph_node *new_node;
13288 if (old_node->definition)
13290 if (!old_node->has_gimple_body_p ())
13291 return NULL;
13292 old_node->get_body ();
13293 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
13294 false, NULL, NULL,
13295 "simdclone");
13297 else
13299 tree old_decl = old_node->decl;
13300 tree new_decl = copy_node (old_node->decl);
13301 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
13302 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
13303 SET_DECL_RTL (new_decl, NULL);
13304 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
13305 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
13306 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
13307 symtab->call_cgraph_insertion_hooks (new_node);
13309 if (new_node == NULL)
13310 return new_node;
13312 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
13314 /* The function cgraph_function_versioning () will force the new
13315 symbol local. Undo this, and inherit external visability from
13316 the old node. */
13317 new_node->local.local = old_node->local.local;
13318 new_node->externally_visible = old_node->externally_visible;
13320 return new_node;
13323 /* Adjust the return type of the given function to its appropriate
13324 vector counterpart. Returns a simd array to be used throughout the
13325 function as a return value. */
13327 static tree
13328 simd_clone_adjust_return_type (struct cgraph_node *node)
13330 tree fndecl = node->decl;
13331 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
13332 unsigned int veclen;
13333 tree t;
13335 /* Adjust the function return type. */
13336 if (orig_rettype == void_type_node)
13337 return NULL_TREE;
13338 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
13339 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
13340 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
13341 veclen = node->simdclone->vecsize_int;
13342 else
13343 veclen = node->simdclone->vecsize_float;
13344 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
13345 if (veclen > node->simdclone->simdlen)
13346 veclen = node->simdclone->simdlen;
13347 if (veclen == node->simdclone->simdlen)
13348 TREE_TYPE (TREE_TYPE (fndecl))
13349 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
13350 node->simdclone->simdlen);
13351 else
13353 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
13354 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
13355 TREE_TYPE (TREE_TYPE (fndecl)) = t;
13357 if (!node->definition)
13358 return NULL_TREE;
13360 t = DECL_RESULT (fndecl);
13361 /* Adjust the DECL_RESULT. */
13362 gcc_assert (TREE_TYPE (t) != void_type_node);
13363 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
13364 relayout_decl (t);
13366 tree atype = build_array_type_nelts (orig_rettype,
13367 node->simdclone->simdlen);
13368 if (veclen != node->simdclone->simdlen)
13369 return build1 (VIEW_CONVERT_EXPR, atype, t);
13371 /* Set up a SIMD array to use as the return value. */
13372 tree retval = create_tmp_var_raw (atype, "retval");
13373 gimple_add_tmp_var (retval);
13374 return retval;
13377 /* Each vector argument has a corresponding array to be used locally
13378 as part of the eventual loop. Create such temporary array and
13379 return it.
13381 PREFIX is the prefix to be used for the temporary.
13383 TYPE is the inner element type.
13385 SIMDLEN is the number of elements. */
13387 static tree
13388 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
13390 tree atype = build_array_type_nelts (type, simdlen);
13391 tree avar = create_tmp_var_raw (atype, prefix);
13392 gimple_add_tmp_var (avar);
13393 return avar;
13396 /* Modify the function argument types to their corresponding vector
13397 counterparts if appropriate. Also, create one array for each simd
13398 argument to be used locally when using the function arguments as
13399 part of the loop.
13401 NODE is the function whose arguments are to be adjusted.
13403 Returns an adjustment vector that will be filled describing how the
13404 argument types will be adjusted. */
13406 static ipa_parm_adjustment_vec
13407 simd_clone_adjust_argument_types (struct cgraph_node *node)
13409 vec<tree> args;
13410 ipa_parm_adjustment_vec adjustments;
13412 if (node->definition)
13413 args = ipa_get_vector_of_formal_parms (node->decl);
13414 else
13415 args = simd_clone_vector_of_formal_parm_types (node->decl);
13416 adjustments.create (args.length ());
13417 unsigned i, j, veclen;
13418 struct ipa_parm_adjustment adj;
13419 for (i = 0; i < node->simdclone->nargs; ++i)
13421 memset (&adj, 0, sizeof (adj));
13422 tree parm = args[i];
13423 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
13424 adj.base_index = i;
13425 adj.base = parm;
13427 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
13428 node->simdclone->args[i].orig_type = parm_type;
13430 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
13432 /* No adjustment necessary for scalar arguments. */
13433 adj.op = IPA_PARM_OP_COPY;
13435 else
13437 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
13438 veclen = node->simdclone->vecsize_int;
13439 else
13440 veclen = node->simdclone->vecsize_float;
13441 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
13442 if (veclen > node->simdclone->simdlen)
13443 veclen = node->simdclone->simdlen;
13444 adj.arg_prefix = "simd";
13445 adj.type = build_vector_type (parm_type, veclen);
13446 node->simdclone->args[i].vector_type = adj.type;
13447 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13449 adjustments.safe_push (adj);
13450 if (j == veclen)
13452 memset (&adj, 0, sizeof (adj));
13453 adj.op = IPA_PARM_OP_NEW;
13454 adj.arg_prefix = "simd";
13455 adj.base_index = i;
13456 adj.type = node->simdclone->args[i].vector_type;
13460 if (node->definition)
13461 node->simdclone->args[i].simd_array
13462 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
13463 parm_type, node->simdclone->simdlen);
13465 adjustments.safe_push (adj);
13468 if (node->simdclone->inbranch)
13470 tree base_type
13471 = simd_clone_compute_base_data_type (node->simdclone->origin,
13472 node->simdclone);
13474 memset (&adj, 0, sizeof (adj));
13475 adj.op = IPA_PARM_OP_NEW;
13476 adj.arg_prefix = "mask";
13478 adj.base_index = i;
13479 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13480 veclen = node->simdclone->vecsize_int;
13481 else
13482 veclen = node->simdclone->vecsize_float;
13483 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13484 if (veclen > node->simdclone->simdlen)
13485 veclen = node->simdclone->simdlen;
13486 adj.type = build_vector_type (base_type, veclen);
13487 adjustments.safe_push (adj);
13489 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13490 adjustments.safe_push (adj);
13492 /* We have previously allocated one extra entry for the mask. Use
13493 it and fill it. */
13494 struct cgraph_simd_clone *sc = node->simdclone;
13495 sc->nargs++;
13496 if (node->definition)
13498 sc->args[i].orig_arg
13499 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13500 sc->args[i].simd_array
13501 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13503 sc->args[i].orig_type = base_type;
13504 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13507 if (node->definition)
13508 ipa_modify_formal_parameters (node->decl, adjustments);
13509 else
13511 tree new_arg_types = NULL_TREE, new_reversed;
13512 bool last_parm_void = false;
13513 if (args.length () > 0 && args.last () == void_type_node)
13514 last_parm_void = true;
13516 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13517 j = adjustments.length ();
13518 for (i = 0; i < j; i++)
13520 struct ipa_parm_adjustment *adj = &adjustments[i];
13521 tree ptype;
13522 if (adj->op == IPA_PARM_OP_COPY)
13523 ptype = args[adj->base_index];
13524 else
13525 ptype = adj->type;
13526 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13528 new_reversed = nreverse (new_arg_types);
13529 if (last_parm_void)
13531 if (new_reversed)
13532 TREE_CHAIN (new_arg_types) = void_list_node;
13533 else
13534 new_reversed = void_list_node;
13537 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13538 TYPE_ARG_TYPES (new_type) = new_reversed;
13539 TREE_TYPE (node->decl) = new_type;
13541 adjustments.release ();
13543 args.release ();
13544 return adjustments;
13547 /* Initialize and copy the function arguments in NODE to their
13548 corresponding local simd arrays. Returns a fresh gimple_seq with
13549 the instruction sequence generated. */
13551 static gimple_seq
13552 simd_clone_init_simd_arrays (struct cgraph_node *node,
13553 ipa_parm_adjustment_vec adjustments)
13555 gimple_seq seq = NULL;
13556 unsigned i = 0, j = 0, k;
13558 for (tree arg = DECL_ARGUMENTS (node->decl);
13559 arg;
13560 arg = DECL_CHAIN (arg), i++, j++)
13562 if (adjustments[j].op == IPA_PARM_OP_COPY)
13563 continue;
13565 node->simdclone->args[i].vector_arg = arg;
13567 tree array = node->simdclone->args[i].simd_array;
13568 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13570 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13571 tree ptr = build_fold_addr_expr (array);
13572 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13573 build_int_cst (ptype, 0));
13574 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13575 gimplify_and_add (t, &seq);
13577 else
13579 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13580 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13581 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13583 tree ptr = build_fold_addr_expr (array);
13584 int elemsize;
13585 if (k)
13587 arg = DECL_CHAIN (arg);
13588 j++;
13590 elemsize
13591 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13592 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13593 build_int_cst (ptype, k * elemsize));
13594 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13595 gimplify_and_add (t, &seq);
13599 return seq;
13602 /* Callback info for ipa_simd_modify_stmt_ops below. */
13604 struct modify_stmt_info {
13605 ipa_parm_adjustment_vec adjustments;
13606 gimple stmt;
13607 /* True if the parent statement was modified by
13608 ipa_simd_modify_stmt_ops. */
13609 bool modified;
13612 /* Callback for walk_gimple_op.
13614 Adjust operands from a given statement as specified in the
13615 adjustments vector in the callback data. */
13617 static tree
13618 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13620 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13621 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13622 tree *orig_tp = tp;
13623 if (TREE_CODE (*tp) == ADDR_EXPR)
13624 tp = &TREE_OPERAND (*tp, 0);
13625 struct ipa_parm_adjustment *cand = NULL;
13626 if (TREE_CODE (*tp) == PARM_DECL)
13627 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13628 else
13630 if (TYPE_P (*tp))
13631 *walk_subtrees = 0;
13634 tree repl = NULL_TREE;
13635 if (cand)
13636 repl = unshare_expr (cand->new_decl);
13637 else
13639 if (tp != orig_tp)
13641 *walk_subtrees = 0;
13642 bool modified = info->modified;
13643 info->modified = false;
13644 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13645 if (!info->modified)
13647 info->modified = modified;
13648 return NULL_TREE;
13650 info->modified = modified;
13651 repl = *tp;
13653 else
13654 return NULL_TREE;
13657 if (tp != orig_tp)
13659 repl = build_fold_addr_expr (repl);
13660 gimple stmt;
13661 if (is_gimple_debug (info->stmt))
13663 tree vexpr = make_node (DEBUG_EXPR_DECL);
13664 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13665 DECL_ARTIFICIAL (vexpr) = 1;
13666 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13667 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13668 repl = vexpr;
13670 else
13672 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
13673 NULL), repl);
13674 repl = gimple_assign_lhs (stmt);
13676 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13677 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13678 *orig_tp = repl;
13680 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13682 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13683 *tp = vce;
13685 else
13686 *tp = repl;
13688 info->modified = true;
13689 return NULL_TREE;
13692 /* Traverse the function body and perform all modifications as
13693 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13694 modified such that the replacement/reduction value will now be an
13695 offset into the corresponding simd_array.
13697 This function will replace all function argument uses with their
13698 corresponding simd array elements, and ajust the return values
13699 accordingly. */
13701 static void
13702 ipa_simd_modify_function_body (struct cgraph_node *node,
13703 ipa_parm_adjustment_vec adjustments,
13704 tree retval_array, tree iter)
13706 basic_block bb;
13707 unsigned int i, j, l;
13709 /* Re-use the adjustments array, but this time use it to replace
13710 every function argument use to an offset into the corresponding
13711 simd_array. */
13712 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13714 if (!node->simdclone->args[i].vector_arg)
13715 continue;
13717 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13718 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13719 adjustments[j].new_decl
13720 = build4 (ARRAY_REF,
13721 basetype,
13722 node->simdclone->args[i].simd_array,
13723 iter,
13724 NULL_TREE, NULL_TREE);
13725 if (adjustments[j].op == IPA_PARM_OP_NONE
13726 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13727 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13730 l = adjustments.length ();
13731 for (i = 1; i < num_ssa_names; i++)
13733 tree name = ssa_name (i);
13734 if (name
13735 && SSA_NAME_VAR (name)
13736 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13738 for (j = 0; j < l; j++)
13739 if (SSA_NAME_VAR (name) == adjustments[j].base
13740 && adjustments[j].new_decl)
13742 tree base_var;
13743 if (adjustments[j].new_ssa_base == NULL_TREE)
13745 base_var
13746 = copy_var_decl (adjustments[j].base,
13747 DECL_NAME (adjustments[j].base),
13748 TREE_TYPE (adjustments[j].base));
13749 adjustments[j].new_ssa_base = base_var;
13751 else
13752 base_var = adjustments[j].new_ssa_base;
13753 if (SSA_NAME_IS_DEFAULT_DEF (name))
13755 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13756 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13757 tree new_decl = unshare_expr (adjustments[j].new_decl);
13758 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13759 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13760 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13761 gimple stmt = gimple_build_assign (name, new_decl);
13762 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13764 else
13765 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13770 struct modify_stmt_info info;
13771 info.adjustments = adjustments;
13773 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13775 gimple_stmt_iterator gsi;
13777 gsi = gsi_start_bb (bb);
13778 while (!gsi_end_p (gsi))
13780 gimple stmt = gsi_stmt (gsi);
13781 info.stmt = stmt;
13782 struct walk_stmt_info wi;
13784 memset (&wi, 0, sizeof (wi));
13785 info.modified = false;
13786 wi.info = &info;
13787 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13789 if (gimple_code (stmt) == GIMPLE_RETURN)
13791 tree retval = gimple_return_retval (stmt);
13792 if (!retval)
13794 gsi_remove (&gsi, true);
13795 continue;
13798 /* Replace `return foo' with `retval_array[iter] = foo'. */
13799 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13800 retval_array, iter, NULL, NULL);
13801 stmt = gimple_build_assign (ref, retval);
13802 gsi_replace (&gsi, stmt, true);
13803 info.modified = true;
13806 if (info.modified)
13808 update_stmt (stmt);
13809 if (maybe_clean_eh_stmt (stmt))
13810 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13812 gsi_next (&gsi);
13817 /* Adjust the argument types in NODE to their appropriate vector
13818 counterparts. */
13820 static void
13821 simd_clone_adjust (struct cgraph_node *node)
13823 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13825 targetm.simd_clone.adjust (node);
13827 tree retval = simd_clone_adjust_return_type (node);
13828 ipa_parm_adjustment_vec adjustments
13829 = simd_clone_adjust_argument_types (node);
13831 push_gimplify_context ();
13833 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13835 /* Adjust all uses of vector arguments accordingly. Adjust all
13836 return values accordingly. */
13837 tree iter = create_tmp_var (unsigned_type_node, "iter");
13838 tree iter1 = make_ssa_name (iter, NULL);
13839 tree iter2 = make_ssa_name (iter, NULL);
13840 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13842 /* Initialize the iteration variable. */
13843 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13844 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13845 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13846 /* Insert the SIMD array and iv initialization at function
13847 entry. */
13848 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13850 pop_gimplify_context (NULL);
13852 /* Create a new BB right before the original exit BB, to hold the
13853 iteration increment and the condition/branch. */
13854 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13855 basic_block incr_bb = create_empty_bb (orig_exit);
13856 add_bb_to_loop (incr_bb, body_bb->loop_father);
13857 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13858 flag. Set it now to be a FALLTHRU_EDGE. */
13859 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13860 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13861 for (unsigned i = 0;
13862 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13864 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13865 redirect_edge_succ (e, incr_bb);
13867 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13868 e->probability = REG_BR_PROB_BASE;
13869 gsi = gsi_last_bb (incr_bb);
13870 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
13871 build_int_cst (unsigned_type_node,
13872 1));
13873 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13875 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13876 struct loop *loop = alloc_loop ();
13877 cfun->has_force_vectorize_loops = true;
13878 loop->safelen = node->simdclone->simdlen;
13879 loop->force_vectorize = true;
13880 loop->header = body_bb;
13882 /* Branch around the body if the mask applies. */
13883 if (node->simdclone->inbranch)
13885 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13886 tree mask_array
13887 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13888 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
13889 tree aref = build4 (ARRAY_REF,
13890 TREE_TYPE (TREE_TYPE (mask_array)),
13891 mask_array, iter1,
13892 NULL, NULL);
13893 g = gimple_build_assign (mask, aref);
13894 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13895 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13896 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13898 aref = build1 (VIEW_CONVERT_EXPR,
13899 build_nonstandard_integer_type (bitsize, 0), mask);
13900 mask = make_ssa_name (TREE_TYPE (aref), NULL);
13901 g = gimple_build_assign (mask, aref);
13902 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13905 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13906 NULL, NULL);
13907 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13908 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13909 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13912 /* Generate the condition. */
13913 g = gimple_build_cond (LT_EXPR,
13914 iter2,
13915 build_int_cst (unsigned_type_node,
13916 node->simdclone->simdlen),
13917 NULL, NULL);
13918 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13919 e = split_block (incr_bb, gsi_stmt (gsi));
13920 basic_block latch_bb = e->dest;
13921 basic_block new_exit_bb;
13922 new_exit_bb = split_block (latch_bb, NULL)->dest;
13923 loop->latch = latch_bb;
13925 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13927 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13928 /* The successor of incr_bb is already pointing to latch_bb; just
13929 change the flags.
13930 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13931 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13933 gimple phi = create_phi_node (iter1, body_bb);
13934 edge preheader_edge = find_edge (entry_bb, body_bb);
13935 edge latch_edge = single_succ_edge (latch_bb);
13936 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13937 UNKNOWN_LOCATION);
13938 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13940 /* Generate the new return. */
13941 gsi = gsi_last_bb (new_exit_bb);
13942 if (retval
13943 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13944 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13945 retval = TREE_OPERAND (retval, 0);
13946 else if (retval)
13948 retval = build1 (VIEW_CONVERT_EXPR,
13949 TREE_TYPE (TREE_TYPE (node->decl)),
13950 retval);
13951 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13952 false, GSI_CONTINUE_LINKING);
13954 g = gimple_build_return (retval);
13955 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13957 /* Handle aligned clauses by replacing default defs of the aligned
13958 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13959 lhs. Handle linear by adding PHIs. */
13960 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13961 if (node->simdclone->args[i].alignment
13962 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13963 && (node->simdclone->args[i].alignment
13964 & (node->simdclone->args[i].alignment - 1)) == 0
13965 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13966 == POINTER_TYPE)
13968 unsigned int alignment = node->simdclone->args[i].alignment;
13969 tree orig_arg = node->simdclone->args[i].orig_arg;
13970 tree def = ssa_default_def (cfun, orig_arg);
13971 if (def && !has_zero_uses (def))
13973 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13974 gimple_seq seq = NULL;
13975 bool need_cvt = false;
13976 gimple call
13977 = gimple_build_call (fn, 2, def, size_int (alignment));
13978 g = call;
13979 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13980 ptr_type_node))
13981 need_cvt = true;
13982 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
13983 gimple_call_set_lhs (g, t);
13984 gimple_seq_add_stmt_without_update (&seq, g);
13985 if (need_cvt)
13987 t = make_ssa_name (orig_arg, NULL);
13988 g = gimple_build_assign_with_ops (NOP_EXPR, t,
13989 gimple_call_lhs (g),
13990 NULL_TREE);
13991 gimple_seq_add_stmt_without_update (&seq, g);
13993 gsi_insert_seq_on_edge_immediate
13994 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13996 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13997 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13998 entry_bb);
13999 node->create_edge (cgraph_node::get_create (fn),
14000 call, entry_bb->count, freq);
14002 imm_use_iterator iter;
14003 use_operand_p use_p;
14004 gimple use_stmt;
14005 tree repl = gimple_get_lhs (g);
14006 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
14007 if (is_gimple_debug (use_stmt) || use_stmt == call)
14008 continue;
14009 else
14010 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
14011 SET_USE (use_p, repl);
14014 else if (node->simdclone->args[i].arg_type
14015 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
14017 tree orig_arg = node->simdclone->args[i].orig_arg;
14018 tree def = ssa_default_def (cfun, orig_arg);
14019 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
14020 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
14021 if (def && !has_zero_uses (def))
14023 iter1 = make_ssa_name (orig_arg, NULL);
14024 iter2 = make_ssa_name (orig_arg, NULL);
14025 phi = create_phi_node (iter1, body_bb);
14026 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
14027 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
14028 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
14029 ? PLUS_EXPR : POINTER_PLUS_EXPR;
14030 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
14031 ? TREE_TYPE (orig_arg) : sizetype;
14032 tree addcst
14033 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
14034 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
14035 gsi = gsi_last_bb (incr_bb);
14036 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
14038 imm_use_iterator iter;
14039 use_operand_p use_p;
14040 gimple use_stmt;
14041 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
14042 if (use_stmt == phi)
14043 continue;
14044 else
14045 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
14046 SET_USE (use_p, iter1);
14050 calculate_dominance_info (CDI_DOMINATORS);
14051 add_loop (loop, loop->header->loop_father);
14052 update_ssa (TODO_update_ssa);
14054 pop_cfun ();
14057 /* If the function in NODE is tagged as an elemental SIMD function,
14058 create the appropriate SIMD clones. */
14060 static void
14061 expand_simd_clones (struct cgraph_node *node)
14063 tree attr = lookup_attribute ("omp declare simd",
14064 DECL_ATTRIBUTES (node->decl));
14065 if (attr == NULL_TREE
14066 || node->global.inlined_to
14067 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
14068 return;
14070 /* Ignore
14071 #pragma omp declare simd
14072 extern int foo ();
14073 in C, there we don't know the argument types at all. */
14074 if (!node->definition
14075 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
14076 return;
14080 /* Start with parsing the "omp declare simd" attribute(s). */
14081 bool inbranch_clause_specified;
14082 struct cgraph_simd_clone *clone_info
14083 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
14084 &inbranch_clause_specified);
14085 if (clone_info == NULL)
14086 continue;
14088 int orig_simdlen = clone_info->simdlen;
14089 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
14090 /* The target can return 0 (no simd clones should be created),
14091 1 (just one ISA of simd clones should be created) or higher
14092 count of ISA variants. In that case, clone_info is initialized
14093 for the first ISA variant. */
14094 int count
14095 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
14096 base_type, 0);
14097 if (count == 0)
14098 continue;
14100 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
14101 also create one inbranch and one !inbranch clone of it. */
14102 for (int i = 0; i < count * 2; i++)
14104 struct cgraph_simd_clone *clone = clone_info;
14105 if (inbranch_clause_specified && (i & 1) != 0)
14106 continue;
14108 if (i != 0)
14110 clone = simd_clone_struct_alloc (clone_info->nargs
14111 + ((i & 1) != 0));
14112 simd_clone_struct_copy (clone, clone_info);
14113 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
14114 and simd_clone_adjust_argument_types did to the first
14115 clone's info. */
14116 clone->nargs -= clone_info->inbranch;
14117 clone->simdlen = orig_simdlen;
14118 /* And call the target hook again to get the right ISA. */
14119 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
14120 base_type,
14121 i / 2);
14122 if ((i & 1) != 0)
14123 clone->inbranch = 1;
14126 /* simd_clone_mangle might fail if such a clone has been created
14127 already. */
14128 tree id = simd_clone_mangle (node, clone);
14129 if (id == NULL_TREE)
14130 continue;
14132 /* Only when we are sure we want to create the clone actually
14133 clone the function (or definitions) or create another
14134 extern FUNCTION_DECL (for prototypes without definitions). */
14135 struct cgraph_node *n = simd_clone_create (node);
14136 if (n == NULL)
14137 continue;
14139 n->simdclone = clone;
14140 clone->origin = node;
14141 clone->next_clone = NULL;
14142 if (node->simd_clones == NULL)
14144 clone->prev_clone = n;
14145 node->simd_clones = n;
14147 else
14149 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
14150 clone->prev_clone->simdclone->next_clone = n;
14151 node->simd_clones->simdclone->prev_clone = n;
14153 symtab->change_decl_assembler_name (n->decl, id);
14154 /* And finally adjust the return type, parameters and for
14155 definitions also function body. */
14156 if (node->definition)
14157 simd_clone_adjust (n);
14158 else
14160 simd_clone_adjust_return_type (n);
14161 simd_clone_adjust_argument_types (n);
14165 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
14168 /* Entry point for IPA simd clone creation pass. */
14170 static unsigned int
14171 ipa_omp_simd_clone (void)
14173 struct cgraph_node *node;
14174 FOR_EACH_FUNCTION (node)
14175 expand_simd_clones (node);
14176 return 0;
14179 namespace {
14181 const pass_data pass_data_omp_simd_clone =
14183 SIMPLE_IPA_PASS, /* type */
14184 "simdclone", /* name */
14185 OPTGROUP_NONE, /* optinfo_flags */
14186 TV_NONE, /* tv_id */
14187 ( PROP_ssa | PROP_cfg ), /* properties_required */
14188 0, /* properties_provided */
14189 0, /* properties_destroyed */
14190 0, /* todo_flags_start */
14191 0, /* todo_flags_finish */
14194 class pass_omp_simd_clone : public simple_ipa_opt_pass
14196 public:
14197 pass_omp_simd_clone(gcc::context *ctxt)
14198 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
14201 /* opt_pass methods: */
14202 virtual bool gate (function *);
14203 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
14206 bool
14207 pass_omp_simd_clone::gate (function *)
14209 return ((flag_openmp || flag_openmp_simd
14210 || flag_cilkplus
14211 || (in_lto_p && !flag_wpa))
14212 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
14215 } // anon namespace
14217 simple_ipa_opt_pass *
14218 make_pass_omp_simd_clone (gcc::context *ctxt)
14220 return new pass_omp_simd_clone (ctxt);
14223 /* Helper function for omp_finish_file routine.
14224 Takes decls from V_DECLS and adds their addresses and sizes to
14225 constructor-vector V_CTOR. It will be later used as DECL_INIT for decl
14226 representing a global symbol for OpenMP descriptor. */
14227 static void
14228 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
14229 vec<constructor_elt, va_gc> *v_ctor)
14231 unsigned len = vec_safe_length (v_decls);
14232 for (unsigned i = 0; i < len; i++)
14234 tree it = (*v_decls)[i];
14235 bool is_function = TREE_CODE (it) != VAR_DECL;
14237 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
14238 if (!is_function)
14239 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
14240 fold_convert (const_ptr_type_node,
14241 DECL_SIZE (it)));
14245 /* Create new symbol containing (address, size) pairs for omp-marked
14246 functions and global variables. */
14247 void
14248 omp_finish_file (void)
14250 const char *funcs_section_name = OFFLOAD_FUNC_TABLE_SECTION_NAME;
14251 const char *vars_section_name = OFFLOAD_VAR_TABLE_SECTION_NAME;
14253 unsigned num_funcs = vec_safe_length (offload_funcs);
14254 unsigned num_vars = vec_safe_length (offload_vars);
14256 if (num_funcs == 0 && num_vars == 0)
14257 return;
14259 if (targetm_common.have_named_sections)
14261 vec<constructor_elt, va_gc> *v_f, *v_v;
14262 vec_alloc (v_f, num_funcs);
14263 vec_alloc (v_v, num_vars * 2);
14265 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
14266 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
14268 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
14269 num_vars * 2);
14270 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
14271 num_funcs);
14272 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
14273 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
14274 tree ctor_v = build_constructor (vars_decl_type, v_v);
14275 tree ctor_f = build_constructor (funcs_decl_type, v_f);
14276 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
14277 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
14278 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
14279 get_identifier (".omp_func_table"),
14280 funcs_decl_type);
14281 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
14282 get_identifier (".omp_var_table"),
14283 vars_decl_type);
14284 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
14285 DECL_INITIAL (funcs_decl) = ctor_f;
14286 DECL_INITIAL (vars_decl) = ctor_v;
14287 set_decl_section_name (funcs_decl, funcs_section_name);
14288 set_decl_section_name (vars_decl, vars_section_name);
14290 varpool_node::finalize_decl (funcs_decl);
14291 varpool_node::finalize_decl (vars_decl);
14293 else
14295 for (unsigned i = 0; i < num_funcs; i++)
14297 tree it = (*offload_funcs)[i];
14298 targetm.record_offload_symbol (it);
14300 for (unsigned i = 0; i < num_vars; i++)
14302 tree it = (*offload_vars)[i];
14303 targetm.record_offload_symbol (it);
14308 #include "gt-omp-low.h"