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 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 2, 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 COPYING. If not, write to the Free
22 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
27 #include "coretypes.h"
31 #include "tree-gimple.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
41 #include "tree-pass.h"
44 #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 /* A chain of variables to add to the top-level block surrounding the
81 construct. In the case of a parallel, this is in the child function. */
84 /* What to do with variables with implicitly determined sharing
86 enum omp_clause_default_kind default_kind;
88 /* Nesting depth of this context. Used to beautify error messages re
89 invalid gotos. The outermost ctx is depth 1, with depth 0 being
90 reserved for the main body of the function. */
93 /* True if this parallel directive is nested within another. */
98 /* A structure describing the main elements of a parallel loop. */
102 tree v, n1, n2, step, chunk_size, for_stmt;
103 enum tree_code cond_code;
105 bool have_nowait, have_ordered;
106 enum omp_clause_schedule_kind sched_kind;
110 static splay_tree all_contexts;
111 static int parallel_nesting_level;
112 struct omp_region *root_omp_region;
114 static void scan_omp (tree *, omp_context *);
115 static void lower_omp (tree *, omp_context *);
116 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
117 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
119 /* Find an OpenMP clause of type KIND within CLAUSES. */
122 find_omp_clause (tree clauses, enum tree_code kind)
124 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
125 if (OMP_CLAUSE_CODE (clauses) == kind)
131 /* Return true if CTX is for an omp parallel. */
134 is_parallel_ctx (omp_context *ctx)
136 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
140 /* Return true if REGION is a combined parallel+workshare region. */
143 is_combined_parallel (struct omp_region *region)
145 return region->is_combined_parallel;
149 /* Extract the header elements of parallel loop FOR_STMT and store
153 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
157 fd->for_stmt = for_stmt;
160 t = OMP_FOR_INIT (for_stmt);
161 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
162 fd->v = GIMPLE_STMT_OPERAND (t, 0);
163 gcc_assert (DECL_P (fd->v));
164 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
165 fd->n1 = GIMPLE_STMT_OPERAND (t, 1);
167 t = OMP_FOR_COND (for_stmt);
168 fd->cond_code = TREE_CODE (t);
169 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
170 fd->n2 = TREE_OPERAND (t, 1);
171 switch (fd->cond_code)
177 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
178 build_int_cst (TREE_TYPE (fd->n2), 1));
179 fd->cond_code = LT_EXPR;
182 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
183 build_int_cst (TREE_TYPE (fd->n2), 1));
184 fd->cond_code = GT_EXPR;
190 t = OMP_FOR_INCR (fd->for_stmt);
191 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
192 gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == fd->v);
193 t = GIMPLE_STMT_OPERAND (t, 1);
194 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
195 switch (TREE_CODE (t))
198 fd->step = TREE_OPERAND (t, 1);
201 fd->step = TREE_OPERAND (t, 1);
202 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
208 fd->have_nowait = fd->have_ordered = false;
209 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
210 fd->chunk_size = NULL_TREE;
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);
229 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
230 gcc_assert (fd->chunk_size == NULL);
231 else if (fd->chunk_size == NULL)
233 /* We only need to compute a default chunk size for ordered
234 static loops and dynamic loops. */
235 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
236 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
237 ? integer_zero_node : integer_one_node;
242 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
243 is the immediate dominator of PAR_ENTRY_BB, return true if there
244 are no data dependencies that would prevent expanding the parallel
245 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
247 When expanding a combined parallel+workshare region, the call to
248 the child function may need additional arguments in the case of
249 OMP_FOR regions. In some cases, these arguments are computed out
250 of variables passed in from the parent to the child via 'struct
251 .omp_data_s'. For instance:
253 #pragma omp parallel for schedule (guided, i * 4)
258 # BLOCK 2 (PAR_ENTRY_BB)
260 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
262 # BLOCK 3 (WS_ENTRY_BB)
263 .omp_data_i = &.omp_data_o;
264 D.1667 = .omp_data_i->i;
266 #pragma omp for schedule (guided, D.1598)
268 When we outline the parallel region, the call to the child function
269 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
270 that value is computed *after* the call site. So, in principle we
271 cannot do the transformation.
273 To see whether the code in WS_ENTRY_BB blocks the combined
274 parallel+workshare call, we collect all the variables used in the
275 OMP_FOR header check whether they appear on the LHS of any
276 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
279 FIXME. If we had the SSA form built at this point, we could merely
280 hoist the code in block 3 into block 2 and be done with it. But at
281 this point we don't have dataflow information and though we could
282 hack something up here, it is really not worth the aggravation. */
285 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
287 struct omp_for_data fd;
288 tree par_stmt, ws_stmt;
290 par_stmt = last_stmt (par_entry_bb);
291 ws_stmt = last_stmt (ws_entry_bb);
293 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
296 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
298 extract_omp_for_data (ws_stmt, &fd);
300 /* FIXME. We give up too easily here. If any of these arguments
301 are not constants, they will likely involve variables that have
302 been mapped into fields of .omp_data_s for sharing with the child
303 function. With appropriate data flow, it would be possible to
305 if (!is_gimple_min_invariant (fd.n1)
306 || !is_gimple_min_invariant (fd.n2)
307 || !is_gimple_min_invariant (fd.step)
308 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
315 /* Collect additional arguments needed to emit a combined
316 parallel+workshare call. WS_STMT is the workshare directive being
320 get_ws_args_for (tree ws_stmt)
324 if (TREE_CODE (ws_stmt) == OMP_FOR)
326 struct omp_for_data fd;
329 extract_omp_for_data (ws_stmt, &fd);
334 t = fold_convert (long_integer_type_node, fd.chunk_size);
335 ws_args = tree_cons (NULL, t, ws_args);
338 t = fold_convert (long_integer_type_node, fd.step);
339 ws_args = tree_cons (NULL, t, ws_args);
341 t = fold_convert (long_integer_type_node, fd.n2);
342 ws_args = tree_cons (NULL, t, ws_args);
344 t = fold_convert (long_integer_type_node, fd.n1);
345 ws_args = tree_cons (NULL, t, ws_args);
349 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
351 basic_block bb = bb_for_stmt (ws_stmt);
352 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
353 t = tree_cons (NULL, t, NULL);
361 /* Discover whether REGION is a combined parallel+workshare region. */
364 determine_parallel_type (struct omp_region *region)
366 basic_block par_entry_bb, par_exit_bb;
367 basic_block ws_entry_bb, ws_exit_bb;
369 if (region == NULL || region->inner == NULL
370 || region->exit == NULL || region->inner->exit == NULL)
373 /* We only support parallel+for and parallel+sections. */
374 if (region->type != OMP_PARALLEL
375 || (region->inner->type != OMP_FOR
376 && region->inner->type != OMP_SECTIONS))
379 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
380 WS_EXIT_BB -> PAR_EXIT_BB. */
381 par_entry_bb = region->entry;
382 par_exit_bb = region->exit;
383 ws_entry_bb = region->inner->entry;
384 ws_exit_bb = region->inner->exit;
386 if (single_succ (par_entry_bb) == ws_entry_bb
387 && single_succ (ws_exit_bb) == par_exit_bb
388 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
389 && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
390 || (last_and_only_stmt (ws_entry_bb)
391 && last_and_only_stmt (par_exit_bb))))
393 tree ws_stmt = last_stmt (ws_entry_bb);
395 if (region->inner->type == OMP_FOR)
397 /* If this is a combined parallel loop, we need to determine
398 whether or not to use the combined library calls. There
399 are two cases where we do not apply the transformation:
400 static loops and any kind of ordered loop. In the first
401 case, we already open code the loop so there is no need
402 to do anything else. In the latter case, the combined
403 parallel loop call would still need extra synchronization
404 to implement ordered semantics, so there would not be any
405 gain in using the combined call. */
406 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
407 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
409 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
410 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
412 region->is_combined_parallel = false;
413 region->inner->is_combined_parallel = false;
418 region->is_combined_parallel = true;
419 region->inner->is_combined_parallel = true;
420 region->ws_args = get_ws_args_for (ws_stmt);
425 /* Return true if EXPR is variable sized. */
428 is_variable_sized (tree expr)
430 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
433 /* Return true if DECL is a reference type. */
436 is_reference (tree decl)
438 return lang_hooks.decls.omp_privatize_by_reference (decl);
441 /* Lookup variables in the decl or field splay trees. The "maybe" form
442 allows for the variable form to not have been entered, otherwise we
443 assert that the variable must have been entered. */
446 lookup_decl (tree var, omp_context *ctx)
449 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
454 maybe_lookup_decl (tree var, omp_context *ctx)
457 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
458 return n ? *n : NULL_TREE;
462 lookup_field (tree var, omp_context *ctx)
465 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
466 return (tree) n->value;
470 maybe_lookup_field (tree var, omp_context *ctx)
473 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
474 return n ? (tree) n->value : NULL_TREE;
477 /* Return true if DECL should be copied by pointer. SHARED_P is true
478 if DECL is to be shared. */
481 use_pointer_for_field (tree decl, bool shared_p)
483 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
486 /* We can only use copy-in/copy-out semantics for shared variables
487 when we know the value is not accessible from an outer scope. */
490 /* ??? Trivially accessible from anywhere. But why would we even
491 be passing an address in this case? Should we simply assert
492 this to be false, or should we have a cleanup pass that removes
493 these from the list of mappings? */
494 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
497 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
498 without analyzing the expression whether or not its location
499 is accessible to anyone else. In the case of nested parallel
500 regions it certainly may be. */
501 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
504 /* Do not use copy-in/copy-out for variables that have their
506 if (TREE_ADDRESSABLE (decl))
513 /* Construct a new automatic decl similar to VAR. */
516 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
518 tree copy = build_decl (VAR_DECL, name, type);
520 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
521 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
522 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
523 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
524 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
525 TREE_USED (copy) = 1;
526 DECL_CONTEXT (copy) = current_function_decl;
527 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
529 TREE_CHAIN (copy) = ctx->block_vars;
530 ctx->block_vars = copy;
536 omp_copy_decl_1 (tree var, omp_context *ctx)
538 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
541 /* Build tree nodes to access the field for VAR on the receiver side. */
544 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
546 tree x, field = lookup_field (var, ctx);
548 /* If the receiver record type was remapped in the child function,
549 remap the field into the new record type. */
550 x = maybe_lookup_field (field, ctx);
554 x = build_fold_indirect_ref (ctx->receiver_decl);
555 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
557 x = build_fold_indirect_ref (x);
562 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
563 of a parallel, this is a component reference; for workshare constructs
564 this is some variable. */
567 build_outer_var_ref (tree var, omp_context *ctx)
571 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
573 else if (is_variable_sized (var))
575 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
576 x = build_outer_var_ref (x, ctx);
577 x = build_fold_indirect_ref (x);
579 else if (is_parallel_ctx (ctx))
581 bool by_ref = use_pointer_for_field (var, false);
582 x = build_receiver_ref (var, by_ref, ctx);
585 x = lookup_decl (var, ctx->outer);
586 else if (is_reference (var))
587 /* This can happen with orphaned constructs. If var is reference, it is
588 possible it is shared and as such valid. */
593 if (is_reference (var))
594 x = build_fold_indirect_ref (x);
599 /* Build tree nodes to access the field for VAR on the sender side. */
602 build_sender_ref (tree var, omp_context *ctx)
604 tree field = lookup_field (var, ctx);
605 return build3 (COMPONENT_REF, TREE_TYPE (field),
606 ctx->sender_decl, field, NULL);
609 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
612 install_var_field (tree var, bool by_ref, omp_context *ctx)
616 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
618 type = TREE_TYPE (var);
620 type = build_pointer_type (type);
622 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
624 /* Remember what variable this field was created for. This does have a
625 side effect of making dwarf2out ignore this member, so for helpful
626 debugging we clear it later in delete_omp_context. */
627 DECL_ABSTRACT_ORIGIN (field) = var;
629 insert_field_into_struct (ctx->record_type, field);
631 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
632 (splay_tree_value) field);
636 install_var_local (tree var, omp_context *ctx)
638 tree new_var = omp_copy_decl_1 (var, ctx);
639 insert_decl_map (&ctx->cb, var, new_var);
643 /* Adjust the replacement for DECL in CTX for the new context. This means
644 copying the DECL_VALUE_EXPR, and fixing up the type. */
647 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
651 new_decl = lookup_decl (decl, ctx);
653 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
655 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
656 && DECL_HAS_VALUE_EXPR_P (decl))
658 tree ve = DECL_VALUE_EXPR (decl);
659 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
660 SET_DECL_VALUE_EXPR (new_decl, ve);
661 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
664 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
666 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
667 if (size == error_mark_node)
668 size = TYPE_SIZE (TREE_TYPE (new_decl));
669 DECL_SIZE (new_decl) = size;
671 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
672 if (size == error_mark_node)
673 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
674 DECL_SIZE_UNIT (new_decl) = size;
678 /* The callback for remap_decl. Search all containing contexts for a
679 mapping of the variable; this avoids having to duplicate the splay
680 tree ahead of time. We know a mapping doesn't already exist in the
681 given context. Create new mappings to implement default semantics. */
684 omp_copy_decl (tree var, copy_body_data *cb)
686 omp_context *ctx = (omp_context *) cb;
689 if (TREE_CODE (var) == LABEL_DECL)
691 new_var = create_artificial_label ();
692 DECL_CONTEXT (new_var) = current_function_decl;
693 insert_decl_map (&ctx->cb, var, new_var);
697 while (!is_parallel_ctx (ctx))
702 new_var = maybe_lookup_decl (var, ctx);
707 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
710 return error_mark_node;
714 /* Return the parallel region associated with STMT. */
716 /* Debugging dumps for parallel regions. */
717 void dump_omp_region (FILE *, struct omp_region *, int);
718 void debug_omp_region (struct omp_region *);
719 void debug_all_omp_regions (void);
721 /* Dump the parallel region tree rooted at REGION. */
724 dump_omp_region (FILE *file, struct omp_region *region, int indent)
726 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
727 tree_code_name[region->type]);
730 dump_omp_region (file, region->inner, indent + 4);
734 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
735 region->cont->index);
739 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
740 region->exit->index);
742 fprintf (file, "%*s[no exit marker]\n", indent, "");
745 dump_omp_region (file, region->next, indent);
749 debug_omp_region (struct omp_region *region)
751 dump_omp_region (stderr, region, 0);
755 debug_all_omp_regions (void)
757 dump_omp_region (stderr, root_omp_region, 0);
761 /* Create a new parallel region starting at STMT inside region PARENT. */
764 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
766 struct omp_region *region = xcalloc (1, sizeof (*region));
768 region->outer = parent;
774 /* This is a nested region. Add it to the list of inner
775 regions in PARENT. */
776 region->next = parent->inner;
777 parent->inner = region;
781 /* This is a toplevel region. Add it to the list of toplevel
782 regions in ROOT_OMP_REGION. */
783 region->next = root_omp_region;
784 root_omp_region = region;
790 /* Release the memory associated with the region tree rooted at REGION. */
793 free_omp_region_1 (struct omp_region *region)
795 struct omp_region *i, *n;
797 for (i = region->inner; i ; i = n)
800 free_omp_region_1 (i);
806 /* Release the memory for the entire omp region tree. */
809 free_omp_regions (void)
811 struct omp_region *r, *n;
812 for (r = root_omp_region; r ; r = n)
815 free_omp_region_1 (r);
817 root_omp_region = NULL;
821 /* Create a new context, with OUTER_CTX being the surrounding context. */
824 new_omp_context (tree stmt, omp_context *outer_ctx)
826 omp_context *ctx = XCNEW (omp_context);
828 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
829 (splay_tree_value) ctx);
834 ctx->outer = outer_ctx;
835 ctx->cb = outer_ctx->cb;
836 ctx->cb.block = NULL;
837 ctx->depth = outer_ctx->depth + 1;
841 ctx->cb.src_fn = current_function_decl;
842 ctx->cb.dst_fn = current_function_decl;
843 ctx->cb.src_node = cgraph_node (current_function_decl);
844 ctx->cb.dst_node = ctx->cb.src_node;
845 ctx->cb.src_cfun = cfun;
846 ctx->cb.copy_decl = omp_copy_decl;
847 ctx->cb.eh_region = -1;
848 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
852 ctx->cb.decl_map = pointer_map_create ();
857 /* Destroy a omp_context data structures. Called through the splay tree
858 value delete callback. */
861 delete_omp_context (splay_tree_value value)
863 omp_context *ctx = (omp_context *) value;
865 pointer_map_destroy (ctx->cb.decl_map);
868 splay_tree_delete (ctx->field_map);
870 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
871 it produces corrupt debug information. */
872 if (ctx->record_type)
875 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
876 DECL_ABSTRACT_ORIGIN (t) = NULL;
882 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
886 fixup_child_record_type (omp_context *ctx)
888 tree f, type = ctx->record_type;
890 /* ??? It isn't sufficient to just call remap_type here, because
891 variably_modified_type_p doesn't work the way we expect for
892 record types. Testing each field for whether it needs remapping
893 and creating a new record by hand works, however. */
894 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
895 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
899 tree name, new_fields = NULL;
901 type = lang_hooks.types.make_type (RECORD_TYPE);
902 name = DECL_NAME (TYPE_NAME (ctx->record_type));
903 name = build_decl (TYPE_DECL, name, type);
904 TYPE_NAME (type) = name;
906 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
908 tree new_f = copy_node (f);
909 DECL_CONTEXT (new_f) = type;
910 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
911 TREE_CHAIN (new_f) = new_fields;
914 /* Arrange to be able to look up the receiver field
915 given the sender field. */
916 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
917 (splay_tree_value) new_f);
919 TYPE_FIELDS (type) = nreverse (new_fields);
923 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
926 /* Instantiate decls as necessary in CTX to satisfy the data sharing
927 specified by CLAUSES. */
930 scan_sharing_clauses (tree clauses, omp_context *ctx)
933 bool scan_array_reductions = false;
935 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
939 switch (OMP_CLAUSE_CODE (c))
941 case OMP_CLAUSE_PRIVATE:
942 decl = OMP_CLAUSE_DECL (c);
943 if (!is_variable_sized (decl))
944 install_var_local (decl, ctx);
947 case OMP_CLAUSE_SHARED:
948 gcc_assert (is_parallel_ctx (ctx));
949 decl = OMP_CLAUSE_DECL (c);
950 gcc_assert (!is_variable_sized (decl));
951 by_ref = use_pointer_for_field (decl, true);
952 /* Global variables don't need to be copied,
953 the receiver side will use them directly. */
954 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
956 if (! TREE_READONLY (decl)
957 || TREE_ADDRESSABLE (decl)
959 || is_reference (decl))
961 install_var_field (decl, by_ref, ctx);
962 install_var_local (decl, ctx);
965 /* We don't need to copy const scalar vars back. */
966 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
969 case OMP_CLAUSE_LASTPRIVATE:
970 /* Let the corresponding firstprivate clause create
972 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
976 case OMP_CLAUSE_FIRSTPRIVATE:
977 case OMP_CLAUSE_REDUCTION:
978 decl = OMP_CLAUSE_DECL (c);
980 if (is_variable_sized (decl))
982 else if (is_parallel_ctx (ctx)
983 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
986 by_ref = use_pointer_for_field (decl, false);
987 install_var_field (decl, by_ref, ctx);
989 install_var_local (decl, ctx);
992 case OMP_CLAUSE_COPYPRIVATE:
994 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
997 case OMP_CLAUSE_COPYIN:
998 decl = OMP_CLAUSE_DECL (c);
999 by_ref = use_pointer_for_field (decl, false);
1000 install_var_field (decl, by_ref, ctx);
1003 case OMP_CLAUSE_DEFAULT:
1004 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1008 case OMP_CLAUSE_NUM_THREADS:
1009 case OMP_CLAUSE_SCHEDULE:
1011 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1014 case OMP_CLAUSE_NOWAIT:
1015 case OMP_CLAUSE_ORDERED:
1023 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1025 switch (OMP_CLAUSE_CODE (c))
1027 case OMP_CLAUSE_LASTPRIVATE:
1028 /* Let the corresponding firstprivate clause create
1030 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1034 case OMP_CLAUSE_PRIVATE:
1035 case OMP_CLAUSE_FIRSTPRIVATE:
1036 case OMP_CLAUSE_REDUCTION:
1037 decl = OMP_CLAUSE_DECL (c);
1038 if (is_variable_sized (decl))
1039 install_var_local (decl, ctx);
1040 fixup_remapped_decl (decl, ctx,
1041 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1042 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1043 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1044 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1045 scan_array_reductions = true;
1048 case OMP_CLAUSE_SHARED:
1049 decl = OMP_CLAUSE_DECL (c);
1050 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1051 fixup_remapped_decl (decl, ctx, false);
1054 case OMP_CLAUSE_COPYPRIVATE:
1055 case OMP_CLAUSE_COPYIN:
1056 case OMP_CLAUSE_DEFAULT:
1058 case OMP_CLAUSE_NUM_THREADS:
1059 case OMP_CLAUSE_SCHEDULE:
1060 case OMP_CLAUSE_NOWAIT:
1061 case OMP_CLAUSE_ORDERED:
1069 if (scan_array_reductions)
1070 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1071 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1072 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1074 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1075 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1079 /* Create a new name for omp child function. Returns an identifier. */
1081 static GTY(()) unsigned int tmp_ompfn_id_num;
1084 create_omp_child_function_name (void)
1086 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1087 size_t len = IDENTIFIER_LENGTH (name);
1088 char *tmp_name, *prefix;
1090 prefix = alloca (len + sizeof ("_omp_fn"));
1091 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1092 strcpy (prefix + len, "_omp_fn");
1093 #ifndef NO_DOT_IN_LABEL
1095 #elif !defined NO_DOLLAR_IN_LABEL
1098 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1099 return get_identifier (tmp_name);
1102 /* Build a decl for the omp child function. It'll not contain a body
1103 yet, just the bare decl. */
1106 create_omp_child_function (omp_context *ctx)
1108 tree decl, type, name, t;
1110 name = create_omp_child_function_name ();
1111 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1113 decl = build_decl (FUNCTION_DECL, name, type);
1114 decl = lang_hooks.decls.pushdecl (decl);
1116 ctx->cb.dst_fn = decl;
1118 TREE_STATIC (decl) = 1;
1119 TREE_USED (decl) = 1;
1120 DECL_ARTIFICIAL (decl) = 1;
1121 DECL_IGNORED_P (decl) = 0;
1122 TREE_PUBLIC (decl) = 0;
1123 DECL_UNINLINABLE (decl) = 1;
1124 DECL_EXTERNAL (decl) = 0;
1125 DECL_CONTEXT (decl) = NULL_TREE;
1126 DECL_INITIAL (decl) = make_node (BLOCK);
1128 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1129 DECL_ARTIFICIAL (t) = 1;
1130 DECL_IGNORED_P (t) = 1;
1131 DECL_RESULT (decl) = t;
1133 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1134 DECL_ARTIFICIAL (t) = 1;
1135 DECL_ARG_TYPE (t) = ptr_type_node;
1136 DECL_CONTEXT (t) = current_function_decl;
1138 DECL_ARGUMENTS (decl) = t;
1139 ctx->receiver_decl = t;
1141 /* Allocate memory for the function structure. The call to
1142 allocate_struct_function clobbers CFUN, so we need to restore
1144 allocate_struct_function (decl);
1145 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1146 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1147 cfun = ctx->cb.src_cfun;
1151 /* Scan an OpenMP parallel directive. */
1154 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1159 /* Ignore parallel directives with empty bodies, unless there
1160 are copyin clauses. */
1162 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1163 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1165 *stmt_p = build_empty_stmt ();
1169 ctx = new_omp_context (*stmt_p, outer_ctx);
1170 if (parallel_nesting_level > 1)
1171 ctx->is_nested = true;
1172 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1173 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1174 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1175 name = create_tmp_var_name (".omp_data_s");
1176 name = build_decl (TYPE_DECL, name, ctx->record_type);
1177 TYPE_NAME (ctx->record_type) = name;
1178 create_omp_child_function (ctx);
1179 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1181 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1182 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1184 if (TYPE_FIELDS (ctx->record_type) == NULL)
1185 ctx->record_type = ctx->receiver_decl = NULL;
1188 layout_type (ctx->record_type);
1189 fixup_child_record_type (ctx);
1194 /* Scan an OpenMP loop directive. */
1197 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1203 ctx = new_omp_context (stmt, outer_ctx);
1205 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1207 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1208 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1209 scan_omp (&OMP_FOR_COND (stmt), ctx);
1210 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1211 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1214 /* Scan an OpenMP sections directive. */
1217 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1223 ctx = new_omp_context (stmt, outer_ctx);
1224 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1225 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1228 /* Scan an OpenMP single directive. */
1231 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1233 tree stmt = *stmt_p;
1237 ctx = new_omp_context (stmt, outer_ctx);
1238 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1239 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1240 name = create_tmp_var_name (".omp_copy_s");
1241 name = build_decl (TYPE_DECL, name, ctx->record_type);
1242 TYPE_NAME (ctx->record_type) = name;
1244 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1245 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1247 if (TYPE_FIELDS (ctx->record_type) == NULL)
1248 ctx->record_type = NULL;
1250 layout_type (ctx->record_type);
1254 /* Check OpenMP nesting restrictions. */
1256 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1258 switch (TREE_CODE (t))
1263 for (; ctx != NULL; ctx = ctx->outer)
1264 switch (TREE_CODE (ctx->stmt))
1271 warning (0, "work-sharing region may not be closely nested inside "
1272 "of work-sharing, critical, ordered or master region");
1281 for (; ctx != NULL; ctx = ctx->outer)
1282 switch (TREE_CODE (ctx->stmt))
1287 warning (0, "master region may not be closely nested inside "
1288 "of work-sharing region");
1297 for (; ctx != NULL; ctx = ctx->outer)
1298 switch (TREE_CODE (ctx->stmt))
1301 warning (0, "ordered region may not be closely nested inside "
1302 "of critical region");
1305 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1306 OMP_CLAUSE_ORDERED) == NULL)
1307 warning (0, "ordered region must be closely nested inside "
1308 "a loop region with an ordered clause");
1317 for (; ctx != NULL; ctx = ctx->outer)
1318 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1319 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1321 warning (0, "critical region may not be nested inside a critical "
1322 "region with the same name");
1332 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1335 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1337 struct walk_stmt_info *wi = data;
1338 omp_context *ctx = wi->info;
1341 if (EXPR_HAS_LOCATION (t))
1342 input_location = EXPR_LOCATION (t);
1344 /* Check the OpenMP nesting restrictions. */
1345 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1346 check_omp_nesting_restrictions (t, ctx);
1349 switch (TREE_CODE (t))
1352 parallel_nesting_level++;
1353 scan_omp_parallel (tp, ctx);
1354 parallel_nesting_level--;
1358 scan_omp_for (tp, ctx);
1362 scan_omp_sections (tp, ctx);
1366 scan_omp_single (tp, ctx);
1373 ctx = new_omp_context (*tp, ctx);
1374 scan_omp (&OMP_BODY (*tp), ctx);
1382 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1383 insert_decl_map (&ctx->cb, var, var);
1392 *tp = remap_decl (t, &ctx->cb);
1396 if (ctx && TYPE_P (t))
1397 *tp = remap_type (t, &ctx->cb);
1398 else if (!DECL_P (t))
1407 /* Scan all the statements starting at STMT_P. CTX contains context
1408 information about the OpenMP directives and clauses found during
1412 scan_omp (tree *stmt_p, omp_context *ctx)
1414 location_t saved_location;
1415 struct walk_stmt_info wi;
1417 memset (&wi, 0, sizeof (wi));
1418 wi.callback = scan_omp_1;
1420 wi.want_bind_expr = (ctx != NULL);
1421 wi.want_locations = true;
1423 saved_location = input_location;
1424 walk_stmts (&wi, stmt_p);
1425 input_location = saved_location;
1428 /* Re-gimplification and code generation routines. */
1430 /* Build a call to GOMP_barrier. */
1433 build_omp_barrier (tree *stmt_list)
1435 tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1436 gimplify_and_add (t, stmt_list);
1439 /* If a context was created for STMT when it was scanned, return it. */
1441 static omp_context *
1442 maybe_lookup_ctx (tree stmt)
1445 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1446 return n ? (omp_context *) n->value : NULL;
1450 /* Find the mapping for DECL in CTX or the immediately enclosing
1451 context that has a mapping for DECL.
1453 If CTX is a nested parallel directive, we may have to use the decl
1454 mappings created in CTX's parent context. Suppose that we have the
1455 following parallel nesting (variable UIDs showed for clarity):
1458 #omp parallel shared(iD.1562) -> outer parallel
1459 iD.1562 = iD.1562 + 1;
1461 #omp parallel shared (iD.1562) -> inner parallel
1462 iD.1562 = iD.1562 - 1;
1464 Each parallel structure will create a distinct .omp_data_s structure
1465 for copying iD.1562 in/out of the directive:
1467 outer parallel .omp_data_s.1.i -> iD.1562
1468 inner parallel .omp_data_s.2.i -> iD.1562
1470 A shared variable mapping will produce a copy-out operation before
1471 the parallel directive and a copy-in operation after it. So, in
1472 this case we would have:
1475 .omp_data_o.1.i = iD.1562;
1476 #omp parallel shared(iD.1562) -> outer parallel
1477 .omp_data_i.1 = &.omp_data_o.1
1478 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1480 .omp_data_o.2.i = iD.1562; -> **
1481 #omp parallel shared(iD.1562) -> inner parallel
1482 .omp_data_i.2 = &.omp_data_o.2
1483 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1486 ** This is a problem. The symbol iD.1562 cannot be referenced
1487 inside the body of the outer parallel region. But since we are
1488 emitting this copy operation while expanding the inner parallel
1489 directive, we need to access the CTX structure of the outer
1490 parallel directive to get the correct mapping:
1492 .omp_data_o.2.i = .omp_data_i.1->i
1494 Since there may be other workshare or parallel directives enclosing
1495 the parallel directive, it may be necessary to walk up the context
1496 parent chain. This is not a problem in general because nested
1497 parallelism happens only rarely. */
1500 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1505 gcc_assert (ctx->is_nested);
1507 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1508 t = maybe_lookup_decl (decl, up);
1510 gcc_assert (t || is_global_var (decl));
1512 return t ? t : decl;
1516 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1517 in outer contexts. */
1520 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1526 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1527 t = maybe_lookup_decl (decl, up);
1529 return t ? t : decl;
1533 /* Construct the initialization value for reduction CLAUSE. */
1536 omp_reduction_init (tree clause, tree type)
1538 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1545 case TRUTH_ORIF_EXPR:
1546 case TRUTH_XOR_EXPR:
1548 return fold_convert (type, integer_zero_node);
1551 case TRUTH_AND_EXPR:
1552 case TRUTH_ANDIF_EXPR:
1554 return fold_convert (type, integer_one_node);
1557 return fold_convert (type, integer_minus_one_node);
1560 if (SCALAR_FLOAT_TYPE_P (type))
1562 REAL_VALUE_TYPE max, min;
1563 if (HONOR_INFINITIES (TYPE_MODE (type)))
1566 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1569 real_maxval (&min, 1, TYPE_MODE (type));
1570 return build_real (type, min);
1574 gcc_assert (INTEGRAL_TYPE_P (type));
1575 return TYPE_MIN_VALUE (type);
1579 if (SCALAR_FLOAT_TYPE_P (type))
1581 REAL_VALUE_TYPE max;
1582 if (HONOR_INFINITIES (TYPE_MODE (type)))
1585 real_maxval (&max, 0, TYPE_MODE (type));
1586 return build_real (type, max);
1590 gcc_assert (INTEGRAL_TYPE_P (type));
1591 return TYPE_MAX_VALUE (type);
1599 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1600 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1601 private variables. Initialization statements go in ILIST, while calls
1602 to destructors go in DLIST. */
1605 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1608 tree_stmt_iterator diter;
1609 tree c, dtor, copyin_seq, x, ptr;
1610 bool copyin_by_ref = false;
1611 bool lastprivate_firstprivate = false;
1614 *dlist = alloc_stmt_list ();
1615 diter = tsi_start (*dlist);
1618 /* Do all the fixed sized types in the first pass, and the variable sized
1619 types in the second pass. This makes sure that the scalar arguments to
1620 the variable sized types are processed before we use them in the
1621 variable sized operations. */
1622 for (pass = 0; pass < 2; ++pass)
1624 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1626 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1632 case OMP_CLAUSE_PRIVATE:
1633 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1636 case OMP_CLAUSE_SHARED:
1637 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1639 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1642 case OMP_CLAUSE_FIRSTPRIVATE:
1643 case OMP_CLAUSE_COPYIN:
1644 case OMP_CLAUSE_REDUCTION:
1646 case OMP_CLAUSE_LASTPRIVATE:
1647 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1649 lastprivate_firstprivate = true;
1658 new_var = var = OMP_CLAUSE_DECL (c);
1659 if (c_kind != OMP_CLAUSE_COPYIN)
1660 new_var = lookup_decl (var, ctx);
1662 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1667 else if (is_variable_sized (var))
1669 /* For variable sized types, we need to allocate the
1670 actual storage here. Call alloca and store the
1671 result in the pointer decl that we created elsewhere. */
1675 ptr = DECL_VALUE_EXPR (new_var);
1676 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1677 ptr = TREE_OPERAND (ptr, 0);
1678 gcc_assert (DECL_P (ptr));
1680 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1681 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1682 x = fold_convert (TREE_TYPE (ptr), x);
1683 x = build_gimple_modify_stmt (ptr, x);
1684 gimplify_and_add (x, ilist);
1686 else if (is_reference (var))
1688 /* For references that are being privatized for Fortran,
1689 allocate new backing storage for the new pointer
1690 variable. This allows us to avoid changing all the
1691 code that expects a pointer to something that expects
1692 a direct variable. Note that this doesn't apply to
1693 C++, since reference types are disallowed in data
1694 sharing clauses there, except for NRV optimized
1699 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1700 if (TREE_CONSTANT (x))
1702 const char *name = NULL;
1703 if (DECL_NAME (var))
1704 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1706 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1708 gimple_add_tmp_var (x);
1709 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1713 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1714 x = fold_convert (TREE_TYPE (new_var), x);
1717 x = build_gimple_modify_stmt (new_var, x);
1718 gimplify_and_add (x, ilist);
1720 new_var = build_fold_indirect_ref (new_var);
1722 else if (c_kind == OMP_CLAUSE_REDUCTION
1723 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1731 switch (OMP_CLAUSE_CODE (c))
1733 case OMP_CLAUSE_SHARED:
1734 /* Shared global vars are just accessed directly. */
1735 if (is_global_var (new_var))
1737 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1738 needs to be delayed until after fixup_child_record_type so
1739 that we get the correct type during the dereference. */
1740 by_ref = use_pointer_for_field (var, true);
1741 x = build_receiver_ref (var, by_ref, ctx);
1742 SET_DECL_VALUE_EXPR (new_var, x);
1743 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1745 /* ??? If VAR is not passed by reference, and the variable
1746 hasn't been initialized yet, then we'll get a warning for
1747 the store into the omp_data_s structure. Ideally, we'd be
1748 able to notice this and not store anything at all, but
1749 we're generating code too early. Suppress the warning. */
1751 TREE_NO_WARNING (var) = 1;
1754 case OMP_CLAUSE_LASTPRIVATE:
1755 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1759 case OMP_CLAUSE_PRIVATE:
1760 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1762 gimplify_and_add (x, ilist);
1766 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1770 gimplify_stmt (&dtor);
1771 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1775 case OMP_CLAUSE_FIRSTPRIVATE:
1776 x = build_outer_var_ref (var, ctx);
1777 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1778 gimplify_and_add (x, ilist);
1782 case OMP_CLAUSE_COPYIN:
1783 by_ref = use_pointer_for_field (var, false);
1784 x = build_receiver_ref (var, by_ref, ctx);
1785 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1786 append_to_statement_list (x, ©in_seq);
1787 copyin_by_ref |= by_ref;
1790 case OMP_CLAUSE_REDUCTION:
1791 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1793 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1794 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1798 x = omp_reduction_init (c, TREE_TYPE (new_var));
1799 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1800 x = build_gimple_modify_stmt (new_var, x);
1801 gimplify_and_add (x, ilist);
1811 /* The copyin sequence is not to be executed by the main thread, since
1812 that would result in self-copies. Perhaps not visible to scalars,
1813 but it certainly is to C++ operator=. */
1816 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1817 x = build2 (NE_EXPR, boolean_type_node, x,
1818 build_int_cst (TREE_TYPE (x), 0));
1819 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1820 gimplify_and_add (x, ilist);
1823 /* If any copyin variable is passed by reference, we must ensure the
1824 master thread doesn't modify it before it is copied over in all
1825 threads. Similarly for variables in both firstprivate and
1826 lastprivate clauses we need to ensure the lastprivate copying
1827 happens after firstprivate copying in all threads. */
1828 if (copyin_by_ref || lastprivate_firstprivate)
1829 build_omp_barrier (ilist);
1833 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1834 both parallel and workshare constructs. PREDICATE may be NULL if it's
1838 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1841 tree sub_list, x, c;
1843 /* Early exit if there are no lastprivate clauses. */
1844 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1845 if (clauses == NULL)
1847 /* If this was a workshare clause, see if it had been combined
1848 with its parallel. In that case, look for the clauses on the
1849 parallel statement itself. */
1850 if (is_parallel_ctx (ctx))
1854 if (ctx == NULL || !is_parallel_ctx (ctx))
1857 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1858 OMP_CLAUSE_LASTPRIVATE);
1859 if (clauses == NULL)
1863 sub_list = alloc_stmt_list ();
1865 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1869 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1872 var = OMP_CLAUSE_DECL (c);
1873 new_var = lookup_decl (var, ctx);
1875 x = build_outer_var_ref (var, ctx);
1876 if (is_reference (var))
1877 new_var = build_fold_indirect_ref (new_var);
1878 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1879 append_to_statement_list (x, &sub_list);
1883 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1887 gimplify_and_add (x, stmt_list);
1891 /* Generate code to implement the REDUCTION clauses. */
1894 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1896 tree sub_list = NULL, x, c;
1899 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1900 update in that case, otherwise use a lock. */
1901 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1902 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1904 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1906 /* Never use OMP_ATOMIC for array reductions. */
1916 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1918 tree var, ref, new_var;
1919 enum tree_code code;
1921 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1924 var = OMP_CLAUSE_DECL (c);
1925 new_var = lookup_decl (var, ctx);
1926 if (is_reference (var))
1927 new_var = build_fold_indirect_ref (new_var);
1928 ref = build_outer_var_ref (var, ctx);
1929 code = OMP_CLAUSE_REDUCTION_CODE (c);
1931 /* reduction(-:var) sums up the partial results, so it acts
1932 identically to reduction(+:var). */
1933 if (code == MINUS_EXPR)
1938 tree addr = build_fold_addr_expr (ref);
1940 addr = save_expr (addr);
1941 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1942 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1943 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1944 gimplify_and_add (x, stmt_list);
1948 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1950 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1952 if (is_reference (var))
1953 ref = build_fold_addr_expr (ref);
1954 SET_DECL_VALUE_EXPR (placeholder, ref);
1955 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1956 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1957 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1958 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1962 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1963 ref = build_outer_var_ref (var, ctx);
1964 x = build_gimple_modify_stmt (ref, x);
1965 append_to_statement_list (x, &sub_list);
1969 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
1970 gimplify_and_add (x, stmt_list);
1972 gimplify_and_add (sub_list, stmt_list);
1974 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
1975 gimplify_and_add (x, stmt_list);
1979 /* Generate code to implement the COPYPRIVATE clauses. */
1982 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1987 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1992 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1995 var = OMP_CLAUSE_DECL (c);
1996 by_ref = use_pointer_for_field (var, false);
1998 ref = build_sender_ref (var, ctx);
1999 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
2000 x = by_ref ? build_fold_addr_expr (x) : x;
2001 x = build_gimple_modify_stmt (ref, x);
2002 gimplify_and_add (x, slist);
2004 ref = build_receiver_ref (var, by_ref, ctx);
2005 if (is_reference (var))
2007 ref = build_fold_indirect_ref (ref);
2008 var = build_fold_indirect_ref (var);
2010 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2011 gimplify_and_add (x, rlist);
2016 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2017 and REDUCTION from the sender (aka parent) side. */
2020 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2024 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2026 tree val, ref, x, var;
2027 bool by_ref, do_in = false, do_out = false;
2029 switch (OMP_CLAUSE_CODE (c))
2031 case OMP_CLAUSE_FIRSTPRIVATE:
2032 case OMP_CLAUSE_COPYIN:
2033 case OMP_CLAUSE_LASTPRIVATE:
2034 case OMP_CLAUSE_REDUCTION:
2040 var = val = OMP_CLAUSE_DECL (c);
2042 var = lookup_decl_in_outer_ctx (val, ctx);
2044 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2045 && is_global_var (var))
2047 if (is_variable_sized (val))
2049 by_ref = use_pointer_for_field (val, false);
2051 switch (OMP_CLAUSE_CODE (c))
2053 case OMP_CLAUSE_FIRSTPRIVATE:
2054 case OMP_CLAUSE_COPYIN:
2058 case OMP_CLAUSE_LASTPRIVATE:
2059 if (by_ref || is_reference (val))
2061 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2069 case OMP_CLAUSE_REDUCTION:
2071 do_out = !(by_ref || is_reference (val));
2080 ref = build_sender_ref (val, ctx);
2081 x = by_ref ? build_fold_addr_expr (var) : var;
2082 x = build_gimple_modify_stmt (ref, x);
2083 gimplify_and_add (x, ilist);
2088 ref = build_sender_ref (val, ctx);
2089 x = build_gimple_modify_stmt (var, ref);
2090 gimplify_and_add (x, olist);
2095 /* Generate code to implement SHARED from the sender (aka parent) side.
2096 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2097 got automatically shared. */
2100 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2102 tree var, ovar, nvar, f, x;
2104 if (ctx->record_type == NULL)
2107 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2109 ovar = DECL_ABSTRACT_ORIGIN (f);
2110 nvar = maybe_lookup_decl (ovar, ctx);
2111 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2116 /* If CTX is a nested parallel directive. Find the immediately
2117 enclosing parallel or workshare construct that contains a
2118 mapping for OVAR. */
2120 var = lookup_decl_in_outer_ctx (ovar, ctx);
2122 if (use_pointer_for_field (ovar, true))
2124 x = build_sender_ref (ovar, ctx);
2125 var = build_fold_addr_expr (var);
2126 x = build_gimple_modify_stmt (x, var);
2127 gimplify_and_add (x, ilist);
2131 x = build_sender_ref (ovar, ctx);
2132 x = build_gimple_modify_stmt (x, var);
2133 gimplify_and_add (x, ilist);
2135 x = build_sender_ref (ovar, ctx);
2136 x = build_gimple_modify_stmt (var, x);
2137 gimplify_and_add (x, olist);
2142 /* Build the function calls to GOMP_parallel_start etc to actually
2143 generate the parallel operation. REGION is the parallel region
2144 being expanded. BB is the block where to insert the code. WS_ARGS
2145 will be set if this is a call to a combined parallel+workshare
2146 construct, it contains the list of additional arguments needed by
2147 the workshare construct. */
2150 expand_parallel_call (struct omp_region *region, basic_block bb,
2151 tree entry_stmt, tree ws_args)
2153 tree t, t1, t2, val, cond, c, list, clauses;
2154 block_stmt_iterator si;
2157 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2158 push_gimplify_context ();
2160 /* Determine what flavor of GOMP_parallel_start we will be
2162 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2163 if (is_combined_parallel (region))
2165 switch (region->inner->type)
2168 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2169 + region->inner->sched_kind;
2172 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2179 /* By default, the value of NUM_THREADS is zero (selected at run time)
2180 and there is no conditional. */
2182 val = build_int_cst (unsigned_type_node, 0);
2184 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2186 cond = OMP_CLAUSE_IF_EXPR (c);
2188 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2190 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2192 /* Ensure 'val' is of the correct type. */
2193 val = fold_convert (unsigned_type_node, val);
2195 /* If we found the clause 'if (cond)', build either
2196 (cond != 0) or (cond ? val : 1u). */
2199 block_stmt_iterator si;
2201 cond = gimple_boolify (cond);
2203 if (integer_zerop (val))
2204 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2205 build_int_cst (TREE_TYPE (cond), 0));
2208 basic_block cond_bb, then_bb, else_bb;
2212 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2213 e = split_block (bb, NULL);
2218 then_bb = create_empty_bb (cond_bb);
2219 else_bb = create_empty_bb (then_bb);
2221 t = build3 (COND_EXPR, void_type_node,
2222 cond, NULL_TREE, NULL_TREE);
2224 si = bsi_start (cond_bb);
2225 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2227 si = bsi_start (then_bb);
2228 t = build_gimple_modify_stmt (tmp, val);
2229 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2231 si = bsi_start (else_bb);
2232 t = build_gimple_modify_stmt (tmp,
2233 build_int_cst (unsigned_type_node, 1));
2234 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2236 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2237 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2238 make_edge (then_bb, bb, EDGE_FALLTHRU);
2239 make_edge (else_bb, bb, EDGE_FALLTHRU);
2245 val = get_formal_tmp_var (val, &list);
2246 si = bsi_start (bb);
2247 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2251 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2253 t1 = null_pointer_node;
2255 t1 = build_fold_addr_expr (t);
2256 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2260 tree args = tree_cons (NULL, t2,
2261 tree_cons (NULL, t1,
2262 tree_cons (NULL, val, ws_args)));
2263 t = build_function_call_expr (built_in_decls[start_ix], args);
2266 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2268 gimplify_and_add (t, &list);
2270 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2272 t = null_pointer_node;
2274 t = build_fold_addr_expr (t);
2275 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2276 gimplify_and_add (t, &list);
2278 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2279 gimplify_and_add (t, &list);
2282 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2284 pop_gimplify_context (NULL_TREE);
2288 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2289 handler. This prevents programs from violating the structured
2290 block semantics with throws. */
2293 maybe_catch_exception (tree *stmt_p)
2297 if (!flag_exceptions)
2300 if (lang_protect_cleanup_actions)
2301 t = lang_protect_cleanup_actions ();
2303 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2304 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2305 EH_FILTER_MUST_NOT_THROW (f) = 1;
2306 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2308 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2309 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2312 append_to_statement_list (t, stmt_p);
2315 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2318 list2chain (tree list)
2322 for (t = list; t; t = TREE_CHAIN (t))
2324 tree var = TREE_VALUE (t);
2326 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2328 TREE_CHAIN (var) = NULL_TREE;
2331 return list ? TREE_VALUE (list) : NULL_TREE;
2335 /* Remove barriers in REGION->EXIT's block. Note that this is only
2336 valid for OMP_PARALLEL regions. Since the end of a parallel region
2337 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2338 left a barrier at the end of the OMP_PARALLEL region can now be
2342 remove_exit_barrier (struct omp_region *region)
2344 block_stmt_iterator si;
2345 basic_block exit_bb;
2350 exit_bb = region->exit;
2352 /* If the parallel region doesn't return, we don't have REGION->EXIT
2357 /* The last insn in the block will be the parallel's OMP_RETURN. The
2358 workshare's OMP_RETURN will be in a preceding block. The kinds of
2359 statements that can appear in between are extremely limited -- no
2360 memory operations at all. Here, we allow nothing at all, so the
2361 only thing we allow to precede this OMP_RETURN is a label. */
2362 si = bsi_last (exit_bb);
2363 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2365 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2368 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2370 si = bsi_last (e->src);
2374 if (TREE_CODE (t) == OMP_RETURN)
2375 OMP_RETURN_NOWAIT (t) = 1;
2380 remove_exit_barriers (struct omp_region *region)
2382 if (region->type == OMP_PARALLEL)
2383 remove_exit_barrier (region);
2387 region = region->inner;
2388 remove_exit_barriers (region);
2389 while (region->next)
2391 region = region->next;
2392 remove_exit_barriers (region);
2397 /* Expand the OpenMP parallel directive starting at REGION. */
2400 expand_omp_parallel (struct omp_region *region)
2402 basic_block entry_bb, exit_bb, new_bb;
2403 struct function *child_cfun, *saved_cfun;
2404 tree child_fn, block, t, ws_args;
2405 block_stmt_iterator si;
2408 bool do_cleanup_cfg = false;
2410 entry_stmt = last_stmt (region->entry);
2411 child_fn = OMP_PARALLEL_FN (entry_stmt);
2412 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2415 entry_bb = region->entry;
2416 exit_bb = region->exit;
2418 if (is_combined_parallel (region))
2419 ws_args = region->ws_args;
2421 ws_args = NULL_TREE;
2423 if (child_cfun->cfg)
2425 /* Due to inlining, it may happen that we have already outlined
2426 the region, in which case all we need to do is make the
2427 sub-graph unreachable and emit the parallel call. */
2428 edge entry_succ_e, exit_succ_e;
2429 block_stmt_iterator si;
2431 entry_succ_e = single_succ_edge (entry_bb);
2433 si = bsi_last (entry_bb);
2434 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2435 bsi_remove (&si, true);
2438 remove_edge (entry_succ_e);
2441 exit_succ_e = single_succ_edge (exit_bb);
2442 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2444 do_cleanup_cfg = true;
2448 /* If the parallel region needs data sent from the parent
2449 function, then the very first statement (except possible
2450 tree profile counter updates) of the parallel body
2451 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2452 &.OMP_DATA_O is passed as an argument to the child function,
2453 we need to replace it with the argument as seen by the child
2456 In most cases, this will end up being the identity assignment
2457 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2458 a function call that has been inlined, the original PARM_DECL
2459 .OMP_DATA_I may have been converted into a different local
2460 variable. In which case, we need to keep the assignment. */
2461 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2463 basic_block entry_succ_bb = single_succ (entry_bb);
2464 block_stmt_iterator si;
2466 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2470 gcc_assert (!bsi_end_p (si));
2471 stmt = bsi_stmt (si);
2472 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2475 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2477 if (TREE_CODE (arg) == ADDR_EXPR
2478 && TREE_OPERAND (arg, 0)
2479 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2481 if (GIMPLE_STMT_OPERAND (stmt, 0)
2482 == DECL_ARGUMENTS (child_fn))
2483 bsi_remove (&si, true);
2485 GIMPLE_STMT_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2491 /* Declare local variables needed in CHILD_CFUN. */
2492 block = DECL_INITIAL (child_fn);
2493 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2494 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2496 /* Reset DECL_CONTEXT on locals and function arguments. */
2497 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2498 DECL_CONTEXT (t) = child_fn;
2500 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2501 DECL_CONTEXT (t) = child_fn;
2503 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2505 si = bsi_last (entry_bb);
2507 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2508 bsi_remove (&si, true);
2509 e = split_block (entry_bb, t);
2511 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2513 /* Move the parallel region into CHILD_CFUN. We need to reset
2514 dominance information because the expansion of the inner
2515 regions has invalidated it. */
2516 free_dominance_info (CDI_DOMINATORS);
2517 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2519 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2520 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2521 = cfun->curr_properties;
2522 cgraph_add_new_function (child_fn, true);
2524 /* Convert OMP_RETURN into a RETURN_EXPR. */
2527 si = bsi_last (exit_bb);
2528 gcc_assert (!bsi_end_p (si)
2529 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2530 t = build1 (RETURN_EXPR, void_type_node, NULL);
2531 bsi_insert_after (&si, t, BSI_SAME_STMT);
2532 bsi_remove (&si, true);
2536 /* Emit a library call to launch the children threads. */
2537 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2541 /* Clean up the unreachable sub-graph we created above. */
2542 free_dominance_info (CDI_DOMINATORS);
2543 free_dominance_info (CDI_POST_DOMINATORS);
2544 cleanup_tree_cfg ();
2549 /* A subroutine of expand_omp_for. Generate code for a parallel
2550 loop with any schedule. Given parameters:
2552 for (V = N1; V cond N2; V += STEP) BODY;
2554 where COND is "<" or ">", we generate pseudocode
2556 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2557 if (more) goto L0; else goto L3;
2564 if (V cond iend) goto L1; else goto L2;
2566 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2569 If this is a combined omp parallel loop, instead of the call to
2570 GOMP_loop_foo_start, we emit 'goto L3'. */
2573 expand_omp_for_generic (struct omp_region *region,
2574 struct omp_for_data *fd,
2575 enum built_in_function start_fn,
2576 enum built_in_function next_fn)
2578 tree type, istart0, iend0, iend;
2580 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2581 basic_block l2_bb = NULL, l3_bb = NULL;
2582 block_stmt_iterator si;
2583 bool in_combined_parallel = is_combined_parallel (region);
2585 type = TREE_TYPE (fd->v);
2587 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2588 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2589 iend = create_tmp_var (type, NULL);
2590 TREE_ADDRESSABLE (istart0) = 1;
2591 TREE_ADDRESSABLE (iend0) = 1;
2593 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
2595 entry_bb = region->entry;
2596 l0_bb = create_empty_bb (entry_bb);
2597 l1_bb = single_succ (entry_bb);
2599 cont_bb = region->cont;
2600 exit_bb = region->exit;
2603 l2_bb = create_empty_bb (cont_bb);
2604 l3_bb = single_succ (cont_bb);
2607 si = bsi_last (entry_bb);
2608 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2609 if (!in_combined_parallel)
2611 tree t0, t1, t2, t3, t4;
2612 /* If this is not a combined parallel loop, emit a call to
2613 GOMP_loop_foo_start in ENTRY_BB. */
2614 list = alloc_stmt_list ();
2615 t4 = build_fold_addr_expr (iend0);
2616 t3 = build_fold_addr_expr (istart0);
2617 t2 = fold_convert (long_integer_type_node, fd->step);
2618 t1 = fold_convert (long_integer_type_node, fd->n2);
2619 t0 = fold_convert (long_integer_type_node, fd->n1);
2622 t = fold_convert (long_integer_type_node, fd->chunk_size);
2623 t = build_call_expr (built_in_decls[start_fn], 6,
2624 t0, t1, t2, t, t3, t4);
2627 t = build_call_expr (built_in_decls[start_fn], 5,
2628 t0, t1, t2, t3, t4);
2629 t = get_formal_tmp_var (t, &list);
2632 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2633 append_to_statement_list (t, &list);
2635 bsi_insert_after (&si, list, BSI_SAME_STMT);
2637 bsi_remove (&si, true);
2639 /* Iteration setup for sequential loop goes in L0_BB. */
2640 list = alloc_stmt_list ();
2641 t = fold_convert (type, istart0);
2642 t = build_gimple_modify_stmt (fd->v, t);
2643 gimplify_and_add (t, &list);
2645 t = fold_convert (type, iend0);
2646 t = build_gimple_modify_stmt (iend, t);
2647 gimplify_and_add (t, &list);
2649 si = bsi_start (l0_bb);
2650 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2652 /* Handle the rare case where BODY doesn't ever return. */
2653 if (cont_bb == NULL)
2655 remove_edge (single_succ_edge (entry_bb));
2656 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
2657 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2661 /* Code to control the increment and predicate for the sequential
2662 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2663 that we can inherit all the edges going out of the loop
2665 list = alloc_stmt_list ();
2667 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2668 t = build_gimple_modify_stmt (fd->v, t);
2669 gimplify_and_add (t, &list);
2671 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2672 t = get_formal_tmp_var (t, &list);
2673 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2674 append_to_statement_list (t, &list);
2676 si = bsi_last (cont_bb);
2677 bsi_insert_after (&si, list, BSI_SAME_STMT);
2678 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2679 bsi_remove (&si, true);
2681 /* Emit code to get the next parallel iteration in L2_BB. */
2682 list = alloc_stmt_list ();
2684 t = build_call_expr (built_in_decls[next_fn], 2,
2685 build_fold_addr_expr (istart0),
2686 build_fold_addr_expr (iend0));
2687 t = get_formal_tmp_var (t, &list);
2688 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2689 append_to_statement_list (t, &list);
2691 si = bsi_start (l2_bb);
2692 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2694 /* Add the loop cleanup function. */
2695 si = bsi_last (exit_bb);
2696 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2697 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2699 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2700 t = build_call_expr (t, 0);
2701 bsi_insert_after (&si, t, BSI_SAME_STMT);
2702 bsi_remove (&si, true);
2704 /* Connect the new blocks. */
2705 remove_edge (single_succ_edge (entry_bb));
2706 if (in_combined_parallel)
2707 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2710 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2711 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2714 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2716 remove_edge (single_succ_edge (cont_bb));
2717 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2718 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2720 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2721 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2725 /* A subroutine of expand_omp_for. Generate code for a parallel
2726 loop with static schedule and no specified chunk size. Given
2729 for (V = N1; V cond N2; V += STEP) BODY;
2731 where COND is "<" or ">", we generate pseudocode
2737 n = (adj + N2 - N1) / STEP;
2739 q += (q * nthreads != n);
2741 e0 = min(s0 + q, n);
2742 if (s0 >= e0) goto L2; else goto L0;
2749 if (V cond e) goto L1;
2754 expand_omp_for_static_nochunk (struct omp_region *region,
2755 struct omp_for_data *fd)
2757 tree n, q, s0, e0, e, t, nthreads, threadid;
2759 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2761 block_stmt_iterator si;
2763 type = TREE_TYPE (fd->v);
2765 entry_bb = region->entry;
2766 seq_start_bb = create_empty_bb (entry_bb);
2767 body_bb = single_succ (entry_bb);
2768 cont_bb = region->cont;
2769 fin_bb = single_succ (cont_bb);
2770 exit_bb = region->exit;
2772 /* Iteration space partitioning goes in ENTRY_BB. */
2773 list = alloc_stmt_list ();
2775 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2776 t = fold_convert (type, t);
2777 nthreads = get_formal_tmp_var (t, &list);
2779 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2780 t = fold_convert (type, t);
2781 threadid = get_formal_tmp_var (t, &list);
2783 fd->n1 = fold_convert (type, fd->n1);
2784 if (!is_gimple_val (fd->n1))
2785 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2787 fd->n2 = fold_convert (type, fd->n2);
2788 if (!is_gimple_val (fd->n2))
2789 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2791 fd->step = fold_convert (type, fd->step);
2792 if (!is_gimple_val (fd->step))
2793 fd->step = get_formal_tmp_var (fd->step, &list);
2795 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2796 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2797 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2798 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2799 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2800 t = fold_convert (type, t);
2801 if (is_gimple_val (t))
2804 n = get_formal_tmp_var (t, &list);
2806 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2807 q = get_formal_tmp_var (t, &list);
2809 t = build2 (MULT_EXPR, type, q, nthreads);
2810 t = build2 (NE_EXPR, type, t, n);
2811 t = build2 (PLUS_EXPR, type, q, t);
2812 q = get_formal_tmp_var (t, &list);
2814 t = build2 (MULT_EXPR, type, q, threadid);
2815 s0 = get_formal_tmp_var (t, &list);
2817 t = build2 (PLUS_EXPR, type, s0, q);
2818 t = build2 (MIN_EXPR, type, t, n);
2819 e0 = get_formal_tmp_var (t, &list);
2821 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2822 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2823 append_to_statement_list (t, &list);
2825 si = bsi_last (entry_bb);
2826 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2827 bsi_insert_after (&si, list, BSI_SAME_STMT);
2828 bsi_remove (&si, true);
2830 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2831 list = alloc_stmt_list ();
2833 t = fold_convert (type, s0);
2834 t = build2 (MULT_EXPR, type, t, fd->step);
2835 t = build2 (PLUS_EXPR, type, t, fd->n1);
2836 t = build_gimple_modify_stmt (fd->v, t);
2837 gimplify_and_add (t, &list);
2839 t = fold_convert (type, e0);
2840 t = build2 (MULT_EXPR, type, t, fd->step);
2841 t = build2 (PLUS_EXPR, type, t, fd->n1);
2842 e = get_formal_tmp_var (t, &list);
2844 si = bsi_start (seq_start_bb);
2845 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2847 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2848 list = alloc_stmt_list ();
2850 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2851 t = build_gimple_modify_stmt (fd->v, t);
2852 gimplify_and_add (t, &list);
2854 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2855 t = get_formal_tmp_var (t, &list);
2856 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2857 append_to_statement_list (t, &list);
2859 si = bsi_last (cont_bb);
2860 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2861 bsi_insert_after (&si, list, BSI_SAME_STMT);
2862 bsi_remove (&si, true);
2864 /* Replace the OMP_RETURN with a barrier, or nothing. */
2865 si = bsi_last (exit_bb);
2866 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2868 list = alloc_stmt_list ();
2869 build_omp_barrier (&list);
2870 bsi_insert_after (&si, list, BSI_SAME_STMT);
2872 bsi_remove (&si, true);
2874 /* Connect all the blocks. */
2875 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2877 remove_edge (single_succ_edge (entry_bb));
2878 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2879 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2881 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2882 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2886 /* A subroutine of expand_omp_for. Generate code for a parallel
2887 loop with static schedule and a specified chunk size. Given
2890 for (V = N1; V cond N2; V += STEP) BODY;
2892 where COND is "<" or ">", we generate pseudocode
2898 n = (adj + N2 - N1) / STEP;
2901 s0 = (trip * nthreads + threadid) * CHUNK;
2902 e0 = min(s0 + CHUNK, n);
2903 if (s0 < n) goto L1; else goto L4;
2910 if (V cond e) goto L2; else goto L3;
2918 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2920 tree n, s0, e0, e, t;
2921 tree trip, nthreads, threadid;
2923 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2924 basic_block trip_update_bb, cont_bb, fin_bb;
2926 block_stmt_iterator si;
2928 type = TREE_TYPE (fd->v);
2930 entry_bb = region->entry;
2931 iter_part_bb = create_empty_bb (entry_bb);
2932 seq_start_bb = create_empty_bb (iter_part_bb);
2933 body_bb = single_succ (entry_bb);
2934 cont_bb = region->cont;
2935 trip_update_bb = create_empty_bb (cont_bb);
2936 fin_bb = single_succ (cont_bb);
2937 exit_bb = region->exit;
2939 /* Trip and adjustment setup goes in ENTRY_BB. */
2940 list = alloc_stmt_list ();
2942 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2943 t = fold_convert (type, t);
2944 nthreads = get_formal_tmp_var (t, &list);
2946 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2947 t = fold_convert (type, t);
2948 threadid = get_formal_tmp_var (t, &list);
2950 fd->n1 = fold_convert (type, fd->n1);
2951 if (!is_gimple_val (fd->n1))
2952 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2954 fd->n2 = fold_convert (type, fd->n2);
2955 if (!is_gimple_val (fd->n2))
2956 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2958 fd->step = fold_convert (type, fd->step);
2959 if (!is_gimple_val (fd->step))
2960 fd->step = get_formal_tmp_var (fd->step, &list);
2962 fd->chunk_size = fold_convert (type, fd->chunk_size);
2963 if (!is_gimple_val (fd->chunk_size))
2964 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2966 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2967 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2968 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2969 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2970 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2971 t = fold_convert (type, t);
2972 if (is_gimple_val (t))
2975 n = get_formal_tmp_var (t, &list);
2977 t = build_int_cst (type, 0);
2978 trip = get_initialized_tmp_var (t, &list, NULL);
2980 si = bsi_last (entry_bb);
2981 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2982 bsi_insert_after (&si, list, BSI_SAME_STMT);
2983 bsi_remove (&si, true);
2985 /* Iteration space partitioning goes in ITER_PART_BB. */
2986 list = alloc_stmt_list ();
2988 t = build2 (MULT_EXPR, type, trip, nthreads);
2989 t = build2 (PLUS_EXPR, type, t, threadid);
2990 t = build2 (MULT_EXPR, type, t, fd->chunk_size);
2991 s0 = get_formal_tmp_var (t, &list);
2993 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
2994 t = build2 (MIN_EXPR, type, t, n);
2995 e0 = get_formal_tmp_var (t, &list);
2997 t = build2 (LT_EXPR, boolean_type_node, s0, n);
2998 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2999 append_to_statement_list (t, &list);
3001 si = bsi_start (iter_part_bb);
3002 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3004 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3005 list = alloc_stmt_list ();
3007 t = fold_convert (type, s0);
3008 t = build2 (MULT_EXPR, type, t, fd->step);
3009 t = build2 (PLUS_EXPR, type, t, fd->n1);
3010 t = build_gimple_modify_stmt (fd->v, t);
3011 gimplify_and_add (t, &list);
3013 t = fold_convert (type, e0);
3014 t = build2 (MULT_EXPR, type, t, fd->step);
3015 t = build2 (PLUS_EXPR, type, t, fd->n1);
3016 e = get_formal_tmp_var (t, &list);
3018 si = bsi_start (seq_start_bb);
3019 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3021 /* The code controlling the sequential loop goes in CONT_BB,
3022 replacing the OMP_CONTINUE. */
3023 list = alloc_stmt_list ();
3025 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3026 t = build_gimple_modify_stmt (fd->v, t);
3027 gimplify_and_add (t, &list);
3029 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3030 t = get_formal_tmp_var (t, &list);
3031 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3032 append_to_statement_list (t, &list);
3034 si = bsi_last (cont_bb);
3035 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3036 bsi_insert_after (&si, list, BSI_SAME_STMT);
3037 bsi_remove (&si, true);
3039 /* Trip update code goes into TRIP_UPDATE_BB. */
3040 list = alloc_stmt_list ();
3042 t = build_int_cst (type, 1);
3043 t = build2 (PLUS_EXPR, type, trip, t);
3044 t = build_gimple_modify_stmt (trip, t);
3045 gimplify_and_add (t, &list);
3047 si = bsi_start (trip_update_bb);
3048 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3050 /* Replace the OMP_RETURN with a barrier, or nothing. */
3051 si = bsi_last (exit_bb);
3052 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3054 list = alloc_stmt_list ();
3055 build_omp_barrier (&list);
3056 bsi_insert_after (&si, list, BSI_SAME_STMT);
3058 bsi_remove (&si, true);
3060 /* Connect the new blocks. */
3061 remove_edge (single_succ_edge (entry_bb));
3062 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3064 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3065 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3067 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3069 remove_edge (single_succ_edge (cont_bb));
3070 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3071 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3073 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3077 /* Expand the OpenMP loop defined by REGION. */
3080 expand_omp_for (struct omp_region *region)
3082 struct omp_for_data fd;
3084 push_gimplify_context ();
3086 extract_omp_for_data (last_stmt (region->entry), &fd);
3087 region->sched_kind = fd.sched_kind;
3089 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3094 if (fd.chunk_size == NULL)
3095 expand_omp_for_static_nochunk (region, &fd);
3097 expand_omp_for_static_chunk (region, &fd);
3101 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3102 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3103 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3104 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3107 pop_gimplify_context (NULL);
3111 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3113 v = GOMP_sections_start (n);
3130 v = GOMP_sections_next ();
3135 If this is a combined parallel sections, replace the call to
3136 GOMP_sections_start with 'goto L1'. */
3139 expand_omp_sections (struct omp_region *region)
3141 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3143 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3144 block_stmt_iterator si;
3145 struct omp_region *inner;
3148 entry_bb = region->entry;
3149 l0_bb = create_empty_bb (entry_bb);
3150 l0 = tree_block_label (l0_bb);
3152 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
3153 l1_bb = region->cont;
3156 l2_bb = single_succ (l1_bb);
3157 default_bb = create_empty_bb (l1_bb->prev_bb);
3159 l1 = tree_block_label (l1_bb);
3163 l2_bb = create_empty_bb (l0_bb);
3168 l2 = tree_block_label (l2_bb);
3170 exit_bb = region->exit;
3172 v = create_tmp_var (unsigned_type_node, ".section");
3174 /* We will build a switch() with enough cases for all the
3175 OMP_SECTION regions, a '0' case to handle the end of more work
3176 and a default case to abort if something goes wrong. */
3177 len = EDGE_COUNT (entry_bb->succs);
3178 label_vec = make_tree_vec (len + 2);
3180 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3181 OMP_SECTIONS statement. */
3182 si = bsi_last (entry_bb);
3183 sections_stmt = bsi_stmt (si);
3184 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3185 if (!is_combined_parallel (region))
3187 /* If we are not inside a combined parallel+sections region,
3188 call GOMP_sections_start. */
3189 t = build_int_cst (unsigned_type_node, len);
3190 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3191 t = build_call_expr (u, 1, t);
3192 t = build_gimple_modify_stmt (v, t);
3193 bsi_insert_after (&si, t, BSI_SAME_STMT);
3195 bsi_remove (&si, true);
3197 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
3198 si = bsi_start (l0_bb);
3200 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3201 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3203 t = build3 (CASE_LABEL_EXPR, void_type_node,
3204 build_int_cst (unsigned_type_node, 0), NULL, l2);
3205 TREE_VEC_ELT (label_vec, 0) = t;
3206 make_edge (l0_bb, l2_bb, 0);
3208 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3209 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3211 basic_block s_entry_bb, s_exit_bb;
3213 s_entry_bb = inner->entry;
3214 s_exit_bb = inner->exit;
3216 t = tree_block_label (s_entry_bb);
3217 u = build_int_cst (unsigned_type_node, i);
3218 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3219 TREE_VEC_ELT (label_vec, i) = u;
3221 si = bsi_last (s_entry_bb);
3222 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3223 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3224 bsi_remove (&si, true);
3226 e = single_pred_edge (s_entry_bb);
3228 redirect_edge_pred (e, l0_bb);
3230 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3232 if (s_exit_bb == NULL)
3235 si = bsi_last (s_exit_bb);
3236 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3237 bsi_remove (&si, true);
3239 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3242 /* Error handling code goes in DEFAULT_BB. */
3243 t = tree_block_label (default_bb);
3244 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3245 TREE_VEC_ELT (label_vec, len + 1) = u;
3246 make_edge (l0_bb, default_bb, 0);
3248 si = bsi_start (default_bb);
3249 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3250 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3252 /* Code to get the next section goes in L1_BB. */
3255 si = bsi_last (l1_bb);
3256 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3258 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3259 t = build_gimple_modify_stmt (v, t);
3260 bsi_insert_after (&si, t, BSI_SAME_STMT);
3261 bsi_remove (&si, true);
3264 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3267 si = bsi_last (exit_bb);
3268 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3269 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3271 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3272 t = build_call_expr (t, 0);
3273 bsi_insert_after (&si, t, BSI_SAME_STMT);
3274 bsi_remove (&si, true);
3277 /* Connect the new blocks. */
3278 if (is_combined_parallel (region))
3280 /* If this was a combined parallel+sections region, we did not
3281 emit a GOMP_sections_start in the entry block, so we just
3282 need to jump to L1_BB to get the next section. */
3283 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3286 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3290 e = single_succ_edge (l1_bb);
3291 redirect_edge_succ (e, l0_bb);
3292 e->flags = EDGE_FALLTHRU;
3297 /* Expand code for an OpenMP single directive. We've already expanded
3298 much of the code, here we simply place the GOMP_barrier call. */
3301 expand_omp_single (struct omp_region *region)
3303 basic_block entry_bb, exit_bb;
3304 block_stmt_iterator si;
3305 bool need_barrier = false;
3307 entry_bb = region->entry;
3308 exit_bb = region->exit;
3310 si = bsi_last (entry_bb);
3311 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3312 be removed. We need to ensure that the thread that entered the single
3313 does not exit before the data is copied out by the other threads. */
3314 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3315 OMP_CLAUSE_COPYPRIVATE))
3316 need_barrier = true;
3317 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3318 bsi_remove (&si, true);
3319 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3321 si = bsi_last (exit_bb);
3322 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3324 tree t = alloc_stmt_list ();
3325 build_omp_barrier (&t);
3326 bsi_insert_after (&si, t, BSI_SAME_STMT);
3328 bsi_remove (&si, true);
3329 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3333 /* Generic expansion for OpenMP synchronization directives: master,
3334 ordered and critical. All we need to do here is remove the entry
3335 and exit markers for REGION. */
3338 expand_omp_synch (struct omp_region *region)
3340 basic_block entry_bb, exit_bb;
3341 block_stmt_iterator si;
3343 entry_bb = region->entry;
3344 exit_bb = region->exit;
3346 si = bsi_last (entry_bb);
3347 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3348 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3349 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3350 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3351 bsi_remove (&si, true);
3352 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3356 si = bsi_last (exit_bb);
3357 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3358 bsi_remove (&si, true);
3359 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3364 /* Expand the parallel region tree rooted at REGION. Expansion
3365 proceeds in depth-first order. Innermost regions are expanded
3366 first. This way, parallel regions that require a new function to
3367 be created (e.g., OMP_PARALLEL) can be expanded without having any
3368 internal dependencies in their body. */
3371 expand_omp (struct omp_region *region)
3376 expand_omp (region->inner);
3378 switch (region->type)
3381 expand_omp_parallel (region);
3385 expand_omp_for (region);
3389 expand_omp_sections (region);
3393 /* Individual omp sections are handled together with their
3394 parent OMP_SECTIONS region. */
3398 expand_omp_single (region);
3404 expand_omp_synch (region);
3411 region = region->next;
3416 /* Helper for build_omp_regions. Scan the dominator tree starting at
3417 block BB. PARENT is the region that contains BB. */
3420 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3422 block_stmt_iterator si;
3427 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3429 struct omp_region *region;
3430 enum tree_code code;
3432 stmt = bsi_stmt (si);
3433 code = TREE_CODE (stmt);
3435 if (code == OMP_RETURN)
3437 /* STMT is the return point out of region PARENT. Mark it
3438 as the exit point and make PARENT the immediately
3439 enclosing region. */
3440 gcc_assert (parent);
3443 parent = parent->outer;
3445 /* If REGION is a parallel region, determine whether it is
3446 a combined parallel+workshare region. */
3447 if (region->type == OMP_PARALLEL)
3448 determine_parallel_type (region);
3450 else if (code == OMP_CONTINUE)
3452 gcc_assert (parent);
3457 /* Otherwise, this directive becomes the parent for a new
3459 region = new_omp_region (bb, code, parent);
3464 for (son = first_dom_son (CDI_DOMINATORS, bb);
3466 son = next_dom_son (CDI_DOMINATORS, son))
3467 build_omp_regions_1 (son, parent);
3471 /* Scan the CFG and build a tree of OMP regions. Return the root of
3472 the OMP region tree. */
3475 build_omp_regions (void)
3477 gcc_assert (root_omp_region == NULL);
3478 calculate_dominance_info (CDI_DOMINATORS);
3479 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3483 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3486 execute_expand_omp (void)
3488 build_omp_regions ();
3490 if (!root_omp_region)
3495 fprintf (dump_file, "\nOMP region tree\n\n");
3496 dump_omp_region (dump_file, root_omp_region, 0);
3497 fprintf (dump_file, "\n");
3500 remove_exit_barriers (root_omp_region);
3502 expand_omp (root_omp_region);
3504 free_dominance_info (CDI_DOMINATORS);
3505 free_dominance_info (CDI_POST_DOMINATORS);
3506 cleanup_tree_cfg ();
3508 free_omp_regions ();
3514 gate_expand_omp (void)
3516 return flag_openmp != 0 && errorcount == 0;
3519 struct tree_opt_pass pass_expand_omp =
3521 "ompexp", /* name */
3522 gate_expand_omp, /* gate */
3523 execute_expand_omp, /* execute */
3526 0, /* static_pass_number */
3528 PROP_gimple_any, /* properties_required */
3529 PROP_gimple_lomp, /* properties_provided */
3530 0, /* properties_destroyed */
3531 0, /* todo_flags_start */
3532 TODO_dump_func, /* todo_flags_finish */
3536 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3538 /* Lower the OpenMP sections directive in *STMT_P. */
3541 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3543 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3545 tree_stmt_iterator tsi;
3550 push_gimplify_context ();
3554 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3556 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3557 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3560 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3561 body = alloc_stmt_list ();
3562 for (i = 0; i < len; i++, tsi_next (&tsi))
3565 tree sec_start, sec_end;
3567 sec_start = tsi_stmt (tsi);
3568 sctx = maybe_lookup_ctx (sec_start);
3571 append_to_statement_list (sec_start, &body);
3573 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3574 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3575 OMP_SECTION_BODY (sec_start) = NULL;
3579 tree l = alloc_stmt_list ();
3580 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3582 append_to_statement_list (l, &body);
3583 OMP_SECTION_LAST (sec_start) = 1;
3586 sec_end = make_node (OMP_RETURN);
3587 append_to_statement_list (sec_end, &body);
3590 block = make_node (BLOCK);
3591 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3594 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3596 pop_gimplify_context (NULL_TREE);
3597 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3599 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3600 TREE_SIDE_EFFECTS (new_stmt) = 1;
3602 new_body = alloc_stmt_list ();
3603 append_to_statement_list (ilist, &new_body);
3604 append_to_statement_list (stmt, &new_body);
3605 append_to_statement_list (bind, &new_body);
3607 t = make_node (OMP_CONTINUE);
3608 append_to_statement_list (t, &new_body);
3610 append_to_statement_list (olist, &new_body);
3611 append_to_statement_list (dlist, &new_body);
3613 maybe_catch_exception (&new_body);
3615 t = make_node (OMP_RETURN);
3616 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3618 append_to_statement_list (t, &new_body);
3620 BIND_EXPR_BODY (new_stmt) = new_body;
3621 OMP_SECTIONS_BODY (stmt) = NULL;
3627 /* A subroutine of lower_omp_single. Expand the simple form of
3628 an OMP_SINGLE, without a copyprivate clause:
3630 if (GOMP_single_start ())
3632 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3634 FIXME. It may be better to delay expanding the logic of this until
3635 pass_expand_omp. The expanded logic may make the job more difficult
3636 to a synchronization analysis pass. */
3639 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3643 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3644 t = build3 (COND_EXPR, void_type_node, t,
3645 OMP_SINGLE_BODY (single_stmt), NULL);
3646 gimplify_and_add (t, pre_p);
3650 /* A subroutine of lower_omp_single. Expand the simple form of
3651 an OMP_SINGLE, with a copyprivate clause:
3653 #pragma omp single copyprivate (a, b, c)
3655 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3658 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3664 GOMP_single_copy_end (©out);
3675 FIXME. It may be better to delay expanding the logic of this until
3676 pass_expand_omp. The expanded logic may make the job more difficult
3677 to a synchronization analysis pass. */
3680 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3682 tree ptr_type, t, l0, l1, l2, copyin_seq;
3684 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3686 ptr_type = build_pointer_type (ctx->record_type);
3687 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3689 l0 = create_artificial_label ();
3690 l1 = create_artificial_label ();
3691 l2 = create_artificial_label ();
3693 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3694 t = fold_convert (ptr_type, t);
3695 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3696 gimplify_and_add (t, pre_p);
3698 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3699 build_int_cst (ptr_type, 0));
3700 t = build3 (COND_EXPR, void_type_node, t,
3701 build_and_jump (&l0), build_and_jump (&l1));
3702 gimplify_and_add (t, pre_p);
3704 t = build1 (LABEL_EXPR, void_type_node, l0);
3705 gimplify_and_add (t, pre_p);
3707 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3710 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3713 t = build_fold_addr_expr (ctx->sender_decl);
3714 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3715 gimplify_and_add (t, pre_p);
3717 t = build_and_jump (&l2);
3718 gimplify_and_add (t, pre_p);
3720 t = build1 (LABEL_EXPR, void_type_node, l1);
3721 gimplify_and_add (t, pre_p);
3723 append_to_statement_list (copyin_seq, pre_p);
3725 t = build1 (LABEL_EXPR, void_type_node, l2);
3726 gimplify_and_add (t, pre_p);
3730 /* Expand code for an OpenMP single directive. */
3733 lower_omp_single (tree *stmt_p, omp_context *ctx)
3735 tree t, bind, block, single_stmt = *stmt_p, dlist;
3737 push_gimplify_context ();
3739 block = make_node (BLOCK);
3740 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3741 TREE_SIDE_EFFECTS (bind) = 1;
3743 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3744 &BIND_EXPR_BODY (bind), &dlist, ctx);
3745 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3747 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3749 if (ctx->record_type)
3750 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3752 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3754 OMP_SINGLE_BODY (single_stmt) = NULL;
3756 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3758 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3760 t = make_node (OMP_RETURN);
3761 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3763 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3765 pop_gimplify_context (bind);
3767 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3768 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3772 /* Expand code for an OpenMP master directive. */
3775 lower_omp_master (tree *stmt_p, omp_context *ctx)
3777 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3779 push_gimplify_context ();
3781 block = make_node (BLOCK);
3782 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3783 TREE_SIDE_EFFECTS (bind) = 1;
3785 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3787 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3788 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3789 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3790 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3792 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3793 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3794 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3795 OMP_MASTER_BODY (stmt) = NULL;
3797 x = build1 (LABEL_EXPR, void_type_node, lab);
3798 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3800 x = make_node (OMP_RETURN);
3801 OMP_RETURN_NOWAIT (x) = 1;
3802 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3804 pop_gimplify_context (bind);
3806 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3807 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3811 /* Expand code for an OpenMP ordered directive. */
3814 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3816 tree bind, block, stmt = *stmt_p, x;
3818 push_gimplify_context ();
3820 block = make_node (BLOCK);
3821 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3822 TREE_SIDE_EFFECTS (bind) = 1;
3824 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3826 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
3827 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3829 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3830 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3831 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3832 OMP_ORDERED_BODY (stmt) = NULL;
3834 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
3835 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3837 x = make_node (OMP_RETURN);
3838 OMP_RETURN_NOWAIT (x) = 1;
3839 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3841 pop_gimplify_context (bind);
3843 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3844 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3848 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3849 substitution of a couple of function calls. But in the NAMED case,
3850 requires that languages coordinate a symbol name. It is therefore
3851 best put here in common code. */
3853 static GTY((param1_is (tree), param2_is (tree)))
3854 splay_tree critical_name_mutexes;
3857 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3859 tree bind, block, stmt = *stmt_p;
3860 tree t, lock, unlock, name;
3862 name = OMP_CRITICAL_NAME (stmt);
3868 if (!critical_name_mutexes)
3869 critical_name_mutexes
3870 = splay_tree_new_ggc (splay_tree_compare_pointers);
3872 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3877 decl = create_tmp_var_raw (ptr_type_node, NULL);
3879 new_str = ACONCAT ((".gomp_critical_user_",
3880 IDENTIFIER_POINTER (name), NULL));
3881 DECL_NAME (decl) = get_identifier (new_str);
3882 TREE_PUBLIC (decl) = 1;
3883 TREE_STATIC (decl) = 1;
3884 DECL_COMMON (decl) = 1;
3885 DECL_ARTIFICIAL (decl) = 1;
3886 DECL_IGNORED_P (decl) = 1;
3887 varpool_finalize_decl (decl);
3889 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3890 (splay_tree_value) decl);
3893 decl = (tree) n->value;
3895 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3896 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
3898 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3899 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
3903 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3904 lock = build_call_expr (lock, 0);
3906 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3907 unlock = build_call_expr (unlock, 0);
3910 push_gimplify_context ();
3912 block = make_node (BLOCK);
3913 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3914 TREE_SIDE_EFFECTS (bind) = 1;
3916 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3918 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3920 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3921 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3922 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3923 OMP_CRITICAL_BODY (stmt) = NULL;
3925 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3927 t = make_node (OMP_RETURN);
3928 OMP_RETURN_NOWAIT (t) = 1;
3929 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3931 pop_gimplify_context (bind);
3932 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3933 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3937 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3938 for a lastprivate clause. Given a loop control predicate of (V
3939 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3940 is appended to *DLIST, iterator initialization is appended to
3944 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3945 tree *dlist, struct omp_context *ctx)
3947 tree clauses, cond, stmts, vinit, t;
3948 enum tree_code cond_code;
3950 cond_code = fd->cond_code;
3951 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3953 /* When possible, use a strict equality expression. This can let VRP
3954 type optimizations deduce the value and remove a copy. */
3955 if (host_integerp (fd->step, 0))
3957 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3958 if (step == 1 || step == -1)
3959 cond_code = EQ_EXPR;
3962 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3964 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3966 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
3969 append_to_statement_list (stmts, dlist);
3971 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
3973 if (cond_code == EQ_EXPR
3974 && host_integerp (fd->n2, 0)
3975 && ! integer_zerop (fd->n2))
3976 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
3978 /* Initialize the iterator variable, so that threads that don't execute
3979 any iterations don't execute the lastprivate clauses by accident. */
3980 t = build_gimple_modify_stmt (fd->v, vinit);
3981 gimplify_and_add (t, body_p);
3986 /* Lower code for an OpenMP loop directive. */
3989 lower_omp_for (tree *stmt_p, omp_context *ctx)
3991 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3992 struct omp_for_data fd;
3996 push_gimplify_context ();
3998 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3999 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4001 /* Move declaration of temporaries in the loop body before we make
4003 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4004 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4006 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4007 TREE_SIDE_EFFECTS (new_stmt) = 1;
4008 body_p = &BIND_EXPR_BODY (new_stmt);
4010 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4013 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4014 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4016 /* Lower the header expressions. At this point, we can assume that
4017 the header is of the form:
4019 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4021 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4022 using the .omp_data_s mapping, if needed. */
4023 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4024 if (!is_gimple_min_invariant (*rhs_p))
4025 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4027 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4028 if (!is_gimple_min_invariant (*rhs_p))
4029 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4031 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4032 if (!is_gimple_min_invariant (*rhs_p))
4033 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4035 /* Once lowered, extract the bounds and clauses. */
4036 extract_omp_for_data (stmt, &fd);
4038 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4040 append_to_statement_list (stmt, body_p);
4042 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4044 t = make_node (OMP_CONTINUE);
4045 append_to_statement_list (t, body_p);
4047 /* After the loop, add exit clauses. */
4048 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4049 append_to_statement_list (dlist, body_p);
4051 maybe_catch_exception (body_p);
4053 /* Region exit marker goes at the end of the loop body. */
4054 t = make_node (OMP_RETURN);
4055 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4056 append_to_statement_list (t, body_p);
4058 pop_gimplify_context (NULL_TREE);
4059 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4061 OMP_FOR_BODY (stmt) = NULL_TREE;
4062 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4066 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
4070 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4072 struct walk_stmt_info *wi = data;
4073 int *info = wi->info;
4076 switch (TREE_CODE (*tp))
4080 *info = *info == 0 ? 1 : -1;
4089 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4090 information for the directive. */
4093 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4095 tree clauses, par_bind, par_body, new_body, bind;
4096 tree olist, ilist, par_olist, par_ilist;
4097 tree stmt, child_fn, t;
4101 clauses = OMP_PARALLEL_CLAUSES (stmt);
4102 par_bind = OMP_PARALLEL_BODY (stmt);
4103 par_body = BIND_EXPR_BODY (par_bind);
4104 child_fn = ctx->cb.dst_fn;
4105 if (!OMP_PARALLEL_COMBINED (stmt))
4107 struct walk_stmt_info wi;
4110 memset (&wi, 0, sizeof (wi));
4111 wi.callback = check_combined_parallel;
4114 walk_stmts (&wi, &par_bind);
4116 OMP_PARALLEL_COMBINED (stmt) = 1;
4119 push_gimplify_context ();
4121 par_olist = NULL_TREE;
4122 par_ilist = NULL_TREE;
4123 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4124 lower_omp (&par_body, ctx);
4125 lower_reduction_clauses (clauses, &par_olist, ctx);
4127 /* Declare all the variables created by mapping and the variables
4128 declared in the scope of the parallel body. */
4129 record_vars_into (ctx->block_vars, child_fn);
4130 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4132 if (ctx->record_type)
4134 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4135 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4140 lower_send_clauses (clauses, &ilist, &olist, ctx);
4141 lower_send_shared_vars (&ilist, &olist, ctx);
4143 /* Once all the expansions are done, sequence all the different
4144 fragments inside OMP_PARALLEL_BODY. */
4145 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4146 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4148 new_body = alloc_stmt_list ();
4150 if (ctx->record_type)
4152 t = build_fold_addr_expr (ctx->sender_decl);
4153 /* fixup_child_record_type might have changed receiver_decl's type. */
4154 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4155 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4156 append_to_statement_list (t, &new_body);
4159 append_to_statement_list (par_ilist, &new_body);
4160 append_to_statement_list (par_body, &new_body);
4161 append_to_statement_list (par_olist, &new_body);
4162 maybe_catch_exception (&new_body);
4163 t = make_node (OMP_RETURN);
4164 append_to_statement_list (t, &new_body);
4165 OMP_PARALLEL_BODY (stmt) = new_body;
4167 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4168 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4172 pop_gimplify_context (NULL_TREE);
4176 /* Pass *TP back through the gimplifier within the context determined by WI.
4177 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4178 flags on ADDR_EXPR. */
4181 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4183 enum gimplify_status gs;
4187 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4188 else if (wi->val_only)
4189 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4191 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4192 gcc_assert (gs == GS_ALL_DONE);
4195 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4198 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4201 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4205 t = create_tmp_var (TREE_TYPE (exp), NULL);
4206 DECL_GIMPLE_REG_P (t) = 1;
4207 stmt = build_gimple_modify_stmt (t, exp);
4208 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4209 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4214 /* Similarly, but copy from the temporary and insert the statement
4215 after the iterator. */
4218 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4222 t = create_tmp_var (TREE_TYPE (exp), NULL);
4223 DECL_GIMPLE_REG_P (t) = 1;
4224 stmt = build_gimple_modify_stmt (exp, t);
4225 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4226 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4231 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4234 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4236 struct walk_stmt_info *wi = data;
4237 omp_context *ctx = wi->info;
4240 /* If we have issued syntax errors, avoid doing any heavy lifting.
4241 Just replace the OpenMP directives with a NOP to avoid
4242 confusing RTL expansion. */
4243 if (errorcount && OMP_DIRECTIVE_P (*tp))
4245 *tp = build_empty_stmt ();
4250 switch (TREE_CODE (*tp))
4253 ctx = maybe_lookup_ctx (t);
4254 lower_omp_parallel (tp, ctx);
4258 ctx = maybe_lookup_ctx (t);
4260 lower_omp_for (tp, ctx);
4264 ctx = maybe_lookup_ctx (t);
4266 lower_omp_sections (tp, ctx);
4270 ctx = maybe_lookup_ctx (t);
4272 lower_omp_single (tp, ctx);
4276 ctx = maybe_lookup_ctx (t);
4278 lower_omp_master (tp, ctx);
4282 ctx = maybe_lookup_ctx (t);
4284 lower_omp_ordered (tp, ctx);
4288 ctx = maybe_lookup_ctx (t);
4290 lower_omp_critical (tp, ctx);
4294 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4296 lower_regimplify (&t, wi);
4300 t = save_tmp_var (t, &wi->tsi);
4302 t = init_tmp_var (t, &wi->tsi);
4310 lower_regimplify (tp, wi);
4314 case ARRAY_RANGE_REF:
4318 case VIEW_CONVERT_EXPR:
4320 lower_regimplify (tp, wi);
4327 wi->val_only = true;
4328 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4333 if (!TYPE_P (t) && !DECL_P (t))
4342 lower_omp (tree *stmt_p, omp_context *ctx)
4344 struct walk_stmt_info wi;
4346 memset (&wi, 0, sizeof (wi));
4347 wi.callback = lower_omp_1;
4350 wi.want_locations = true;
4352 walk_stmts (&wi, stmt_p);
4355 /* Main entry point. */
4358 execute_lower_omp (void)
4360 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4361 delete_omp_context);
4363 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4364 gcc_assert (parallel_nesting_level == 0);
4366 if (all_contexts->root)
4367 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4371 splay_tree_delete (all_contexts);
4372 all_contexts = NULL;
4378 gate_lower_omp (void)
4380 return flag_openmp != 0;
4383 struct tree_opt_pass pass_lower_omp =
4385 "omplower", /* name */
4386 gate_lower_omp, /* gate */
4387 execute_lower_omp, /* execute */
4390 0, /* static_pass_number */
4392 PROP_gimple_any, /* properties_required */
4393 PROP_gimple_lomp, /* properties_provided */
4394 0, /* properties_destroyed */
4395 0, /* todo_flags_start */
4396 TODO_dump_func, /* todo_flags_finish */
4400 /* The following is a utility to diagnose OpenMP structured block violations.
4401 It is not part of the "omplower" pass, as that's invoked too late. It
4402 should be invoked by the respective front ends after gimplification. */
4404 static splay_tree all_labels;
4406 /* Check for mismatched contexts and generate an error if needed. Return
4407 true if an error is detected. */
4410 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4414 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4417 /* Try to avoid confusing the user by producing and error message
4418 with correct "exit" or "enter" verbage. We prefer "exit"
4419 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4420 if (branch_ctx == NULL)
4426 if (TREE_VALUE (label_ctx) == branch_ctx)
4431 label_ctx = TREE_CHAIN (label_ctx);
4436 error ("invalid exit from OpenMP structured block");
4438 error ("invalid entry to OpenMP structured block");
4440 *stmt_p = build_empty_stmt ();
4444 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4445 where in the tree each label is found. */
4448 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4450 struct walk_stmt_info *wi = data;
4451 tree context = (tree) wi->info;
4456 switch (TREE_CODE (t))
4461 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4467 /* The minimal context here is just a tree of statements. */
4468 inner_context = tree_cons (NULL, t, context);
4469 wi->info = inner_context;
4470 walk_stmts (wi, &OMP_BODY (t));
4475 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4476 inner_context = tree_cons (NULL, t, context);
4477 wi->info = inner_context;
4478 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4479 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4480 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4481 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4482 walk_stmts (wi, &OMP_FOR_BODY (t));
4487 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4488 (splay_tree_value) context);
4498 /* Pass 2: Check each branch and see if its context differs from that of
4499 the destination label's context. */
4502 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4504 struct walk_stmt_info *wi = data;
4505 tree context = (tree) wi->info;
4510 switch (TREE_CODE (t))
4515 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4522 walk_stmts (wi, &OMP_BODY (t));
4527 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4529 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4530 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4531 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4532 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4533 walk_stmts (wi, &OMP_FOR_BODY (t));
4539 tree lab = GOTO_DESTINATION (t);
4540 if (TREE_CODE (lab) != LABEL_DECL)
4543 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4544 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4550 tree vec = SWITCH_LABELS (t);
4551 int i, len = TREE_VEC_LENGTH (vec);
4552 for (i = 0; i < len; ++i)
4554 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4555 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4556 if (diagnose_sb_0 (tp, context, (tree) n->value))
4563 diagnose_sb_0 (tp, context, NULL_TREE);
4574 diagnose_omp_structured_block_errors (tree fndecl)
4576 tree save_current = current_function_decl;
4577 struct walk_stmt_info wi;
4579 current_function_decl = fndecl;
4581 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4583 memset (&wi, 0, sizeof (wi));
4584 wi.callback = diagnose_sb_1;
4585 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4587 memset (&wi, 0, sizeof (wi));
4588 wi.callback = diagnose_sb_2;
4589 wi.want_locations = true;
4590 wi.want_return_expr = true;
4591 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4593 splay_tree_delete (all_labels);
4596 current_function_decl = save_current;
4599 #include "gt-omp-low.h"