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, 2006, 2007, 2008 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
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
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/>. */
26 #include "coretypes.h"
30 #include "tree-gimple.h"
31 #include "tree-inline.h"
32 #include "langhooks.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
40 #include "tree-pass.h"
43 #include "splay-tree.h"
47 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
48 phases. The first phase scans the function looking for OMP statements
49 and then for variables that must be replaced to satisfy data sharing
50 clauses. The second phase expands code for the constructs, as well as
51 re-gimplifying things when variables have been replaced with complex
54 Final code generation is done by pass_expand_omp. The flowgraph is
55 scanned for parallel regions which are then moved to a new
56 function, to be invoked by the thread library. */
58 /* Context structure. Used to store information about each parallel
59 directive in the code. */
61 typedef struct omp_context
63 /* This field must be at the beginning, as we do "inheritance": Some
64 callback functions for tree-inline.c (e.g., omp_copy_decl)
65 receive a copy_body_data pointer that is up-casted to an
66 omp_context pointer. */
69 /* The tree of contexts corresponding to the encountered constructs. */
70 struct omp_context *outer;
73 /* Map variables to fields in a structure that allows communication
74 between sending and receiving threads. */
80 /* These are used just by task contexts, if task firstprivate fn is
81 needed. srecord_type is used to communicate from the thread
82 that encountered the task construct to task firstprivate fn,
83 record_type is allocated by GOMP_task, initialized by task firstprivate
84 fn and passed to the task body fn. */
85 splay_tree sfield_map;
88 /* A chain of variables to add to the top-level block surrounding the
89 construct. In the case of a parallel, this is in the child function. */
92 /* What to do with variables with implicitly determined sharing
94 enum omp_clause_default_kind default_kind;
96 /* Nesting depth of this context. Used to beautify error messages re
97 invalid gotos. The outermost ctx is depth 1, with depth 0 being
98 reserved for the main body of the function. */
101 /* True if this parallel directive is nested within another. */
106 struct omp_for_data_loop
108 tree v, n1, n2, step;
109 enum tree_code cond_code;
112 /* A structure describing the main elements of a parallel loop. */
116 struct omp_for_data_loop loop;
117 tree chunk_size, for_stmt;
120 bool have_nowait, have_ordered;
121 enum omp_clause_schedule_kind sched_kind;
122 struct omp_for_data_loop *loops;
126 static splay_tree all_contexts;
127 static int taskreg_nesting_level;
128 struct omp_region *root_omp_region;
129 static bitmap task_shared_vars;
131 static void scan_omp (tree *, omp_context *);
132 static void lower_omp (tree *, omp_context *);
133 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
134 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
136 /* Find an OpenMP clause of type KIND within CLAUSES. */
139 find_omp_clause (tree clauses, enum tree_code kind)
141 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
142 if (OMP_CLAUSE_CODE (clauses) == kind)
148 /* Return true if CTX is for an omp parallel. */
151 is_parallel_ctx (omp_context *ctx)
153 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
157 /* Return true if CTX is for an omp task. */
160 is_task_ctx (omp_context *ctx)
162 return TREE_CODE (ctx->stmt) == OMP_TASK;
166 /* Return true if CTX is for an omp parallel or omp task. */
169 is_taskreg_ctx (omp_context *ctx)
171 return TREE_CODE (ctx->stmt) == OMP_PARALLEL
172 || TREE_CODE (ctx->stmt) == OMP_TASK;
176 /* Return true if REGION is a combined parallel+workshare region. */
179 is_combined_parallel (struct omp_region *region)
181 return region->is_combined_parallel;
185 /* Extract the header elements of parallel loop FOR_STMT and store
189 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd,
190 struct omp_for_data_loop *loops)
192 tree t, var, *collapse_iter, *collapse_count;
193 tree count = NULL_TREE, iter_type = long_integer_type_node;
194 struct omp_for_data_loop *loop;
196 struct omp_for_data_loop dummy_loop;
198 fd->for_stmt = for_stmt;
200 fd->collapse = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
201 if (fd->collapse > 1)
204 fd->loops = &fd->loop;
206 fd->have_nowait = fd->have_ordered = false;
207 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
208 fd->chunk_size = NULL_TREE;
209 collapse_iter = NULL;
210 collapse_count = NULL;
212 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
213 switch (OMP_CLAUSE_CODE (t))
215 case OMP_CLAUSE_NOWAIT:
216 fd->have_nowait = true;
218 case OMP_CLAUSE_ORDERED:
219 fd->have_ordered = true;
221 case OMP_CLAUSE_SCHEDULE:
222 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
223 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
225 case OMP_CLAUSE_COLLAPSE:
226 if (fd->collapse > 1)
228 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
229 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
235 /* FIXME: for now map schedule(auto) to schedule(static).
236 There should be analysis to determine whether all iterations
237 are approximately the same amount of work (then schedule(static)
238 is best) or if it varries (then schedule(dynamic,N) is better). */
239 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
241 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
242 gcc_assert (fd->chunk_size == NULL);
244 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
245 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
246 gcc_assert (fd->chunk_size == NULL);
247 else if (fd->chunk_size == NULL)
249 /* We only need to compute a default chunk size for ordered
250 static loops and dynamic loops. */
251 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
254 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
255 ? integer_zero_node : integer_one_node;
258 for (i = 0; i < fd->collapse; i++)
260 if (fd->collapse == 1)
262 else if (loops != NULL)
267 t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
268 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
269 loop->v = GIMPLE_STMT_OPERAND (t, 0);
270 gcc_assert (SSA_VAR_P (loop->v));
271 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
272 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
273 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
274 loop->n1 = GIMPLE_STMT_OPERAND (t, 1);
276 t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
277 loop->cond_code = TREE_CODE (t);
278 gcc_assert (TREE_OPERAND (t, 0) == var);
279 loop->n2 = TREE_OPERAND (t, 1);
280 switch (loop->cond_code)
286 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
287 loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
288 loop->n2, size_one_node);
290 loop->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
291 build_int_cst (TREE_TYPE (loop->n2), 1));
292 loop->cond_code = LT_EXPR;
295 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
296 loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
297 loop->n2, size_int (-1));
299 loop->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
300 build_int_cst (TREE_TYPE (loop->n2), 1));
301 loop->cond_code = GT_EXPR;
307 t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
308 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
309 gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == var);
310 t = GIMPLE_STMT_OPERAND (t, 1);
311 gcc_assert (TREE_OPERAND (t, 0) == var);
312 switch (TREE_CODE (t))
315 case POINTER_PLUS_EXPR:
316 loop->step = TREE_OPERAND (t, 1);
319 loop->step = TREE_OPERAND (t, 1);
320 loop->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (loop->step),
327 if (iter_type != long_long_unsigned_type_node)
329 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
330 iter_type = long_long_unsigned_type_node;
331 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
332 && TYPE_PRECISION (TREE_TYPE (loop->v))
333 >= TYPE_PRECISION (iter_type))
337 if (loop->cond_code == LT_EXPR)
338 n = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
339 loop->n2, loop->step);
342 if (TREE_CODE (n) != INTEGER_CST
343 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
344 iter_type = long_long_unsigned_type_node;
346 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
347 > TYPE_PRECISION (iter_type))
351 if (loop->cond_code == LT_EXPR)
354 n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
355 loop->n2, loop->step);
359 n1 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->v),
360 loop->n2, loop->step);
363 if (TREE_CODE (n1) != INTEGER_CST
364 || TREE_CODE (n2) != INTEGER_CST
365 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
366 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
367 iter_type = long_long_unsigned_type_node;
371 if (collapse_count && *collapse_count == NULL)
373 if ((i == 0 || count != NULL_TREE)
374 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
375 && TREE_CONSTANT (loop->n1)
376 && TREE_CONSTANT (loop->n2)
377 && TREE_CODE (loop->step) == INTEGER_CST)
379 tree itype = TREE_TYPE (loop->v);
381 if (POINTER_TYPE_P (itype))
383 = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
384 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
385 t = fold_build2 (PLUS_EXPR, itype,
386 fold_convert (itype, loop->step), t);
387 t = fold_build2 (PLUS_EXPR, itype, t,
388 fold_convert (itype, loop->n2));
389 t = fold_build2 (MINUS_EXPR, itype, t,
390 fold_convert (itype, loop->n1));
391 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
392 t = fold_build2 (TRUNC_DIV_EXPR, itype,
393 fold_build1 (NEGATE_EXPR, itype, t),
394 fold_build1 (NEGATE_EXPR, itype,
398 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
399 fold_convert (itype, loop->step));
400 t = fold_convert (long_long_unsigned_type_node, t);
401 if (count != NULL_TREE)
402 count = fold_build2 (MULT_EXPR, long_long_unsigned_type_node,
406 if (TREE_CODE (count) != INTEGER_CST)
416 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
417 iter_type = long_long_unsigned_type_node;
419 iter_type = long_integer_type_node;
421 else if (collapse_iter && *collapse_iter != NULL)
422 iter_type = TREE_TYPE (*collapse_iter);
423 fd->iter_type = iter_type;
424 if (collapse_iter && *collapse_iter == NULL)
425 *collapse_iter = create_tmp_var (iter_type, ".iter");
426 if (collapse_count && *collapse_count == NULL)
429 *collapse_count = fold_convert (iter_type, count);
431 *collapse_count = create_tmp_var (iter_type, ".count");
434 if (fd->collapse > 1)
436 fd->loop.v = *collapse_iter;
437 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
438 fd->loop.n2 = *collapse_count;
439 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
440 fd->loop.cond_code = LT_EXPR;
445 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
446 is the immediate dominator of PAR_ENTRY_BB, return true if there
447 are no data dependencies that would prevent expanding the parallel
448 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
450 When expanding a combined parallel+workshare region, the call to
451 the child function may need additional arguments in the case of
452 OMP_FOR regions. In some cases, these arguments are computed out
453 of variables passed in from the parent to the child via 'struct
454 .omp_data_s'. For instance:
456 #pragma omp parallel for schedule (guided, i * 4)
461 # BLOCK 2 (PAR_ENTRY_BB)
463 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
465 # BLOCK 3 (WS_ENTRY_BB)
466 .omp_data_i = &.omp_data_o;
467 D.1667 = .omp_data_i->i;
469 #pragma omp for schedule (guided, D.1598)
471 When we outline the parallel region, the call to the child function
472 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
473 that value is computed *after* the call site. So, in principle we
474 cannot do the transformation.
476 To see whether the code in WS_ENTRY_BB blocks the combined
477 parallel+workshare call, we collect all the variables used in the
478 OMP_FOR header check whether they appear on the LHS of any
479 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
482 FIXME. If we had the SSA form built at this point, we could merely
483 hoist the code in block 3 into block 2 and be done with it. But at
484 this point we don't have dataflow information and though we could
485 hack something up here, it is really not worth the aggravation. */
488 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
490 struct omp_for_data fd;
491 tree par_stmt, ws_stmt;
493 par_stmt = last_stmt (par_entry_bb);
494 ws_stmt = last_stmt (ws_entry_bb);
496 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
499 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
501 extract_omp_for_data (ws_stmt, &fd, NULL);
503 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
505 if (fd.iter_type != long_integer_type_node)
508 /* FIXME. We give up too easily here. If any of these arguments
509 are not constants, they will likely involve variables that have
510 been mapped into fields of .omp_data_s for sharing with the child
511 function. With appropriate data flow, it would be possible to
513 if (!is_gimple_min_invariant (fd.loop.n1)
514 || !is_gimple_min_invariant (fd.loop.n2)
515 || !is_gimple_min_invariant (fd.loop.step)
516 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
523 /* Collect additional arguments needed to emit a combined
524 parallel+workshare call. WS_STMT is the workshare directive being
528 get_ws_args_for (tree ws_stmt)
532 if (TREE_CODE (ws_stmt) == OMP_FOR)
534 struct omp_for_data fd;
537 extract_omp_for_data (ws_stmt, &fd, NULL);
542 t = fold_convert (long_integer_type_node, fd.chunk_size);
543 ws_args = tree_cons (NULL, t, ws_args);
546 t = fold_convert (long_integer_type_node, fd.loop.step);
547 ws_args = tree_cons (NULL, t, ws_args);
549 t = fold_convert (long_integer_type_node, fd.loop.n2);
550 ws_args = tree_cons (NULL, t, ws_args);
552 t = fold_convert (long_integer_type_node, fd.loop.n1);
553 ws_args = tree_cons (NULL, t, ws_args);
557 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
559 /* Number of sections is equal to the number of edges from the
560 OMP_SECTIONS_SWITCH statement, except for the one to the exit
561 of the sections region. */
562 basic_block bb = single_succ (bb_for_stmt (ws_stmt));
563 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
564 t = tree_cons (NULL, t, NULL);
572 /* Discover whether REGION is a combined parallel+workshare region. */
575 determine_parallel_type (struct omp_region *region)
577 basic_block par_entry_bb, par_exit_bb;
578 basic_block ws_entry_bb, ws_exit_bb;
580 if (region == NULL || region->inner == NULL
581 || region->exit == NULL || region->inner->exit == NULL
582 || region->inner->cont == NULL)
585 /* We only support parallel+for and parallel+sections. */
586 if (region->type != OMP_PARALLEL
587 || (region->inner->type != OMP_FOR
588 && region->inner->type != OMP_SECTIONS))
591 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
592 WS_EXIT_BB -> PAR_EXIT_BB. */
593 par_entry_bb = region->entry;
594 par_exit_bb = region->exit;
595 ws_entry_bb = region->inner->entry;
596 ws_exit_bb = region->inner->exit;
598 if (single_succ (par_entry_bb) == ws_entry_bb
599 && single_succ (ws_exit_bb) == par_exit_bb
600 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
601 && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
602 || (last_and_only_stmt (ws_entry_bb)
603 && last_and_only_stmt (par_exit_bb))))
605 tree ws_stmt = last_stmt (ws_entry_bb);
607 if (region->inner->type == OMP_FOR)
609 /* If this is a combined parallel loop, we need to determine
610 whether or not to use the combined library calls. There
611 are two cases where we do not apply the transformation:
612 static loops and any kind of ordered loop. In the first
613 case, we already open code the loop so there is no need
614 to do anything else. In the latter case, the combined
615 parallel loop call would still need extra synchronization
616 to implement ordered semantics, so there would not be any
617 gain in using the combined call. */
618 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
619 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
621 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
622 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
624 region->is_combined_parallel = false;
625 region->inner->is_combined_parallel = false;
630 region->is_combined_parallel = true;
631 region->inner->is_combined_parallel = true;
632 region->ws_args = get_ws_args_for (ws_stmt);
637 /* Return true if EXPR is variable sized. */
640 is_variable_sized (const_tree expr)
642 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
645 /* Return true if DECL is a reference type. */
648 is_reference (tree decl)
650 return lang_hooks.decls.omp_privatize_by_reference (decl);
653 /* Lookup variables in the decl or field splay trees. The "maybe" form
654 allows for the variable form to not have been entered, otherwise we
655 assert that the variable must have been entered. */
658 lookup_decl (tree var, omp_context *ctx)
661 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
666 maybe_lookup_decl (const_tree var, omp_context *ctx)
669 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
670 return n ? *n : NULL_TREE;
674 lookup_field (tree var, omp_context *ctx)
677 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
678 return (tree) n->value;
682 lookup_sfield (tree var, omp_context *ctx)
685 n = splay_tree_lookup (ctx->sfield_map
686 ? ctx->sfield_map : ctx->field_map,
687 (splay_tree_key) var);
688 return (tree) n->value;
692 maybe_lookup_field (tree var, omp_context *ctx)
695 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
696 return n ? (tree) n->value : NULL_TREE;
699 /* Return true if DECL should be copied by pointer. SHARED_CTX is
700 the parallel context if DECL is to be shared. */
703 use_pointer_for_field (tree decl, omp_context *shared_ctx)
705 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
708 /* We can only use copy-in/copy-out semantics for shared variables
709 when we know the value is not accessible from an outer scope. */
712 /* ??? Trivially accessible from anywhere. But why would we even
713 be passing an address in this case? Should we simply assert
714 this to be false, or should we have a cleanup pass that removes
715 these from the list of mappings? */
716 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
719 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
720 without analyzing the expression whether or not its location
721 is accessible to anyone else. In the case of nested parallel
722 regions it certainly may be. */
723 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
726 /* Do not use copy-in/copy-out for variables that have their
728 if (TREE_ADDRESSABLE (decl))
731 /* Disallow copy-in/out in nested parallel if
732 decl is shared in outer parallel, otherwise
733 each thread could store the shared variable
734 in its own copy-in location, making the
735 variable no longer really shared. */
736 if (!TREE_READONLY (decl) && shared_ctx->is_nested)
740 for (up = shared_ctx->outer; up; up = up->outer)
741 if (maybe_lookup_decl (decl, up))
744 if (up && is_taskreg_ctx (up))
748 for (c = OMP_TASKREG_CLAUSES (up->stmt);
749 c; c = OMP_CLAUSE_CHAIN (c))
750 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
751 && OMP_CLAUSE_DECL (c) == decl)
759 /* For tasks avoid using copy-in/out, unless they are readonly
760 (in which case just copy-in is used). As tasks can be
761 deferred or executed in different thread, when GOMP_task
762 returns, the task hasn't necessarily terminated. */
763 if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
765 tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
766 if (is_gimple_reg (outer))
768 /* Taking address of OUTER in lower_send_shared_vars
769 might need regimplification of everything that uses the
771 if (!task_shared_vars)
772 task_shared_vars = BITMAP_ALLOC (NULL);
773 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
774 TREE_ADDRESSABLE (outer) = 1;
783 /* Create a new VAR_DECL and copy information from VAR to it. */
786 copy_var_decl (tree var, tree name, tree type)
788 tree copy = build_decl (VAR_DECL, name, type);
790 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
791 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
792 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
793 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
794 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
795 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
796 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
797 DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (var);
798 TREE_USED (copy) = 1;
799 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
804 /* Construct a new automatic decl similar to VAR. */
807 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
809 tree copy = copy_var_decl (var, name, type);
811 DECL_CONTEXT (copy) = current_function_decl;
812 TREE_CHAIN (copy) = ctx->block_vars;
813 ctx->block_vars = copy;
819 omp_copy_decl_1 (tree var, omp_context *ctx)
821 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
824 /* Build tree nodes to access the field for VAR on the receiver side. */
827 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
829 tree x, field = lookup_field (var, ctx);
831 /* If the receiver record type was remapped in the child function,
832 remap the field into the new record type. */
833 x = maybe_lookup_field (field, ctx);
837 x = build_fold_indirect_ref (ctx->receiver_decl);
838 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
840 x = build_fold_indirect_ref (x);
845 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
846 of a parallel, this is a component reference; for workshare constructs
847 this is some variable. */
850 build_outer_var_ref (tree var, omp_context *ctx)
854 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
856 else if (is_variable_sized (var))
858 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
859 x = build_outer_var_ref (x, ctx);
860 x = build_fold_indirect_ref (x);
862 else if (is_taskreg_ctx (ctx))
864 bool by_ref = use_pointer_for_field (var, NULL);
865 x = build_receiver_ref (var, by_ref, ctx);
868 x = lookup_decl (var, ctx->outer);
869 else if (is_reference (var))
870 /* This can happen with orphaned constructs. If var is reference, it is
871 possible it is shared and as such valid. */
876 if (is_reference (var))
877 x = build_fold_indirect_ref (x);
882 /* Build tree nodes to access the field for VAR on the sender side. */
885 build_sender_ref (tree var, omp_context *ctx)
887 tree field = lookup_sfield (var, ctx);
888 return build3 (COMPONENT_REF, TREE_TYPE (field),
889 ctx->sender_decl, field, NULL);
892 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
895 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
897 tree field, type, sfield = NULL_TREE;
899 gcc_assert ((mask & 1) == 0
900 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
901 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
902 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
904 type = TREE_TYPE (var);
906 type = build_pointer_type (type);
907 else if ((mask & 3) == 1 && is_reference (var))
908 type = TREE_TYPE (type);
910 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
912 /* Remember what variable this field was created for. This does have a
913 side effect of making dwarf2out ignore this member, so for helpful
914 debugging we clear it later in delete_omp_context. */
915 DECL_ABSTRACT_ORIGIN (field) = var;
916 if (type == TREE_TYPE (var))
918 DECL_ALIGN (field) = DECL_ALIGN (var);
919 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
920 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
923 DECL_ALIGN (field) = TYPE_ALIGN (type);
927 insert_field_into_struct (ctx->record_type, field);
928 if (ctx->srecord_type)
930 sfield = build_decl (FIELD_DECL, DECL_NAME (var), type);
931 DECL_ABSTRACT_ORIGIN (sfield) = var;
932 DECL_ALIGN (sfield) = DECL_ALIGN (field);
933 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
934 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
935 insert_field_into_struct (ctx->srecord_type, sfield);
940 if (ctx->srecord_type == NULL_TREE)
944 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
945 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
946 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
948 sfield = build_decl (FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
949 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
950 insert_field_into_struct (ctx->srecord_type, sfield);
951 splay_tree_insert (ctx->sfield_map,
952 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
953 (splay_tree_value) sfield);
957 insert_field_into_struct ((mask & 1) ? ctx->record_type
958 : ctx->srecord_type, field);
962 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
963 (splay_tree_value) field);
964 if ((mask & 2) && ctx->sfield_map)
965 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
966 (splay_tree_value) sfield);
970 install_var_local (tree var, omp_context *ctx)
972 tree new_var = omp_copy_decl_1 (var, ctx);
973 insert_decl_map (&ctx->cb, var, new_var);
977 /* Adjust the replacement for DECL in CTX for the new context. This means
978 copying the DECL_VALUE_EXPR, and fixing up the type. */
981 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
985 new_decl = lookup_decl (decl, ctx);
987 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
989 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
990 && DECL_HAS_VALUE_EXPR_P (decl))
992 tree ve = DECL_VALUE_EXPR (decl);
993 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
994 SET_DECL_VALUE_EXPR (new_decl, ve);
995 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
998 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1000 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1001 if (size == error_mark_node)
1002 size = TYPE_SIZE (TREE_TYPE (new_decl));
1003 DECL_SIZE (new_decl) = size;
1005 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1006 if (size == error_mark_node)
1007 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1008 DECL_SIZE_UNIT (new_decl) = size;
1012 /* The callback for remap_decl. Search all containing contexts for a
1013 mapping of the variable; this avoids having to duplicate the splay
1014 tree ahead of time. We know a mapping doesn't already exist in the
1015 given context. Create new mappings to implement default semantics. */
1018 omp_copy_decl (tree var, copy_body_data *cb)
1020 omp_context *ctx = (omp_context *) cb;
1023 if (TREE_CODE (var) == LABEL_DECL)
1025 new_var = create_artificial_label ();
1026 DECL_CONTEXT (new_var) = current_function_decl;
1027 insert_decl_map (&ctx->cb, var, new_var);
1031 while (!is_taskreg_ctx (ctx))
1036 new_var = maybe_lookup_decl (var, ctx);
1041 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1044 return error_mark_node;
1048 /* Return the parallel region associated with STMT. */
1050 /* Debugging dumps for parallel regions. */
1051 void dump_omp_region (FILE *, struct omp_region *, int);
1052 void debug_omp_region (struct omp_region *);
1053 void debug_all_omp_regions (void);
1055 /* Dump the parallel region tree rooted at REGION. */
1058 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1060 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1061 tree_code_name[region->type]);
1064 dump_omp_region (file, region->inner, indent + 4);
1068 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
1069 region->cont->index);
1073 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
1074 region->exit->index);
1076 fprintf (file, "%*s[no exit marker]\n", indent, "");
1079 dump_omp_region (file, region->next, indent);
1083 debug_omp_region (struct omp_region *region)
1085 dump_omp_region (stderr, region, 0);
1089 debug_all_omp_regions (void)
1091 dump_omp_region (stderr, root_omp_region, 0);
1095 /* Create a new parallel region starting at STMT inside region PARENT. */
1098 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
1100 struct omp_region *region = xcalloc (1, sizeof (*region));
1102 region->outer = parent;
1104 region->type = type;
1108 /* This is a nested region. Add it to the list of inner
1109 regions in PARENT. */
1110 region->next = parent->inner;
1111 parent->inner = region;
1115 /* This is a toplevel region. Add it to the list of toplevel
1116 regions in ROOT_OMP_REGION. */
1117 region->next = root_omp_region;
1118 root_omp_region = region;
1124 /* Release the memory associated with the region tree rooted at REGION. */
1127 free_omp_region_1 (struct omp_region *region)
1129 struct omp_region *i, *n;
1131 for (i = region->inner; i ; i = n)
1134 free_omp_region_1 (i);
1140 /* Release the memory for the entire omp region tree. */
1143 free_omp_regions (void)
1145 struct omp_region *r, *n;
1146 for (r = root_omp_region; r ; r = n)
1149 free_omp_region_1 (r);
1151 root_omp_region = NULL;
1155 /* Create a new context, with OUTER_CTX being the surrounding context. */
1157 static omp_context *
1158 new_omp_context (tree stmt, omp_context *outer_ctx)
1160 omp_context *ctx = XCNEW (omp_context);
1162 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1163 (splay_tree_value) ctx);
1168 ctx->outer = outer_ctx;
1169 ctx->cb = outer_ctx->cb;
1170 ctx->cb.block = NULL;
1171 ctx->depth = outer_ctx->depth + 1;
1175 ctx->cb.src_fn = current_function_decl;
1176 ctx->cb.dst_fn = current_function_decl;
1177 ctx->cb.src_node = cgraph_node (current_function_decl);
1178 ctx->cb.dst_node = ctx->cb.src_node;
1179 ctx->cb.src_cfun = cfun;
1180 ctx->cb.copy_decl = omp_copy_decl;
1181 ctx->cb.eh_region = -1;
1182 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1186 ctx->cb.decl_map = pointer_map_create ();
1191 /* Destroy a omp_context data structures. Called through the splay tree
1192 value delete callback. */
1195 delete_omp_context (splay_tree_value value)
1197 omp_context *ctx = (omp_context *) value;
1199 pointer_map_destroy (ctx->cb.decl_map);
1202 splay_tree_delete (ctx->field_map);
1203 if (ctx->sfield_map)
1204 splay_tree_delete (ctx->sfield_map);
1206 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1207 it produces corrupt debug information. */
1208 if (ctx->record_type)
1211 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1212 DECL_ABSTRACT_ORIGIN (t) = NULL;
1214 if (ctx->srecord_type)
1217 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = TREE_CHAIN (t))
1218 DECL_ABSTRACT_ORIGIN (t) = NULL;
1224 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1228 fixup_child_record_type (omp_context *ctx)
1230 tree f, type = ctx->record_type;
1232 /* ??? It isn't sufficient to just call remap_type here, because
1233 variably_modified_type_p doesn't work the way we expect for
1234 record types. Testing each field for whether it needs remapping
1235 and creating a new record by hand works, however. */
1236 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
1237 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1241 tree name, new_fields = NULL;
1243 type = lang_hooks.types.make_type (RECORD_TYPE);
1244 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1245 name = build_decl (TYPE_DECL, name, type);
1246 TYPE_NAME (type) = name;
1248 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
1250 tree new_f = copy_node (f);
1251 DECL_CONTEXT (new_f) = type;
1252 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1253 TREE_CHAIN (new_f) = new_fields;
1254 walk_tree (&DECL_SIZE (new_f), copy_body_r, &ctx->cb, NULL);
1255 walk_tree (&DECL_SIZE_UNIT (new_f), copy_body_r, &ctx->cb, NULL);
1256 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_body_r, &ctx->cb, NULL);
1259 /* Arrange to be able to look up the receiver field
1260 given the sender field. */
1261 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1262 (splay_tree_value) new_f);
1264 TYPE_FIELDS (type) = nreverse (new_fields);
1268 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1271 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1272 specified by CLAUSES. */
1275 scan_sharing_clauses (tree clauses, omp_context *ctx)
1278 bool scan_array_reductions = false;
1280 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1284 switch (OMP_CLAUSE_CODE (c))
1286 case OMP_CLAUSE_PRIVATE:
1287 decl = OMP_CLAUSE_DECL (c);
1288 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1290 else if (!is_variable_sized (decl))
1291 install_var_local (decl, ctx);
1294 case OMP_CLAUSE_SHARED:
1295 gcc_assert (is_taskreg_ctx (ctx));
1296 decl = OMP_CLAUSE_DECL (c);
1297 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1298 || !is_variable_sized (decl));
1299 /* Global variables don't need to be copied,
1300 the receiver side will use them directly. */
1301 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1303 by_ref = use_pointer_for_field (decl, ctx);
1304 if (! TREE_READONLY (decl)
1305 || TREE_ADDRESSABLE (decl)
1307 || is_reference (decl))
1309 install_var_field (decl, by_ref, 3, ctx);
1310 install_var_local (decl, ctx);
1313 /* We don't need to copy const scalar vars back. */
1314 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1317 case OMP_CLAUSE_LASTPRIVATE:
1318 /* Let the corresponding firstprivate clause create
1320 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1324 case OMP_CLAUSE_FIRSTPRIVATE:
1325 case OMP_CLAUSE_REDUCTION:
1326 decl = OMP_CLAUSE_DECL (c);
1328 if (is_variable_sized (decl))
1330 if (is_task_ctx (ctx))
1331 install_var_field (decl, false, 1, ctx);
1334 else if (is_taskreg_ctx (ctx))
1337 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1338 by_ref = use_pointer_for_field (decl, NULL);
1340 if (is_task_ctx (ctx)
1341 && (global || by_ref || is_reference (decl)))
1343 install_var_field (decl, false, 1, ctx);
1345 install_var_field (decl, by_ref, 2, ctx);
1348 install_var_field (decl, by_ref, 3, ctx);
1350 install_var_local (decl, ctx);
1353 case OMP_CLAUSE_COPYPRIVATE:
1355 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
1358 case OMP_CLAUSE_COPYIN:
1359 decl = OMP_CLAUSE_DECL (c);
1360 by_ref = use_pointer_for_field (decl, NULL);
1361 install_var_field (decl, by_ref, 3, ctx);
1364 case OMP_CLAUSE_DEFAULT:
1365 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1369 case OMP_CLAUSE_NUM_THREADS:
1370 case OMP_CLAUSE_SCHEDULE:
1372 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1375 case OMP_CLAUSE_NOWAIT:
1376 case OMP_CLAUSE_ORDERED:
1377 case OMP_CLAUSE_COLLAPSE:
1378 case OMP_CLAUSE_UNTIED:
1386 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1388 switch (OMP_CLAUSE_CODE (c))
1390 case OMP_CLAUSE_LASTPRIVATE:
1391 /* Let the corresponding firstprivate clause create
1393 if (OMP_CLAUSE_LASTPRIVATE_STMT (c))
1394 scan_array_reductions = true;
1395 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1399 case OMP_CLAUSE_PRIVATE:
1400 case OMP_CLAUSE_FIRSTPRIVATE:
1401 case OMP_CLAUSE_REDUCTION:
1402 decl = OMP_CLAUSE_DECL (c);
1403 if (is_variable_sized (decl))
1404 install_var_local (decl, ctx);
1405 fixup_remapped_decl (decl, ctx,
1406 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1407 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1408 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1409 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1410 scan_array_reductions = true;
1413 case OMP_CLAUSE_SHARED:
1414 decl = OMP_CLAUSE_DECL (c);
1415 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1416 fixup_remapped_decl (decl, ctx, false);
1419 case OMP_CLAUSE_COPYPRIVATE:
1420 case OMP_CLAUSE_COPYIN:
1421 case OMP_CLAUSE_DEFAULT:
1423 case OMP_CLAUSE_NUM_THREADS:
1424 case OMP_CLAUSE_SCHEDULE:
1425 case OMP_CLAUSE_NOWAIT:
1426 case OMP_CLAUSE_ORDERED:
1427 case OMP_CLAUSE_COLLAPSE:
1428 case OMP_CLAUSE_UNTIED:
1436 if (scan_array_reductions)
1437 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1438 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1439 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1441 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1442 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1444 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1445 && OMP_CLAUSE_LASTPRIVATE_STMT (c))
1446 scan_omp (&OMP_CLAUSE_LASTPRIVATE_STMT (c), ctx);
1449 /* Create a new name for omp child function. Returns an identifier. */
1451 static GTY(()) unsigned int tmp_ompfn_id_num;
1454 create_omp_child_function_name (bool task_copy)
1456 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1457 size_t len = IDENTIFIER_LENGTH (name);
1458 char *tmp_name, *prefix;
1461 suffix = task_copy ? "_omp_cpyfn" : "_omp_fn";
1462 prefix = alloca (len + strlen (suffix) + 1);
1463 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1464 strcpy (prefix + len, suffix);
1465 #ifndef NO_DOT_IN_LABEL
1467 #elif !defined NO_DOLLAR_IN_LABEL
1470 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1471 return get_identifier (tmp_name);
1474 /* Build a decl for the omp child function. It'll not contain a body
1475 yet, just the bare decl. */
1478 create_omp_child_function (omp_context *ctx, bool task_copy)
1480 tree decl, type, name, t;
1482 name = create_omp_child_function_name (task_copy);
1484 type = build_function_type_list (void_type_node, ptr_type_node,
1485 ptr_type_node, NULL_TREE);
1487 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1489 decl = build_decl (FUNCTION_DECL, name, type);
1490 decl = lang_hooks.decls.pushdecl (decl);
1493 ctx->cb.dst_fn = decl;
1495 OMP_TASK_COPYFN (ctx->stmt) = decl;
1497 TREE_STATIC (decl) = 1;
1498 TREE_USED (decl) = 1;
1499 DECL_ARTIFICIAL (decl) = 1;
1500 DECL_IGNORED_P (decl) = 0;
1501 TREE_PUBLIC (decl) = 0;
1502 DECL_UNINLINABLE (decl) = 1;
1503 DECL_EXTERNAL (decl) = 0;
1504 DECL_CONTEXT (decl) = NULL_TREE;
1505 DECL_INITIAL (decl) = make_node (BLOCK);
1507 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1508 DECL_ARTIFICIAL (t) = 1;
1509 DECL_IGNORED_P (t) = 1;
1510 DECL_RESULT (decl) = t;
1512 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1513 DECL_ARTIFICIAL (t) = 1;
1514 DECL_ARG_TYPE (t) = ptr_type_node;
1515 DECL_CONTEXT (t) = current_function_decl;
1517 DECL_ARGUMENTS (decl) = t;
1519 ctx->receiver_decl = t;
1522 t = build_decl (PARM_DECL, get_identifier (".omp_data_o"),
1524 DECL_ARTIFICIAL (t) = 1;
1525 DECL_ARG_TYPE (t) = ptr_type_node;
1526 DECL_CONTEXT (t) = current_function_decl;
1528 TREE_CHAIN (t) = DECL_ARGUMENTS (decl);
1529 DECL_ARGUMENTS (decl) = t;
1532 /* Allocate memory for the function structure. The call to
1533 allocate_struct_function clobbers CFUN, so we need to restore
1535 push_struct_function (decl);
1536 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1537 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1542 /* Scan an OpenMP parallel directive. */
1545 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1550 /* Ignore parallel directives with empty bodies, unless there
1551 are copyin clauses. */
1553 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1554 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1556 *stmt_p = build_empty_stmt ();
1560 ctx = new_omp_context (*stmt_p, outer_ctx);
1561 if (taskreg_nesting_level > 1)
1562 ctx->is_nested = true;
1563 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1564 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1565 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1566 name = create_tmp_var_name (".omp_data_s");
1567 name = build_decl (TYPE_DECL, name, ctx->record_type);
1568 TYPE_NAME (ctx->record_type) = name;
1569 create_omp_child_function (ctx, false);
1570 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1572 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1573 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1575 if (TYPE_FIELDS (ctx->record_type) == NULL)
1576 ctx->record_type = ctx->receiver_decl = NULL;
1579 layout_type (ctx->record_type);
1580 fixup_child_record_type (ctx);
1584 /* Scan an OpenMP task directive. */
1587 scan_omp_task (tree *stmt_p, omp_context *outer_ctx)
1592 /* Ignore task directives with empty bodies. */
1594 && empty_body_p (OMP_TASK_BODY (*stmt_p)))
1596 *stmt_p = build_empty_stmt ();
1600 ctx = new_omp_context (*stmt_p, outer_ctx);
1601 if (taskreg_nesting_level > 1)
1602 ctx->is_nested = true;
1603 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1604 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1605 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1606 name = create_tmp_var_name (".omp_data_s");
1607 name = build_decl (TYPE_DECL, name, ctx->record_type);
1608 TYPE_NAME (ctx->record_type) = name;
1609 create_omp_child_function (ctx, false);
1610 OMP_TASK_FN (*stmt_p) = ctx->cb.dst_fn;
1612 scan_sharing_clauses (OMP_TASK_CLAUSES (*stmt_p), ctx);
1614 if (ctx->srecord_type)
1616 name = create_tmp_var_name (".omp_data_a");
1617 name = build_decl (TYPE_DECL, name, ctx->srecord_type);
1618 TYPE_NAME (ctx->srecord_type) = name;
1619 create_omp_child_function (ctx, true);
1622 scan_omp (&OMP_TASK_BODY (*stmt_p), ctx);
1624 if (TYPE_FIELDS (ctx->record_type) == NULL)
1626 ctx->record_type = ctx->receiver_decl = NULL;
1627 OMP_TASK_ARG_SIZE (*stmt_p)
1628 = build_int_cst (long_integer_type_node, 0);
1629 OMP_TASK_ARG_ALIGN (*stmt_p)
1630 = build_int_cst (long_integer_type_node, 1);
1634 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1635 /* Move VLA fields to the end. */
1636 p = &TYPE_FIELDS (ctx->record_type);
1638 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1639 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1642 *p = TREE_CHAIN (*p);
1643 TREE_CHAIN (*q) = NULL_TREE;
1644 q = &TREE_CHAIN (*q);
1647 p = &TREE_CHAIN (*p);
1649 layout_type (ctx->record_type);
1650 fixup_child_record_type (ctx);
1651 if (ctx->srecord_type)
1652 layout_type (ctx->srecord_type);
1653 OMP_TASK_ARG_SIZE (*stmt_p)
1654 = fold_convert (long_integer_type_node,
1655 TYPE_SIZE_UNIT (ctx->record_type));
1656 OMP_TASK_ARG_ALIGN (*stmt_p)
1657 = build_int_cst (long_integer_type_node,
1658 TYPE_ALIGN_UNIT (ctx->record_type));
1663 /* Scan an OpenMP loop directive. */
1666 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1673 ctx = new_omp_context (stmt, outer_ctx);
1675 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1677 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1678 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1680 scan_omp (&TREE_VEC_ELT (OMP_FOR_INIT (stmt), i), ctx);
1681 scan_omp (&TREE_VEC_ELT (OMP_FOR_COND (stmt), i), ctx);
1682 scan_omp (&TREE_VEC_ELT (OMP_FOR_INCR (stmt), i), ctx);
1684 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1687 /* Scan an OpenMP sections directive. */
1690 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1696 ctx = new_omp_context (stmt, outer_ctx);
1697 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1698 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1701 /* Scan an OpenMP single directive. */
1704 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1706 tree stmt = *stmt_p;
1710 ctx = new_omp_context (stmt, outer_ctx);
1711 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1712 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1713 name = create_tmp_var_name (".omp_copy_s");
1714 name = build_decl (TYPE_DECL, name, ctx->record_type);
1715 TYPE_NAME (ctx->record_type) = name;
1717 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1718 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1720 if (TYPE_FIELDS (ctx->record_type) == NULL)
1721 ctx->record_type = NULL;
1723 layout_type (ctx->record_type);
1727 /* Check OpenMP nesting restrictions. */
1729 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1731 switch (TREE_CODE (t))
1737 for (; ctx != NULL; ctx = ctx->outer)
1738 switch (TREE_CODE (ctx->stmt))
1746 if (TREE_CODE (t) == CALL_EXPR)
1748 warning (0, "barrier region may not be closely nested inside "
1749 "of work-sharing, critical, ordered, master or "
1750 "explicit task region");
1753 warning (0, "work-sharing region may not be closely nested inside "
1754 "of work-sharing, critical, ordered, master or explicit "
1764 for (; ctx != NULL; ctx = ctx->outer)
1765 switch (TREE_CODE (ctx->stmt))
1771 warning (0, "master region may not be closely nested inside "
1772 "of work-sharing or explicit task region");
1781 for (; ctx != NULL; ctx = ctx->outer)
1782 switch (TREE_CODE (ctx->stmt))
1786 warning (0, "ordered region may not be closely nested inside "
1787 "of critical or explicit task region");
1790 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1791 OMP_CLAUSE_ORDERED) == NULL)
1792 warning (0, "ordered region must be closely nested inside "
1793 "a loop region with an ordered clause");
1802 for (; ctx != NULL; ctx = ctx->outer)
1803 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1804 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1806 warning (0, "critical region may not be nested inside a critical "
1807 "region with the same name");
1817 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1820 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1822 struct walk_stmt_info *wi = data;
1823 omp_context *ctx = wi->info;
1826 if (EXPR_HAS_LOCATION (t))
1827 input_location = EXPR_LOCATION (t);
1829 /* Check the OpenMP nesting restrictions. */
1832 if (OMP_DIRECTIVE_P (t))
1833 check_omp_nesting_restrictions (t, ctx);
1834 else if (TREE_CODE (t) == CALL_EXPR)
1836 tree fndecl = get_callee_fndecl (t);
1837 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
1838 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
1839 check_omp_nesting_restrictions (t, ctx);
1844 switch (TREE_CODE (t))
1847 taskreg_nesting_level++;
1848 scan_omp_parallel (tp, ctx);
1849 taskreg_nesting_level--;
1853 taskreg_nesting_level++;
1854 scan_omp_task (tp, ctx);
1855 taskreg_nesting_level--;
1859 scan_omp_for (tp, ctx);
1863 scan_omp_sections (tp, ctx);
1867 scan_omp_single (tp, ctx);
1874 ctx = new_omp_context (*tp, ctx);
1875 scan_omp (&OMP_BODY (*tp), ctx);
1883 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1884 insert_decl_map (&ctx->cb, var, var);
1893 *tp = remap_decl (t, &ctx->cb);
1897 if (ctx && TYPE_P (t))
1898 *tp = remap_type (t, &ctx->cb);
1899 else if (!DECL_P (t))
1908 /* Scan all the statements starting at STMT_P. CTX contains context
1909 information about the OpenMP directives and clauses found during
1913 scan_omp (tree *stmt_p, omp_context *ctx)
1915 location_t saved_location;
1916 struct walk_stmt_info wi;
1918 memset (&wi, 0, sizeof (wi));
1919 wi.callback = scan_omp_1;
1921 wi.want_bind_expr = (ctx != NULL);
1922 wi.want_locations = true;
1924 saved_location = input_location;
1925 walk_stmts (&wi, stmt_p);
1926 input_location = saved_location;
1929 /* Re-gimplification and code generation routines. */
1931 /* Build a call to GOMP_barrier. */
1934 build_omp_barrier (void)
1936 return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1939 /* If a context was created for STMT when it was scanned, return it. */
1941 static omp_context *
1942 maybe_lookup_ctx (tree stmt)
1945 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1946 return n ? (omp_context *) n->value : NULL;
1950 /* Find the mapping for DECL in CTX or the immediately enclosing
1951 context that has a mapping for DECL.
1953 If CTX is a nested parallel directive, we may have to use the decl
1954 mappings created in CTX's parent context. Suppose that we have the
1955 following parallel nesting (variable UIDs showed for clarity):
1958 #omp parallel shared(iD.1562) -> outer parallel
1959 iD.1562 = iD.1562 + 1;
1961 #omp parallel shared (iD.1562) -> inner parallel
1962 iD.1562 = iD.1562 - 1;
1964 Each parallel structure will create a distinct .omp_data_s structure
1965 for copying iD.1562 in/out of the directive:
1967 outer parallel .omp_data_s.1.i -> iD.1562
1968 inner parallel .omp_data_s.2.i -> iD.1562
1970 A shared variable mapping will produce a copy-out operation before
1971 the parallel directive and a copy-in operation after it. So, in
1972 this case we would have:
1975 .omp_data_o.1.i = iD.1562;
1976 #omp parallel shared(iD.1562) -> outer parallel
1977 .omp_data_i.1 = &.omp_data_o.1
1978 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1980 .omp_data_o.2.i = iD.1562; -> **
1981 #omp parallel shared(iD.1562) -> inner parallel
1982 .omp_data_i.2 = &.omp_data_o.2
1983 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1986 ** This is a problem. The symbol iD.1562 cannot be referenced
1987 inside the body of the outer parallel region. But since we are
1988 emitting this copy operation while expanding the inner parallel
1989 directive, we need to access the CTX structure of the outer
1990 parallel directive to get the correct mapping:
1992 .omp_data_o.2.i = .omp_data_i.1->i
1994 Since there may be other workshare or parallel directives enclosing
1995 the parallel directive, it may be necessary to walk up the context
1996 parent chain. This is not a problem in general because nested
1997 parallelism happens only rarely. */
2000 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2005 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2006 t = maybe_lookup_decl (decl, up);
2008 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2010 return t ? t : decl;
2014 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2015 in outer contexts. */
2018 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2023 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2024 t = maybe_lookup_decl (decl, up);
2026 return t ? t : decl;
2030 /* Construct the initialization value for reduction CLAUSE. */
2033 omp_reduction_init (tree clause, tree type)
2035 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2042 case TRUTH_ORIF_EXPR:
2043 case TRUTH_XOR_EXPR:
2045 return fold_convert (type, integer_zero_node);
2048 case TRUTH_AND_EXPR:
2049 case TRUTH_ANDIF_EXPR:
2051 return fold_convert (type, integer_one_node);
2054 return fold_convert (type, integer_minus_one_node);
2057 if (SCALAR_FLOAT_TYPE_P (type))
2059 REAL_VALUE_TYPE max, min;
2060 if (HONOR_INFINITIES (TYPE_MODE (type)))
2063 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2066 real_maxval (&min, 1, TYPE_MODE (type));
2067 return build_real (type, min);
2071 gcc_assert (INTEGRAL_TYPE_P (type));
2072 return TYPE_MIN_VALUE (type);
2076 if (SCALAR_FLOAT_TYPE_P (type))
2078 REAL_VALUE_TYPE max;
2079 if (HONOR_INFINITIES (TYPE_MODE (type)))
2082 real_maxval (&max, 0, TYPE_MODE (type));
2083 return build_real (type, max);
2087 gcc_assert (INTEGRAL_TYPE_P (type));
2088 return TYPE_MAX_VALUE (type);
2096 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2097 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2098 private variables. Initialization statements go in ILIST, while calls
2099 to destructors go in DLIST. */
2102 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
2105 tree_stmt_iterator diter;
2106 tree c, dtor, copyin_seq, x, ptr;
2107 bool copyin_by_ref = false;
2108 bool lastprivate_firstprivate = false;
2111 *dlist = alloc_stmt_list ();
2112 diter = tsi_start (*dlist);
2115 /* Do all the fixed sized types in the first pass, and the variable sized
2116 types in the second pass. This makes sure that the scalar arguments to
2117 the variable sized types are processed before we use them in the
2118 variable sized operations. */
2119 for (pass = 0; pass < 2; ++pass)
2121 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2123 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2129 case OMP_CLAUSE_PRIVATE:
2130 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2133 case OMP_CLAUSE_SHARED:
2134 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2136 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2139 case OMP_CLAUSE_FIRSTPRIVATE:
2140 case OMP_CLAUSE_COPYIN:
2141 case OMP_CLAUSE_REDUCTION:
2143 case OMP_CLAUSE_LASTPRIVATE:
2144 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2146 lastprivate_firstprivate = true;
2155 new_var = var = OMP_CLAUSE_DECL (c);
2156 if (c_kind != OMP_CLAUSE_COPYIN)
2157 new_var = lookup_decl (var, ctx);
2159 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2164 else if (is_variable_sized (var))
2166 /* For variable sized types, we need to allocate the
2167 actual storage here. Call alloca and store the
2168 result in the pointer decl that we created elsewhere. */
2172 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2174 ptr = DECL_VALUE_EXPR (new_var);
2175 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2176 ptr = TREE_OPERAND (ptr, 0);
2177 gcc_assert (DECL_P (ptr));
2178 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2179 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
2180 x = fold_convert (TREE_TYPE (ptr), x);
2181 x = build_gimple_modify_stmt (ptr, x);
2182 gimplify_and_add (x, ilist);
2185 else if (is_reference (var))
2187 /* For references that are being privatized for Fortran,
2188 allocate new backing storage for the new pointer
2189 variable. This allows us to avoid changing all the
2190 code that expects a pointer to something that expects
2191 a direct variable. Note that this doesn't apply to
2192 C++, since reference types are disallowed in data
2193 sharing clauses there, except for NRV optimized
2198 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2199 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2201 x = build_receiver_ref (var, false, ctx);
2202 x = build_fold_addr_expr (x);
2204 else if (TREE_CONSTANT (x))
2206 const char *name = NULL;
2207 if (DECL_NAME (var))
2208 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2210 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2212 gimple_add_tmp_var (x);
2213 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
2217 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
2218 x = fold_convert (TREE_TYPE (new_var), x);
2221 x = build_gimple_modify_stmt (new_var, x);
2222 gimplify_and_add (x, ilist);
2224 new_var = build_fold_indirect_ref (new_var);
2226 else if (c_kind == OMP_CLAUSE_REDUCTION
2227 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2235 switch (OMP_CLAUSE_CODE (c))
2237 case OMP_CLAUSE_SHARED:
2238 /* Shared global vars are just accessed directly. */
2239 if (is_global_var (new_var))
2241 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2242 needs to be delayed until after fixup_child_record_type so
2243 that we get the correct type during the dereference. */
2244 by_ref = use_pointer_for_field (var, ctx);
2245 x = build_receiver_ref (var, by_ref, ctx);
2246 SET_DECL_VALUE_EXPR (new_var, x);
2247 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2249 /* ??? If VAR is not passed by reference, and the variable
2250 hasn't been initialized yet, then we'll get a warning for
2251 the store into the omp_data_s structure. Ideally, we'd be
2252 able to notice this and not store anything at all, but
2253 we're generating code too early. Suppress the warning. */
2255 TREE_NO_WARNING (var) = 1;
2258 case OMP_CLAUSE_LASTPRIVATE:
2259 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2263 case OMP_CLAUSE_PRIVATE:
2264 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2265 x = build_outer_var_ref (var, ctx);
2266 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2268 if (is_task_ctx (ctx))
2269 x = build_receiver_ref (var, false, ctx);
2271 x = build_outer_var_ref (var, ctx);
2275 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2277 gimplify_and_add (x, ilist);
2281 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2285 gimplify_stmt (&dtor);
2286 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
2290 case OMP_CLAUSE_FIRSTPRIVATE:
2291 if (is_task_ctx (ctx))
2293 if (is_reference (var) || is_variable_sized (var))
2295 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2297 || use_pointer_for_field (var, NULL))
2299 x = build_receiver_ref (var, false, ctx);
2300 SET_DECL_VALUE_EXPR (new_var, x);
2301 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2305 x = build_outer_var_ref (var, ctx);
2306 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2307 gimplify_and_add (x, ilist);
2311 case OMP_CLAUSE_COPYIN:
2312 by_ref = use_pointer_for_field (var, NULL);
2313 x = build_receiver_ref (var, by_ref, ctx);
2314 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2315 append_to_statement_list (x, ©in_seq);
2316 copyin_by_ref |= by_ref;
2319 case OMP_CLAUSE_REDUCTION:
2320 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2322 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2323 x = build_outer_var_ref (var, ctx);
2325 if (is_reference (var))
2326 x = build_fold_addr_expr (x);
2327 SET_DECL_VALUE_EXPR (placeholder, x);
2328 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2329 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
2330 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
2331 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2335 x = omp_reduction_init (c, TREE_TYPE (new_var));
2336 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2337 x = build_gimple_modify_stmt (new_var, x);
2338 gimplify_and_add (x, ilist);
2348 /* The copyin sequence is not to be executed by the main thread, since
2349 that would result in self-copies. Perhaps not visible to scalars,
2350 but it certainly is to C++ operator=. */
2353 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2354 x = build2 (NE_EXPR, boolean_type_node, x,
2355 build_int_cst (TREE_TYPE (x), 0));
2356 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2357 gimplify_and_add (x, ilist);
2360 /* If any copyin variable is passed by reference, we must ensure the
2361 master thread doesn't modify it before it is copied over in all
2362 threads. Similarly for variables in both firstprivate and
2363 lastprivate clauses we need to ensure the lastprivate copying
2364 happens after firstprivate copying in all threads. */
2365 if (copyin_by_ref || lastprivate_firstprivate)
2366 gimplify_and_add (build_omp_barrier (), ilist);
2370 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2371 both parallel and workshare constructs. PREDICATE may be NULL if it's
2375 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
2378 tree sub_list, x, c;
2379 bool par_clauses = false;
2381 /* Early exit if there are no lastprivate clauses. */
2382 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
2383 if (clauses == NULL)
2385 /* If this was a workshare clause, see if it had been combined
2386 with its parallel. In that case, look for the clauses on the
2387 parallel statement itself. */
2388 if (is_parallel_ctx (ctx))
2392 if (ctx == NULL || !is_parallel_ctx (ctx))
2395 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
2396 OMP_CLAUSE_LASTPRIVATE);
2397 if (clauses == NULL)
2402 sub_list = alloc_stmt_list ();
2404 for (c = clauses; c ;)
2408 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2410 var = OMP_CLAUSE_DECL (c);
2411 new_var = lookup_decl (var, ctx);
2413 if (OMP_CLAUSE_LASTPRIVATE_STMT (c))
2414 gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c), &sub_list);
2415 OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL;
2417 x = build_outer_var_ref (var, ctx);
2418 if (is_reference (var))
2419 new_var = build_fold_indirect_ref (new_var);
2420 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2421 append_to_statement_list (x, &sub_list);
2423 c = OMP_CLAUSE_CHAIN (c);
2424 if (c == NULL && !par_clauses)
2426 /* If this was a workshare clause, see if it had been combined
2427 with its parallel. In that case, continue looking for the
2428 clauses also on the parallel statement itself. */
2429 if (is_parallel_ctx (ctx))
2433 if (ctx == NULL || !is_parallel_ctx (ctx))
2436 c = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
2437 OMP_CLAUSE_LASTPRIVATE);
2443 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
2447 gimplify_and_add (x, stmt_list);
2451 /* Generate code to implement the REDUCTION clauses. */
2454 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
2456 tree sub_list = NULL, x, c;
2459 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
2460 update in that case, otherwise use a lock. */
2461 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
2462 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2464 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2466 /* Never use OMP_ATOMIC for array reductions. */
2476 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2478 tree var, ref, new_var;
2479 enum tree_code code;
2481 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
2484 var = OMP_CLAUSE_DECL (c);
2485 new_var = lookup_decl (var, ctx);
2486 if (is_reference (var))
2487 new_var = build_fold_indirect_ref (new_var);
2488 ref = build_outer_var_ref (var, ctx);
2489 code = OMP_CLAUSE_REDUCTION_CODE (c);
2491 /* reduction(-:var) sums up the partial results, so it acts
2492 identically to reduction(+:var). */
2493 if (code == MINUS_EXPR)
2498 tree addr = build_fold_addr_expr (ref);
2500 addr = save_expr (addr);
2501 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
2502 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
2503 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
2504 gimplify_and_add (x, stmt_list);
2508 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2510 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2512 if (is_reference (var))
2513 ref = build_fold_addr_expr (ref);
2514 SET_DECL_VALUE_EXPR (placeholder, ref);
2515 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2516 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
2517 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
2518 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2522 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2523 ref = build_outer_var_ref (var, ctx);
2524 x = build_gimple_modify_stmt (ref, x);
2525 append_to_statement_list (x, &sub_list);
2529 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
2530 gimplify_and_add (x, stmt_list);
2532 gimplify_and_add (sub_list, stmt_list);
2534 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
2535 gimplify_and_add (x, stmt_list);
2539 /* Generate code to implement the COPYPRIVATE clauses. */
2542 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
2547 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2552 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2555 var = OMP_CLAUSE_DECL (c);
2556 by_ref = use_pointer_for_field (var, NULL);
2558 ref = build_sender_ref (var, ctx);
2559 x = lookup_decl_in_outer_ctx (var, ctx);
2560 x = by_ref ? build_fold_addr_expr (x) : x;
2561 x = build_gimple_modify_stmt (ref, x);
2562 gimplify_and_add (x, slist);
2564 ref = build_receiver_ref (var, by_ref, ctx);
2565 if (is_reference (var))
2567 ref = build_fold_indirect_ref (ref);
2568 var = build_fold_indirect_ref (var);
2570 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2571 gimplify_and_add (x, rlist);
2576 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2577 and REDUCTION from the sender (aka parent) side. */
2580 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2584 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2586 tree val, ref, x, var;
2587 bool by_ref, do_in = false, do_out = false;
2589 switch (OMP_CLAUSE_CODE (c))
2591 case OMP_CLAUSE_PRIVATE:
2592 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2595 case OMP_CLAUSE_FIRSTPRIVATE:
2596 case OMP_CLAUSE_COPYIN:
2597 case OMP_CLAUSE_LASTPRIVATE:
2598 case OMP_CLAUSE_REDUCTION:
2604 val = OMP_CLAUSE_DECL (c);
2605 var = lookup_decl_in_outer_ctx (val, ctx);
2607 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2608 && is_global_var (var))
2610 if (is_variable_sized (val))
2612 by_ref = use_pointer_for_field (val, NULL);
2614 switch (OMP_CLAUSE_CODE (c))
2616 case OMP_CLAUSE_PRIVATE:
2617 case OMP_CLAUSE_FIRSTPRIVATE:
2618 case OMP_CLAUSE_COPYIN:
2622 case OMP_CLAUSE_LASTPRIVATE:
2623 if (by_ref || is_reference (val))
2625 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2632 if (lang_hooks.decls.omp_private_outer_ref (val))
2637 case OMP_CLAUSE_REDUCTION:
2639 do_out = !(by_ref || is_reference (val));
2648 ref = build_sender_ref (val, ctx);
2649 x = by_ref ? build_fold_addr_expr (var) : var;
2650 x = build_gimple_modify_stmt (ref, x);
2651 gimplify_and_add (x, ilist);
2652 if (is_task_ctx (ctx))
2653 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
2658 ref = build_sender_ref (val, ctx);
2659 x = build_gimple_modify_stmt (var, ref);
2660 gimplify_and_add (x, olist);
2665 /* Generate code to implement SHARED from the sender (aka parent) side.
2666 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2667 got automatically shared. */
2670 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2672 tree var, ovar, nvar, f, x, record_type;
2674 if (ctx->record_type == NULL)
2677 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
2678 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
2680 ovar = DECL_ABSTRACT_ORIGIN (f);
2681 nvar = maybe_lookup_decl (ovar, ctx);
2682 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2685 /* If CTX is a nested parallel directive. Find the immediately
2686 enclosing parallel or workshare construct that contains a
2687 mapping for OVAR. */
2688 var = lookup_decl_in_outer_ctx (ovar, ctx);
2690 if (use_pointer_for_field (ovar, ctx))
2692 x = build_sender_ref (ovar, ctx);
2693 var = build_fold_addr_expr (var);
2694 x = build_gimple_modify_stmt (x, var);
2695 gimplify_and_add (x, ilist);
2699 x = build_sender_ref (ovar, ctx);
2700 x = build_gimple_modify_stmt (x, var);
2701 gimplify_and_add (x, ilist);
2703 if (!TREE_READONLY (var))
2705 x = build_sender_ref (ovar, ctx);
2706 x = build_gimple_modify_stmt (var, x);
2707 gimplify_and_add (x, olist);
2713 /* Build the function calls to GOMP_parallel_start etc to actually
2714 generate the parallel operation. REGION is the parallel region
2715 being expanded. BB is the block where to insert the code. WS_ARGS
2716 will be set if this is a call to a combined parallel+workshare
2717 construct, it contains the list of additional arguments needed by
2718 the workshare construct. */
2721 expand_parallel_call (struct omp_region *region, basic_block bb,
2722 tree entry_stmt, tree ws_args)
2724 tree t, t1, t2, val, cond, c, clauses;
2725 block_stmt_iterator si;
2728 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2730 /* Determine what flavor of GOMP_parallel_start we will be
2732 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2733 if (is_combined_parallel (region))
2735 switch (region->inner->type)
2738 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
2739 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2740 + (region->inner->sched_kind
2741 == OMP_CLAUSE_SCHEDULE_RUNTIME
2742 ? 3 : region->inner->sched_kind);
2745 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2752 /* By default, the value of NUM_THREADS is zero (selected at run time)
2753 and there is no conditional. */
2755 val = build_int_cst (unsigned_type_node, 0);
2757 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2759 cond = OMP_CLAUSE_IF_EXPR (c);
2761 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2763 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2765 /* Ensure 'val' is of the correct type. */
2766 val = fold_convert (unsigned_type_node, val);
2768 /* If we found the clause 'if (cond)', build either
2769 (cond != 0) or (cond ? val : 1u). */
2772 block_stmt_iterator si;
2774 cond = gimple_boolify (cond);
2776 if (integer_zerop (val))
2777 val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
2778 build_int_cst (TREE_TYPE (cond), 0));
2781 basic_block cond_bb, then_bb, else_bb;
2782 edge e, e_then, e_else;
2783 tree t, tmp_then, tmp_else, tmp_join, tmp_var;
2785 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
2786 if (gimple_in_ssa_p (cfun))
2788 tmp_then = make_ssa_name (tmp_var, NULL_TREE);
2789 tmp_else = make_ssa_name (tmp_var, NULL_TREE);
2790 tmp_join = make_ssa_name (tmp_var, NULL_TREE);
2799 e = split_block (bb, NULL);
2804 then_bb = create_empty_bb (cond_bb);
2805 else_bb = create_empty_bb (then_bb);
2806 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
2807 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
2809 t = build3 (COND_EXPR, void_type_node,
2810 cond, NULL_TREE, NULL_TREE);
2812 si = bsi_start (cond_bb);
2813 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2815 si = bsi_start (then_bb);
2816 t = build_gimple_modify_stmt (tmp_then, val);
2817 if (gimple_in_ssa_p (cfun))
2818 SSA_NAME_DEF_STMT (tmp_then) = t;
2819 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2821 si = bsi_start (else_bb);
2822 t = build_gimple_modify_stmt (tmp_else,
2823 build_int_cst (unsigned_type_node, 1));
2824 if (gimple_in_ssa_p (cfun))
2825 SSA_NAME_DEF_STMT (tmp_else) = t;
2826 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2828 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2829 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2830 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
2831 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
2833 if (gimple_in_ssa_p (cfun))
2835 tree phi = create_phi_node (tmp_join, bb);
2836 SSA_NAME_DEF_STMT (tmp_join) = phi;
2837 add_phi_arg (phi, tmp_then, e_then);
2838 add_phi_arg (phi, tmp_else, e_else);
2844 si = bsi_start (bb);
2845 val = force_gimple_operand_bsi (&si, val, true, NULL_TREE,
2846 false, BSI_CONTINUE_LINKING);
2850 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2852 t1 = null_pointer_node;
2854 t1 = build_fold_addr_expr (t);
2855 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2859 tree args = tree_cons (NULL, t2,
2860 tree_cons (NULL, t1,
2861 tree_cons (NULL, val, ws_args)));
2862 t = build_function_call_expr (built_in_decls[start_ix], args);
2865 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2867 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2868 false, BSI_CONTINUE_LINKING);
2870 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2872 t = null_pointer_node;
2874 t = build_fold_addr_expr (t);
2875 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2876 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2877 false, BSI_CONTINUE_LINKING);
2879 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2880 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2881 false, BSI_CONTINUE_LINKING);
2885 static void maybe_catch_exception (tree *stmt_p);
2888 /* Finalize task copyfn. */
2891 expand_task_copyfn (tree task_stmt)
2893 struct function *child_cfun;
2894 tree child_fn, old_fn;
2896 child_fn = OMP_TASK_COPYFN (task_stmt);
2897 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2899 /* Inform the callgraph about the new function. */
2900 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2901 = cfun->curr_properties;
2903 old_fn = current_function_decl;
2904 push_cfun (child_cfun);
2905 current_function_decl = child_fn;
2906 gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
2907 maybe_catch_exception (&BIND_EXPR_BODY (DECL_SAVED_TREE (child_fn)));
2909 current_function_decl = old_fn;
2911 cgraph_add_new_function (child_fn, false);
2914 /* Build the function call to GOMP_task to actually
2915 generate the task operation. BB is the block where to insert the code. */
2918 expand_task_call (basic_block bb, tree entry_stmt)
2920 tree t, t1, t2, t3, flags, cond, c, clauses;
2921 block_stmt_iterator si;
2923 clauses = OMP_TASK_CLAUSES (entry_stmt);
2925 if (OMP_TASK_COPYFN (entry_stmt))
2926 expand_task_copyfn (entry_stmt);
2928 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2930 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
2932 cond = boolean_true_node;
2934 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2935 flags = build_int_cst (unsigned_type_node, (c ? 1 : 0));
2938 t = OMP_TASK_DATA_ARG (entry_stmt);
2940 t2 = null_pointer_node;
2942 t2 = build_fold_addr_expr (t);
2943 t1 = build_fold_addr_expr (OMP_TASK_FN (entry_stmt));
2944 t = OMP_TASK_COPYFN (entry_stmt);
2946 t3 = null_pointer_node;
2948 t3 = build_fold_addr_expr (t);
2950 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
2951 OMP_TASK_ARG_SIZE (entry_stmt),
2952 OMP_TASK_ARG_ALIGN (entry_stmt), cond, flags);
2954 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2955 false, BSI_CONTINUE_LINKING);
2959 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2960 handler. This prevents programs from violating the structured
2961 block semantics with throws. */
2964 maybe_catch_exception (tree *stmt_p)
2968 if (!flag_exceptions)
2971 if (lang_protect_cleanup_actions)
2972 t = lang_protect_cleanup_actions ();
2974 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2975 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2976 EH_FILTER_MUST_NOT_THROW (f) = 1;
2977 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2979 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2980 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2983 append_to_statement_list (t, stmt_p);
2986 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2989 list2chain (tree list)
2993 for (t = list; t; t = TREE_CHAIN (t))
2995 tree var = TREE_VALUE (t);
2997 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2999 TREE_CHAIN (var) = NULL_TREE;
3002 return list ? TREE_VALUE (list) : NULL_TREE;
3006 /* Remove barriers in REGION->EXIT's block. Note that this is only
3007 valid for OMP_PARALLEL regions. Since the end of a parallel region
3008 is an implicit barrier, any workshare inside the OMP_PARALLEL that
3009 left a barrier at the end of the OMP_PARALLEL region can now be
3013 remove_exit_barrier (struct omp_region *region)
3015 block_stmt_iterator si;
3016 basic_block exit_bb;
3021 exit_bb = region->exit;
3023 /* If the parallel region doesn't return, we don't have REGION->EXIT
3028 /* The last insn in the block will be the parallel's OMP_RETURN. The
3029 workshare's OMP_RETURN will be in a preceding block. The kinds of
3030 statements that can appear in between are extremely limited -- no
3031 memory operations at all. Here, we allow nothing at all, so the
3032 only thing we allow to precede this OMP_RETURN is a label. */
3033 si = bsi_last (exit_bb);
3034 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3036 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
3039 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3041 si = bsi_last (e->src);
3045 if (TREE_CODE (t) == OMP_RETURN)
3046 OMP_RETURN_NOWAIT (t) = 1;
3051 remove_exit_barriers (struct omp_region *region)
3053 if (region->type == OMP_PARALLEL)
3054 remove_exit_barrier (region);
3058 region = region->inner;
3059 remove_exit_barriers (region);
3060 while (region->next)
3062 region = region->next;
3063 remove_exit_barriers (region);
3068 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3069 calls. These can't be declared as const functions, but
3070 within one parallel body they are constant, so they can be
3071 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3072 which are declared const. Similarly for task body, except
3073 that in untied task omp_get_thread_num () can change at any task
3074 scheduling point. */
3077 optimize_omp_library_calls (tree entry_stmt)
3080 block_stmt_iterator bsi;
3082 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
3084 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
3085 bool untied_task = (TREE_CODE (entry_stmt) == OMP_TASK
3086 && find_omp_clause (OMP_TASK_CLAUSES (entry_stmt),
3087 OMP_CLAUSE_UNTIED) != NULL);
3090 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
3092 tree stmt = bsi_stmt (bsi);
3093 tree call = get_call_expr_in (stmt);
3097 && (decl = get_callee_fndecl (call))
3098 && DECL_EXTERNAL (decl)
3099 && TREE_PUBLIC (decl)
3100 && DECL_INITIAL (decl) == NULL)
3104 if (DECL_NAME (decl) == thr_num_id)
3106 /* In #pragma omp task untied omp_get_thread_num () can change
3107 during the execution of the task region. */
3110 built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
3112 else if (DECL_NAME (decl) == num_thr_id)
3113 built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
3117 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3118 || call_expr_nargs (call) != 0)
3121 if (flag_exceptions && !TREE_NOTHROW (decl))
3124 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3125 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
3126 != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
3129 CALL_EXPR_FN (call) = build_fold_addr_expr (built_in);
3134 /* Expand the OpenMP parallel or task directive starting at REGION. */
3137 expand_omp_taskreg (struct omp_region *region)
3139 basic_block entry_bb, exit_bb, new_bb;
3140 struct function *child_cfun;
3141 tree child_fn, block, t, ws_args;
3142 block_stmt_iterator si;
3146 entry_stmt = last_stmt (region->entry);
3147 child_fn = OMP_TASKREG_FN (entry_stmt);
3148 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3149 /* If this function has been already instrumented, make sure
3150 the child function isn't instrumented again. */
3151 child_cfun->after_tree_profile = cfun->after_tree_profile;
3153 entry_bb = region->entry;
3154 exit_bb = region->exit;
3156 if (is_combined_parallel (region))
3157 ws_args = region->ws_args;
3159 ws_args = NULL_TREE;
3161 if (child_cfun->cfg)
3163 /* Due to inlining, it may happen that we have already outlined
3164 the region, in which case all we need to do is make the
3165 sub-graph unreachable and emit the parallel call. */
3166 edge entry_succ_e, exit_succ_e;
3167 block_stmt_iterator si;
3169 entry_succ_e = single_succ_edge (entry_bb);
3171 si = bsi_last (entry_bb);
3172 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL
3173 || TREE_CODE (bsi_stmt (si)) == OMP_TASK);
3174 bsi_remove (&si, true);
3179 exit_succ_e = single_succ_edge (exit_bb);
3180 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3182 remove_edge_and_dominated_blocks (entry_succ_e);
3186 /* If the parallel region needs data sent from the parent
3187 function, then the very first statement (except possible
3188 tree profile counter updates) of the parallel body
3189 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3190 &.OMP_DATA_O is passed as an argument to the child function,
3191 we need to replace it with the argument as seen by the child
3194 In most cases, this will end up being the identity assignment
3195 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3196 a function call that has been inlined, the original PARM_DECL
3197 .OMP_DATA_I may have been converted into a different local
3198 variable. In which case, we need to keep the assignment. */
3199 if (OMP_TASKREG_DATA_ARG (entry_stmt))
3201 basic_block entry_succ_bb = single_succ (entry_bb);
3202 block_stmt_iterator si;
3203 tree parcopy_stmt = NULL_TREE, arg, narg;
3205 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
3209 gcc_assert (!bsi_end_p (si));
3210 stmt = bsi_stmt (si);
3211 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
3214 arg = GIMPLE_STMT_OPERAND (stmt, 1);
3216 if (TREE_CODE (arg) == ADDR_EXPR
3217 && TREE_OPERAND (arg, 0)
3218 == OMP_TASKREG_DATA_ARG (entry_stmt))
3220 parcopy_stmt = stmt;
3225 gcc_assert (parcopy_stmt != NULL_TREE);
3226 arg = DECL_ARGUMENTS (child_fn);
3228 if (!gimple_in_ssa_p (cfun))
3230 if (GIMPLE_STMT_OPERAND (parcopy_stmt, 0) == arg)
3231 bsi_remove (&si, true);
3233 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = arg;
3237 /* If we are in ssa form, we must load the value from the default
3238 definition of the argument. That should not be defined now,
3239 since the argument is not used uninitialized. */
3240 gcc_assert (gimple_default_def (cfun, arg) == NULL);
3241 narg = make_ssa_name (arg, build_empty_stmt ());
3242 set_default_def (arg, narg);
3243 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = narg;
3244 update_stmt (parcopy_stmt);
3248 /* Declare local variables needed in CHILD_CFUN. */
3249 block = DECL_INITIAL (child_fn);
3250 BLOCK_VARS (block) = list2chain (child_cfun->local_decls);
3251 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
3253 /* Reset DECL_CONTEXT on function arguments. */
3254 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
3255 DECL_CONTEXT (t) = child_fn;
3257 /* Split ENTRY_BB at OMP_PARALLEL or OMP_TASK, so that it can be
3258 moved to the child function. */
3259 si = bsi_last (entry_bb);
3261 gcc_assert (t && (TREE_CODE (t) == OMP_PARALLEL
3262 || TREE_CODE (t) == OMP_TASK));
3263 bsi_remove (&si, true);
3264 e = split_block (entry_bb, t);
3266 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3268 /* Convert OMP_RETURN into a RETURN_EXPR. */
3271 si = bsi_last (exit_bb);
3272 gcc_assert (!bsi_end_p (si)
3273 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3274 t = build1 (RETURN_EXPR, void_type_node, NULL);
3275 bsi_insert_after (&si, t, BSI_SAME_STMT);
3276 bsi_remove (&si, true);
3279 /* Move the parallel region into CHILD_CFUN. */
3281 if (gimple_in_ssa_p (cfun))
3283 push_cfun (child_cfun);
3284 init_tree_ssa (child_cfun);
3285 init_ssa_operands ();
3286 cfun->gimple_df->in_ssa_p = true;
3289 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
3291 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3293 /* Inform the callgraph about the new function. */
3294 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
3295 = cfun->curr_properties;
3296 cgraph_add_new_function (child_fn, true);
3298 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3299 fixed in a following pass. */
3300 push_cfun (child_cfun);
3302 optimize_omp_library_calls (entry_stmt);
3303 rebuild_cgraph_edges ();
3305 /* Some EH regions might become dead, see PR34608. If
3306 pass_cleanup_cfg isn't the first pass to happen with the
3307 new child, these dead EH edges might cause problems.
3308 Clean them up now. */
3309 if (flag_exceptions)
3312 tree save_current = current_function_decl;
3313 bool changed = false;
3315 current_function_decl = child_fn;
3317 changed |= tree_purge_dead_eh_edges (bb);
3319 cleanup_tree_cfg ();
3320 current_function_decl = save_current;
3325 /* Emit a library call to launch the children threads. */
3326 if (TREE_CODE (entry_stmt) == OMP_PARALLEL)
3327 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3329 expand_task_call (new_bb, entry_stmt);
3330 update_ssa (TODO_update_ssa_only_virtuals);
3334 /* A subroutine of expand_omp_for. Generate code for a parallel
3335 loop with any schedule. Given parameters:
3337 for (V = N1; V cond N2; V += STEP) BODY;
3339 where COND is "<" or ">", we generate pseudocode
3341 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3342 if (more) goto L0; else goto L3;
3349 if (V cond iend) goto L1; else goto L2;
3351 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3354 If this is a combined omp parallel loop, instead of the call to
3355 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3357 For collapsed loops, given parameters:
3359 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3360 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3361 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3364 we generate pseudocode
3370 count3 = (adj + N32 - N31) / STEP3;
3375 count2 = (adj + N22 - N21) / STEP2;
3380 count1 = (adj + N12 - N11) / STEP1;
3381 count = count1 * count2 * count3;
3382 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3383 if (more) goto L0; else goto L3;
3387 V3 = N31 + (T % count3) * STEP3;
3389 V2 = N21 + (T % count2) * STEP2;
3391 V1 = N11 + T * STEP1;
3396 if (V < iend) goto L10; else goto L2;
3399 if (V3 cond3 N32) goto L1; else goto L11;
3403 if (V2 cond2 N22) goto L1; else goto L12;
3409 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3415 expand_omp_for_generic (struct omp_region *region,
3416 struct omp_for_data *fd,
3417 enum built_in_function start_fn,
3418 enum built_in_function next_fn)
3420 tree type, istart0, iend0, iend, phi;
3421 tree t, vmain, vback, bias = NULL_TREE;
3422 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3423 basic_block l2_bb = NULL, l3_bb = NULL;
3424 block_stmt_iterator si;
3425 bool in_combined_parallel = is_combined_parallel (region);
3426 bool broken_loop = region->cont == NULL;
3428 tree *counts = NULL;
3431 gcc_assert (!broken_loop || !in_combined_parallel);
3432 gcc_assert (fd->iter_type == long_integer_type_node
3433 || !in_combined_parallel);
3435 type = TREE_TYPE (fd->loop.v);
3436 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3437 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3438 TREE_ADDRESSABLE (istart0) = 1;
3439 TREE_ADDRESSABLE (iend0) = 1;
3440 if (gimple_in_ssa_p (cfun))
3442 add_referenced_var (istart0);
3443 add_referenced_var (iend0);
3446 /* See if we need to bias by LLONG_MIN. */
3447 if (fd->iter_type == long_long_unsigned_type_node
3448 && TREE_CODE (type) == INTEGER_TYPE
3449 && !TYPE_UNSIGNED (type))
3453 if (fd->loop.cond_code == LT_EXPR)
3456 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3460 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3463 if (TREE_CODE (n1) != INTEGER_CST
3464 || TREE_CODE (n2) != INTEGER_CST
3465 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3466 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3469 entry_bb = region->entry;
3470 cont_bb = region->cont;
3472 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3473 gcc_assert (broken_loop
3474 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3475 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3476 l1_bb = single_succ (l0_bb);
3479 l2_bb = create_empty_bb (cont_bb);
3480 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3481 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3485 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3486 exit_bb = region->exit;
3488 si = bsi_last (entry_bb);
3490 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3491 if (fd->collapse > 1)
3493 /* collapsed loops need work for expansion in SSA form. */
3494 gcc_assert (!gimple_in_ssa_p (cfun));
3495 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3496 for (i = 0; i < fd->collapse; i++)
3498 tree itype = TREE_TYPE (fd->loops[i].v);
3500 if (POINTER_TYPE_P (itype))
3501 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
3502 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3504 t = fold_build2 (PLUS_EXPR, itype,
3505 fold_convert (itype, fd->loops[i].step), t);
3506 t = fold_build2 (PLUS_EXPR, itype, t,
3507 fold_convert (itype, fd->loops[i].n2));
3508 t = fold_build2 (MINUS_EXPR, itype, t,
3509 fold_convert (itype, fd->loops[i].n1));
3510 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3511 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3512 fold_build1 (NEGATE_EXPR, itype, t),
3513 fold_build1 (NEGATE_EXPR, itype,
3514 fold_convert (itype,
3515 fd->loops[i].step)));
3517 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3518 fold_convert (itype, fd->loops[i].step));
3519 t = fold_convert (type, t);
3520 if (TREE_CODE (t) == INTEGER_CST)
3524 counts[i] = create_tmp_var (type, ".count");
3525 t = build_gimple_modify_stmt (counts[i], t);
3526 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3527 true, BSI_SAME_STMT);
3529 if (SSA_VAR_P (fd->loop.n2))
3532 t = build_gimple_modify_stmt (fd->loop.n2, counts[0]);
3535 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3536 t = build_gimple_modify_stmt (fd->loop.n2, t);
3538 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3539 true, BSI_SAME_STMT);
3543 if (in_combined_parallel)
3545 /* In a combined parallel loop, emit a call to
3546 GOMP_loop_foo_next. */
3547 t = build_call_expr (built_in_decls[next_fn], 2,
3548 build_fold_addr_expr (istart0),
3549 build_fold_addr_expr (iend0));
3553 tree t0, t1, t2, t3, t4;
3554 /* If this is not a combined parallel loop, emit a call to
3555 GOMP_loop_foo_start in ENTRY_BB. */
3556 t4 = build_fold_addr_expr (iend0);
3557 t3 = build_fold_addr_expr (istart0);
3558 t2 = fold_convert (fd->iter_type, fd->loop.step);
3559 t1 = fold_convert (fd->iter_type, fd->loop.n2);
3560 t0 = fold_convert (fd->iter_type, fd->loop.n1);
3563 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
3564 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
3566 if (fd->iter_type == long_integer_type_node)
3570 t = fold_convert (fd->iter_type, fd->chunk_size);
3571 t = build_call_expr (built_in_decls[start_fn], 6,
3572 t0, t1, t2, t, t3, t4);
3575 t = build_call_expr (built_in_decls[start_fn], 5,
3576 t0, t1, t2, t3, t4);
3583 /* The GOMP_loop_ull_*start functions have additional boolean
3584 argument, true for < loops and false for > loops.
3585 In Fortran, the C bool type can be different from
3586 boolean_type_node. */
3587 c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
3588 t5 = build_int_cst (c_bool_type,
3589 fd->loop.cond_code == LT_EXPR ? 1 : 0);
3592 t = fold_convert (fd->iter_type, fd->chunk_size);
3593 t = build_call_expr (built_in_decls[start_fn], 7,
3594 t5, t0, t1, t2, t, t3, t4);
3597 t = build_call_expr (built_in_decls[start_fn], 6,
3598 t5, t0, t1, t2, t3, t4);
3601 if (TREE_TYPE (t) != boolean_type_node)
3602 t = fold_build2 (NE_EXPR, boolean_type_node,
3603 t, build_int_cst (TREE_TYPE (t), 0));
3604 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3605 true, BSI_SAME_STMT);
3606 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3607 bsi_insert_after (&si, t, BSI_SAME_STMT);
3609 /* Remove the OMP_FOR statement. */
3610 bsi_remove (&si, true);
3612 /* Iteration setup for sequential loop goes in L0_BB. */
3613 si = bsi_start (l0_bb);
3615 t = fold_convert (type, fold_build2 (MINUS_EXPR, fd->iter_type,
3618 t = fold_convert (type, istart0);
3619 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3620 false, BSI_CONTINUE_LINKING);
3621 t = build_gimple_modify_stmt (fd->loop.v, t);
3622 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3623 if (gimple_in_ssa_p (cfun))
3624 SSA_NAME_DEF_STMT (fd->loop.v) = t;
3627 t = fold_convert (type, fold_build2 (MINUS_EXPR, fd->iter_type,
3630 t = fold_convert (type, iend0);
3631 iend = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3632 false, BSI_CONTINUE_LINKING);
3633 if (fd->collapse > 1)
3635 tree tem = create_tmp_var (type, ".tem");
3637 t = build_gimple_modify_stmt (tem, fd->loop.v);
3638 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3639 for (i = fd->collapse - 1; i >= 0; i--)
3641 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
3643 if (POINTER_TYPE_P (vtype))
3644 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (vtype), 0);
3645 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
3646 t = fold_convert (itype, t);
3647 t = fold_build2 (MULT_EXPR, itype, t, fd->loops[i].step);
3648 if (POINTER_TYPE_P (vtype))
3649 t = fold_build2 (POINTER_PLUS_EXPR, vtype,
3650 fd->loops[i].n1, fold_convert (sizetype, t));
3652 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3653 t = build_gimple_modify_stmt (fd->loops[i].v, t);
3654 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3655 false, BSI_CONTINUE_LINKING);
3658 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3659 t = build_gimple_modify_stmt (tem, t);
3660 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3661 false, BSI_CONTINUE_LINKING);
3668 /* Code to control the increment and predicate for the sequential
3669 loop goes in the CONT_BB. */
3670 si = bsi_last (cont_bb);
3672 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
3673 vmain = TREE_OPERAND (t, 1);
3674 vback = TREE_OPERAND (t, 0);
3676 if (POINTER_TYPE_P (type))
3677 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
3678 fold_convert (sizetype, fd->loop.step));
3680 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3681 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3682 true, BSI_SAME_STMT);
3683 t = build_gimple_modify_stmt (vback, t);
3684 bsi_insert_before (&si, t, BSI_SAME_STMT);
3685 if (gimple_in_ssa_p (cfun))
3686 SSA_NAME_DEF_STMT (vback) = t;
3688 t = build2 (fd->loop.cond_code, boolean_type_node, vback, iend);
3689 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3690 bsi_insert_before (&si, t, BSI_SAME_STMT);
3692 /* Remove OMP_CONTINUE. */
3693 bsi_remove (&si, true);
3695 if (fd->collapse > 1)
3697 basic_block last_bb, bb;
3700 for (i = fd->collapse - 1; i >= 0; i--)
3702 tree vtype = TREE_TYPE (fd->loops[i].v);
3704 bb = create_empty_bb (last_bb);
3705 si = bsi_start (bb);
3707 if (i < fd->collapse - 1)
3709 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
3710 e->probability = REG_BR_PROB_BASE / 8;
3712 t = build_gimple_modify_stmt (fd->loops[i + 1].v,
3713 fd->loops[i + 1].n1);
3714 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3715 false, BSI_CONTINUE_LINKING);
3720 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
3722 if (POINTER_TYPE_P (vtype))
3723 t = fold_build2 (POINTER_PLUS_EXPR, vtype,
3725 fold_convert (sizetype, fd->loops[i].step));
3727 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
3729 t = build_gimple_modify_stmt (fd->loops[i].v, t);
3730 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3731 false, BSI_CONTINUE_LINKING);
3735 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
3736 fd->loops[i].v, fd->loops[i].n2);
3737 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3738 false, BSI_CONTINUE_LINKING);
3739 t = build3 (COND_EXPR, void_type_node, t,
3740 NULL_TREE, NULL_TREE);
3741 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3742 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
3743 e->probability = REG_BR_PROB_BASE * 7 / 8;
3746 make_edge (bb, l1_bb, EDGE_FALLTHRU);
3751 /* Emit code to get the next parallel iteration in L2_BB. */
3752 si = bsi_start (l2_bb);
3754 t = build_call_expr (built_in_decls[next_fn], 2,
3755 build_fold_addr_expr (istart0),
3756 build_fold_addr_expr (iend0));
3757 if (TREE_TYPE (t) != boolean_type_node)
3758 t = fold_build2 (NE_EXPR, boolean_type_node,
3759 t, build_int_cst (TREE_TYPE (t), 0));
3760 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3761 false, BSI_CONTINUE_LINKING);
3762 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3763 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3766 /* Add the loop cleanup function. */
3767 si = bsi_last (exit_bb);
3768 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3769 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
3771 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
3772 t = build_call_expr (t, 0);
3773 bsi_insert_after (&si, t, BSI_SAME_STMT);
3774 bsi_remove (&si, true);
3776 /* Connect the new blocks. */
3777 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
3778 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
3782 e = find_edge (cont_bb, l3_bb);
3783 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
3785 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
3786 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
3787 PHI_ARG_DEF_FROM_EDGE (phi, e));
3790 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3791 if (fd->collapse > 1)
3793 e = find_edge (cont_bb, l1_bb);
3795 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3799 e = find_edge (cont_bb, l1_bb);
3800 e->flags = EDGE_TRUE_VALUE;
3802 e->probability = REG_BR_PROB_BASE * 7 / 8;
3803 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
3804 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
3806 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
3807 recompute_dominator (CDI_DOMINATORS, l2_bb));
3808 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
3809 recompute_dominator (CDI_DOMINATORS, l3_bb));
3810 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
3811 recompute_dominator (CDI_DOMINATORS, l0_bb));
3812 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
3813 recompute_dominator (CDI_DOMINATORS, l1_bb));
3818 /* A subroutine of expand_omp_for. Generate code for a parallel
3819 loop with static schedule and no specified chunk size. Given
3822 for (V = N1; V cond N2; V += STEP) BODY;
3824 where COND is "<" or ">", we generate pseudocode
3830 if ((__typeof (V)) -1 > 0 && cond is >)
3831 n = -(adj + N2 - N1) / -STEP;
3833 n = (adj + N2 - N1) / STEP;
3835 q += (q * nthreads != n);
3837 e0 = min(s0 + q, n);
3839 if (s0 >= e0) goto L2; else goto L0;
3845 if (V cond e) goto L1;
3850 expand_omp_for_static_nochunk (struct omp_region *region,
3851 struct omp_for_data *fd)
3853 tree n, q, s0, e0, e, t, nthreads, threadid;
3854 tree type, itype, vmain, vback;
3855 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
3857 block_stmt_iterator si;
3859 itype = type = TREE_TYPE (fd->loop.v);
3860 if (POINTER_TYPE_P (type))
3861 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
3863 entry_bb = region->entry;
3864 cont_bb = region->cont;
3865 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3866 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3867 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3868 body_bb = single_succ (seq_start_bb);
3869 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
3870 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3871 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
3872 exit_bb = region->exit;
3874 /* Iteration space partitioning goes in ENTRY_BB. */
3875 si = bsi_last (entry_bb);
3876 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3878 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
3879 t = fold_convert (itype, t);
3880 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3881 true, BSI_SAME_STMT);
3883 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3884 t = fold_convert (itype, t);
3885 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3886 true, BSI_SAME_STMT);
3889 = force_gimple_operand_bsi (&si, fold_convert (type, fd->loop.n1),
3890 true, NULL_TREE, true, BSI_SAME_STMT);
3892 = force_gimple_operand_bsi (&si, fold_convert (itype, fd->loop.n2),
3893 true, NULL_TREE, true, BSI_SAME_STMT);
3895 = force_gimple_operand_bsi (&si, fold_convert (itype, fd->loop.step),
3896 true, NULL_TREE, true, BSI_SAME_STMT);
3898 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
3899 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
3900 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
3901 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
3902 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
3903 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3904 fold_build1 (NEGATE_EXPR, itype, t),
3905 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
3907 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
3908 t = fold_convert (itype, t);
3909 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3911 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
3912 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3914 t = fold_build2 (MULT_EXPR, itype, q, nthreads);
3915 t = fold_build2 (NE_EXPR, itype, t, n);
3916 t = fold_build2 (PLUS_EXPR, itype, q, t);
3917 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3919 t = build2 (MULT_EXPR, itype, q, threadid);
3920 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3922 t = fold_build2 (PLUS_EXPR, itype, s0, q);
3923 t = fold_build2 (MIN_EXPR, itype, t, n);
3924 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3926 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
3927 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3928 bsi_insert_before (&si, t, BSI_SAME_STMT);
3930 /* Remove the OMP_FOR statement. */
3931 bsi_remove (&si, true);
3933 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3934 si = bsi_start (seq_start_bb);
3936 t = fold_convert (itype, s0);
3937 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
3938 if (POINTER_TYPE_P (type))
3939 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
3940 fold_convert (sizetype, t));
3942 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
3943 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3944 false, BSI_CONTINUE_LINKING);
3945 t = build_gimple_modify_stmt (fd->loop.v, t);
3946 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3947 if (gimple_in_ssa_p (cfun))
3948 SSA_NAME_DEF_STMT (fd->loop.v) = t;
3950 t = fold_convert (itype, e0);
3951 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
3952 if (POINTER_TYPE_P (type))
3953 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
3954 fold_convert (sizetype, t));
3956 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
3957 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3958 false, BSI_CONTINUE_LINKING);
3960 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
3961 si = bsi_last (cont_bb);
3963 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
3964 vmain = TREE_OPERAND (t, 1);
3965 vback = TREE_OPERAND (t, 0);
3967 if (POINTER_TYPE_P (type))
3968 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
3969 fold_convert (sizetype, fd->loop.step));
3971 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3972 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3973 true, BSI_SAME_STMT);
3974 t = build_gimple_modify_stmt (vback, t);
3975 bsi_insert_before (&si, t, BSI_SAME_STMT);
3976 if (gimple_in_ssa_p (cfun))
3977 SSA_NAME_DEF_STMT (vback) = t;
3979 t = build2 (fd->loop.cond_code, boolean_type_node, vback, e);
3980 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3981 bsi_insert_before (&si, t, BSI_SAME_STMT);
3983 /* Remove the OMP_CONTINUE statement. */
3984 bsi_remove (&si, true);
3986 /* Replace the OMP_RETURN with a barrier, or nothing. */
3987 si = bsi_last (exit_bb);
3988 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3989 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3990 false, BSI_SAME_STMT);
3991 bsi_remove (&si, true);
3993 /* Connect all the blocks. */
3994 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
3995 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
3997 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3998 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4000 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
4001 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4002 recompute_dominator (CDI_DOMINATORS, body_bb));
4003 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4004 recompute_dominator (CDI_DOMINATORS, fin_bb));
4008 /* A subroutine of expand_omp_for. Generate code for a parallel
4009 loop with static schedule and a specified chunk size. Given
4012 for (V = N1; V cond N2; V += STEP) BODY;
4014 where COND is "<" or ">", we generate pseudocode
4020 if ((__typeof (V)) -1 > 0 && cond is >)
4021 n = -(adj + N2 - N1) / -STEP;
4023 n = (adj + N2 - N1) / STEP;
4025 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4026 here so that V is defined
4027 if the loop is not entered
4029 s0 = (trip * nthreads + threadid) * CHUNK;
4030 e0 = min(s0 + CHUNK, n);
4031 if (s0 < n) goto L1; else goto L4;
4038 if (V cond e) goto L2; else goto L3;
4046 expand_omp_for_static_chunk (struct omp_region *region,
4047 struct omp_for_data *fd)
4049 tree n, s0, e0, e, t, phi, nphi, args;
4050 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4051 tree type, itype, cont, v_main, v_back, v_extra;
4052 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4053 basic_block trip_update_bb, cont_bb, fin_bb;
4054 block_stmt_iterator si;
4057 itype = type = TREE_TYPE (fd->loop.v);
4058 if (POINTER_TYPE_P (type))
4059 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
4061 entry_bb = region->entry;
4062 se = split_block (entry_bb, last_stmt (entry_bb));
4064 iter_part_bb = se->dest;
4065 cont_bb = region->cont;
4066 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4067 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4068 == FALLTHRU_EDGE (cont_bb)->dest);
4069 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4070 body_bb = single_succ (seq_start_bb);
4071 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4072 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4073 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4074 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4075 exit_bb = region->exit;
4077 /* Trip and adjustment setup goes in ENTRY_BB. */
4078 si = bsi_last (entry_bb);
4079 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
4081 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
4082 t = fold_convert (itype, t);
4083 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4084 true, BSI_SAME_STMT);
4086 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
4087 t = fold_convert (itype, t);
4088 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4089 true, BSI_SAME_STMT);
4092 = force_gimple_operand_bsi (&si, fold_convert (type, fd->loop.n1),
4093 true, NULL_TREE, true, BSI_SAME_STMT);
4095 = force_gimple_operand_bsi (&si, fold_convert (itype, fd->loop.n2),
4096 true, NULL_TREE, true, BSI_SAME_STMT);
4098 = force_gimple_operand_bsi (&si, fold_convert (itype, fd->loop.step),
4099 true, NULL_TREE, true, BSI_SAME_STMT);
4101 = force_gimple_operand_bsi (&si, fold_convert (itype, fd->chunk_size),
4102 true, NULL_TREE, true, BSI_SAME_STMT);
4104 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4105 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4106 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4107 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4108 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4109 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4110 fold_build1 (NEGATE_EXPR, itype, t),
4111 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4113 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4114 t = fold_convert (itype, t);
4115 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4116 true, BSI_SAME_STMT);
4118 trip_var = create_tmp_var (itype, ".trip");
4119 if (gimple_in_ssa_p (cfun))
4121 add_referenced_var (trip_var);
4122 trip_init = make_ssa_name (trip_var, NULL_TREE);
4123 trip_main = make_ssa_name (trip_var, NULL_TREE);
4124 trip_back = make_ssa_name (trip_var, NULL_TREE);
4128 trip_init = trip_var;
4129 trip_main = trip_var;
4130 trip_back = trip_var;
4133 t = build_gimple_modify_stmt (trip_init, build_int_cst (itype, 0));
4134 bsi_insert_before (&si, t, BSI_SAME_STMT);
4135 if (gimple_in_ssa_p (cfun))
4136 SSA_NAME_DEF_STMT (trip_init) = t;
4138 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4139 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4140 if (POINTER_TYPE_P (type))
4141 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4142 fold_convert (sizetype, t));
4144 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4145 v_extra = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4146 true, BSI_SAME_STMT);
4148 /* Remove the OMP_FOR. */
4149 bsi_remove (&si, true);
4151 /* Iteration space partitioning goes in ITER_PART_BB. */
4152 si = bsi_last (iter_part_bb);
4154 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4155 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4156 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4157 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4158 false, BSI_CONTINUE_LINKING);
4160 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4161 t = fold_build2 (MIN_EXPR, itype, t, n);
4162 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4163 false, BSI_CONTINUE_LINKING);
4165 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4166 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
4167 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
4169 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4170 si = bsi_start (seq_start_bb);
4172 t = fold_convert (itype, s0);
4173 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4174 if (POINTER_TYPE_P (type))
4175 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4176 fold_convert (sizetype, t));
4178 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4179 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
4180 false, BSI_CONTINUE_LINKING);
4181 t = build_gimple_modify_stmt (fd->loop.v, t);
4182 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
4183 if (gimple_in_ssa_p (cfun))
4184 SSA_NAME_DEF_STMT (fd->loop.v) = t;
4186 t = fold_convert (itype, e0);
4187 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4188 if (POINTER_TYPE_P (type))
4189 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4190 fold_convert (sizetype, t));
4192 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4193 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
4194 false, BSI_CONTINUE_LINKING);
4196 /* The code controlling the sequential loop goes in CONT_BB,
4197 replacing the OMP_CONTINUE. */
4198 si = bsi_last (cont_bb);
4199 cont = bsi_stmt (si);
4200 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
4201 v_main = TREE_OPERAND (cont, 1);
4202 v_back = TREE_OPERAND (cont, 0);
4204 if (POINTER_TYPE_P (type))
4205 t = fold_build2 (POINTER_PLUS_EXPR, type, v_main,
4206 fold_convert (sizetype, fd->loop.step));
4208 t = build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4209 t = build_gimple_modify_stmt (v_back, t);
4210 bsi_insert_before (&si, t, BSI_SAME_STMT);
4211 if (gimple_in_ssa_p (cfun))
4212 SSA_NAME_DEF_STMT (v_back) = t;
4214 t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
4215 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
4216 bsi_insert_before (&si, t, BSI_SAME_STMT);
4218 /* Remove OMP_CONTINUE. */
4219 bsi_remove (&si, true);
4221 /* Trip update code goes into TRIP_UPDATE_BB. */
4222 si = bsi_start (trip_update_bb);
4224 t = build_int_cst (itype, 1);
4225 t = build2 (PLUS_EXPR, itype, trip_main, t);
4226 t = build_gimple_modify_stmt (trip_back, t);
4227 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
4228 if (gimple_in_ssa_p (cfun))
4229 SSA_NAME_DEF_STMT (trip_back) = t;
4231 /* Replace the OMP_RETURN with a barrier, or nothing. */
4232 si = bsi_last (exit_bb);
4233 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
4234 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
4235 false, BSI_SAME_STMT);
4236 bsi_remove (&si, true);
4238 /* Connect the new blocks. */
4239 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4240 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4242 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4243 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4245 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4247 if (gimple_in_ssa_p (cfun))
4249 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4250 remove arguments of the phi nodes in fin_bb. We need to create
4251 appropriate phi nodes in iter_part_bb instead. */
4252 se = single_pred_edge (fin_bb);
4253 re = single_succ_edge (trip_update_bb);
4254 ene = single_succ_edge (entry_bb);
4256 args = PENDING_STMT (re);
4257 PENDING_STMT (re) = NULL_TREE;
4258 for (phi = phi_nodes (fin_bb);
4260 phi = PHI_CHAIN (phi), args = TREE_CHAIN (args))
4262 t = PHI_RESULT (phi);
4263 gcc_assert (t == TREE_PURPOSE (args));
4264 nphi = create_phi_node (t, iter_part_bb);
4265 SSA_NAME_DEF_STMT (t) = nphi;
4267 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4268 /* A special case -- fd->loop.v is not yet computed in
4269 iter_part_bb, we need to use v_extra instead. */
4270 if (t == fd->loop.v)
4272 add_phi_arg (nphi, t, ene);
4273 add_phi_arg (nphi, TREE_VALUE (args), re);
4275 gcc_assert (!phi && !args);
4276 while ((phi = phi_nodes (fin_bb)) != NULL_TREE)
4277 remove_phi_node (phi, NULL_TREE, false);
4279 /* Make phi node for trip. */
4280 phi = create_phi_node (trip_main, iter_part_bb);
4281 SSA_NAME_DEF_STMT (trip_main) = phi;
4282 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
4283 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
4286 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4287 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4288 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4289 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4290 recompute_dominator (CDI_DOMINATORS, fin_bb));
4291 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4292 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4293 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4294 recompute_dominator (CDI_DOMINATORS, body_bb));
4298 /* Expand the OpenMP loop defined by REGION. */
4301 expand_omp_for (struct omp_region *region)
4303 struct omp_for_data fd;
4304 struct omp_for_data_loop *loops;
4307 = (struct omp_for_data_loop *)
4308 alloca (TREE_VEC_LENGTH (OMP_FOR_INIT (last_stmt (region->entry)))
4309 * sizeof (struct omp_for_data_loop));
4311 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4312 region->sched_kind = fd.sched_kind;
4314 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4315 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4316 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4319 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4320 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4321 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4324 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4327 && region->cont != NULL)
4329 if (fd.chunk_size == NULL)
4330 expand_omp_for_static_nochunk (region, &fd);
4332 expand_omp_for_static_chunk (region, &fd);
4336 int fn_index, start_ix, next_ix;
4338 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4339 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4340 ? 3 : fd.sched_kind;
4341 fn_index += fd.have_ordered * 4;
4342 start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
4343 next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
4344 if (fd.iter_type == long_long_unsigned_type_node)
4346 start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4347 - BUILT_IN_GOMP_LOOP_STATIC_START;
4348 next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4349 - BUILT_IN_GOMP_LOOP_STATIC_NEXT;
4351 expand_omp_for_generic (region, &fd, start_ix, next_ix);
4354 update_ssa (TODO_update_ssa_only_virtuals);
4358 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4360 v = GOMP_sections_start (n);
4377 v = GOMP_sections_next ();
4382 If this is a combined parallel sections, replace the call to
4383 GOMP_sections_start with call to GOMP_sections_next. */
4386 expand_omp_sections (struct omp_region *region)
4388 tree label_vec, l1, l2, t, u, sections_stmt, vin, vmain, vnext, cont;
4389 unsigned i, casei, len;
4390 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
4391 block_stmt_iterator si;
4394 struct omp_region *inner;
4395 bool exit_reachable = region->cont != NULL;
4397 gcc_assert (exit_reachable == (region->exit != NULL));
4398 entry_bb = region->entry;
4399 l0_bb = single_succ (entry_bb);
4400 l1_bb = region->cont;
4401 l2_bb = region->exit;
4404 if (single_pred (l2_bb) == l0_bb)
4405 l2 = tree_block_label (l2_bb);
4408 /* This can happen if there are reductions. */
4409 len = EDGE_COUNT (l0_bb->succs);
4410 gcc_assert (len > 0);
4411 e = EDGE_SUCC (l0_bb, len - 1);
4412 si = bsi_last (e->dest);
4414 if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION)
4415 l2 = tree_block_label (e->dest);
4417 FOR_EACH_EDGE (e, ei, l0_bb->succs)
4419 si = bsi_last (e->dest);
4420 if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION)
4422 l2 = tree_block_label (e->dest);
4427 default_bb = create_empty_bb (l1_bb->prev_bb);
4428 l1 = tree_block_label (l1_bb);
4432 default_bb = create_empty_bb (l0_bb);
4434 l2 = tree_block_label (default_bb);
4437 /* We will build a switch() with enough cases for all the
4438 OMP_SECTION regions, a '0' case to handle the end of more work
4439 and a default case to abort if something goes wrong. */
4440 len = EDGE_COUNT (l0_bb->succs);
4441 label_vec = make_tree_vec (len + 1);
4443 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
4444 OMP_SECTIONS statement. */
4445 si = bsi_last (entry_bb);
4446 sections_stmt = bsi_stmt (si);
4447 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
4448 vin = OMP_SECTIONS_CONTROL (sections_stmt);
4449 if (!is_combined_parallel (region))
4451 /* If we are not inside a combined parallel+sections region,
4452 call GOMP_sections_start. */
4453 t = build_int_cst (unsigned_type_node,
4454 exit_reachable ? len - 1 : len);
4455 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
4456 t = build_call_expr (u, 1, t);
4460 /* Otherwise, call GOMP_sections_next. */
4461 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
4462 t = build_call_expr (u, 0);
4464 t = build_gimple_modify_stmt (vin, t);
4465 bsi_insert_after (&si, t, BSI_SAME_STMT);
4466 if (gimple_in_ssa_p (cfun))
4467 SSA_NAME_DEF_STMT (vin) = t;
4468 bsi_remove (&si, true);
4470 /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB. */
4471 si = bsi_last (l0_bb);
4472 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
4475 cont = last_stmt (l1_bb);
4476 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
4477 vmain = TREE_OPERAND (cont, 1);
4478 vnext = TREE_OPERAND (cont, 0);
4486 t = build3 (SWITCH_EXPR, void_type_node, vmain, NULL, label_vec);
4487 bsi_insert_after (&si, t, BSI_SAME_STMT);
4488 bsi_remove (&si, true);
4493 t = build3 (CASE_LABEL_EXPR, void_type_node,
4494 build_int_cst (unsigned_type_node, 0), NULL, l2);
4495 TREE_VEC_ELT (label_vec, 0) = t;
4499 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
4500 for (inner = region->inner, casei = 1;
4502 inner = inner->next, i++, casei++)
4504 basic_block s_entry_bb, s_exit_bb;
4506 /* Skip optional reduction region. */
4507 if (inner->type == OMP_ATOMIC_LOAD)
4514 s_entry_bb = inner->entry;
4515 s_exit_bb = inner->exit;
4517 t = tree_block_label (s_entry_bb);
4518 u = build_int_cst (unsigned_type_node, casei);
4519 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
4520 TREE_VEC_ELT (label_vec, i) = u;
4522 si = bsi_last (s_entry_bb);
4523 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
4524 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
4525 bsi_remove (&si, true);
4526 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
4528 if (s_exit_bb == NULL)
4531 si = bsi_last (s_exit_bb);
4532 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
4533 bsi_remove (&si, true);
4535 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
4538 /* Error handling code goes in DEFAULT_BB. */
4539 t = tree_block_label (default_bb);
4540 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
4541 TREE_VEC_ELT (label_vec, len) = u;
4542 make_edge (l0_bb, default_bb, 0);
4544 si = bsi_start (default_bb);
4545 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
4546 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
4550 /* Code to get the next section goes in L1_BB. */
4551 si = bsi_last (l1_bb);
4552 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
4554 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
4555 t = build_gimple_modify_stmt (vnext, t);
4556 bsi_insert_after (&si, t, BSI_SAME_STMT);
4557 if (gimple_in_ssa_p (cfun))
4558 SSA_NAME_DEF_STMT (vnext) = t;
4559 bsi_remove (&si, true);
4561 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
4563 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
4564 si = bsi_last (l2_bb);
4565 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
4566 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
4568 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
4569 t = build_call_expr (t, 0);
4570 bsi_insert_after (&si, t, BSI_SAME_STMT);
4571 bsi_remove (&si, true);
4574 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
4578 /* Expand code for an OpenMP single directive. We've already expanded
4579 much of the code, here we simply place the GOMP_barrier call. */
4582 expand_omp_single (struct omp_region *region)
4584 basic_block entry_bb, exit_bb;
4585 block_stmt_iterator si;
4586 bool need_barrier = false;
4588 entry_bb = region->entry;
4589 exit_bb = region->exit;
4591 si = bsi_last (entry_bb);
4592 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
4593 be removed. We need to ensure that the thread that entered the single
4594 does not exit before the data is copied out by the other threads. */
4595 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
4596 OMP_CLAUSE_COPYPRIVATE))
4597 need_barrier = true;
4598 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
4599 bsi_remove (&si, true);
4600 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4602 si = bsi_last (exit_bb);
4603 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
4604 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
4605 false, BSI_SAME_STMT);
4606 bsi_remove (&si, true);
4607 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4611 /* Generic expansion for OpenMP synchronization directives: master,
4612 ordered and critical. All we need to do here is remove the entry
4613 and exit markers for REGION. */
4616 expand_omp_synch (struct omp_region *region)
4618 basic_block entry_bb, exit_bb;
4619 block_stmt_iterator si;
4621 entry_bb = region->entry;
4622 exit_bb = region->exit;
4624 si = bsi_last (entry_bb);
4625 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
4626 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
4627 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
4628 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
4629 bsi_remove (&si, true);
4630 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4634 si = bsi_last (exit_bb);
4635 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
4636 bsi_remove (&si, true);
4637 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4641 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
4642 operation as a __sync_fetch_and_op builtin. INDEX is log2 of the
4643 size of the data type, and thus usable to find the index of the builtin
4644 decl. Returns false if the expression is not of the proper form. */
4647 expand_omp_atomic_fetch_op (basic_block load_bb,
4648 tree addr, tree loaded_val,
4649 tree stored_val, int index)
4651 enum built_in_function base;
4652 tree decl, itype, call;
4653 enum insn_code *optab;
4655 basic_block store_bb = single_succ (load_bb);
4656 block_stmt_iterator bsi;
4659 /* We expect to find the following sequences:
4662 OMP_ATOMIC_LOAD (tmp, mem)
4665 val = tmp OP something; (or: something OP tmp)
4668 ???FIXME: Allow a more flexible sequence.
4669 Perhaps use data flow to pick the statements.
4673 bsi = bsi_after_labels (store_bb);
4674 stmt = bsi_stmt (bsi);
4675 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
4678 if (TREE_CODE (bsi_stmt (bsi)) != OMP_ATOMIC_STORE)
4681 if (!operand_equal_p (GIMPLE_STMT_OPERAND (stmt, 0), stored_val, 0))
4684 rhs = GIMPLE_STMT_OPERAND (stmt, 1);
4686 /* Check for one of the supported fetch-op operations. */
4687 switch (TREE_CODE (rhs))
4690 case POINTER_PLUS_EXPR:
4691 base = BUILT_IN_FETCH_AND_ADD_N;
4692 optab = sync_add_optab;
4695 base = BUILT_IN_FETCH_AND_SUB_N;
4696 optab = sync_add_optab;
4699 base = BUILT_IN_FETCH_AND_AND_N;
4700 optab = sync_and_optab;
4703 base = BUILT_IN_FETCH_AND_OR_N;
4704 optab = sync_ior_optab;
4707 base = BUILT_IN_FETCH_AND_XOR_N;
4708 optab = sync_xor_optab;
4713 /* Make sure the expression is of the proper form. */
4714 if (operand_equal_p (TREE_OPERAND (rhs, 0), loaded_val, 0))
4715 rhs = TREE_OPERAND (rhs, 1);
4716 else if (commutative_tree_code (TREE_CODE (rhs))
4717 && operand_equal_p (TREE_OPERAND (rhs, 1), loaded_val, 0))
4718 rhs = TREE_OPERAND (rhs, 0);
4722 decl = built_in_decls[base + index + 1];
4723 itype = TREE_TYPE (TREE_TYPE (decl));
4725 if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing)
4728 bsi = bsi_last (load_bb);
4729 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
4730 call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
4731 force_gimple_operand_bsi (&bsi, call, true, NULL_TREE, true, BSI_SAME_STMT);
4732 bsi_remove (&bsi, true);
4734 bsi = bsi_last (store_bb);
4735 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
4736 bsi_remove (&bsi, true);
4737 bsi = bsi_last (store_bb);
4738 bsi_remove (&bsi, true);
4740 if (gimple_in_ssa_p (cfun))
4741 update_ssa (TODO_update_ssa_no_phi);
4746 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
4750 newval = rhs; // with oldval replacing *addr in rhs
4751 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
4752 if (oldval != newval)
4755 INDEX is log2 of the size of the data type, and thus usable to find the
4756 index of the builtin decl. */
4759 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
4760 tree addr, tree loaded_val, tree stored_val,
4763 tree loadedi, storedi, initial, new_storedi, old_vali;
4764 tree type, itype, cmpxchg, iaddr;
4765 block_stmt_iterator bsi;
4766 basic_block loop_header = single_succ (load_bb);
4770 cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1];
4771 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
4772 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
4774 if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing)
4777 /* Load the initial value, replacing the OMP_ATOMIC_LOAD. */
4778 bsi = bsi_last (load_bb);
4779 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
4780 /* For floating-point values, we'll need to view-convert them to integers
4781 so that we can perform the atomic compare and swap. Simplify the
4782 following code by always setting up the "i"ntegral variables. */
4783 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
4785 iaddr = create_tmp_var (build_pointer_type (itype), NULL);
4786 x = build_gimple_modify_stmt (iaddr,
4787 fold_convert (TREE_TYPE (iaddr), addr));
4788 force_gimple_operand_bsi (&bsi, x, true, NULL_TREE,
4789 true, BSI_SAME_STMT);
4790 DECL_NO_TBAA_P (iaddr) = 1;
4791 DECL_POINTER_ALIAS_SET (iaddr) = 0;
4792 loadedi = create_tmp_var (itype, NULL);
4793 if (gimple_in_ssa_p (cfun))
4795 add_referenced_var (iaddr);
4796 add_referenced_var (loadedi);
4797 loadedi = make_ssa_name (loadedi, NULL);
4803 loadedi = loaded_val;
4805 initial = force_gimple_operand_bsi (&bsi, build_fold_indirect_ref (iaddr),
4806 true, NULL_TREE, true, BSI_SAME_STMT);
4808 /* Move the value to the LOADEDI temporary. */
4809 if (gimple_in_ssa_p (cfun))
4811 gcc_assert (phi_nodes (loop_header) == NULL_TREE);
4812 phi = create_phi_node (loadedi, loop_header);
4813 SSA_NAME_DEF_STMT (loadedi) = phi;
4814 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
4818 bsi_insert_before (&bsi,
4819 build_gimple_modify_stmt (loadedi, initial),
4821 if (loadedi != loaded_val)
4823 block_stmt_iterator bsi2;
4825 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
4826 bsi2 = bsi_start (loop_header);
4827 if (gimple_in_ssa_p (cfun))
4829 x = force_gimple_operand_bsi (&bsi2, x, true, NULL_TREE,
4830 true, BSI_SAME_STMT);
4831 x = build_gimple_modify_stmt (loaded_val, x);
4832 bsi_insert_before (&bsi2, x, BSI_SAME_STMT);
4833 SSA_NAME_DEF_STMT (loaded_val) = x;
4837 x = build_gimple_modify_stmt (loaded_val, x);
4838 force_gimple_operand_bsi (&bsi2, x, true, NULL_TREE,
4839 true, BSI_SAME_STMT);
4842 bsi_remove (&bsi, true);
4844 bsi = bsi_last (store_bb);
4845 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
4848 storedi = stored_val;
4851 force_gimple_operand_bsi (&bsi,
4852 build1 (VIEW_CONVERT_EXPR, itype,
4853 stored_val), true, NULL_TREE, true,
4856 /* Build the compare&swap statement. */
4857 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
4858 new_storedi = force_gimple_operand_bsi (&bsi,
4859 fold_convert (itype, new_storedi),
4861 true, BSI_SAME_STMT);
4863 if (gimple_in_ssa_p (cfun))
4867 old_vali = create_tmp_var (itype, NULL);
4868 if (gimple_in_ssa_p (cfun))
4869 add_referenced_var (old_vali);
4870 x = build_gimple_modify_stmt (old_vali, loadedi);
4871 force_gimple_operand_bsi (&bsi, x, true, NULL_TREE,
4872 true, BSI_SAME_STMT);
4874 x = build_gimple_modify_stmt (loadedi, new_storedi);
4875 force_gimple_operand_bsi (&bsi, x, true, NULL_TREE,
4876 true, BSI_SAME_STMT);
4879 /* Note that we always perform the comparison as an integer, even for
4880 floating point. This allows the atomic operation to properly
4881 succeed even with NaNs and -0.0. */
4882 x = build2 (NE_EXPR, boolean_type_node, new_storedi, old_vali);
4883 x = build3 (COND_EXPR, void_type_node, x, NULL_TREE, NULL_TREE);
4884 bsi_insert_before (&bsi, x, BSI_SAME_STMT);
4887 e = single_succ_edge (store_bb);
4888 e->flags &= ~EDGE_FALLTHRU;
4889 e->flags |= EDGE_FALSE_VALUE;
4891 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
4893 /* Copy the new value to loadedi (we already did that before the condition
4894 if we are not in SSA). */
4895 if (gimple_in_ssa_p (cfun))
4897 phi = phi_nodes (loop_header);
4898 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
4901 /* Remove OMP_ATOMIC_STORE. */
4902 bsi_remove (&bsi, true);
4904 if (gimple_in_ssa_p (cfun))
4905 update_ssa (TODO_update_ssa_no_phi);
4910 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
4912 GOMP_atomic_start ();
4916 The result is not globally atomic, but works so long as all parallel
4917 references are within #pragma omp atomic directives. According to
4918 responses received from omp@openmp.org, appears to be within spec.
4919 Which makes sense, since that's how several other compilers handle
4920 this situation as well.
4921 LOADED_VAL and ADDR are the operands of OMP_ATOMIC_LOAD we're expanding.
4922 STORED_VAL is the operand of the matching OMP_ATOMIC_STORE.
4925 OMP_ATOMIC_LOAD (loaded_val, addr) with
4929 OMP_ATOMIC_ATORE (stored_val) with
4934 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
4935 tree addr, tree loaded_val, tree stored_val)
4937 block_stmt_iterator bsi;
4940 bsi = bsi_last (load_bb);
4941 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
4943 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
4944 t = build_function_call_expr (t, 0);
4945 force_gimple_operand_bsi (&bsi, t, true, NULL_TREE, true, BSI_SAME_STMT);
4947 t = build_gimple_modify_stmt (loaded_val, build_fold_indirect_ref (addr));
4948 if (gimple_in_ssa_p (cfun))
4949 SSA_NAME_DEF_STMT (loaded_val) = t;
4950 bsi_insert_before (&bsi, t, BSI_SAME_STMT);
4951 bsi_remove (&bsi, true);
4953 bsi = bsi_last (store_bb);
4954 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
4956 t = build_gimple_modify_stmt (build_fold_indirect_ref (unshare_expr (addr)),
4958 bsi_insert_before (&bsi, t, BSI_SAME_STMT);
4960 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
4961 t = build_function_call_expr (t, 0);
4962 force_gimple_operand_bsi (&bsi, t, true, NULL_TREE, true, BSI_SAME_STMT);
4963 bsi_remove (&bsi, true);
4965 if (gimple_in_ssa_p (cfun))
4966 update_ssa (TODO_update_ssa_no_phi);
4970 /* Expand an OMP_ATOMIC statement. We try to expand
4971 using expand_omp_atomic_fetch_op. If it failed, we try to
4972 call expand_omp_atomic_pipeline, and if it fails too, the
4973 ultimate fallback is wrapping the operation in a mutex
4974 (expand_omp_atomic_mutex). REGION is the atomic region built
4975 by build_omp_regions_1(). */
4978 expand_omp_atomic (struct omp_region *region)
4980 basic_block load_bb = region->entry, store_bb = region->exit;
4981 tree load = last_stmt (load_bb), store = last_stmt (store_bb);
4982 tree loaded_val = TREE_OPERAND (load, 0);
4983 tree addr = TREE_OPERAND (load, 1);
4984 tree stored_val = TREE_OPERAND (store, 0);
4985 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
4986 HOST_WIDE_INT index;
4988 /* Make sure the type is one of the supported sizes. */
4989 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
4990 index = exact_log2 (index);
4991 if (index >= 0 && index <= 4)
4993 unsigned int align = TYPE_ALIGN_UNIT (type);
4995 /* __sync builtins require strict data alignment. */
4996 if (exact_log2 (align) >= index)
4998 /* When possible, use specialized atomic update functions. */
4999 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5000 && store_bb == single_succ (load_bb))
5002 if (expand_omp_atomic_fetch_op (load_bb, addr,
5003 loaded_val, stored_val, index))
5007 /* If we don't have specialized __sync builtins, try and implement
5008 as a compare and swap loop. */
5009 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5010 loaded_val, stored_val, index))
5015 /* The ultimate fallback is wrapping the operation in a mutex. */
5016 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5020 /* Expand the parallel region tree rooted at REGION. Expansion
5021 proceeds in depth-first order. Innermost regions are expanded
5022 first. This way, parallel regions that require a new function to
5023 be created (e.g., OMP_PARALLEL) can be expanded without having any
5024 internal dependencies in their body. */
5027 expand_omp (struct omp_region *region)
5031 /* First, determine whether this is a combined parallel+workshare
5033 if (region->type == OMP_PARALLEL)
5034 determine_parallel_type (region);
5037 expand_omp (region->inner);
5039 switch (region->type)
5042 expand_omp_taskreg (region);
5046 expand_omp_taskreg (region);
5050 expand_omp_for (region);
5054 expand_omp_sections (region);
5058 /* Individual omp sections are handled together with their
5059 parent OMP_SECTIONS region. */
5063 expand_omp_single (region);
5069 expand_omp_synch (region);
5072 case OMP_ATOMIC_LOAD:
5073 expand_omp_atomic (region);
5081 region = region->next;
5086 /* Helper for build_omp_regions. Scan the dominator tree starting at
5087 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5088 true, the function ends once a single tree is built (otherwise, whole
5089 forest of OMP constructs may be built). */
5092 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5095 block_stmt_iterator si;
5100 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
5102 struct omp_region *region;
5103 enum tree_code code;
5105 stmt = bsi_stmt (si);
5106 code = TREE_CODE (stmt);
5107 if (code == OMP_RETURN)
5109 /* STMT is the return point out of region PARENT. Mark it
5110 as the exit point and make PARENT the immediately
5111 enclosing region. */
5112 gcc_assert (parent);
5115 parent = parent->outer;
5117 else if (code == OMP_ATOMIC_STORE)
5119 /* OMP_ATOMIC_STORE is analogous to OMP_RETURN, but matches with
5121 gcc_assert (parent);
5122 gcc_assert (parent->type == OMP_ATOMIC_LOAD);
5125 parent = parent->outer;
5128 else if (code == OMP_CONTINUE)
5130 gcc_assert (parent);
5133 else if (code == OMP_SECTIONS_SWITCH)
5135 /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
5140 /* Otherwise, this directive becomes the parent for a new
5142 region = new_omp_region (bb, code, parent);
5147 if (single_tree && !parent)
5150 for (son = first_dom_son (CDI_DOMINATORS, bb);
5152 son = next_dom_son (CDI_DOMINATORS, son))
5153 build_omp_regions_1 (son, parent, single_tree);
5156 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5160 build_omp_regions_root (basic_block root)
5162 gcc_assert (root_omp_region == NULL);
5163 build_omp_regions_1 (root, NULL, true);
5164 gcc_assert (root_omp_region != NULL);
5167 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5170 omp_expand_local (basic_block head)
5172 build_omp_regions_root (head);
5173 if (dump_file && (dump_flags & TDF_DETAILS))
5175 fprintf (dump_file, "\nOMP region tree\n\n");
5176 dump_omp_region (dump_file, root_omp_region, 0);
5177 fprintf (dump_file, "\n");
5180 remove_exit_barriers (root_omp_region);
5181 expand_omp (root_omp_region);
5183 free_omp_regions ();
5186 /* Scan the CFG and build a tree of OMP regions. Return the root of
5187 the OMP region tree. */
5190 build_omp_regions (void)
5192 gcc_assert (root_omp_region == NULL);
5193 calculate_dominance_info (CDI_DOMINATORS);
5194 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5198 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5201 execute_expand_omp (void)
5203 build_omp_regions ();
5205 if (!root_omp_region)
5210 fprintf (dump_file, "\nOMP region tree\n\n");
5211 dump_omp_region (dump_file, root_omp_region, 0);
5212 fprintf (dump_file, "\n");
5215 remove_exit_barriers (root_omp_region);
5217 expand_omp (root_omp_region);
5219 cleanup_tree_cfg ();
5221 free_omp_regions ();
5226 /* OMP expansion -- the default pass, run before creation of SSA form. */
5229 gate_expand_omp (void)
5231 return (flag_openmp != 0 && errorcount == 0);
5234 struct gimple_opt_pass pass_expand_omp =
5238 "ompexp", /* name */
5239 gate_expand_omp, /* gate */
5240 execute_expand_omp, /* execute */
5243 0, /* static_pass_number */
5245 PROP_gimple_any, /* properties_required */
5246 PROP_gimple_lomp, /* properties_provided */
5247 0, /* properties_destroyed */
5248 0, /* todo_flags_start */
5249 TODO_dump_func /* todo_flags_finish */
5253 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
5255 /* Lower the OpenMP sections directive in *STMT_P. */
5258 lower_omp_sections (tree *stmt_p, omp_context *ctx)
5260 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body, control;
5262 tree_stmt_iterator tsi;
5267 push_gimplify_context ();
5271 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
5273 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
5274 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
5277 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
5278 body = alloc_stmt_list ();
5279 for (i = 0; i < len; i++, tsi_next (&tsi))
5282 tree sec_start, sec_end;
5284 sec_start = tsi_stmt (tsi);
5285 sctx = maybe_lookup_ctx (sec_start);
5288 append_to_statement_list (sec_start, &body);
5290 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
5291 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
5292 OMP_SECTION_BODY (sec_start) = NULL;
5296 tree l = alloc_stmt_list ();
5297 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
5299 append_to_statement_list (l, &body);
5300 OMP_SECTION_LAST (sec_start) = 1;
5303 sec_end = make_node (OMP_RETURN);
5304 append_to_statement_list (sec_end, &body);
5307 block = make_node (BLOCK);
5308 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
5311 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
5313 pop_gimplify_context (NULL_TREE);
5314 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
5316 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
5317 TREE_SIDE_EFFECTS (new_stmt) = 1;
5319 new_body = alloc_stmt_list ();
5320 append_to_statement_list (ilist, &new_body);
5321 append_to_statement_list (stmt, &new_body);
5322 append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
5323 append_to_statement_list (bind, &new_body);
5325 control = create_tmp_var (unsigned_type_node, ".section");
5326 t = build2 (OMP_CONTINUE, void_type_node, control, control);
5327 OMP_SECTIONS_CONTROL (stmt) = control;
5328 append_to_statement_list (t, &new_body);
5330 append_to_statement_list (olist, &new_body);
5331 append_to_statement_list (dlist, &new_body);
5333 maybe_catch_exception (&new_body);
5335 t = make_node (OMP_RETURN);
5336 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
5338 append_to_statement_list (t, &new_body);
5340 BIND_EXPR_BODY (new_stmt) = new_body;
5341 OMP_SECTIONS_BODY (stmt) = NULL;
5347 /* A subroutine of lower_omp_single. Expand the simple form of
5348 an OMP_SINGLE, without a copyprivate clause:
5350 if (GOMP_single_start ())
5352 [ GOMP_barrier (); ] -> unless 'nowait' is present.
5354 FIXME. It may be better to delay expanding the logic of this until
5355 pass_expand_omp. The expanded logic may make the job more difficult
5356 to a synchronization analysis pass. */
5359 lower_omp_single_simple (tree single_stmt, tree *pre_p)
5363 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
5364 if (TREE_TYPE (t) != boolean_type_node)
5365 t = fold_build2 (NE_EXPR, boolean_type_node,
5366 t, build_int_cst (TREE_TYPE (t), 0));
5367 t = build3 (COND_EXPR, void_type_node, t,
5368 OMP_SINGLE_BODY (single_stmt), NULL);
5369 gimplify_and_add (t, pre_p);
5373 /* A subroutine of lower_omp_single. Expand the simple form of
5374 an OMP_SINGLE, with a copyprivate clause:
5376 #pragma omp single copyprivate (a, b, c)
5378 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
5381 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
5387 GOMP_single_copy_end (©out);
5398 FIXME. It may be better to delay expanding the logic of this until
5399 pass_expand_omp. The expanded logic may make the job more difficult
5400 to a synchronization analysis pass. */
5403 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
5405 tree ptr_type, t, l0, l1, l2, copyin_seq;
5407 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
5409 ptr_type = build_pointer_type (ctx->record_type);
5410 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
5412 l0 = create_artificial_label ();
5413 l1 = create_artificial_label ();
5414 l2 = create_artificial_label ();
5416 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
5417 t = fold_convert (ptr_type, t);
5418 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
5419 gimplify_and_add (t, pre_p);
5421 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
5422 build_int_cst (ptr_type, 0));
5423 t = build3 (COND_EXPR, void_type_node, t,
5424 build_and_jump (&l0), build_and_jump (&l1));
5425 gimplify_and_add (t, pre_p);
5427 t = build1 (LABEL_EXPR, void_type_node, l0);
5428 gimplify_and_add (t, pre_p);
5430 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
5433 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
5436 t = build_fold_addr_expr (ctx->sender_decl);
5437 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
5438 gimplify_and_add (t, pre_p);
5440 t = build_and_jump (&l2);
5441 gimplify_and_add (t, pre_p);
5443 t = build1 (LABEL_EXPR, void_type_node, l1);
5444 gimplify_and_add (t, pre_p);
5446 append_to_statement_list (copyin_seq, pre_p);
5448 t = build1 (LABEL_EXPR, void_type_node, l2);
5449 gimplify_and_add (t, pre_p);
5453 /* Expand code for an OpenMP single directive. */
5456 lower_omp_single (tree *stmt_p, omp_context *ctx)
5458 tree t, bind, block, single_stmt = *stmt_p, dlist;
5460 push_gimplify_context ();
5462 block = make_node (BLOCK);
5463 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
5464 TREE_SIDE_EFFECTS (bind) = 1;
5466 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
5467 &BIND_EXPR_BODY (bind), &dlist, ctx);
5468 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
5470 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
5472 if (ctx->record_type)
5473 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
5475 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
5477 OMP_SINGLE_BODY (single_stmt) = NULL;
5479 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
5481 maybe_catch_exception (&BIND_EXPR_BODY (bind));
5483 t = make_node (OMP_RETURN);
5484 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
5486 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
5488 pop_gimplify_context (bind);
5490 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
5491 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
5495 /* Expand code for an OpenMP master directive. */
5498 lower_omp_master (tree *stmt_p, omp_context *ctx)
5500 tree bind, block, stmt = *stmt_p, lab = NULL, x;
5502 push_gimplify_context ();
5504 block = make_node (BLOCK);
5505 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
5506 TREE_SIDE_EFFECTS (bind) = 1;
5508 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
5510 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
5511 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
5512 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
5513 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
5515 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
5516 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
5517 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
5518 OMP_MASTER_BODY (stmt) = NULL;
5520 x = build1 (LABEL_EXPR, void_type_node, lab);
5521 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
5523 x = make_node (OMP_RETURN);
5524 OMP_RETURN_NOWAIT (x) = 1;
5525 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
5527 pop_gimplify_context (bind);
5529 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
5530 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
5534 /* Expand code for an OpenMP ordered directive. */
5537 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
5539 tree bind, block, stmt = *stmt_p, x;
5541 push_gimplify_context ();
5543 block = make_node (BLOCK);
5544 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
5545 TREE_SIDE_EFFECTS (bind) = 1;
5547 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
5549 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
5550 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
5552 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
5553 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
5554 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
5555 OMP_ORDERED_BODY (stmt) = NULL;
5557 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
5558 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
5560 x = make_node (OMP_RETURN);
5561 OMP_RETURN_NOWAIT (x) = 1;
5562 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
5564 pop_gimplify_context (bind);
5566 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
5567 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
5571 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
5572 substitution of a couple of function calls. But in the NAMED case,
5573 requires that languages coordinate a symbol name. It is therefore
5574 best put here in common code. */
5576 static GTY((param1_is (tree), param2_is (tree)))
5577 splay_tree critical_name_mutexes;
5580 lower_omp_critical (tree *stmt_p, omp_context *ctx)
5582 tree bind, block, stmt = *stmt_p;
5583 tree t, lock, unlock, name;
5585 name = OMP_CRITICAL_NAME (stmt);
5591 if (!critical_name_mutexes)
5592 critical_name_mutexes
5593 = splay_tree_new_ggc (splay_tree_compare_pointers);
5595 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
5600 decl = create_tmp_var_raw (ptr_type_node, NULL);
5602 new_str = ACONCAT ((".gomp_critical_user_",
5603 IDENTIFIER_POINTER (name), NULL));
5604 DECL_NAME (decl) = get_identifier (new_str);
5605 TREE_PUBLIC (decl) = 1;
5606 TREE_STATIC (decl) = 1;
5607 DECL_COMMON (decl) = 1;
5608 DECL_ARTIFICIAL (decl) = 1;
5609 DECL_IGNORED_P (decl) = 1;
5610 varpool_finalize_decl (decl);
5612 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
5613 (splay_tree_value) decl);
5616 decl = (tree) n->value;
5618 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
5619 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
5621 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
5622 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
5626 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
5627 lock = build_call_expr (lock, 0);
5629 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
5630 unlock = build_call_expr (unlock, 0);
5633 push_gimplify_context ();
5635 block = make_node (BLOCK);
5636 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
5637 TREE_SIDE_EFFECTS (bind) = 1;
5639 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
5641 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
5643 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
5644 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
5645 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
5646 OMP_CRITICAL_BODY (stmt) = NULL;
5648 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
5650 t = make_node (OMP_RETURN);
5651 OMP_RETURN_NOWAIT (t) = 1;
5652 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
5654 pop_gimplify_context (bind);
5655 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
5656 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
5660 /* A subroutine of lower_omp_for. Generate code to emit the predicate
5661 for a lastprivate clause. Given a loop control predicate of (V
5662 cond N2), we gate the clause on (!(V cond N2)). The lowered form
5663 is appended to *DLIST, iterator initialization is appended to
5667 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
5668 tree *dlist, struct omp_context *ctx)
5670 tree clauses, cond, stmts, vinit, t;
5671 enum tree_code cond_code;
5673 cond_code = fd->loop.cond_code;
5674 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
5676 /* When possible, use a strict equality expression. This can let VRP
5677 type optimizations deduce the value and remove a copy. */
5678 if (host_integerp (fd->loop.step, 0))
5680 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
5681 if (step == 1 || step == -1)
5682 cond_code = EQ_EXPR;
5685 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
5687 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
5689 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
5692 append_to_statement_list (*dlist, &stmts);
5695 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
5696 vinit = fd->loop.n1;
5697 if (cond_code == EQ_EXPR
5698 && host_integerp (fd->loop.n2, 0)
5699 && ! integer_zerop (fd->loop.n2))
5700 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
5702 /* Initialize the iterator variable, so that threads that don't execute
5703 any iterations don't execute the lastprivate clauses by accident. */
5704 t = build_gimple_modify_stmt (fd->loop.v, vinit);
5705 gimplify_and_add (t, body_p);
5710 /* Lower code for an OpenMP loop directive. */
5713 lower_omp_for (tree *stmt_p, omp_context *ctx)
5715 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
5716 struct omp_for_data fd;
5721 push_gimplify_context ();
5723 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
5724 lower_omp (&OMP_FOR_BODY (stmt), ctx);
5726 /* Move declaration of temporaries in the loop body before we make
5728 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
5729 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
5731 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
5732 TREE_SIDE_EFFECTS (new_stmt) = 1;
5733 body_p = &BIND_EXPR_BODY (new_stmt);
5735 /* The pre-body and input clauses go before the lowered OMP_FOR. */
5738 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
5739 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
5741 /* Lower the header expressions. At this point, we can assume that
5742 the header is of the form:
5744 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
5746 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
5747 using the .omp_data_s mapping, if needed. */
5748 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
5750 rhs_p = &GIMPLE_STMT_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i), 1);
5751 if (!is_gimple_min_invariant (*rhs_p))
5752 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
5754 rhs_p = &TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_COND (stmt), i), 1);
5755 if (!is_gimple_min_invariant (*rhs_p))
5756 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
5758 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND
5759 (TREE_VEC_ELT (OMP_FOR_INCR (stmt), i), 1), 1);
5760 if (!is_gimple_min_invariant (*rhs_p))
5761 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
5764 /* Once lowered, extract the bounds and clauses. */
5765 extract_omp_for_data (stmt, &fd, NULL);
5767 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
5769 append_to_statement_list (stmt, body_p);
5771 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
5773 t = build2 (OMP_CONTINUE, void_type_node, fd.loop.v, fd.loop.v);
5774 append_to_statement_list (t, body_p);
5776 /* After the loop, add exit clauses. */
5777 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
5778 append_to_statement_list (dlist, body_p);
5780 maybe_catch_exception (body_p);
5782 /* Region exit marker goes at the end of the loop body. */
5783 t = make_node (OMP_RETURN);
5784 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
5785 append_to_statement_list (t, body_p);
5787 pop_gimplify_context (NULL_TREE);
5788 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
5790 OMP_FOR_BODY (stmt) = NULL_TREE;
5791 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
5795 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
5799 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
5801 struct walk_stmt_info *wi = data;
5802 int *info = wi->info;
5805 switch (TREE_CODE (*tp))
5809 *info = *info == 0 ? 1 : -1;
5818 struct omp_taskcopy_context
5820 /* This field must be at the beginning, as we do "inheritance": Some
5821 callback functions for tree-inline.c (e.g., omp_copy_decl)
5822 receive a copy_body_data pointer that is up-casted to an
5823 omp_context pointer. */
5829 task_copyfn_copy_decl (tree var, copy_body_data *cb)
5831 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
5833 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
5834 return create_tmp_var (TREE_TYPE (var), NULL);
5840 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
5842 tree name, new_fields = NULL, type, f;
5844 type = lang_hooks.types.make_type (RECORD_TYPE);
5845 name = DECL_NAME (TYPE_NAME (orig_type));
5846 name = build_decl (TYPE_DECL, name, type);
5847 TYPE_NAME (type) = name;
5849 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
5851 tree new_f = copy_node (f);
5852 DECL_CONTEXT (new_f) = type;
5853 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
5854 TREE_CHAIN (new_f) = new_fields;
5855 walk_tree (&DECL_SIZE (new_f), copy_body_r, &tcctx->cb, NULL);
5856 walk_tree (&DECL_SIZE_UNIT (new_f), copy_body_r, &tcctx->cb, NULL);
5857 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_body_r, &tcctx->cb, NULL);
5859 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
5861 TYPE_FIELDS (type) = nreverse (new_fields);
5866 /* Create task copyfn. */
5869 create_task_copyfn (tree task_stmt, omp_context *ctx)
5871 struct function *child_cfun;
5872 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
5873 tree record_type, srecord_type, bind, list;
5874 bool record_needs_remap = false, srecord_needs_remap = false;
5876 struct omp_taskcopy_context tcctx;
5878 child_fn = OMP_TASK_COPYFN (task_stmt);
5879 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5880 gcc_assert (child_cfun->cfg == NULL);
5881 child_cfun->dont_save_pending_sizes_p = 1;
5882 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
5884 /* Reset DECL_CONTEXT on function arguments. */
5885 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
5886 DECL_CONTEXT (t) = child_fn;
5888 /* Populate the function. */
5889 push_gimplify_context ();
5890 current_function_decl = child_fn;
5892 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
5893 TREE_SIDE_EFFECTS (bind) = 1;
5895 DECL_SAVED_TREE (child_fn) = bind;
5896 DECL_SOURCE_LOCATION (child_fn) = EXPR_LOCATION (task_stmt);
5898 /* Remap src and dst argument types if needed. */
5899 record_type = ctx->record_type;
5900 srecord_type = ctx->srecord_type;
5901 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
5902 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
5904 record_needs_remap = true;
5907 for (f = TYPE_FIELDS (srecord_type); f ; f = TREE_CHAIN (f))
5908 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
5910 srecord_needs_remap = true;
5914 if (record_needs_remap || srecord_needs_remap)
5916 memset (&tcctx, '\0', sizeof (tcctx));
5917 tcctx.cb.src_fn = ctx->cb.src_fn;
5918 tcctx.cb.dst_fn = child_fn;
5919 tcctx.cb.src_node = cgraph_node (tcctx.cb.src_fn);
5920 tcctx.cb.dst_node = tcctx.cb.src_node;
5921 tcctx.cb.src_cfun = ctx->cb.src_cfun;
5922 tcctx.cb.copy_decl = task_copyfn_copy_decl;
5923 tcctx.cb.eh_region = -1;
5924 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
5925 tcctx.cb.decl_map = pointer_map_create ();
5928 if (record_needs_remap)
5929 record_type = task_copyfn_remap_type (&tcctx, record_type);
5930 if (srecord_needs_remap)
5931 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
5934 tcctx.cb.decl_map = NULL;
5936 push_cfun (child_cfun);
5938 arg = DECL_ARGUMENTS (child_fn);
5939 TREE_TYPE (arg) = build_pointer_type (record_type);
5940 sarg = TREE_CHAIN (arg);
5941 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
5943 /* First pass: initialize temporaries used in record_type and srecord_type
5944 sizes and field offsets. */
5945 if (tcctx.cb.decl_map)
5946 for (c = OMP_TASK_CLAUSES (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
5947 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
5951 decl = OMP_CLAUSE_DECL (c);
5952 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
5955 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
5956 sf = (tree) n->value;
5957 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
5958 src = build_fold_indirect_ref (sarg);
5959 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
5960 t = build_gimple_modify_stmt (*p, src);
5961 append_to_statement_list (t, &list);
5964 /* Second pass: copy shared var pointers and copy construct non-VLA
5965 firstprivate vars. */
5966 for (c = OMP_TASK_CLAUSES (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
5967 switch (OMP_CLAUSE_CODE (c))
5969 case OMP_CLAUSE_SHARED:
5970 decl = OMP_CLAUSE_DECL (c);
5971 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
5974 f = (tree) n->value;
5975 if (tcctx.cb.decl_map)
5976 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
5977 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
5978 sf = (tree) n->value;
5979 if (tcctx.cb.decl_map)
5980 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
5981 src = build_fold_indirect_ref (sarg);
5982 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
5983 dst = build_fold_indirect_ref (arg);
5984 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
5985 t = build_gimple_modify_stmt (dst, src);
5986 append_to_statement_list (t, &list);
5988 case OMP_CLAUSE_FIRSTPRIVATE:
5989 decl = OMP_CLAUSE_DECL (c);
5990 if (is_variable_sized (decl))
5992 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
5995 f = (tree) n->value;
5996 if (tcctx.cb.decl_map)
5997 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
5998 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6001 sf = (tree) n->value;
6002 if (tcctx.cb.decl_map)
6003 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6004 src = build_fold_indirect_ref (sarg);
6005 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6006 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6007 src = build_fold_indirect_ref (src);
6011 dst = build_fold_indirect_ref (arg);
6012 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6013 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6014 append_to_statement_list (t, &list);
6016 case OMP_CLAUSE_PRIVATE:
6017 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6019 decl = OMP_CLAUSE_DECL (c);
6020 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6021 f = (tree) n->value;
6022 if (tcctx.cb.decl_map)
6023 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6024 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6027 sf = (tree) n->value;
6028 if (tcctx.cb.decl_map)
6029 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6030 src = build_fold_indirect_ref (sarg);
6031 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6032 if (use_pointer_for_field (decl, NULL))
6033 src = build_fold_indirect_ref (src);
6037 dst = build_fold_indirect_ref (arg);
6038 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6039 t = build_gimple_modify_stmt (dst, src);
6040 append_to_statement_list (t, &list);
6046 /* Last pass: handle VLA firstprivates. */
6047 if (tcctx.cb.decl_map)
6048 for (c = OMP_TASK_CLAUSES (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6049 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6053 decl = OMP_CLAUSE_DECL (c);
6054 if (!is_variable_sized (decl))
6056 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6059 f = (tree) n->value;
6060 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6061 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6062 ind = DECL_VALUE_EXPR (decl);
6063 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6064 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6065 n = splay_tree_lookup (ctx->sfield_map,
6066 (splay_tree_key) TREE_OPERAND (ind, 0));
6067 sf = (tree) n->value;
6068 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6069 src = build_fold_indirect_ref (sarg);
6070 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6071 src = build_fold_indirect_ref (src);
6072 dst = build_fold_indirect_ref (arg);
6073 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6074 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6075 append_to_statement_list (t, &list);
6076 n = splay_tree_lookup (ctx->field_map,
6077 (splay_tree_key) TREE_OPERAND (ind, 0));
6078 df = (tree) n->value;
6079 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6080 ptr = build_fold_indirect_ref (arg);
6081 ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
6082 t = build_gimple_modify_stmt (ptr, build_fold_addr_expr (dst));
6083 append_to_statement_list (t, &list);
6086 t = build1 (RETURN_EXPR, void_type_node, NULL);
6087 append_to_statement_list (t, &list);
6089 if (tcctx.cb.decl_map)
6090 pointer_map_destroy (tcctx.cb.decl_map);
6091 pop_gimplify_context (NULL);
6092 BIND_EXPR_BODY (bind) = list;
6094 current_function_decl = ctx->cb.src_fn;
6097 /* Lower the OpenMP parallel or task directive in *STMT_P. CTX holds context
6098 information for the directive. */
6101 lower_omp_taskreg (tree *stmt_p, omp_context *ctx)
6103 tree clauses, par_bind, par_body, new_body, bind;
6104 tree olist, ilist, par_olist, par_ilist;
6105 tree stmt, child_fn, t;
6109 clauses = OMP_TASKREG_CLAUSES (stmt);
6110 par_bind = OMP_TASKREG_BODY (stmt);
6111 par_body = BIND_EXPR_BODY (par_bind);
6112 child_fn = ctx->cb.dst_fn;
6113 if (TREE_CODE (stmt) == OMP_PARALLEL && !OMP_PARALLEL_COMBINED (stmt))
6115 struct walk_stmt_info wi;
6118 memset (&wi, 0, sizeof (wi));
6119 wi.callback = check_combined_parallel;
6122 walk_stmts (&wi, &par_bind);
6124 OMP_PARALLEL_COMBINED (stmt) = 1;
6126 if (ctx->srecord_type)
6127 create_task_copyfn (stmt, ctx);
6129 push_gimplify_context ();
6131 par_olist = NULL_TREE;
6132 par_ilist = NULL_TREE;
6133 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6134 lower_omp (&par_body, ctx);
6135 if (TREE_CODE (stmt) == OMP_PARALLEL)
6136 lower_reduction_clauses (clauses, &par_olist, ctx);
6138 /* Declare all the variables created by mapping and the variables
6139 declared in the scope of the parallel body. */
6140 record_vars_into (ctx->block_vars, child_fn);
6141 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
6143 if (ctx->record_type)
6146 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6147 : ctx->record_type, ".omp_data_o");
6148 OMP_TASKREG_DATA_ARG (stmt) = ctx->sender_decl;
6153 lower_send_clauses (clauses, &ilist, &olist, ctx);
6154 lower_send_shared_vars (&ilist, &olist, ctx);
6156 /* Once all the expansions are done, sequence all the different
6157 fragments inside OMP_TASKREG_BODY. */
6158 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6159 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
6161 new_body = alloc_stmt_list ();
6163 if (ctx->record_type)
6165 t = build_fold_addr_expr (ctx->sender_decl);
6166 /* fixup_child_record_type might have changed receiver_decl's type. */
6167 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
6168 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
6169 append_to_statement_list (t, &new_body);
6172 append_to_statement_list (par_ilist, &new_body);
6173 append_to_statement_list (par_body, &new_body);
6174 append_to_statement_list (par_olist, &new_body);
6175 maybe_catch_exception (&new_body);
6176 t = make_node (OMP_RETURN);
6177 append_to_statement_list (t, &new_body);
6178 OMP_TASKREG_BODY (stmt) = new_body;
6180 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
6181 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
6185 pop_gimplify_context (NULL_TREE);
6188 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
6192 lower_omp_2 (tree *tp, int *walk_subtrees, void *data)
6195 omp_context *ctx = data;
6197 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6198 if (TREE_CODE (t) == VAR_DECL
6199 && ((ctx && DECL_HAS_VALUE_EXPR_P (t))
6200 || (task_shared_vars
6201 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))))
6204 /* If a global variable has been privatized, TREE_CONSTANT on
6205 ADDR_EXPR might be wrong. */
6206 if (ctx && TREE_CODE (t) == ADDR_EXPR)
6207 recompute_tree_invariant_for_addr_expr (t);
6209 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6214 lower_omp_1 (tree *tp, omp_context *ctx, tree_stmt_iterator *tsi)
6221 if (EXPR_HAS_LOCATION (t))
6222 input_location = EXPR_LOCATION (t);
6224 /* If we have issued syntax errors, avoid doing any heavy lifting.
6225 Just replace the OpenMP directives with a NOP to avoid
6226 confusing RTL expansion. */
6227 if (errorcount && OMP_DIRECTIVE_P (t))
6229 *tp = build_empty_stmt ();
6233 switch (TREE_CODE (t))
6235 case STATEMENT_LIST:
6237 tree_stmt_iterator i;
6238 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
6239 lower_omp_1 (tsi_stmt_ptr (i), ctx, &i);
6244 lower_omp_1 (&COND_EXPR_THEN (t), ctx, NULL);
6245 lower_omp_1 (&COND_EXPR_ELSE (t), ctx, NULL);
6246 if ((ctx || task_shared_vars)
6247 && walk_tree (&COND_EXPR_COND (t), lower_omp_2, ctx, NULL))
6250 gimplify_expr (&COND_EXPR_COND (t), &pre, NULL,
6251 is_gimple_condexpr, fb_rvalue);
6255 tsi_link_before (tsi, pre, TSI_SAME_STMT);
6258 append_to_statement_list (t, &pre);
6265 lower_omp_1 (&CATCH_BODY (t), ctx, NULL);
6267 case EH_FILTER_EXPR:
6268 lower_omp_1 (&EH_FILTER_FAILURE (t), ctx, NULL);
6270 case TRY_CATCH_EXPR:
6271 case TRY_FINALLY_EXPR:
6272 lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
6273 lower_omp_1 (&TREE_OPERAND (t, 1), ctx, NULL);
6276 lower_omp_1 (&BIND_EXPR_BODY (t), ctx, NULL);
6279 lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
6284 ctx = maybe_lookup_ctx (t);
6285 lower_omp_taskreg (tp, ctx);
6288 ctx = maybe_lookup_ctx (t);
6290 lower_omp_for (tp, ctx);
6293 ctx = maybe_lookup_ctx (t);
6295 lower_omp_sections (tp, ctx);
6298 ctx = maybe_lookup_ctx (t);
6300 lower_omp_single (tp, ctx);
6303 ctx = maybe_lookup_ctx (t);
6305 lower_omp_master (tp, ctx);
6308 ctx = maybe_lookup_ctx (t);
6310 lower_omp_ordered (tp, ctx);
6313 ctx = maybe_lookup_ctx (t);
6315 lower_omp_critical (tp, ctx);
6319 if ((ctx || task_shared_vars)
6320 && walk_tree (tp, lower_omp_2, ctx, NULL))
6322 /* The gimplifier doesn't gimplify CALL_EXPR_STATIC_CHAIN.
6323 Handle that here. */
6324 tree call = get_call_expr_in (t);
6326 && CALL_EXPR_STATIC_CHAIN (call)
6327 && walk_tree (&CALL_EXPR_STATIC_CHAIN (call), lower_omp_2,
6331 gimplify_expr (&CALL_EXPR_STATIC_CHAIN (call), &pre, NULL,
6332 is_gimple_val, fb_rvalue);
6336 tsi_link_before (tsi, pre, TSI_SAME_STMT);
6339 append_to_statement_list (t, &pre);
6340 lower_omp_1 (&pre, ctx, NULL);
6352 gimplify_expr (tp, &pre, NULL, is_gimple_stmt, fb_none);
6354 tsi_link_before (tsi, pre, TSI_SAME_STMT);
6362 lower_omp (tree *stmt_p, omp_context *ctx)
6364 lower_omp_1 (stmt_p, ctx, NULL);
6367 /* Main entry point. */
6370 execute_lower_omp (void)
6372 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
6373 delete_omp_context);
6375 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
6376 gcc_assert (taskreg_nesting_level == 0);
6378 if (all_contexts->root)
6380 if (task_shared_vars)
6381 push_gimplify_context ();
6382 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
6383 if (task_shared_vars)
6384 pop_gimplify_context (NULL);
6389 splay_tree_delete (all_contexts);
6390 all_contexts = NULL;
6392 BITMAP_FREE (task_shared_vars);
6397 gate_lower_omp (void)
6399 return flag_openmp != 0;
6402 struct gimple_opt_pass pass_lower_omp =
6406 "omplower", /* name */
6407 gate_lower_omp, /* gate */
6408 execute_lower_omp, /* execute */
6411 0, /* static_pass_number */
6413 PROP_gimple_any, /* properties_required */
6414 PROP_gimple_lomp, /* properties_provided */
6415 0, /* properties_destroyed */
6416 0, /* todo_flags_start */
6417 TODO_dump_func /* todo_flags_finish */
6421 /* The following is a utility to diagnose OpenMP structured block violations.
6422 It is not part of the "omplower" pass, as that's invoked too late. It
6423 should be invoked by the respective front ends after gimplification. */
6425 static splay_tree all_labels;
6427 /* Check for mismatched contexts and generate an error if needed. Return
6428 true if an error is detected. */
6431 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
6435 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
6438 /* Try to avoid confusing the user by producing and error message
6439 with correct "exit" or "enter" verbiage. We prefer "exit"
6440 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
6441 if (branch_ctx == NULL)
6447 if (TREE_VALUE (label_ctx) == branch_ctx)
6452 label_ctx = TREE_CHAIN (label_ctx);
6457 error ("invalid exit from OpenMP structured block");
6459 error ("invalid entry to OpenMP structured block");
6461 *stmt_p = build_empty_stmt ();
6465 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
6466 where in the tree each label is found. */
6469 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
6471 struct walk_stmt_info *wi = data;
6472 tree context = (tree) wi->info;
6478 switch (TREE_CODE (t))
6484 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
6490 /* The minimal context here is just a tree of statements. */
6491 inner_context = tree_cons (NULL, t, context);
6492 wi->info = inner_context;
6493 walk_stmts (wi, &OMP_BODY (t));
6498 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
6499 inner_context = tree_cons (NULL, t, context);
6500 wi->info = inner_context;
6501 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
6503 walk_tree (&TREE_VEC_ELT (OMP_FOR_INIT (t), i), diagnose_sb_1,
6505 walk_tree (&TREE_VEC_ELT (OMP_FOR_COND (t), i), diagnose_sb_1,
6507 walk_tree (&TREE_VEC_ELT (OMP_FOR_INCR (t), i), diagnose_sb_1,
6510 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
6511 walk_stmts (wi, &OMP_FOR_BODY (t));
6516 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
6517 (splay_tree_value) context);
6527 /* Pass 2: Check each branch and see if its context differs from that of
6528 the destination label's context. */
6531 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
6533 struct walk_stmt_info *wi = data;
6534 tree context = (tree) wi->info;
6540 switch (TREE_CODE (t))
6546 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
6553 walk_stmts (wi, &OMP_BODY (t));
6558 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
6560 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
6562 walk_tree (&TREE_VEC_ELT (OMP_FOR_INIT (t), i), diagnose_sb_2,
6564 walk_tree (&TREE_VEC_ELT (OMP_FOR_COND (t), i), diagnose_sb_2,
6566 walk_tree (&TREE_VEC_ELT (OMP_FOR_INCR (t), i), diagnose_sb_2,
6569 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
6570 walk_stmts (wi, &OMP_FOR_BODY (t));
6576 tree lab = GOTO_DESTINATION (t);
6577 if (TREE_CODE (lab) != LABEL_DECL)
6580 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
6581 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
6587 tree vec = SWITCH_LABELS (t);
6588 int i, len = TREE_VEC_LENGTH (vec);
6589 for (i = 0; i < len; ++i)
6591 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
6592 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
6593 if (diagnose_sb_0 (tp, context, (tree) n->value))
6600 diagnose_sb_0 (tp, context, NULL_TREE);
6611 diagnose_omp_structured_block_errors (tree fndecl)
6613 tree save_current = current_function_decl;
6614 struct walk_stmt_info wi;
6616 current_function_decl = fndecl;
6618 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
6620 memset (&wi, 0, sizeof (wi));
6621 wi.callback = diagnose_sb_1;
6622 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
6624 memset (&wi, 0, sizeof (wi));
6625 wi.callback = diagnose_sb_2;
6626 wi.want_locations = true;
6627 wi.want_return_expr = true;
6628 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
6630 splay_tree_delete (all_labels);
6633 current_function_decl = save_current;
6636 #include "gt-omp-low.h"