PR c++/31187
[official-gcc.git] / gcc / omp-low.c
blobf176f9e410215b60942770b52892b4f591ea7efa
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
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to the Free
22 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "rtl.h"
31 #include "tree-gimple.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
36 #include "timevar.h"
37 #include "flags.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "toplev.h"
41 #include "tree-pass.h"
42 #include "ggc.h"
43 #include "except.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
52 expressions.
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. */
67 copy_body_data cb;
69 /* The tree of contexts corresponding to the encountered constructs. */
70 struct omp_context *outer;
71 tree stmt;
73 /* Map variables to fields in a structure that allows communication
74 between sending and receiving threads. */
75 splay_tree field_map;
76 tree record_type;
77 tree sender_decl;
78 tree receiver_decl;
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. */
82 tree block_vars;
84 /* What to do with variables with implicitly determined sharing
85 attributes. */
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. */
91 int depth;
93 /* True if this parallel directive is nested within another. */
94 bool is_nested;
95 } omp_context;
98 /* A structure describing the main elements of a parallel loop. */
100 struct omp_for_data
102 tree v, n1, n2, step, chunk_size, for_stmt;
103 enum tree_code cond_code;
104 tree pre;
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. */
121 static tree
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)
126 return clauses;
128 return NULL_TREE;
131 /* Return true if CTX is for an omp parallel. */
133 static inline bool
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. */
142 static inline bool
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
150 them into *FD. */
152 static void
153 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
155 tree t;
157 fd->for_stmt = for_stmt;
158 fd->pre = NULL;
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)
173 case LT_EXPR:
174 case GT_EXPR:
175 break;
176 case LE_EXPR:
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;
180 break;
181 case GE_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;
185 break;
186 default:
187 gcc_unreachable ();
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))
197 case PLUS_EXPR:
198 fd->step = TREE_OPERAND (t, 1);
199 break;
200 case MINUS_EXPR:
201 fd->step = TREE_OPERAND (t, 1);
202 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
203 break;
204 default:
205 gcc_unreachable ();
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;
217 break;
218 case OMP_CLAUSE_ORDERED:
219 fd->have_ordered = true;
220 break;
221 case OMP_CLAUSE_SCHEDULE:
222 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
223 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
224 break;
225 default:
226 break;
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)
254 for (j ...)
256 Is lowered into:
258 # BLOCK 2 (PAR_ENTRY_BB)
259 .omp_data_o.i = i;
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;
265 D.1598 = D.1667 * 4;
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
277 call.
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. */
284 static bool
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)
294 return true;
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
304 see through this. */
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)))
309 return false;
311 return true;
315 /* Collect additional arguments needed to emit a combined
316 parallel+workshare call. WS_STMT is the workshare directive being
317 expanded. */
319 static tree
320 get_ws_args_for (tree ws_stmt)
322 tree t;
324 if (TREE_CODE (ws_stmt) == OMP_FOR)
326 struct omp_for_data fd;
327 tree ws_args;
329 extract_omp_for_data (ws_stmt, &fd);
331 ws_args = NULL_TREE;
332 if (fd.chunk_size)
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);
347 return 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);
354 return t;
357 gcc_unreachable ();
361 /* Discover whether REGION is a combined parallel+workshare region. */
363 static void
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)
371 return;
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))
377 return;
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))
390 tree ws_stmt = last_stmt (region->inner->entry);
392 if (region->inner->type == OMP_FOR)
394 /* If this is a combined parallel loop, we need to determine
395 whether or not to use the combined library calls. There
396 are two cases where we do not apply the transformation:
397 static loops and any kind of ordered loop. In the first
398 case, we already open code the loop so there is no need
399 to do anything else. In the latter case, the combined
400 parallel loop call would still need extra synchronization
401 to implement ordered semantics, so there would not be any
402 gain in using the combined call. */
403 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
404 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
405 if (c == NULL
406 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
407 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
409 region->is_combined_parallel = false;
410 region->inner->is_combined_parallel = false;
411 return;
415 region->is_combined_parallel = true;
416 region->inner->is_combined_parallel = true;
417 region->ws_args = get_ws_args_for (ws_stmt);
422 /* Return true if EXPR is variable sized. */
424 static inline bool
425 is_variable_sized (tree expr)
427 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
430 /* Return true if DECL is a reference type. */
432 static inline bool
433 is_reference (tree decl)
435 return lang_hooks.decls.omp_privatize_by_reference (decl);
438 /* Lookup variables in the decl or field splay trees. The "maybe" form
439 allows for the variable form to not have been entered, otherwise we
440 assert that the variable must have been entered. */
442 static inline tree
443 lookup_decl (tree var, omp_context *ctx)
445 tree *n;
446 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
447 return *n;
450 static inline tree
451 maybe_lookup_decl (tree var, omp_context *ctx)
453 tree *n;
454 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
455 return n ? *n : NULL_TREE;
458 static inline tree
459 lookup_field (tree var, omp_context *ctx)
461 splay_tree_node n;
462 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
463 return (tree) n->value;
466 static inline tree
467 maybe_lookup_field (tree var, omp_context *ctx)
469 splay_tree_node n;
470 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
471 return n ? (tree) n->value : NULL_TREE;
474 /* Return true if DECL should be copied by pointer. SHARED_P is true
475 if DECL is to be shared. */
477 static bool
478 use_pointer_for_field (tree decl, bool shared_p)
480 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
481 return true;
483 /* We can only use copy-in/copy-out semantics for shared variables
484 when we know the value is not accessible from an outer scope. */
485 if (shared_p)
487 /* ??? Trivially accessible from anywhere. But why would we even
488 be passing an address in this case? Should we simply assert
489 this to be false, or should we have a cleanup pass that removes
490 these from the list of mappings? */
491 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
492 return true;
494 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
495 without analyzing the expression whether or not its location
496 is accessible to anyone else. In the case of nested parallel
497 regions it certainly may be. */
498 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
499 return true;
501 /* Do not use copy-in/copy-out for variables that have their
502 address taken. */
503 if (TREE_ADDRESSABLE (decl))
504 return true;
507 return false;
510 /* Construct a new automatic decl similar to VAR. */
512 static tree
513 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
515 tree copy = build_decl (VAR_DECL, name, type);
517 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
518 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
519 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
520 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
521 TREE_USED (copy) = 1;
522 DECL_CONTEXT (copy) = current_function_decl;
523 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
525 TREE_CHAIN (copy) = ctx->block_vars;
526 ctx->block_vars = copy;
528 return copy;
531 static tree
532 omp_copy_decl_1 (tree var, omp_context *ctx)
534 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
537 /* Build tree nodes to access the field for VAR on the receiver side. */
539 static tree
540 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
542 tree x, field = lookup_field (var, ctx);
544 /* If the receiver record type was remapped in the child function,
545 remap the field into the new record type. */
546 x = maybe_lookup_field (field, ctx);
547 if (x != NULL)
548 field = x;
550 x = build_fold_indirect_ref (ctx->receiver_decl);
551 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
552 if (by_ref)
553 x = build_fold_indirect_ref (x);
555 return x;
558 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
559 of a parallel, this is a component reference; for workshare constructs
560 this is some variable. */
562 static tree
563 build_outer_var_ref (tree var, omp_context *ctx)
565 tree x;
567 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
568 x = var;
569 else if (is_variable_sized (var))
571 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
572 x = build_outer_var_ref (x, ctx);
573 x = build_fold_indirect_ref (x);
575 else if (is_parallel_ctx (ctx))
577 bool by_ref = use_pointer_for_field (var, false);
578 x = build_receiver_ref (var, by_ref, ctx);
580 else if (ctx->outer)
581 x = lookup_decl (var, ctx->outer);
582 else if (is_reference (var))
583 /* This can happen with orphaned constructs. If var is reference, it is
584 possible it is shared and as such valid. */
585 x = var;
586 else
587 gcc_unreachable ();
589 if (is_reference (var))
590 x = build_fold_indirect_ref (x);
592 return x;
595 /* Build tree nodes to access the field for VAR on the sender side. */
597 static tree
598 build_sender_ref (tree var, omp_context *ctx)
600 tree field = lookup_field (var, ctx);
601 return build3 (COMPONENT_REF, TREE_TYPE (field),
602 ctx->sender_decl, field, NULL);
605 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
607 static void
608 install_var_field (tree var, bool by_ref, omp_context *ctx)
610 tree field, type;
612 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
614 type = TREE_TYPE (var);
615 if (by_ref)
616 type = build_pointer_type (type);
618 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
620 /* Remember what variable this field was created for. This does have a
621 side effect of making dwarf2out ignore this member, so for helpful
622 debugging we clear it later in delete_omp_context. */
623 DECL_ABSTRACT_ORIGIN (field) = var;
625 insert_field_into_struct (ctx->record_type, field);
627 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
628 (splay_tree_value) field);
631 static tree
632 install_var_local (tree var, omp_context *ctx)
634 tree new_var = omp_copy_decl_1 (var, ctx);
635 insert_decl_map (&ctx->cb, var, new_var);
636 return new_var;
639 /* Adjust the replacement for DECL in CTX for the new context. This means
640 copying the DECL_VALUE_EXPR, and fixing up the type. */
642 static void
643 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
645 tree new_decl, size;
647 new_decl = lookup_decl (decl, ctx);
649 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
651 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
652 && DECL_HAS_VALUE_EXPR_P (decl))
654 tree ve = DECL_VALUE_EXPR (decl);
655 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
656 SET_DECL_VALUE_EXPR (new_decl, ve);
657 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
660 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
662 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
663 if (size == error_mark_node)
664 size = TYPE_SIZE (TREE_TYPE (new_decl));
665 DECL_SIZE (new_decl) = size;
667 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
668 if (size == error_mark_node)
669 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
670 DECL_SIZE_UNIT (new_decl) = size;
674 /* The callback for remap_decl. Search all containing contexts for a
675 mapping of the variable; this avoids having to duplicate the splay
676 tree ahead of time. We know a mapping doesn't already exist in the
677 given context. Create new mappings to implement default semantics. */
679 static tree
680 omp_copy_decl (tree var, copy_body_data *cb)
682 omp_context *ctx = (omp_context *) cb;
683 tree new_var;
685 if (TREE_CODE (var) == LABEL_DECL)
687 new_var = create_artificial_label ();
688 DECL_CONTEXT (new_var) = current_function_decl;
689 insert_decl_map (&ctx->cb, var, new_var);
690 return new_var;
693 while (!is_parallel_ctx (ctx))
695 ctx = ctx->outer;
696 if (ctx == NULL)
697 return var;
698 new_var = maybe_lookup_decl (var, ctx);
699 if (new_var)
700 return new_var;
703 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
704 return var;
706 return error_mark_node;
710 /* Return the parallel region associated with STMT. */
712 /* Debugging dumps for parallel regions. */
713 void dump_omp_region (FILE *, struct omp_region *, int);
714 void debug_omp_region (struct omp_region *);
715 void debug_all_omp_regions (void);
717 /* Dump the parallel region tree rooted at REGION. */
719 void
720 dump_omp_region (FILE *file, struct omp_region *region, int indent)
722 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
723 tree_code_name[region->type]);
725 if (region->inner)
726 dump_omp_region (file, region->inner, indent + 4);
728 if (region->cont)
730 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
731 region->cont->index);
734 if (region->exit)
735 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
736 region->exit->index);
737 else
738 fprintf (file, "%*s[no exit marker]\n", indent, "");
740 if (region->next)
741 dump_omp_region (file, region->next, indent);
744 void
745 debug_omp_region (struct omp_region *region)
747 dump_omp_region (stderr, region, 0);
750 void
751 debug_all_omp_regions (void)
753 dump_omp_region (stderr, root_omp_region, 0);
757 /* Create a new parallel region starting at STMT inside region PARENT. */
759 struct omp_region *
760 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
762 struct omp_region *region = xcalloc (1, sizeof (*region));
764 region->outer = parent;
765 region->entry = bb;
766 region->type = type;
768 if (parent)
770 /* This is a nested region. Add it to the list of inner
771 regions in PARENT. */
772 region->next = parent->inner;
773 parent->inner = region;
775 else
777 /* This is a toplevel region. Add it to the list of toplevel
778 regions in ROOT_OMP_REGION. */
779 region->next = root_omp_region;
780 root_omp_region = region;
783 return region;
786 /* Release the memory associated with the region tree rooted at REGION. */
788 static void
789 free_omp_region_1 (struct omp_region *region)
791 struct omp_region *i, *n;
793 for (i = region->inner; i ; i = n)
795 n = i->next;
796 free_omp_region_1 (i);
799 free (region);
802 /* Release the memory for the entire omp region tree. */
804 void
805 free_omp_regions (void)
807 struct omp_region *r, *n;
808 for (r = root_omp_region; r ; r = n)
810 n = r->next;
811 free_omp_region_1 (r);
813 root_omp_region = NULL;
817 /* Create a new context, with OUTER_CTX being the surrounding context. */
819 static omp_context *
820 new_omp_context (tree stmt, omp_context *outer_ctx)
822 omp_context *ctx = XCNEW (omp_context);
824 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
825 (splay_tree_value) ctx);
826 ctx->stmt = stmt;
828 if (outer_ctx)
830 ctx->outer = outer_ctx;
831 ctx->cb = outer_ctx->cb;
832 ctx->cb.block = NULL;
833 ctx->depth = outer_ctx->depth + 1;
835 else
837 ctx->cb.src_fn = current_function_decl;
838 ctx->cb.dst_fn = current_function_decl;
839 ctx->cb.src_node = cgraph_node (current_function_decl);
840 ctx->cb.dst_node = ctx->cb.src_node;
841 ctx->cb.src_cfun = cfun;
842 ctx->cb.copy_decl = omp_copy_decl;
843 ctx->cb.eh_region = -1;
844 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
845 ctx->depth = 1;
848 ctx->cb.decl_map = pointer_map_create ();
850 return ctx;
853 /* Destroy a omp_context data structures. Called through the splay tree
854 value delete callback. */
856 static void
857 delete_omp_context (splay_tree_value value)
859 omp_context *ctx = (omp_context *) value;
861 pointer_map_destroy (ctx->cb.decl_map);
863 if (ctx->field_map)
864 splay_tree_delete (ctx->field_map);
866 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
867 it produces corrupt debug information. */
868 if (ctx->record_type)
870 tree t;
871 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
872 DECL_ABSTRACT_ORIGIN (t) = NULL;
875 XDELETE (ctx);
878 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
879 context. */
881 static void
882 fixup_child_record_type (omp_context *ctx)
884 tree f, type = ctx->record_type;
886 /* ??? It isn't sufficient to just call remap_type here, because
887 variably_modified_type_p doesn't work the way we expect for
888 record types. Testing each field for whether it needs remapping
889 and creating a new record by hand works, however. */
890 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
891 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
892 break;
893 if (f)
895 tree name, new_fields = NULL;
897 type = lang_hooks.types.make_type (RECORD_TYPE);
898 name = DECL_NAME (TYPE_NAME (ctx->record_type));
899 name = build_decl (TYPE_DECL, name, type);
900 TYPE_NAME (type) = name;
902 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
904 tree new_f = copy_node (f);
905 DECL_CONTEXT (new_f) = type;
906 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
907 TREE_CHAIN (new_f) = new_fields;
908 new_fields = new_f;
910 /* Arrange to be able to look up the receiver field
911 given the sender field. */
912 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
913 (splay_tree_value) new_f);
915 TYPE_FIELDS (type) = nreverse (new_fields);
916 layout_type (type);
919 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
922 /* Instantiate decls as necessary in CTX to satisfy the data sharing
923 specified by CLAUSES. */
925 static void
926 scan_sharing_clauses (tree clauses, omp_context *ctx)
928 tree c, decl;
929 bool scan_array_reductions = false;
931 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
933 bool by_ref;
935 switch (OMP_CLAUSE_CODE (c))
937 case OMP_CLAUSE_PRIVATE:
938 decl = OMP_CLAUSE_DECL (c);
939 if (!is_variable_sized (decl))
940 install_var_local (decl, ctx);
941 break;
943 case OMP_CLAUSE_SHARED:
944 gcc_assert (is_parallel_ctx (ctx));
945 decl = OMP_CLAUSE_DECL (c);
946 gcc_assert (!is_variable_sized (decl));
947 by_ref = use_pointer_for_field (decl, true);
948 /* Global variables don't need to be copied,
949 the receiver side will use them directly. */
950 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
951 break;
952 if (! TREE_READONLY (decl)
953 || TREE_ADDRESSABLE (decl)
954 || by_ref
955 || is_reference (decl))
957 install_var_field (decl, by_ref, ctx);
958 install_var_local (decl, ctx);
959 break;
961 /* We don't need to copy const scalar vars back. */
962 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
963 goto do_private;
965 case OMP_CLAUSE_LASTPRIVATE:
966 /* Let the corresponding firstprivate clause create
967 the variable. */
968 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
969 break;
970 /* FALLTHRU */
972 case OMP_CLAUSE_FIRSTPRIVATE:
973 case OMP_CLAUSE_REDUCTION:
974 decl = OMP_CLAUSE_DECL (c);
975 do_private:
976 if (is_variable_sized (decl))
977 break;
978 else if (is_parallel_ctx (ctx)
979 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
980 ctx)))
982 by_ref = use_pointer_for_field (decl, false);
983 install_var_field (decl, by_ref, ctx);
985 install_var_local (decl, ctx);
986 break;
988 case OMP_CLAUSE_COPYPRIVATE:
989 if (ctx->outer)
990 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
991 /* FALLTHRU */
993 case OMP_CLAUSE_COPYIN:
994 decl = OMP_CLAUSE_DECL (c);
995 by_ref = use_pointer_for_field (decl, false);
996 install_var_field (decl, by_ref, ctx);
997 break;
999 case OMP_CLAUSE_DEFAULT:
1000 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1001 break;
1003 case OMP_CLAUSE_IF:
1004 case OMP_CLAUSE_NUM_THREADS:
1005 case OMP_CLAUSE_SCHEDULE:
1006 if (ctx->outer)
1007 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1008 break;
1010 case OMP_CLAUSE_NOWAIT:
1011 case OMP_CLAUSE_ORDERED:
1012 break;
1014 default:
1015 gcc_unreachable ();
1019 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1021 switch (OMP_CLAUSE_CODE (c))
1023 case OMP_CLAUSE_LASTPRIVATE:
1024 /* Let the corresponding firstprivate clause create
1025 the variable. */
1026 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1027 break;
1028 /* FALLTHRU */
1030 case OMP_CLAUSE_PRIVATE:
1031 case OMP_CLAUSE_FIRSTPRIVATE:
1032 case OMP_CLAUSE_REDUCTION:
1033 decl = OMP_CLAUSE_DECL (c);
1034 if (is_variable_sized (decl))
1035 install_var_local (decl, ctx);
1036 fixup_remapped_decl (decl, ctx,
1037 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1038 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1039 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1040 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1041 scan_array_reductions = true;
1042 break;
1044 case OMP_CLAUSE_SHARED:
1045 decl = OMP_CLAUSE_DECL (c);
1046 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1047 fixup_remapped_decl (decl, ctx, false);
1048 break;
1050 case OMP_CLAUSE_COPYPRIVATE:
1051 case OMP_CLAUSE_COPYIN:
1052 case OMP_CLAUSE_DEFAULT:
1053 case OMP_CLAUSE_IF:
1054 case OMP_CLAUSE_NUM_THREADS:
1055 case OMP_CLAUSE_SCHEDULE:
1056 case OMP_CLAUSE_NOWAIT:
1057 case OMP_CLAUSE_ORDERED:
1058 break;
1060 default:
1061 gcc_unreachable ();
1065 if (scan_array_reductions)
1066 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1068 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1070 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1071 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1075 /* Create a new name for omp child function. Returns an identifier. */
1077 static GTY(()) unsigned int tmp_ompfn_id_num;
1079 static tree
1080 create_omp_child_function_name (void)
1082 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1083 size_t len = IDENTIFIER_LENGTH (name);
1084 char *tmp_name, *prefix;
1086 prefix = alloca (len + sizeof ("_omp_fn"));
1087 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1088 strcpy (prefix + len, "_omp_fn");
1089 #ifndef NO_DOT_IN_LABEL
1090 prefix[len] = '.';
1091 #elif !defined NO_DOLLAR_IN_LABEL
1092 prefix[len] = '$';
1093 #endif
1094 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1095 return get_identifier (tmp_name);
1098 /* Build a decl for the omp child function. It'll not contain a body
1099 yet, just the bare decl. */
1101 static void
1102 create_omp_child_function (omp_context *ctx)
1104 tree decl, type, name, t;
1106 name = create_omp_child_function_name ();
1107 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1109 decl = build_decl (FUNCTION_DECL, name, type);
1110 decl = lang_hooks.decls.pushdecl (decl);
1112 ctx->cb.dst_fn = decl;
1114 TREE_STATIC (decl) = 1;
1115 TREE_USED (decl) = 1;
1116 DECL_ARTIFICIAL (decl) = 1;
1117 DECL_IGNORED_P (decl) = 0;
1118 TREE_PUBLIC (decl) = 0;
1119 DECL_UNINLINABLE (decl) = 1;
1120 DECL_EXTERNAL (decl) = 0;
1121 DECL_CONTEXT (decl) = NULL_TREE;
1122 DECL_INITIAL (decl) = make_node (BLOCK);
1124 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1125 DECL_ARTIFICIAL (t) = 1;
1126 DECL_IGNORED_P (t) = 1;
1127 DECL_RESULT (decl) = t;
1129 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1130 DECL_ARTIFICIAL (t) = 1;
1131 DECL_ARG_TYPE (t) = ptr_type_node;
1132 DECL_CONTEXT (t) = current_function_decl;
1133 TREE_USED (t) = 1;
1134 DECL_ARGUMENTS (decl) = t;
1135 ctx->receiver_decl = t;
1137 /* Allocate memory for the function structure. The call to
1138 allocate_struct_function clobbers CFUN, so we need to restore
1139 it afterward. */
1140 allocate_struct_function (decl);
1141 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1142 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1143 cfun = ctx->cb.src_cfun;
1147 /* Scan an OpenMP parallel directive. */
1149 static void
1150 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1152 omp_context *ctx;
1153 tree name;
1155 /* Ignore parallel directives with empty bodies, unless there
1156 are copyin clauses. */
1157 if (optimize > 0
1158 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1159 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1161 *stmt_p = build_empty_stmt ();
1162 return;
1165 ctx = new_omp_context (*stmt_p, outer_ctx);
1166 if (parallel_nesting_level > 1)
1167 ctx->is_nested = true;
1168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1171 name = create_tmp_var_name (".omp_data_s");
1172 name = build_decl (TYPE_DECL, name, ctx->record_type);
1173 TYPE_NAME (ctx->record_type) = name;
1174 create_omp_child_function (ctx);
1175 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1177 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1178 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1180 if (TYPE_FIELDS (ctx->record_type) == NULL)
1181 ctx->record_type = ctx->receiver_decl = NULL;
1182 else
1184 layout_type (ctx->record_type);
1185 fixup_child_record_type (ctx);
1190 /* Scan an OpenMP loop directive. */
1192 static void
1193 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1195 omp_context *ctx;
1196 tree stmt;
1198 stmt = *stmt_p;
1199 ctx = new_omp_context (stmt, outer_ctx);
1201 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1203 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1204 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1205 scan_omp (&OMP_FOR_COND (stmt), ctx);
1206 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1207 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1210 /* Scan an OpenMP sections directive. */
1212 static void
1213 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1215 tree stmt;
1216 omp_context *ctx;
1218 stmt = *stmt_p;
1219 ctx = new_omp_context (stmt, outer_ctx);
1220 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1221 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1224 /* Scan an OpenMP single directive. */
1226 static void
1227 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1229 tree stmt = *stmt_p;
1230 omp_context *ctx;
1231 tree name;
1233 ctx = new_omp_context (stmt, outer_ctx);
1234 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1235 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1236 name = create_tmp_var_name (".omp_copy_s");
1237 name = build_decl (TYPE_DECL, name, ctx->record_type);
1238 TYPE_NAME (ctx->record_type) = name;
1240 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1241 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1243 if (TYPE_FIELDS (ctx->record_type) == NULL)
1244 ctx->record_type = NULL;
1245 else
1246 layout_type (ctx->record_type);
1250 /* Check OpenMP nesting restrictions. */
1251 static void
1252 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1254 switch (TREE_CODE (t))
1256 case OMP_FOR:
1257 case OMP_SECTIONS:
1258 case OMP_SINGLE:
1259 for (; ctx != NULL; ctx = ctx->outer)
1260 switch (TREE_CODE (ctx->stmt))
1262 case OMP_FOR:
1263 case OMP_SECTIONS:
1264 case OMP_SINGLE:
1265 case OMP_ORDERED:
1266 case OMP_MASTER:
1267 warning (0, "work-sharing region may not be closely nested inside "
1268 "of work-sharing, critical, ordered or master region");
1269 return;
1270 case OMP_PARALLEL:
1271 return;
1272 default:
1273 break;
1275 break;
1276 case OMP_MASTER:
1277 for (; ctx != NULL; ctx = ctx->outer)
1278 switch (TREE_CODE (ctx->stmt))
1280 case OMP_FOR:
1281 case OMP_SECTIONS:
1282 case OMP_SINGLE:
1283 warning (0, "master region may not be closely nested inside "
1284 "of work-sharing region");
1285 return;
1286 case OMP_PARALLEL:
1287 return;
1288 default:
1289 break;
1291 break;
1292 case OMP_ORDERED:
1293 for (; ctx != NULL; ctx = ctx->outer)
1294 switch (TREE_CODE (ctx->stmt))
1296 case OMP_CRITICAL:
1297 warning (0, "ordered region may not be closely nested inside "
1298 "of critical region");
1299 return;
1300 case OMP_FOR:
1301 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1302 OMP_CLAUSE_ORDERED) == NULL)
1303 warning (0, "ordered region must be closely nested inside "
1304 "a loop region with an ordered clause");
1305 return;
1306 case OMP_PARALLEL:
1307 return;
1308 default:
1309 break;
1311 break;
1312 case OMP_CRITICAL:
1313 for (; ctx != NULL; ctx = ctx->outer)
1314 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1315 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1317 warning (0, "critical region may not be nested inside a critical "
1318 "region with the same name");
1319 return;
1321 break;
1322 default:
1323 break;
1328 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1330 static tree
1331 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1333 struct walk_stmt_info *wi = data;
1334 omp_context *ctx = wi->info;
1335 tree t = *tp;
1337 if (EXPR_HAS_LOCATION (t))
1338 input_location = EXPR_LOCATION (t);
1340 /* Check the OpenMP nesting restrictions. */
1341 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1342 check_omp_nesting_restrictions (t, ctx);
1344 *walk_subtrees = 0;
1345 switch (TREE_CODE (t))
1347 case OMP_PARALLEL:
1348 parallel_nesting_level++;
1349 scan_omp_parallel (tp, ctx);
1350 parallel_nesting_level--;
1351 break;
1353 case OMP_FOR:
1354 scan_omp_for (tp, ctx);
1355 break;
1357 case OMP_SECTIONS:
1358 scan_omp_sections (tp, ctx);
1359 break;
1361 case OMP_SINGLE:
1362 scan_omp_single (tp, ctx);
1363 break;
1365 case OMP_SECTION:
1366 case OMP_MASTER:
1367 case OMP_ORDERED:
1368 case OMP_CRITICAL:
1369 ctx = new_omp_context (*tp, ctx);
1370 scan_omp (&OMP_BODY (*tp), ctx);
1371 break;
1373 case BIND_EXPR:
1375 tree var;
1376 *walk_subtrees = 1;
1378 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1379 insert_decl_map (&ctx->cb, var, var);
1381 break;
1383 case VAR_DECL:
1384 case PARM_DECL:
1385 case LABEL_DECL:
1386 case RESULT_DECL:
1387 if (ctx)
1388 *tp = remap_decl (t, &ctx->cb);
1389 break;
1391 default:
1392 if (ctx && TYPE_P (t))
1393 *tp = remap_type (t, &ctx->cb);
1394 else if (!DECL_P (t))
1395 *walk_subtrees = 1;
1396 break;
1399 return NULL_TREE;
1403 /* Scan all the statements starting at STMT_P. CTX contains context
1404 information about the OpenMP directives and clauses found during
1405 the scan. */
1407 static void
1408 scan_omp (tree *stmt_p, omp_context *ctx)
1410 location_t saved_location;
1411 struct walk_stmt_info wi;
1413 memset (&wi, 0, sizeof (wi));
1414 wi.callback = scan_omp_1;
1415 wi.info = ctx;
1416 wi.want_bind_expr = (ctx != NULL);
1417 wi.want_locations = true;
1419 saved_location = input_location;
1420 walk_stmts (&wi, stmt_p);
1421 input_location = saved_location;
1424 /* Re-gimplification and code generation routines. */
1426 /* Build a call to GOMP_barrier. */
1428 static void
1429 build_omp_barrier (tree *stmt_list)
1431 tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1432 gimplify_and_add (t, stmt_list);
1435 /* If a context was created for STMT when it was scanned, return it. */
1437 static omp_context *
1438 maybe_lookup_ctx (tree stmt)
1440 splay_tree_node n;
1441 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1442 return n ? (omp_context *) n->value : NULL;
1446 /* Find the mapping for DECL in CTX or the immediately enclosing
1447 context that has a mapping for DECL.
1449 If CTX is a nested parallel directive, we may have to use the decl
1450 mappings created in CTX's parent context. Suppose that we have the
1451 following parallel nesting (variable UIDs showed for clarity):
1453 iD.1562 = 0;
1454 #omp parallel shared(iD.1562) -> outer parallel
1455 iD.1562 = iD.1562 + 1;
1457 #omp parallel shared (iD.1562) -> inner parallel
1458 iD.1562 = iD.1562 - 1;
1460 Each parallel structure will create a distinct .omp_data_s structure
1461 for copying iD.1562 in/out of the directive:
1463 outer parallel .omp_data_s.1.i -> iD.1562
1464 inner parallel .omp_data_s.2.i -> iD.1562
1466 A shared variable mapping will produce a copy-out operation before
1467 the parallel directive and a copy-in operation after it. So, in
1468 this case we would have:
1470 iD.1562 = 0;
1471 .omp_data_o.1.i = iD.1562;
1472 #omp parallel shared(iD.1562) -> outer parallel
1473 .omp_data_i.1 = &.omp_data_o.1
1474 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1476 .omp_data_o.2.i = iD.1562; -> **
1477 #omp parallel shared(iD.1562) -> inner parallel
1478 .omp_data_i.2 = &.omp_data_o.2
1479 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1482 ** This is a problem. The symbol iD.1562 cannot be referenced
1483 inside the body of the outer parallel region. But since we are
1484 emitting this copy operation while expanding the inner parallel
1485 directive, we need to access the CTX structure of the outer
1486 parallel directive to get the correct mapping:
1488 .omp_data_o.2.i = .omp_data_i.1->i
1490 Since there may be other workshare or parallel directives enclosing
1491 the parallel directive, it may be necessary to walk up the context
1492 parent chain. This is not a problem in general because nested
1493 parallelism happens only rarely. */
1495 static tree
1496 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1498 tree t;
1499 omp_context *up;
1501 gcc_assert (ctx->is_nested);
1503 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1504 t = maybe_lookup_decl (decl, up);
1506 gcc_assert (t);
1508 return t;
1512 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1513 in outer contexts. */
1515 static tree
1516 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1518 tree t = NULL;
1519 omp_context *up;
1521 if (ctx->is_nested)
1522 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1523 t = maybe_lookup_decl (decl, up);
1525 return t ? t : decl;
1529 /* Construct the initialization value for reduction CLAUSE. */
1531 tree
1532 omp_reduction_init (tree clause, tree type)
1534 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1536 case PLUS_EXPR:
1537 case MINUS_EXPR:
1538 case BIT_IOR_EXPR:
1539 case BIT_XOR_EXPR:
1540 case TRUTH_OR_EXPR:
1541 case TRUTH_ORIF_EXPR:
1542 case TRUTH_XOR_EXPR:
1543 case NE_EXPR:
1544 return fold_convert (type, integer_zero_node);
1546 case MULT_EXPR:
1547 case TRUTH_AND_EXPR:
1548 case TRUTH_ANDIF_EXPR:
1549 case EQ_EXPR:
1550 return fold_convert (type, integer_one_node);
1552 case BIT_AND_EXPR:
1553 return fold_convert (type, integer_minus_one_node);
1555 case MAX_EXPR:
1556 if (SCALAR_FLOAT_TYPE_P (type))
1558 REAL_VALUE_TYPE max, min;
1559 if (HONOR_INFINITIES (TYPE_MODE (type)))
1561 real_inf (&max);
1562 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1564 else
1565 real_maxval (&min, 1, TYPE_MODE (type));
1566 return build_real (type, min);
1568 else
1570 gcc_assert (INTEGRAL_TYPE_P (type));
1571 return TYPE_MIN_VALUE (type);
1574 case MIN_EXPR:
1575 if (SCALAR_FLOAT_TYPE_P (type))
1577 REAL_VALUE_TYPE max;
1578 if (HONOR_INFINITIES (TYPE_MODE (type)))
1579 real_inf (&max);
1580 else
1581 real_maxval (&max, 0, TYPE_MODE (type));
1582 return build_real (type, max);
1584 else
1586 gcc_assert (INTEGRAL_TYPE_P (type));
1587 return TYPE_MAX_VALUE (type);
1590 default:
1591 gcc_unreachable ();
1595 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1596 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1597 private variables. Initialization statements go in ILIST, while calls
1598 to destructors go in DLIST. */
1600 static void
1601 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1602 omp_context *ctx)
1604 tree_stmt_iterator diter;
1605 tree c, dtor, copyin_seq, x, ptr;
1606 bool copyin_by_ref = false;
1607 bool lastprivate_firstprivate = false;
1608 int pass;
1610 *dlist = alloc_stmt_list ();
1611 diter = tsi_start (*dlist);
1612 copyin_seq = NULL;
1614 /* Do all the fixed sized types in the first pass, and the variable sized
1615 types in the second pass. This makes sure that the scalar arguments to
1616 the variable sized types are processed before we use them in the
1617 variable sized operations. */
1618 for (pass = 0; pass < 2; ++pass)
1620 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1622 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1623 tree var, new_var;
1624 bool by_ref;
1626 switch (c_kind)
1628 case OMP_CLAUSE_PRIVATE:
1629 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1630 continue;
1631 break;
1632 case OMP_CLAUSE_SHARED:
1633 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1635 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1636 continue;
1638 case OMP_CLAUSE_FIRSTPRIVATE:
1639 case OMP_CLAUSE_COPYIN:
1640 case OMP_CLAUSE_REDUCTION:
1641 break;
1642 case OMP_CLAUSE_LASTPRIVATE:
1643 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1645 lastprivate_firstprivate = true;
1646 if (pass != 0)
1647 continue;
1649 break;
1650 default:
1651 continue;
1654 new_var = var = OMP_CLAUSE_DECL (c);
1655 if (c_kind != OMP_CLAUSE_COPYIN)
1656 new_var = lookup_decl (var, ctx);
1658 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1660 if (pass != 0)
1661 continue;
1663 else if (is_variable_sized (var))
1665 /* For variable sized types, we need to allocate the
1666 actual storage here. Call alloca and store the
1667 result in the pointer decl that we created elsewhere. */
1668 if (pass == 0)
1669 continue;
1671 ptr = DECL_VALUE_EXPR (new_var);
1672 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1673 ptr = TREE_OPERAND (ptr, 0);
1674 gcc_assert (DECL_P (ptr));
1676 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1677 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1678 x = fold_convert (TREE_TYPE (ptr), x);
1679 x = build_gimple_modify_stmt (ptr, x);
1680 gimplify_and_add (x, ilist);
1682 else if (is_reference (var))
1684 /* For references that are being privatized for Fortran,
1685 allocate new backing storage for the new pointer
1686 variable. This allows us to avoid changing all the
1687 code that expects a pointer to something that expects
1688 a direct variable. Note that this doesn't apply to
1689 C++, since reference types are disallowed in data
1690 sharing clauses there, except for NRV optimized
1691 return values. */
1692 if (pass == 0)
1693 continue;
1695 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1696 if (TREE_CONSTANT (x))
1698 const char *name = NULL;
1699 if (DECL_NAME (var))
1700 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1702 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1703 name);
1704 gimple_add_tmp_var (x);
1705 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1707 else
1709 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1710 x = fold_convert (TREE_TYPE (new_var), x);
1713 x = build_gimple_modify_stmt (new_var, x);
1714 gimplify_and_add (x, ilist);
1716 new_var = build_fold_indirect_ref (new_var);
1718 else if (c_kind == OMP_CLAUSE_REDUCTION
1719 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1721 if (pass == 0)
1722 continue;
1724 else if (pass != 0)
1725 continue;
1727 switch (OMP_CLAUSE_CODE (c))
1729 case OMP_CLAUSE_SHARED:
1730 /* Shared global vars are just accessed directly. */
1731 if (is_global_var (new_var))
1732 break;
1733 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1734 needs to be delayed until after fixup_child_record_type so
1735 that we get the correct type during the dereference. */
1736 by_ref = use_pointer_for_field (var, true);
1737 x = build_receiver_ref (var, by_ref, ctx);
1738 SET_DECL_VALUE_EXPR (new_var, x);
1739 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1741 /* ??? If VAR is not passed by reference, and the variable
1742 hasn't been initialized yet, then we'll get a warning for
1743 the store into the omp_data_s structure. Ideally, we'd be
1744 able to notice this and not store anything at all, but
1745 we're generating code too early. Suppress the warning. */
1746 if (!by_ref)
1747 TREE_NO_WARNING (var) = 1;
1748 break;
1750 case OMP_CLAUSE_LASTPRIVATE:
1751 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1752 break;
1753 /* FALLTHRU */
1755 case OMP_CLAUSE_PRIVATE:
1756 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1757 if (x)
1758 gimplify_and_add (x, ilist);
1759 /* FALLTHRU */
1761 do_dtor:
1762 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1763 if (x)
1765 dtor = x;
1766 gimplify_stmt (&dtor);
1767 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1769 break;
1771 case OMP_CLAUSE_FIRSTPRIVATE:
1772 x = build_outer_var_ref (var, ctx);
1773 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1774 gimplify_and_add (x, ilist);
1775 goto do_dtor;
1776 break;
1778 case OMP_CLAUSE_COPYIN:
1779 by_ref = use_pointer_for_field (var, false);
1780 x = build_receiver_ref (var, by_ref, ctx);
1781 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1782 append_to_statement_list (x, &copyin_seq);
1783 copyin_by_ref |= by_ref;
1784 break;
1786 case OMP_CLAUSE_REDUCTION:
1787 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1789 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1790 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1792 else
1794 x = omp_reduction_init (c, TREE_TYPE (new_var));
1795 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1796 x = build_gimple_modify_stmt (new_var, x);
1797 gimplify_and_add (x, ilist);
1799 break;
1801 default:
1802 gcc_unreachable ();
1807 /* The copyin sequence is not to be executed by the main thread, since
1808 that would result in self-copies. Perhaps not visible to scalars,
1809 but it certainly is to C++ operator=. */
1810 if (copyin_seq)
1812 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1813 x = build2 (NE_EXPR, boolean_type_node, x,
1814 build_int_cst (TREE_TYPE (x), 0));
1815 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1816 gimplify_and_add (x, ilist);
1819 /* If any copyin variable is passed by reference, we must ensure the
1820 master thread doesn't modify it before it is copied over in all
1821 threads. Similarly for variables in both firstprivate and
1822 lastprivate clauses we need to ensure the lastprivate copying
1823 happens after firstprivate copying in all threads. */
1824 if (copyin_by_ref || lastprivate_firstprivate)
1825 build_omp_barrier (ilist);
1829 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1830 both parallel and workshare constructs. PREDICATE may be NULL if it's
1831 always true. */
1833 static void
1834 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1835 omp_context *ctx)
1837 tree sub_list, x, c;
1839 /* Early exit if there are no lastprivate clauses. */
1840 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1841 if (clauses == NULL)
1843 /* If this was a workshare clause, see if it had been combined
1844 with its parallel. In that case, look for the clauses on the
1845 parallel statement itself. */
1846 if (is_parallel_ctx (ctx))
1847 return;
1849 ctx = ctx->outer;
1850 if (ctx == NULL || !is_parallel_ctx (ctx))
1851 return;
1853 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1854 OMP_CLAUSE_LASTPRIVATE);
1855 if (clauses == NULL)
1856 return;
1859 sub_list = alloc_stmt_list ();
1861 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1863 tree var, new_var;
1865 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1866 continue;
1868 var = OMP_CLAUSE_DECL (c);
1869 new_var = lookup_decl (var, ctx);
1871 x = build_outer_var_ref (var, ctx);
1872 if (is_reference (var))
1873 new_var = build_fold_indirect_ref (new_var);
1874 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1875 append_to_statement_list (x, &sub_list);
1878 if (predicate)
1879 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1880 else
1881 x = sub_list;
1883 gimplify_and_add (x, stmt_list);
1887 /* Generate code to implement the REDUCTION clauses. */
1889 static void
1890 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1892 tree sub_list = NULL, x, c;
1893 int count = 0;
1895 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1896 update in that case, otherwise use a lock. */
1897 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1898 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1900 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1902 /* Never use OMP_ATOMIC for array reductions. */
1903 count = -1;
1904 break;
1906 count++;
1909 if (count == 0)
1910 return;
1912 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1914 tree var, ref, new_var;
1915 enum tree_code code;
1917 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1918 continue;
1920 var = OMP_CLAUSE_DECL (c);
1921 new_var = lookup_decl (var, ctx);
1922 if (is_reference (var))
1923 new_var = build_fold_indirect_ref (new_var);
1924 ref = build_outer_var_ref (var, ctx);
1925 code = OMP_CLAUSE_REDUCTION_CODE (c);
1927 /* reduction(-:var) sums up the partial results, so it acts
1928 identically to reduction(+:var). */
1929 if (code == MINUS_EXPR)
1930 code = PLUS_EXPR;
1932 if (count == 1)
1934 tree addr = build_fold_addr_expr (ref);
1936 addr = save_expr (addr);
1937 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1938 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1939 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1940 gimplify_and_add (x, stmt_list);
1941 return;
1944 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1946 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1948 if (is_reference (var))
1949 ref = build_fold_addr_expr (ref);
1950 SET_DECL_VALUE_EXPR (placeholder, ref);
1951 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1952 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1953 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1954 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1956 else
1958 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1959 ref = build_outer_var_ref (var, ctx);
1960 x = build_gimple_modify_stmt (ref, x);
1961 append_to_statement_list (x, &sub_list);
1965 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
1966 gimplify_and_add (x, stmt_list);
1968 gimplify_and_add (sub_list, stmt_list);
1970 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
1971 gimplify_and_add (x, stmt_list);
1975 /* Generate code to implement the COPYPRIVATE clauses. */
1977 static void
1978 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1979 omp_context *ctx)
1981 tree c;
1983 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1985 tree var, ref, x;
1986 bool by_ref;
1988 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1989 continue;
1991 var = OMP_CLAUSE_DECL (c);
1992 by_ref = use_pointer_for_field (var, false);
1994 ref = build_sender_ref (var, ctx);
1995 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
1996 x = by_ref ? build_fold_addr_expr (x) : x;
1997 x = build_gimple_modify_stmt (ref, x);
1998 gimplify_and_add (x, slist);
2000 ref = build_receiver_ref (var, by_ref, ctx);
2001 if (is_reference (var))
2003 ref = build_fold_indirect_ref (ref);
2004 var = build_fold_indirect_ref (var);
2006 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2007 gimplify_and_add (x, rlist);
2012 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2013 and REDUCTION from the sender (aka parent) side. */
2015 static void
2016 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2018 tree c;
2020 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2022 tree val, ref, x, var;
2023 bool by_ref, do_in = false, do_out = false;
2025 switch (OMP_CLAUSE_CODE (c))
2027 case OMP_CLAUSE_FIRSTPRIVATE:
2028 case OMP_CLAUSE_COPYIN:
2029 case OMP_CLAUSE_LASTPRIVATE:
2030 case OMP_CLAUSE_REDUCTION:
2031 break;
2032 default:
2033 continue;
2036 var = val = OMP_CLAUSE_DECL (c);
2037 if (ctx->is_nested)
2038 var = lookup_decl_in_outer_ctx (val, ctx);
2040 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2041 && is_global_var (var))
2042 continue;
2043 if (is_variable_sized (val))
2044 continue;
2045 by_ref = use_pointer_for_field (val, false);
2047 switch (OMP_CLAUSE_CODE (c))
2049 case OMP_CLAUSE_FIRSTPRIVATE:
2050 case OMP_CLAUSE_COPYIN:
2051 do_in = true;
2052 break;
2054 case OMP_CLAUSE_LASTPRIVATE:
2055 if (by_ref || is_reference (val))
2057 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2058 continue;
2059 do_in = true;
2061 else
2062 do_out = true;
2063 break;
2065 case OMP_CLAUSE_REDUCTION:
2066 do_in = true;
2067 do_out = !(by_ref || is_reference (val));
2068 break;
2070 default:
2071 gcc_unreachable ();
2074 if (do_in)
2076 ref = build_sender_ref (val, ctx);
2077 x = by_ref ? build_fold_addr_expr (var) : var;
2078 x = build_gimple_modify_stmt (ref, x);
2079 gimplify_and_add (x, ilist);
2082 if (do_out)
2084 ref = build_sender_ref (val, ctx);
2085 x = build_gimple_modify_stmt (var, ref);
2086 gimplify_and_add (x, olist);
2091 /* Generate code to implement SHARED from the sender (aka parent) side.
2092 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2093 got automatically shared. */
2095 static void
2096 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2098 tree var, ovar, nvar, f, x;
2100 if (ctx->record_type == NULL)
2101 return;
2103 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2105 ovar = DECL_ABSTRACT_ORIGIN (f);
2106 nvar = maybe_lookup_decl (ovar, ctx);
2107 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2108 continue;
2110 var = ovar;
2112 /* If CTX is a nested parallel directive. Find the immediately
2113 enclosing parallel or workshare construct that contains a
2114 mapping for OVAR. */
2115 if (ctx->is_nested)
2116 var = lookup_decl_in_outer_ctx (ovar, ctx);
2118 if (use_pointer_for_field (ovar, true))
2120 x = build_sender_ref (ovar, ctx);
2121 var = build_fold_addr_expr (var);
2122 x = build_gimple_modify_stmt (x, var);
2123 gimplify_and_add (x, ilist);
2125 else
2127 x = build_sender_ref (ovar, ctx);
2128 x = build_gimple_modify_stmt (x, var);
2129 gimplify_and_add (x, ilist);
2131 x = build_sender_ref (ovar, ctx);
2132 x = build_gimple_modify_stmt (var, x);
2133 gimplify_and_add (x, olist);
2138 /* Build the function calls to GOMP_parallel_start etc to actually
2139 generate the parallel operation. REGION is the parallel region
2140 being expanded. BB is the block where to insert the code. WS_ARGS
2141 will be set if this is a call to a combined parallel+workshare
2142 construct, it contains the list of additional arguments needed by
2143 the workshare construct. */
2145 static void
2146 expand_parallel_call (struct omp_region *region, basic_block bb,
2147 tree entry_stmt, tree ws_args)
2149 tree t, t1, t2, val, cond, c, list, clauses;
2150 block_stmt_iterator si;
2151 int start_ix;
2153 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2154 push_gimplify_context ();
2156 /* Determine what flavor of GOMP_parallel_start we will be
2157 emitting. */
2158 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2159 if (is_combined_parallel (region))
2161 switch (region->inner->type)
2163 case OMP_FOR:
2164 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2165 + region->inner->sched_kind;
2166 break;
2167 case OMP_SECTIONS:
2168 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2169 break;
2170 default:
2171 gcc_unreachable ();
2175 /* By default, the value of NUM_THREADS is zero (selected at run time)
2176 and there is no conditional. */
2177 cond = NULL_TREE;
2178 val = build_int_cst (unsigned_type_node, 0);
2180 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2181 if (c)
2182 cond = OMP_CLAUSE_IF_EXPR (c);
2184 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2185 if (c)
2186 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2188 /* Ensure 'val' is of the correct type. */
2189 val = fold_convert (unsigned_type_node, val);
2191 /* If we found the clause 'if (cond)', build either
2192 (cond != 0) or (cond ? val : 1u). */
2193 if (cond)
2195 block_stmt_iterator si;
2197 cond = gimple_boolify (cond);
2199 if (integer_zerop (val))
2200 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2201 build_int_cst (TREE_TYPE (cond), 0));
2202 else
2204 basic_block cond_bb, then_bb, else_bb;
2205 edge e;
2206 tree t, then_lab, else_lab, tmp;
2208 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2209 e = split_block (bb, NULL);
2210 cond_bb = e->src;
2211 bb = e->dest;
2212 remove_edge (e);
2214 then_bb = create_empty_bb (cond_bb);
2215 else_bb = create_empty_bb (then_bb);
2216 then_lab = create_artificial_label ();
2217 else_lab = create_artificial_label ();
2219 t = build3 (COND_EXPR, void_type_node,
2220 cond,
2221 build_and_jump (&then_lab),
2222 build_and_jump (&else_lab));
2224 si = bsi_start (cond_bb);
2225 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2227 si = bsi_start (then_bb);
2228 t = build1 (LABEL_EXPR, void_type_node, then_lab);
2229 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2230 t = build_gimple_modify_stmt (tmp, val);
2231 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2233 si = bsi_start (else_bb);
2234 t = build1 (LABEL_EXPR, void_type_node, else_lab);
2235 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2236 t = build_gimple_modify_stmt (tmp,
2237 build_int_cst (unsigned_type_node, 1));
2238 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2240 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2241 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2242 make_edge (then_bb, bb, EDGE_FALLTHRU);
2243 make_edge (else_bb, bb, EDGE_FALLTHRU);
2245 val = tmp;
2248 list = NULL_TREE;
2249 val = get_formal_tmp_var (val, &list);
2250 si = bsi_start (bb);
2251 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2254 list = NULL_TREE;
2255 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2256 if (t == NULL)
2257 t1 = null_pointer_node;
2258 else
2259 t1 = build_fold_addr_expr (t);
2260 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2262 if (ws_args)
2264 tree args = tree_cons (NULL, t2,
2265 tree_cons (NULL, t1,
2266 tree_cons (NULL, val, ws_args)));
2267 t = build_function_call_expr (built_in_decls[start_ix], args);
2269 else
2270 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2272 gimplify_and_add (t, &list);
2274 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2275 if (t == NULL)
2276 t = null_pointer_node;
2277 else
2278 t = build_fold_addr_expr (t);
2279 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2280 gimplify_and_add (t, &list);
2282 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2283 gimplify_and_add (t, &list);
2285 si = bsi_last (bb);
2286 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2288 pop_gimplify_context (NULL_TREE);
2292 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2293 handler. This prevents programs from violating the structured
2294 block semantics with throws. */
2296 static void
2297 maybe_catch_exception (tree *stmt_p)
2299 tree f, t;
2301 if (!flag_exceptions)
2302 return;
2304 if (lang_protect_cleanup_actions)
2305 t = lang_protect_cleanup_actions ();
2306 else
2307 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2308 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2309 EH_FILTER_MUST_NOT_THROW (f) = 1;
2310 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2312 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2313 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2315 *stmt_p = NULL;
2316 append_to_statement_list (t, stmt_p);
2319 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2321 static tree
2322 list2chain (tree list)
2324 tree t;
2326 for (t = list; t; t = TREE_CHAIN (t))
2328 tree var = TREE_VALUE (t);
2329 if (TREE_CHAIN (t))
2330 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2331 else
2332 TREE_CHAIN (var) = NULL_TREE;
2335 return list ? TREE_VALUE (list) : NULL_TREE;
2339 /* Remove barriers in REGION->EXIT's block. Note that this is only
2340 valid for OMP_PARALLEL regions. Since the end of a parallel region
2341 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2342 left a barrier at the end of the OMP_PARALLEL region can now be
2343 removed. */
2345 static void
2346 remove_exit_barrier (struct omp_region *region)
2348 block_stmt_iterator si;
2349 basic_block exit_bb;
2350 edge_iterator ei;
2351 edge e;
2352 tree t;
2354 exit_bb = region->exit;
2356 /* If the parallel region doesn't return, we don't have REGION->EXIT
2357 block at all. */
2358 if (! exit_bb)
2359 return;
2361 /* The last insn in the block will be the parallel's OMP_RETURN. The
2362 workshare's OMP_RETURN will be in a preceding block. The kinds of
2363 statements that can appear in between are extremely limited -- no
2364 memory operations at all. Here, we allow nothing at all, so the
2365 only thing we allow to precede this OMP_RETURN is a label. */
2366 si = bsi_last (exit_bb);
2367 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2368 bsi_prev (&si);
2369 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2370 return;
2372 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2374 si = bsi_last (e->src);
2375 if (bsi_end_p (si))
2376 continue;
2377 t = bsi_stmt (si);
2378 if (TREE_CODE (t) == OMP_RETURN)
2379 OMP_RETURN_NOWAIT (t) = 1;
2383 static void
2384 remove_exit_barriers (struct omp_region *region)
2386 if (region->type == OMP_PARALLEL)
2387 remove_exit_barrier (region);
2389 if (region->inner)
2391 region = region->inner;
2392 remove_exit_barriers (region);
2393 while (region->next)
2395 region = region->next;
2396 remove_exit_barriers (region);
2401 /* Expand the OpenMP parallel directive starting at REGION. */
2403 static void
2404 expand_omp_parallel (struct omp_region *region)
2406 basic_block entry_bb, exit_bb, new_bb;
2407 struct function *child_cfun, *saved_cfun;
2408 tree child_fn, block, t, ws_args;
2409 block_stmt_iterator si;
2410 tree entry_stmt;
2411 edge e;
2413 entry_stmt = last_stmt (region->entry);
2414 child_fn = OMP_PARALLEL_FN (entry_stmt);
2415 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2416 saved_cfun = cfun;
2418 entry_bb = region->entry;
2419 exit_bb = region->exit;
2421 if (is_combined_parallel (region))
2422 ws_args = region->ws_args;
2423 else
2424 ws_args = NULL_TREE;
2426 if (child_cfun->cfg)
2428 /* Due to inlining, it may happen that we have already outlined
2429 the region, in which case all we need to do is make the
2430 sub-graph unreachable and emit the parallel call. */
2431 edge entry_succ_e, exit_succ_e;
2432 block_stmt_iterator si;
2434 entry_succ_e = single_succ_edge (entry_bb);
2436 si = bsi_last (entry_bb);
2437 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2438 bsi_remove (&si, true);
2440 new_bb = entry_bb;
2441 remove_edge (entry_succ_e);
2442 if (exit_bb)
2444 exit_succ_e = single_succ_edge (exit_bb);
2445 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2448 else
2450 /* If the parallel region needs data sent from the parent
2451 function, then the very first statement (except possible
2452 tree profile counter updates) of the parallel body
2453 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2454 &.OMP_DATA_O is passed as an argument to the child function,
2455 we need to replace it with the argument as seen by the child
2456 function.
2458 In most cases, this will end up being the identity assignment
2459 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2460 a function call that has been inlined, the original PARM_DECL
2461 .OMP_DATA_I may have been converted into a different local
2462 variable. In which case, we need to keep the assignment. */
2463 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2465 basic_block entry_succ_bb = single_succ (entry_bb);
2466 block_stmt_iterator si;
2468 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2470 tree stmt, arg;
2472 gcc_assert (!bsi_end_p (si));
2473 stmt = bsi_stmt (si);
2474 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2475 continue;
2477 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2478 STRIP_NOPS (arg);
2479 if (TREE_CODE (arg) == ADDR_EXPR
2480 && TREE_OPERAND (arg, 0)
2481 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2483 if (GIMPLE_STMT_OPERAND (stmt, 0)
2484 == DECL_ARGUMENTS (child_fn))
2485 bsi_remove (&si, true);
2486 else
2487 GIMPLE_STMT_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2488 break;
2493 /* Declare local variables needed in CHILD_CFUN. */
2494 block = DECL_INITIAL (child_fn);
2495 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2496 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
2498 /* Reset DECL_CONTEXT on locals and function arguments. */
2499 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2500 DECL_CONTEXT (t) = child_fn;
2502 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2503 DECL_CONTEXT (t) = child_fn;
2505 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2506 child function. */
2507 si = bsi_last (entry_bb);
2508 t = bsi_stmt (si);
2509 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2510 bsi_remove (&si, true);
2511 e = split_block (entry_bb, t);
2512 entry_bb = e->dest;
2513 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2515 /* Move the parallel region into CHILD_CFUN. We need to reset
2516 dominance information because the expansion of the inner
2517 regions has invalidated it. */
2518 free_dominance_info (CDI_DOMINATORS);
2519 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2520 if (exit_bb)
2521 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2522 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2523 = cfun->curr_properties;
2524 cgraph_add_new_function (child_fn, true);
2526 /* Convert OMP_RETURN into a RETURN_EXPR. */
2527 if (exit_bb)
2529 si = bsi_last (exit_bb);
2530 gcc_assert (!bsi_end_p (si)
2531 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2532 t = build1 (RETURN_EXPR, void_type_node, NULL);
2533 bsi_insert_after (&si, t, BSI_SAME_STMT);
2534 bsi_remove (&si, true);
2538 /* Emit a library call to launch the children threads. */
2539 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2543 /* A subroutine of expand_omp_for. Generate code for a parallel
2544 loop with any schedule. Given parameters:
2546 for (V = N1; V cond N2; V += STEP) BODY;
2548 where COND is "<" or ">", we generate pseudocode
2550 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2551 if (more) goto L0; else goto L3;
2553 V = istart0;
2554 iend = iend0;
2556 BODY;
2557 V += STEP;
2558 if (V cond iend) goto L1; else goto L2;
2560 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2563 If this is a combined omp parallel loop, instead of the call to
2564 GOMP_loop_foo_start, we emit 'goto L3'. */
2566 static void
2567 expand_omp_for_generic (struct omp_region *region,
2568 struct omp_for_data *fd,
2569 enum built_in_function start_fn,
2570 enum built_in_function next_fn)
2572 tree l0, l1, l2 = NULL, l3 = NULL;
2573 tree type, istart0, iend0, iend;
2574 tree t, list;
2575 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2576 basic_block l2_bb = NULL, l3_bb = NULL;
2577 block_stmt_iterator si;
2578 bool in_combined_parallel = is_combined_parallel (region);
2580 type = TREE_TYPE (fd->v);
2582 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2583 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2584 iend = create_tmp_var (type, NULL);
2585 TREE_ADDRESSABLE (istart0) = 1;
2586 TREE_ADDRESSABLE (iend0) = 1;
2588 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
2590 entry_bb = region->entry;
2591 l0_bb = create_empty_bb (entry_bb);
2592 l1_bb = single_succ (entry_bb);
2594 l0 = tree_block_label (l0_bb);
2595 l1 = tree_block_label (l1_bb);
2597 cont_bb = region->cont;
2598 exit_bb = region->exit;
2599 if (cont_bb)
2601 l2_bb = create_empty_bb (cont_bb);
2602 l3_bb = single_succ (cont_bb);
2604 l2 = tree_block_label (l2_bb);
2605 l3 = tree_block_label (l3_bb);
2608 si = bsi_last (entry_bb);
2609 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2610 if (!in_combined_parallel)
2612 tree t0, t1, t2, t3, t4;
2613 /* If this is not a combined parallel loop, emit a call to
2614 GOMP_loop_foo_start in ENTRY_BB. */
2615 list = alloc_stmt_list ();
2616 t4 = build_fold_addr_expr (iend0);
2617 t3 = build_fold_addr_expr (istart0);
2618 t2 = fold_convert (long_integer_type_node, fd->step);
2619 t1 = fold_convert (long_integer_type_node, fd->n2);
2620 t0 = fold_convert (long_integer_type_node, fd->n1);
2621 if (fd->chunk_size)
2623 t = fold_convert (long_integer_type_node, fd->chunk_size);
2624 t = build_call_expr (built_in_decls[start_fn], 6,
2625 t0, t1, t2, t, t3, t4);
2627 else
2628 t = build_call_expr (built_in_decls[start_fn], 5,
2629 t0, t1, t2, t3, t4);
2630 t = get_formal_tmp_var (t, &list);
2631 if (cont_bb)
2633 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2634 build_and_jump (&l3));
2635 append_to_statement_list (t, &list);
2637 bsi_insert_after (&si, list, BSI_SAME_STMT);
2639 bsi_remove (&si, true);
2641 /* Iteration setup for sequential loop goes in L0_BB. */
2642 list = alloc_stmt_list ();
2643 t = fold_convert (type, istart0);
2644 t = build_gimple_modify_stmt (fd->v, t);
2645 gimplify_and_add (t, &list);
2647 t = fold_convert (type, iend0);
2648 t = build_gimple_modify_stmt (iend, t);
2649 gimplify_and_add (t, &list);
2651 si = bsi_start (l0_bb);
2652 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2654 /* Handle the rare case where BODY doesn't ever return. */
2655 if (cont_bb == NULL)
2657 remove_edge (single_succ_edge (entry_bb));
2658 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
2659 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2660 return;
2663 /* Code to control the increment and predicate for the sequential
2664 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2665 that we can inherit all the edges going out of the loop
2666 body). */
2667 list = alloc_stmt_list ();
2669 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2670 t = build_gimple_modify_stmt (fd->v, t);
2671 gimplify_and_add (t, &list);
2673 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2674 t = get_formal_tmp_var (t, &list);
2675 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2676 build_and_jump (&l2));
2677 append_to_statement_list (t, &list);
2679 si = bsi_last (cont_bb);
2680 bsi_insert_after (&si, list, BSI_SAME_STMT);
2681 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2682 bsi_remove (&si, true);
2684 /* Emit code to get the next parallel iteration in L2_BB. */
2685 list = alloc_stmt_list ();
2687 t = build_call_expr (built_in_decls[next_fn], 2,
2688 build_fold_addr_expr (istart0),
2689 build_fold_addr_expr (iend0));
2690 t = get_formal_tmp_var (t, &list);
2691 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2692 build_and_jump (&l3));
2693 append_to_statement_list (t, &list);
2695 si = bsi_start (l2_bb);
2696 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2698 /* Add the loop cleanup function. */
2699 si = bsi_last (exit_bb);
2700 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2701 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2702 else
2703 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2704 t = build_call_expr (t, 0);
2705 bsi_insert_after (&si, t, BSI_SAME_STMT);
2706 bsi_remove (&si, true);
2708 /* Connect the new blocks. */
2709 remove_edge (single_succ_edge (entry_bb));
2710 if (in_combined_parallel)
2711 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2712 else
2714 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2715 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2718 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2720 remove_edge (single_succ_edge (cont_bb));
2721 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2722 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2724 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2725 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2729 /* A subroutine of expand_omp_for. Generate code for a parallel
2730 loop with static schedule and no specified chunk size. Given
2731 parameters:
2733 for (V = N1; V cond N2; V += STEP) BODY;
2735 where COND is "<" or ">", we generate pseudocode
2737 if (cond is <)
2738 adj = STEP - 1;
2739 else
2740 adj = STEP + 1;
2741 n = (adj + N2 - N1) / STEP;
2742 q = n / nthreads;
2743 q += (q * nthreads != n);
2744 s0 = q * threadid;
2745 e0 = min(s0 + q, n);
2746 if (s0 >= e0) goto L2; else goto L0;
2748 V = s0 * STEP + N1;
2749 e = e0 * STEP + N1;
2751 BODY;
2752 V += STEP;
2753 if (V cond e) goto L1;
2757 static void
2758 expand_omp_for_static_nochunk (struct omp_region *region,
2759 struct omp_for_data *fd)
2761 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
2762 tree type, list;
2763 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2764 basic_block fin_bb;
2765 block_stmt_iterator si;
2767 type = TREE_TYPE (fd->v);
2769 entry_bb = region->entry;
2770 seq_start_bb = create_empty_bb (entry_bb);
2771 body_bb = single_succ (entry_bb);
2772 cont_bb = region->cont;
2773 fin_bb = single_succ (cont_bb);
2774 exit_bb = region->exit;
2776 l0 = tree_block_label (seq_start_bb);
2777 l1 = tree_block_label (body_bb);
2778 l2 = tree_block_label (fin_bb);
2780 /* Iteration space partitioning goes in ENTRY_BB. */
2781 list = alloc_stmt_list ();
2783 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2784 t = fold_convert (type, t);
2785 nthreads = get_formal_tmp_var (t, &list);
2787 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2788 t = fold_convert (type, t);
2789 threadid = get_formal_tmp_var (t, &list);
2791 fd->n1 = fold_convert (type, fd->n1);
2792 if (!is_gimple_val (fd->n1))
2793 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2795 fd->n2 = fold_convert (type, fd->n2);
2796 if (!is_gimple_val (fd->n2))
2797 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2799 fd->step = fold_convert (type, fd->step);
2800 if (!is_gimple_val (fd->step))
2801 fd->step = get_formal_tmp_var (fd->step, &list);
2803 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2804 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2805 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2806 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2807 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2808 t = fold_convert (type, t);
2809 if (is_gimple_val (t))
2810 n = t;
2811 else
2812 n = get_formal_tmp_var (t, &list);
2814 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2815 q = get_formal_tmp_var (t, &list);
2817 t = build2 (MULT_EXPR, type, q, nthreads);
2818 t = build2 (NE_EXPR, type, t, n);
2819 t = build2 (PLUS_EXPR, type, q, t);
2820 q = get_formal_tmp_var (t, &list);
2822 t = build2 (MULT_EXPR, type, q, threadid);
2823 s0 = get_formal_tmp_var (t, &list);
2825 t = build2 (PLUS_EXPR, type, s0, q);
2826 t = build2 (MIN_EXPR, type, t, n);
2827 e0 = get_formal_tmp_var (t, &list);
2829 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2830 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
2831 build_and_jump (&l0));
2832 append_to_statement_list (t, &list);
2834 si = bsi_last (entry_bb);
2835 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2836 bsi_insert_after (&si, list, BSI_SAME_STMT);
2837 bsi_remove (&si, true);
2839 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2840 list = alloc_stmt_list ();
2842 t = fold_convert (type, s0);
2843 t = build2 (MULT_EXPR, type, t, fd->step);
2844 t = build2 (PLUS_EXPR, type, t, fd->n1);
2845 t = build_gimple_modify_stmt (fd->v, t);
2846 gimplify_and_add (t, &list);
2848 t = fold_convert (type, e0);
2849 t = build2 (MULT_EXPR, type, t, fd->step);
2850 t = build2 (PLUS_EXPR, type, t, fd->n1);
2851 e = get_formal_tmp_var (t, &list);
2853 si = bsi_start (seq_start_bb);
2854 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2856 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2857 list = alloc_stmt_list ();
2859 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2860 t = build_gimple_modify_stmt (fd->v, t);
2861 gimplify_and_add (t, &list);
2863 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2864 t = get_formal_tmp_var (t, &list);
2865 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2866 build_and_jump (&l2));
2867 append_to_statement_list (t, &list);
2869 si = bsi_last (cont_bb);
2870 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2871 bsi_insert_after (&si, list, BSI_SAME_STMT);
2872 bsi_remove (&si, true);
2874 /* Replace the OMP_RETURN with a barrier, or nothing. */
2875 si = bsi_last (exit_bb);
2876 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2878 list = alloc_stmt_list ();
2879 build_omp_barrier (&list);
2880 bsi_insert_after (&si, list, BSI_SAME_STMT);
2882 bsi_remove (&si, true);
2884 /* Connect all the blocks. */
2885 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2887 remove_edge (single_succ_edge (entry_bb));
2888 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2889 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2891 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2892 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2896 /* A subroutine of expand_omp_for. Generate code for a parallel
2897 loop with static schedule and a specified chunk size. Given
2898 parameters:
2900 for (V = N1; V cond N2; V += STEP) BODY;
2902 where COND is "<" or ">", we generate pseudocode
2904 if (cond is <)
2905 adj = STEP - 1;
2906 else
2907 adj = STEP + 1;
2908 n = (adj + N2 - N1) / STEP;
2909 trip = 0;
2911 s0 = (trip * nthreads + threadid) * CHUNK;
2912 e0 = min(s0 + CHUNK, n);
2913 if (s0 < n) goto L1; else goto L4;
2915 V = s0 * STEP + N1;
2916 e = e0 * STEP + N1;
2918 BODY;
2919 V += STEP;
2920 if (V cond e) goto L2; else goto L3;
2922 trip += 1;
2923 goto L0;
2927 static void
2928 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2930 tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
2931 tree trip, nthreads, threadid;
2932 tree type;
2933 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2934 basic_block trip_update_bb, cont_bb, fin_bb;
2935 tree list;
2936 block_stmt_iterator si;
2938 type = TREE_TYPE (fd->v);
2940 entry_bb = region->entry;
2941 iter_part_bb = create_empty_bb (entry_bb);
2942 seq_start_bb = create_empty_bb (iter_part_bb);
2943 body_bb = single_succ (entry_bb);
2944 cont_bb = region->cont;
2945 trip_update_bb = create_empty_bb (cont_bb);
2946 fin_bb = single_succ (cont_bb);
2947 exit_bb = region->exit;
2949 l0 = tree_block_label (iter_part_bb);
2950 l1 = tree_block_label (seq_start_bb);
2951 l2 = tree_block_label (body_bb);
2952 l3 = tree_block_label (trip_update_bb);
2953 l4 = tree_block_label (fin_bb);
2955 /* Trip and adjustment setup goes in ENTRY_BB. */
2956 list = alloc_stmt_list ();
2958 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2959 t = fold_convert (type, t);
2960 nthreads = get_formal_tmp_var (t, &list);
2962 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2963 t = fold_convert (type, t);
2964 threadid = get_formal_tmp_var (t, &list);
2966 fd->n1 = fold_convert (type, fd->n1);
2967 if (!is_gimple_val (fd->n1))
2968 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2970 fd->n2 = fold_convert (type, fd->n2);
2971 if (!is_gimple_val (fd->n2))
2972 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2974 fd->step = fold_convert (type, fd->step);
2975 if (!is_gimple_val (fd->step))
2976 fd->step = get_formal_tmp_var (fd->step, &list);
2978 fd->chunk_size = fold_convert (type, fd->chunk_size);
2979 if (!is_gimple_val (fd->chunk_size))
2980 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2982 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2983 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2984 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2985 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2986 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2987 t = fold_convert (type, t);
2988 if (is_gimple_val (t))
2989 n = t;
2990 else
2991 n = get_formal_tmp_var (t, &list);
2993 t = build_int_cst (type, 0);
2994 trip = get_initialized_tmp_var (t, &list, NULL);
2996 si = bsi_last (entry_bb);
2997 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2998 bsi_insert_after (&si, list, BSI_SAME_STMT);
2999 bsi_remove (&si, true);
3001 /* Iteration space partitioning goes in ITER_PART_BB. */
3002 list = alloc_stmt_list ();
3004 t = build2 (MULT_EXPR, type, trip, nthreads);
3005 t = build2 (PLUS_EXPR, type, t, threadid);
3006 t = build2 (MULT_EXPR, type, t, fd->chunk_size);
3007 s0 = get_formal_tmp_var (t, &list);
3009 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3010 t = build2 (MIN_EXPR, type, t, n);
3011 e0 = get_formal_tmp_var (t, &list);
3013 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3014 t = build3 (COND_EXPR, void_type_node, t,
3015 build_and_jump (&l1), build_and_jump (&l4));
3016 append_to_statement_list (t, &list);
3018 si = bsi_start (iter_part_bb);
3019 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3021 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3022 list = alloc_stmt_list ();
3024 t = fold_convert (type, s0);
3025 t = build2 (MULT_EXPR, type, t, fd->step);
3026 t = build2 (PLUS_EXPR, type, t, fd->n1);
3027 t = build_gimple_modify_stmt (fd->v, t);
3028 gimplify_and_add (t, &list);
3030 t = fold_convert (type, e0);
3031 t = build2 (MULT_EXPR, type, t, fd->step);
3032 t = build2 (PLUS_EXPR, type, t, fd->n1);
3033 e = get_formal_tmp_var (t, &list);
3035 si = bsi_start (seq_start_bb);
3036 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3038 /* The code controlling the sequential loop goes in CONT_BB,
3039 replacing the OMP_CONTINUE. */
3040 list = alloc_stmt_list ();
3042 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3043 t = build_gimple_modify_stmt (fd->v, t);
3044 gimplify_and_add (t, &list);
3046 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3047 t = get_formal_tmp_var (t, &list);
3048 t = build3 (COND_EXPR, void_type_node, t,
3049 build_and_jump (&l2), build_and_jump (&l3));
3050 append_to_statement_list (t, &list);
3052 si = bsi_last (cont_bb);
3053 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3054 bsi_insert_after (&si, list, BSI_SAME_STMT);
3055 bsi_remove (&si, true);
3057 /* Trip update code goes into TRIP_UPDATE_BB. */
3058 list = alloc_stmt_list ();
3060 t = build_int_cst (type, 1);
3061 t = build2 (PLUS_EXPR, type, trip, t);
3062 t = build_gimple_modify_stmt (trip, t);
3063 gimplify_and_add (t, &list);
3065 si = bsi_start (trip_update_bb);
3066 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3068 /* Replace the OMP_RETURN with a barrier, or nothing. */
3069 si = bsi_last (exit_bb);
3070 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3072 list = alloc_stmt_list ();
3073 build_omp_barrier (&list);
3074 bsi_insert_after (&si, list, BSI_SAME_STMT);
3076 bsi_remove (&si, true);
3078 /* Connect the new blocks. */
3079 remove_edge (single_succ_edge (entry_bb));
3080 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3082 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3083 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3085 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3087 remove_edge (single_succ_edge (cont_bb));
3088 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3089 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3091 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3095 /* Expand the OpenMP loop defined by REGION. */
3097 static void
3098 expand_omp_for (struct omp_region *region)
3100 struct omp_for_data fd;
3102 push_gimplify_context ();
3104 extract_omp_for_data (last_stmt (region->entry), &fd);
3105 region->sched_kind = fd.sched_kind;
3107 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3108 && !fd.have_ordered
3109 && region->cont
3110 && region->exit)
3112 if (fd.chunk_size == NULL)
3113 expand_omp_for_static_nochunk (region, &fd);
3114 else
3115 expand_omp_for_static_chunk (region, &fd);
3117 else
3119 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3120 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3121 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3122 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3125 pop_gimplify_context (NULL);
3129 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3131 v = GOMP_sections_start (n);
3133 switch (v)
3135 case 0:
3136 goto L2;
3137 case 1:
3138 section 1;
3139 goto L1;
3140 case 2:
3142 case n:
3144 default:
3145 abort ();
3148 v = GOMP_sections_next ();
3149 goto L0;
3151 reduction;
3153 If this is a combined parallel sections, replace the call to
3154 GOMP_sections_start with 'goto L1'. */
3156 static void
3157 expand_omp_sections (struct omp_region *region)
3159 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3160 unsigned i, len;
3161 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3162 block_stmt_iterator si;
3163 struct omp_region *inner;
3164 edge e;
3166 entry_bb = region->entry;
3167 l0_bb = create_empty_bb (entry_bb);
3168 l0 = tree_block_label (l0_bb);
3170 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
3171 l1_bb = region->cont;
3172 if (l1_bb)
3174 l2_bb = single_succ (l1_bb);
3175 default_bb = create_empty_bb (l1_bb->prev_bb);
3177 l1 = tree_block_label (l1_bb);
3179 else
3181 l2_bb = create_empty_bb (l0_bb);
3182 default_bb = l2_bb;
3184 l1 = NULL;
3186 l2 = tree_block_label (l2_bb);
3188 exit_bb = region->exit;
3190 v = create_tmp_var (unsigned_type_node, ".section");
3192 /* We will build a switch() with enough cases for all the
3193 OMP_SECTION regions, a '0' case to handle the end of more work
3194 and a default case to abort if something goes wrong. */
3195 len = EDGE_COUNT (entry_bb->succs);
3196 label_vec = make_tree_vec (len + 2);
3198 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3199 OMP_SECTIONS statement. */
3200 si = bsi_last (entry_bb);
3201 sections_stmt = bsi_stmt (si);
3202 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3203 if (!is_combined_parallel (region))
3205 /* If we are not inside a combined parallel+sections region,
3206 call GOMP_sections_start. */
3207 t = build_int_cst (unsigned_type_node, len);
3208 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3209 t = build_call_expr (u, 1, t);
3210 t = build_gimple_modify_stmt (v, t);
3211 bsi_insert_after (&si, t, BSI_SAME_STMT);
3213 bsi_remove (&si, true);
3215 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
3216 si = bsi_start (l0_bb);
3218 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3219 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3221 t = build3 (CASE_LABEL_EXPR, void_type_node,
3222 build_int_cst (unsigned_type_node, 0), NULL, l2);
3223 TREE_VEC_ELT (label_vec, 0) = t;
3224 make_edge (l0_bb, l2_bb, 0);
3226 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3227 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3229 basic_block s_entry_bb, s_exit_bb;
3231 s_entry_bb = inner->entry;
3232 s_exit_bb = inner->exit;
3234 t = tree_block_label (s_entry_bb);
3235 u = build_int_cst (unsigned_type_node, i);
3236 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3237 TREE_VEC_ELT (label_vec, i) = u;
3239 si = bsi_last (s_entry_bb);
3240 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3241 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3242 bsi_remove (&si, true);
3244 e = single_pred_edge (s_entry_bb);
3245 e->flags = 0;
3246 redirect_edge_pred (e, l0_bb);
3248 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3250 if (s_exit_bb == NULL)
3251 continue;
3253 si = bsi_last (s_exit_bb);
3254 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3255 bsi_remove (&si, true);
3257 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3260 /* Error handling code goes in DEFAULT_BB. */
3261 t = tree_block_label (default_bb);
3262 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3263 TREE_VEC_ELT (label_vec, len + 1) = u;
3264 make_edge (l0_bb, default_bb, 0);
3266 si = bsi_start (default_bb);
3267 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3268 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3270 /* Code to get the next section goes in L1_BB. */
3271 if (l1_bb)
3273 si = bsi_last (l1_bb);
3274 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3276 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3277 t = build_gimple_modify_stmt (v, t);
3278 bsi_insert_after (&si, t, BSI_SAME_STMT);
3279 bsi_remove (&si, true);
3282 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3283 if (exit_bb)
3285 si = bsi_last (exit_bb);
3286 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3287 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3288 else
3289 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3290 t = build_call_expr (t, 0);
3291 bsi_insert_after (&si, t, BSI_SAME_STMT);
3292 bsi_remove (&si, true);
3295 /* Connect the new blocks. */
3296 if (is_combined_parallel (region))
3298 /* If this was a combined parallel+sections region, we did not
3299 emit a GOMP_sections_start in the entry block, so we just
3300 need to jump to L1_BB to get the next section. */
3301 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3303 else
3304 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3306 if (l1_bb)
3308 e = single_succ_edge (l1_bb);
3309 redirect_edge_succ (e, l0_bb);
3310 e->flags = EDGE_FALLTHRU;
3315 /* Expand code for an OpenMP single directive. We've already expanded
3316 much of the code, here we simply place the GOMP_barrier call. */
3318 static void
3319 expand_omp_single (struct omp_region *region)
3321 basic_block entry_bb, exit_bb;
3322 block_stmt_iterator si;
3323 bool need_barrier = false;
3325 entry_bb = region->entry;
3326 exit_bb = region->exit;
3328 si = bsi_last (entry_bb);
3329 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3330 be removed. We need to ensure that the thread that entered the single
3331 does not exit before the data is copied out by the other threads. */
3332 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3333 OMP_CLAUSE_COPYPRIVATE))
3334 need_barrier = true;
3335 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3336 bsi_remove (&si, true);
3337 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3339 si = bsi_last (exit_bb);
3340 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3342 tree t = alloc_stmt_list ();
3343 build_omp_barrier (&t);
3344 bsi_insert_after (&si, t, BSI_SAME_STMT);
3346 bsi_remove (&si, true);
3347 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3351 /* Generic expansion for OpenMP synchronization directives: master,
3352 ordered and critical. All we need to do here is remove the entry
3353 and exit markers for REGION. */
3355 static void
3356 expand_omp_synch (struct omp_region *region)
3358 basic_block entry_bb, exit_bb;
3359 block_stmt_iterator si;
3361 entry_bb = region->entry;
3362 exit_bb = region->exit;
3364 si = bsi_last (entry_bb);
3365 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3366 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3367 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3368 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3369 bsi_remove (&si, true);
3370 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3372 if (exit_bb)
3374 si = bsi_last (exit_bb);
3375 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3376 bsi_remove (&si, true);
3377 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3382 /* Expand the parallel region tree rooted at REGION. Expansion
3383 proceeds in depth-first order. Innermost regions are expanded
3384 first. This way, parallel regions that require a new function to
3385 be created (e.g., OMP_PARALLEL) can be expanded without having any
3386 internal dependencies in their body. */
3388 static void
3389 expand_omp (struct omp_region *region)
3391 while (region)
3393 if (region->inner)
3394 expand_omp (region->inner);
3396 switch (region->type)
3398 case OMP_PARALLEL:
3399 expand_omp_parallel (region);
3400 break;
3402 case OMP_FOR:
3403 expand_omp_for (region);
3404 break;
3406 case OMP_SECTIONS:
3407 expand_omp_sections (region);
3408 break;
3410 case OMP_SECTION:
3411 /* Individual omp sections are handled together with their
3412 parent OMP_SECTIONS region. */
3413 break;
3415 case OMP_SINGLE:
3416 expand_omp_single (region);
3417 break;
3419 case OMP_MASTER:
3420 case OMP_ORDERED:
3421 case OMP_CRITICAL:
3422 expand_omp_synch (region);
3423 break;
3425 default:
3426 gcc_unreachable ();
3429 region = region->next;
3434 /* Helper for build_omp_regions. Scan the dominator tree starting at
3435 block BB. PARENT is the region that contains BB. */
3437 static void
3438 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3440 block_stmt_iterator si;
3441 tree stmt;
3442 basic_block son;
3444 si = bsi_last (bb);
3445 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3447 struct omp_region *region;
3448 enum tree_code code;
3450 stmt = bsi_stmt (si);
3451 code = TREE_CODE (stmt);
3453 if (code == OMP_RETURN)
3455 /* STMT is the return point out of region PARENT. Mark it
3456 as the exit point and make PARENT the immediately
3457 enclosing region. */
3458 gcc_assert (parent);
3459 region = parent;
3460 region->exit = bb;
3461 parent = parent->outer;
3463 /* If REGION is a parallel region, determine whether it is
3464 a combined parallel+workshare region. */
3465 if (region->type == OMP_PARALLEL)
3466 determine_parallel_type (region);
3468 else if (code == OMP_CONTINUE)
3470 gcc_assert (parent);
3471 parent->cont = bb;
3473 else
3475 /* Otherwise, this directive becomes the parent for a new
3476 region. */
3477 region = new_omp_region (bb, code, parent);
3478 parent = region;
3482 for (son = first_dom_son (CDI_DOMINATORS, bb);
3483 son;
3484 son = next_dom_son (CDI_DOMINATORS, son))
3485 build_omp_regions_1 (son, parent);
3489 /* Scan the CFG and build a tree of OMP regions. Return the root of
3490 the OMP region tree. */
3492 static void
3493 build_omp_regions (void)
3495 gcc_assert (root_omp_region == NULL);
3496 calculate_dominance_info (CDI_DOMINATORS);
3497 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3501 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3503 static unsigned int
3504 execute_expand_omp (void)
3506 build_omp_regions ();
3508 if (!root_omp_region)
3509 return 0;
3511 if (dump_file)
3513 fprintf (dump_file, "\nOMP region tree\n\n");
3514 dump_omp_region (dump_file, root_omp_region, 0);
3515 fprintf (dump_file, "\n");
3518 remove_exit_barriers (root_omp_region);
3520 expand_omp (root_omp_region);
3522 free_dominance_info (CDI_DOMINATORS);
3523 free_dominance_info (CDI_POST_DOMINATORS);
3524 cleanup_tree_cfg ();
3526 free_omp_regions ();
3528 return 0;
3531 static bool
3532 gate_expand_omp (void)
3534 return flag_openmp != 0 && errorcount == 0;
3537 struct tree_opt_pass pass_expand_omp =
3539 "ompexp", /* name */
3540 gate_expand_omp, /* gate */
3541 execute_expand_omp, /* execute */
3542 NULL, /* sub */
3543 NULL, /* next */
3544 0, /* static_pass_number */
3545 0, /* tv_id */
3546 PROP_gimple_any, /* properties_required */
3547 PROP_gimple_lomp, /* properties_provided */
3548 0, /* properties_destroyed */
3549 0, /* todo_flags_start */
3550 TODO_dump_func, /* todo_flags_finish */
3551 0 /* letter */
3554 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3556 /* Lower the OpenMP sections directive in *STMT_P. */
3558 static void
3559 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3561 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3562 tree t, dlist;
3563 tree_stmt_iterator tsi;
3564 unsigned i, len;
3566 stmt = *stmt_p;
3568 push_gimplify_context ();
3570 dlist = NULL;
3571 ilist = NULL;
3572 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3574 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3575 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3576 continue;
3578 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3579 body = alloc_stmt_list ();
3580 for (i = 0; i < len; i++, tsi_next (&tsi))
3582 omp_context *sctx;
3583 tree sec_start, sec_end;
3585 sec_start = tsi_stmt (tsi);
3586 sctx = maybe_lookup_ctx (sec_start);
3587 gcc_assert (sctx);
3589 append_to_statement_list (sec_start, &body);
3591 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3592 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3593 OMP_SECTION_BODY (sec_start) = NULL;
3595 if (i == len - 1)
3597 tree l = alloc_stmt_list ();
3598 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3599 &l, ctx);
3600 append_to_statement_list (l, &body);
3601 OMP_SECTION_LAST (sec_start) = 1;
3604 sec_end = make_node (OMP_RETURN);
3605 append_to_statement_list (sec_end, &body);
3608 block = make_node (BLOCK);
3609 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3611 olist = NULL_TREE;
3612 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3614 pop_gimplify_context (NULL_TREE);
3615 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3617 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3618 TREE_SIDE_EFFECTS (new_stmt) = 1;
3620 new_body = alloc_stmt_list ();
3621 append_to_statement_list (ilist, &new_body);
3622 append_to_statement_list (stmt, &new_body);
3623 append_to_statement_list (bind, &new_body);
3625 t = make_node (OMP_CONTINUE);
3626 append_to_statement_list (t, &new_body);
3628 append_to_statement_list (olist, &new_body);
3629 append_to_statement_list (dlist, &new_body);
3631 maybe_catch_exception (&new_body);
3633 t = make_node (OMP_RETURN);
3634 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3635 OMP_CLAUSE_NOWAIT);
3636 append_to_statement_list (t, &new_body);
3638 BIND_EXPR_BODY (new_stmt) = new_body;
3639 OMP_SECTIONS_BODY (stmt) = NULL;
3641 *stmt_p = new_stmt;
3645 /* A subroutine of lower_omp_single. Expand the simple form of
3646 an OMP_SINGLE, without a copyprivate clause:
3648 if (GOMP_single_start ())
3649 BODY;
3650 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3652 FIXME. It may be better to delay expanding the logic of this until
3653 pass_expand_omp. The expanded logic may make the job more difficult
3654 to a synchronization analysis pass. */
3656 static void
3657 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3659 tree t;
3661 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3662 t = build3 (COND_EXPR, void_type_node, t,
3663 OMP_SINGLE_BODY (single_stmt), NULL);
3664 gimplify_and_add (t, pre_p);
3668 /* A subroutine of lower_omp_single. Expand the simple form of
3669 an OMP_SINGLE, with a copyprivate clause:
3671 #pragma omp single copyprivate (a, b, c)
3673 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3676 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3678 BODY;
3679 copyout.a = a;
3680 copyout.b = b;
3681 copyout.c = c;
3682 GOMP_single_copy_end (&copyout);
3684 else
3686 a = copyout_p->a;
3687 b = copyout_p->b;
3688 c = copyout_p->c;
3690 GOMP_barrier ();
3693 FIXME. It may be better to delay expanding the logic of this until
3694 pass_expand_omp. The expanded logic may make the job more difficult
3695 to a synchronization analysis pass. */
3697 static void
3698 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3700 tree ptr_type, t, l0, l1, l2, copyin_seq;
3702 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3704 ptr_type = build_pointer_type (ctx->record_type);
3705 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3707 l0 = create_artificial_label ();
3708 l1 = create_artificial_label ();
3709 l2 = create_artificial_label ();
3711 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3712 t = fold_convert (ptr_type, t);
3713 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3714 gimplify_and_add (t, pre_p);
3716 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3717 build_int_cst (ptr_type, 0));
3718 t = build3 (COND_EXPR, void_type_node, t,
3719 build_and_jump (&l0), build_and_jump (&l1));
3720 gimplify_and_add (t, pre_p);
3722 t = build1 (LABEL_EXPR, void_type_node, l0);
3723 gimplify_and_add (t, pre_p);
3725 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3727 copyin_seq = NULL;
3728 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3729 &copyin_seq, ctx);
3731 t = build_fold_addr_expr (ctx->sender_decl);
3732 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3733 gimplify_and_add (t, pre_p);
3735 t = build_and_jump (&l2);
3736 gimplify_and_add (t, pre_p);
3738 t = build1 (LABEL_EXPR, void_type_node, l1);
3739 gimplify_and_add (t, pre_p);
3741 append_to_statement_list (copyin_seq, pre_p);
3743 t = build1 (LABEL_EXPR, void_type_node, l2);
3744 gimplify_and_add (t, pre_p);
3748 /* Expand code for an OpenMP single directive. */
3750 static void
3751 lower_omp_single (tree *stmt_p, omp_context *ctx)
3753 tree t, bind, block, single_stmt = *stmt_p, dlist;
3755 push_gimplify_context ();
3757 block = make_node (BLOCK);
3758 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3759 TREE_SIDE_EFFECTS (bind) = 1;
3761 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3762 &BIND_EXPR_BODY (bind), &dlist, ctx);
3763 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3765 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3767 if (ctx->record_type)
3768 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3769 else
3770 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3772 OMP_SINGLE_BODY (single_stmt) = NULL;
3774 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3776 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3778 t = make_node (OMP_RETURN);
3779 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3780 OMP_CLAUSE_NOWAIT);
3781 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3783 pop_gimplify_context (bind);
3785 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3786 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3790 /* Expand code for an OpenMP master directive. */
3792 static void
3793 lower_omp_master (tree *stmt_p, omp_context *ctx)
3795 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3797 push_gimplify_context ();
3799 block = make_node (BLOCK);
3800 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3801 TREE_SIDE_EFFECTS (bind) = 1;
3803 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3805 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3806 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3807 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3808 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3810 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3811 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3812 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3813 OMP_MASTER_BODY (stmt) = NULL;
3815 x = build1 (LABEL_EXPR, void_type_node, lab);
3816 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3818 x = make_node (OMP_RETURN);
3819 OMP_RETURN_NOWAIT (x) = 1;
3820 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3822 pop_gimplify_context (bind);
3824 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3825 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3829 /* Expand code for an OpenMP ordered directive. */
3831 static void
3832 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3834 tree bind, block, stmt = *stmt_p, x;
3836 push_gimplify_context ();
3838 block = make_node (BLOCK);
3839 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3840 TREE_SIDE_EFFECTS (bind) = 1;
3842 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3844 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
3845 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3847 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3848 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3849 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3850 OMP_ORDERED_BODY (stmt) = NULL;
3852 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
3853 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3855 x = make_node (OMP_RETURN);
3856 OMP_RETURN_NOWAIT (x) = 1;
3857 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3859 pop_gimplify_context (bind);
3861 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3862 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3866 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3867 substitution of a couple of function calls. But in the NAMED case,
3868 requires that languages coordinate a symbol name. It is therefore
3869 best put here in common code. */
3871 static GTY((param1_is (tree), param2_is (tree)))
3872 splay_tree critical_name_mutexes;
3874 static void
3875 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3877 tree bind, block, stmt = *stmt_p;
3878 tree t, lock, unlock, name;
3880 name = OMP_CRITICAL_NAME (stmt);
3881 if (name)
3883 tree decl;
3884 splay_tree_node n;
3886 if (!critical_name_mutexes)
3887 critical_name_mutexes
3888 = splay_tree_new_ggc (splay_tree_compare_pointers);
3890 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3891 if (n == NULL)
3893 char *new_str;
3895 decl = create_tmp_var_raw (ptr_type_node, NULL);
3897 new_str = ACONCAT ((".gomp_critical_user_",
3898 IDENTIFIER_POINTER (name), NULL));
3899 DECL_NAME (decl) = get_identifier (new_str);
3900 TREE_PUBLIC (decl) = 1;
3901 TREE_STATIC (decl) = 1;
3902 DECL_COMMON (decl) = 1;
3903 DECL_ARTIFICIAL (decl) = 1;
3904 DECL_IGNORED_P (decl) = 1;
3905 varpool_finalize_decl (decl);
3907 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3908 (splay_tree_value) decl);
3910 else
3911 decl = (tree) n->value;
3913 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3914 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
3916 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3917 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
3919 else
3921 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3922 lock = build_call_expr (lock, 0);
3924 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3925 unlock = build_call_expr (unlock, 0);
3928 push_gimplify_context ();
3930 block = make_node (BLOCK);
3931 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3932 TREE_SIDE_EFFECTS (bind) = 1;
3934 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3936 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3938 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3939 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3940 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3941 OMP_CRITICAL_BODY (stmt) = NULL;
3943 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3945 t = make_node (OMP_RETURN);
3946 OMP_RETURN_NOWAIT (t) = 1;
3947 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3949 pop_gimplify_context (bind);
3950 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3951 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3955 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3956 for a lastprivate clause. Given a loop control predicate of (V
3957 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3958 is appended to *DLIST, iterator initialization is appended to
3959 *BODY_P. */
3961 static void
3962 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3963 tree *dlist, struct omp_context *ctx)
3965 tree clauses, cond, stmts, vinit, t;
3966 enum tree_code cond_code;
3968 cond_code = fd->cond_code;
3969 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3971 /* When possible, use a strict equality expression. This can let VRP
3972 type optimizations deduce the value and remove a copy. */
3973 if (host_integerp (fd->step, 0))
3975 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3976 if (step == 1 || step == -1)
3977 cond_code = EQ_EXPR;
3980 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3982 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3983 stmts = NULL;
3984 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
3985 if (stmts != NULL)
3987 append_to_statement_list (stmts, dlist);
3989 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
3990 vinit = fd->n1;
3991 if (cond_code == EQ_EXPR
3992 && host_integerp (fd->n2, 0)
3993 && ! integer_zerop (fd->n2))
3994 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
3996 /* Initialize the iterator variable, so that threads that don't execute
3997 any iterations don't execute the lastprivate clauses by accident. */
3998 t = build_gimple_modify_stmt (fd->v, vinit);
3999 gimplify_and_add (t, body_p);
4004 /* Lower code for an OpenMP loop directive. */
4006 static void
4007 lower_omp_for (tree *stmt_p, omp_context *ctx)
4009 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
4010 struct omp_for_data fd;
4012 stmt = *stmt_p;
4014 push_gimplify_context ();
4016 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4017 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4019 /* Move declaration of temporaries in the loop body before we make
4020 it go away. */
4021 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4022 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4024 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4025 TREE_SIDE_EFFECTS (new_stmt) = 1;
4026 body_p = &BIND_EXPR_BODY (new_stmt);
4028 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4029 ilist = NULL;
4030 dlist = NULL;
4031 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4032 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4034 /* Lower the header expressions. At this point, we can assume that
4035 the header is of the form:
4037 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4039 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4040 using the .omp_data_s mapping, if needed. */
4041 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4042 if (!is_gimple_min_invariant (*rhs_p))
4043 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4045 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4046 if (!is_gimple_min_invariant (*rhs_p))
4047 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4049 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4050 if (!is_gimple_min_invariant (*rhs_p))
4051 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4053 /* Once lowered, extract the bounds and clauses. */
4054 extract_omp_for_data (stmt, &fd);
4056 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4058 append_to_statement_list (stmt, body_p);
4060 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4062 t = make_node (OMP_CONTINUE);
4063 append_to_statement_list (t, body_p);
4065 /* After the loop, add exit clauses. */
4066 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4067 append_to_statement_list (dlist, body_p);
4069 maybe_catch_exception (body_p);
4071 /* Region exit marker goes at the end of the loop body. */
4072 t = make_node (OMP_RETURN);
4073 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4074 append_to_statement_list (t, body_p);
4076 pop_gimplify_context (NULL_TREE);
4077 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4079 OMP_FOR_BODY (stmt) = NULL_TREE;
4080 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4081 *stmt_p = new_stmt;
4085 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4086 information for the directive. */
4088 static void
4089 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4091 tree clauses, par_bind, par_body, new_body, bind;
4092 tree olist, ilist, par_olist, par_ilist;
4093 tree stmt, child_fn, t;
4095 stmt = *stmt_p;
4097 clauses = OMP_PARALLEL_CLAUSES (stmt);
4098 par_bind = OMP_PARALLEL_BODY (stmt);
4099 par_body = BIND_EXPR_BODY (par_bind);
4100 child_fn = ctx->cb.dst_fn;
4102 push_gimplify_context ();
4104 par_olist = NULL_TREE;
4105 par_ilist = NULL_TREE;
4106 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4107 lower_omp (&par_body, ctx);
4108 lower_reduction_clauses (clauses, &par_olist, ctx);
4110 /* Declare all the variables created by mapping and the variables
4111 declared in the scope of the parallel body. */
4112 record_vars_into (ctx->block_vars, child_fn);
4113 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4115 if (ctx->record_type)
4117 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4118 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4121 olist = NULL_TREE;
4122 ilist = NULL_TREE;
4123 lower_send_clauses (clauses, &ilist, &olist, ctx);
4124 lower_send_shared_vars (&ilist, &olist, ctx);
4126 /* Once all the expansions are done, sequence all the different
4127 fragments inside OMP_PARALLEL_BODY. */
4128 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4129 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4131 new_body = alloc_stmt_list ();
4133 if (ctx->record_type)
4135 t = build_fold_addr_expr (ctx->sender_decl);
4136 /* fixup_child_record_type might have changed receiver_decl's type. */
4137 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4138 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4139 append_to_statement_list (t, &new_body);
4142 append_to_statement_list (par_ilist, &new_body);
4143 append_to_statement_list (par_body, &new_body);
4144 append_to_statement_list (par_olist, &new_body);
4145 maybe_catch_exception (&new_body);
4146 t = make_node (OMP_RETURN);
4147 append_to_statement_list (t, &new_body);
4148 OMP_PARALLEL_BODY (stmt) = new_body;
4150 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4151 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4153 *stmt_p = bind;
4155 pop_gimplify_context (NULL_TREE);
4159 /* Pass *TP back through the gimplifier within the context determined by WI.
4160 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4161 flags on ADDR_EXPR. */
4163 static void
4164 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4166 enum gimplify_status gs;
4167 tree pre = NULL;
4169 if (wi->is_lhs)
4170 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4171 else if (wi->val_only)
4172 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4173 else
4174 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4175 gcc_assert (gs == GS_ALL_DONE);
4177 if (pre)
4178 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4181 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4183 static tree
4184 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4186 tree t, stmt;
4188 t = create_tmp_var (TREE_TYPE (exp), NULL);
4189 DECL_GIMPLE_REG_P (t) = 1;
4190 stmt = build_gimple_modify_stmt (t, exp);
4191 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4192 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4194 return t;
4197 /* Similarly, but copy from the temporary and insert the statement
4198 after the iterator. */
4200 static tree
4201 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4203 tree t, stmt;
4205 t = create_tmp_var (TREE_TYPE (exp), NULL);
4206 DECL_GIMPLE_REG_P (t) = 1;
4207 stmt = build_gimple_modify_stmt (exp, t);
4208 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4209 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4211 return t;
4214 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4216 static tree
4217 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4219 struct walk_stmt_info *wi = data;
4220 omp_context *ctx = wi->info;
4221 tree t = *tp;
4223 /* If we have issued syntax errors, avoid doing any heavy lifting.
4224 Just replace the OpenMP directives with a NOP to avoid
4225 confusing RTL expansion. */
4226 if (errorcount && OMP_DIRECTIVE_P (*tp))
4228 *tp = build_empty_stmt ();
4229 return NULL_TREE;
4232 *walk_subtrees = 0;
4233 switch (TREE_CODE (*tp))
4235 case OMP_PARALLEL:
4236 ctx = maybe_lookup_ctx (t);
4237 lower_omp_parallel (tp, ctx);
4238 break;
4240 case OMP_FOR:
4241 ctx = maybe_lookup_ctx (t);
4242 gcc_assert (ctx);
4243 lower_omp_for (tp, ctx);
4244 break;
4246 case OMP_SECTIONS:
4247 ctx = maybe_lookup_ctx (t);
4248 gcc_assert (ctx);
4249 lower_omp_sections (tp, ctx);
4250 break;
4252 case OMP_SINGLE:
4253 ctx = maybe_lookup_ctx (t);
4254 gcc_assert (ctx);
4255 lower_omp_single (tp, ctx);
4256 break;
4258 case OMP_MASTER:
4259 ctx = maybe_lookup_ctx (t);
4260 gcc_assert (ctx);
4261 lower_omp_master (tp, ctx);
4262 break;
4264 case OMP_ORDERED:
4265 ctx = maybe_lookup_ctx (t);
4266 gcc_assert (ctx);
4267 lower_omp_ordered (tp, ctx);
4268 break;
4270 case OMP_CRITICAL:
4271 ctx = maybe_lookup_ctx (t);
4272 gcc_assert (ctx);
4273 lower_omp_critical (tp, ctx);
4274 break;
4276 case VAR_DECL:
4277 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4279 lower_regimplify (&t, wi);
4280 if (wi->val_only)
4282 if (wi->is_lhs)
4283 t = save_tmp_var (t, &wi->tsi);
4284 else
4285 t = init_tmp_var (t, &wi->tsi);
4287 *tp = t;
4289 break;
4291 case ADDR_EXPR:
4292 if (ctx)
4293 lower_regimplify (tp, wi);
4294 break;
4296 case ARRAY_REF:
4297 case ARRAY_RANGE_REF:
4298 case REALPART_EXPR:
4299 case IMAGPART_EXPR:
4300 case COMPONENT_REF:
4301 case VIEW_CONVERT_EXPR:
4302 if (ctx)
4303 lower_regimplify (tp, wi);
4304 break;
4306 case INDIRECT_REF:
4307 if (ctx)
4309 wi->is_lhs = false;
4310 wi->val_only = true;
4311 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4313 break;
4315 default:
4316 if (!TYPE_P (t) && !DECL_P (t))
4317 *walk_subtrees = 1;
4318 break;
4321 return NULL_TREE;
4324 static void
4325 lower_omp (tree *stmt_p, omp_context *ctx)
4327 struct walk_stmt_info wi;
4329 memset (&wi, 0, sizeof (wi));
4330 wi.callback = lower_omp_1;
4331 wi.info = ctx;
4332 wi.val_only = true;
4333 wi.want_locations = true;
4335 walk_stmts (&wi, stmt_p);
4338 /* Main entry point. */
4340 static unsigned int
4341 execute_lower_omp (void)
4343 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4344 delete_omp_context);
4346 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4347 gcc_assert (parallel_nesting_level == 0);
4349 if (all_contexts->root)
4350 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4352 if (all_contexts)
4354 splay_tree_delete (all_contexts);
4355 all_contexts = NULL;
4357 return 0;
4360 static bool
4361 gate_lower_omp (void)
4363 return flag_openmp != 0;
4366 struct tree_opt_pass pass_lower_omp =
4368 "omplower", /* name */
4369 gate_lower_omp, /* gate */
4370 execute_lower_omp, /* execute */
4371 NULL, /* sub */
4372 NULL, /* next */
4373 0, /* static_pass_number */
4374 0, /* tv_id */
4375 PROP_gimple_any, /* properties_required */
4376 PROP_gimple_lomp, /* properties_provided */
4377 0, /* properties_destroyed */
4378 0, /* todo_flags_start */
4379 TODO_dump_func, /* todo_flags_finish */
4380 0 /* letter */
4383 /* The following is a utility to diagnose OpenMP structured block violations.
4384 It is not part of the "omplower" pass, as that's invoked too late. It
4385 should be invoked by the respective front ends after gimplification. */
4387 static splay_tree all_labels;
4389 /* Check for mismatched contexts and generate an error if needed. Return
4390 true if an error is detected. */
4392 static bool
4393 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4395 bool exit_p = true;
4397 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4398 return false;
4400 /* Try to avoid confusing the user by producing and error message
4401 with correct "exit" or "enter" verbage. We prefer "exit"
4402 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4403 if (branch_ctx == NULL)
4404 exit_p = false;
4405 else
4407 while (label_ctx)
4409 if (TREE_VALUE (label_ctx) == branch_ctx)
4411 exit_p = false;
4412 break;
4414 label_ctx = TREE_CHAIN (label_ctx);
4418 if (exit_p)
4419 error ("invalid exit from OpenMP structured block");
4420 else
4421 error ("invalid entry to OpenMP structured block");
4423 *stmt_p = build_empty_stmt ();
4424 return true;
4427 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4428 where in the tree each label is found. */
4430 static tree
4431 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4433 struct walk_stmt_info *wi = data;
4434 tree context = (tree) wi->info;
4435 tree inner_context;
4436 tree t = *tp;
4438 *walk_subtrees = 0;
4439 switch (TREE_CODE (t))
4441 case OMP_PARALLEL:
4442 case OMP_SECTIONS:
4443 case OMP_SINGLE:
4444 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4445 /* FALLTHRU */
4446 case OMP_SECTION:
4447 case OMP_MASTER:
4448 case OMP_ORDERED:
4449 case OMP_CRITICAL:
4450 /* The minimal context here is just a tree of statements. */
4451 inner_context = tree_cons (NULL, t, context);
4452 wi->info = inner_context;
4453 walk_stmts (wi, &OMP_BODY (t));
4454 wi->info = context;
4455 break;
4457 case OMP_FOR:
4458 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4459 inner_context = tree_cons (NULL, t, context);
4460 wi->info = inner_context;
4461 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4462 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4463 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4464 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4465 walk_stmts (wi, &OMP_FOR_BODY (t));
4466 wi->info = context;
4467 break;
4469 case LABEL_EXPR:
4470 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4471 (splay_tree_value) context);
4472 break;
4474 default:
4475 break;
4478 return NULL_TREE;
4481 /* Pass 2: Check each branch and see if its context differs from that of
4482 the destination label's context. */
4484 static tree
4485 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4487 struct walk_stmt_info *wi = data;
4488 tree context = (tree) wi->info;
4489 splay_tree_node n;
4490 tree t = *tp;
4492 *walk_subtrees = 0;
4493 switch (TREE_CODE (t))
4495 case OMP_PARALLEL:
4496 case OMP_SECTIONS:
4497 case OMP_SINGLE:
4498 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4499 /* FALLTHRU */
4500 case OMP_SECTION:
4501 case OMP_MASTER:
4502 case OMP_ORDERED:
4503 case OMP_CRITICAL:
4504 wi->info = t;
4505 walk_stmts (wi, &OMP_BODY (t));
4506 wi->info = context;
4507 break;
4509 case OMP_FOR:
4510 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4511 wi->info = t;
4512 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4513 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4514 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4515 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4516 walk_stmts (wi, &OMP_FOR_BODY (t));
4517 wi->info = context;
4518 break;
4520 case GOTO_EXPR:
4522 tree lab = GOTO_DESTINATION (t);
4523 if (TREE_CODE (lab) != LABEL_DECL)
4524 break;
4526 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4527 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4529 break;
4531 case SWITCH_EXPR:
4533 tree vec = SWITCH_LABELS (t);
4534 int i, len = TREE_VEC_LENGTH (vec);
4535 for (i = 0; i < len; ++i)
4537 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4538 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4539 if (diagnose_sb_0 (tp, context, (tree) n->value))
4540 break;
4543 break;
4545 case RETURN_EXPR:
4546 diagnose_sb_0 (tp, context, NULL_TREE);
4547 break;
4549 default:
4550 break;
4553 return NULL_TREE;
4556 void
4557 diagnose_omp_structured_block_errors (tree fndecl)
4559 tree save_current = current_function_decl;
4560 struct walk_stmt_info wi;
4562 current_function_decl = fndecl;
4564 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4566 memset (&wi, 0, sizeof (wi));
4567 wi.callback = diagnose_sb_1;
4568 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4570 memset (&wi, 0, sizeof (wi));
4571 wi.callback = diagnose_sb_2;
4572 wi.want_locations = true;
4573 wi.want_return_expr = true;
4574 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4576 splay_tree_delete (all_labels);
4577 all_labels = NULL;
4579 current_function_decl = save_current;
4582 #include "gt-omp-low.h"