2007-07-01 H.J. Lu <hongjiu.lu@intel.com>
[official-gcc.git] / gcc / omp-low.c
blob700645f6551dd39d4dbd5f7d45f60a107dc4009b
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_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
520 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
521 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
522 TREE_USED (copy) = 1;
523 DECL_CONTEXT (copy) = current_function_decl;
524 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
526 TREE_CHAIN (copy) = ctx->block_vars;
527 ctx->block_vars = copy;
529 return copy;
532 static tree
533 omp_copy_decl_1 (tree var, omp_context *ctx)
535 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
538 /* Build tree nodes to access the field for VAR on the receiver side. */
540 static tree
541 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
543 tree x, field = lookup_field (var, ctx);
545 /* If the receiver record type was remapped in the child function,
546 remap the field into the new record type. */
547 x = maybe_lookup_field (field, ctx);
548 if (x != NULL)
549 field = x;
551 x = build_fold_indirect_ref (ctx->receiver_decl);
552 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
553 if (by_ref)
554 x = build_fold_indirect_ref (x);
556 return x;
559 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
560 of a parallel, this is a component reference; for workshare constructs
561 this is some variable. */
563 static tree
564 build_outer_var_ref (tree var, omp_context *ctx)
566 tree x;
568 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
569 x = var;
570 else if (is_variable_sized (var))
572 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
573 x = build_outer_var_ref (x, ctx);
574 x = build_fold_indirect_ref (x);
576 else if (is_parallel_ctx (ctx))
578 bool by_ref = use_pointer_for_field (var, false);
579 x = build_receiver_ref (var, by_ref, ctx);
581 else if (ctx->outer)
582 x = lookup_decl (var, ctx->outer);
583 else if (is_reference (var))
584 /* This can happen with orphaned constructs. If var is reference, it is
585 possible it is shared and as such valid. */
586 x = var;
587 else
588 gcc_unreachable ();
590 if (is_reference (var))
591 x = build_fold_indirect_ref (x);
593 return x;
596 /* Build tree nodes to access the field for VAR on the sender side. */
598 static tree
599 build_sender_ref (tree var, omp_context *ctx)
601 tree field = lookup_field (var, ctx);
602 return build3 (COMPONENT_REF, TREE_TYPE (field),
603 ctx->sender_decl, field, NULL);
606 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
608 static void
609 install_var_field (tree var, bool by_ref, omp_context *ctx)
611 tree field, type;
613 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
615 type = TREE_TYPE (var);
616 if (by_ref)
617 type = build_pointer_type (type);
619 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
621 /* Remember what variable this field was created for. This does have a
622 side effect of making dwarf2out ignore this member, so for helpful
623 debugging we clear it later in delete_omp_context. */
624 DECL_ABSTRACT_ORIGIN (field) = var;
626 insert_field_into_struct (ctx->record_type, field);
628 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
629 (splay_tree_value) field);
632 static tree
633 install_var_local (tree var, omp_context *ctx)
635 tree new_var = omp_copy_decl_1 (var, ctx);
636 insert_decl_map (&ctx->cb, var, new_var);
637 return new_var;
640 /* Adjust the replacement for DECL in CTX for the new context. This means
641 copying the DECL_VALUE_EXPR, and fixing up the type. */
643 static void
644 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
646 tree new_decl, size;
648 new_decl = lookup_decl (decl, ctx);
650 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
652 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
653 && DECL_HAS_VALUE_EXPR_P (decl))
655 tree ve = DECL_VALUE_EXPR (decl);
656 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
657 SET_DECL_VALUE_EXPR (new_decl, ve);
658 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
661 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
663 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
664 if (size == error_mark_node)
665 size = TYPE_SIZE (TREE_TYPE (new_decl));
666 DECL_SIZE (new_decl) = size;
668 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
669 if (size == error_mark_node)
670 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
671 DECL_SIZE_UNIT (new_decl) = size;
675 /* The callback for remap_decl. Search all containing contexts for a
676 mapping of the variable; this avoids having to duplicate the splay
677 tree ahead of time. We know a mapping doesn't already exist in the
678 given context. Create new mappings to implement default semantics. */
680 static tree
681 omp_copy_decl (tree var, copy_body_data *cb)
683 omp_context *ctx = (omp_context *) cb;
684 tree new_var;
686 if (TREE_CODE (var) == LABEL_DECL)
688 new_var = create_artificial_label ();
689 DECL_CONTEXT (new_var) = current_function_decl;
690 insert_decl_map (&ctx->cb, var, new_var);
691 return new_var;
694 while (!is_parallel_ctx (ctx))
696 ctx = ctx->outer;
697 if (ctx == NULL)
698 return var;
699 new_var = maybe_lookup_decl (var, ctx);
700 if (new_var)
701 return new_var;
704 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
705 return var;
707 return error_mark_node;
711 /* Return the parallel region associated with STMT. */
713 /* Debugging dumps for parallel regions. */
714 void dump_omp_region (FILE *, struct omp_region *, int);
715 void debug_omp_region (struct omp_region *);
716 void debug_all_omp_regions (void);
718 /* Dump the parallel region tree rooted at REGION. */
720 void
721 dump_omp_region (FILE *file, struct omp_region *region, int indent)
723 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
724 tree_code_name[region->type]);
726 if (region->inner)
727 dump_omp_region (file, region->inner, indent + 4);
729 if (region->cont)
731 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
732 region->cont->index);
735 if (region->exit)
736 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
737 region->exit->index);
738 else
739 fprintf (file, "%*s[no exit marker]\n", indent, "");
741 if (region->next)
742 dump_omp_region (file, region->next, indent);
745 void
746 debug_omp_region (struct omp_region *region)
748 dump_omp_region (stderr, region, 0);
751 void
752 debug_all_omp_regions (void)
754 dump_omp_region (stderr, root_omp_region, 0);
758 /* Create a new parallel region starting at STMT inside region PARENT. */
760 struct omp_region *
761 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
763 struct omp_region *region = xcalloc (1, sizeof (*region));
765 region->outer = parent;
766 region->entry = bb;
767 region->type = type;
769 if (parent)
771 /* This is a nested region. Add it to the list of inner
772 regions in PARENT. */
773 region->next = parent->inner;
774 parent->inner = region;
776 else
778 /* This is a toplevel region. Add it to the list of toplevel
779 regions in ROOT_OMP_REGION. */
780 region->next = root_omp_region;
781 root_omp_region = region;
784 return region;
787 /* Release the memory associated with the region tree rooted at REGION. */
789 static void
790 free_omp_region_1 (struct omp_region *region)
792 struct omp_region *i, *n;
794 for (i = region->inner; i ; i = n)
796 n = i->next;
797 free_omp_region_1 (i);
800 free (region);
803 /* Release the memory for the entire omp region tree. */
805 void
806 free_omp_regions (void)
808 struct omp_region *r, *n;
809 for (r = root_omp_region; r ; r = n)
811 n = r->next;
812 free_omp_region_1 (r);
814 root_omp_region = NULL;
818 /* Create a new context, with OUTER_CTX being the surrounding context. */
820 static omp_context *
821 new_omp_context (tree stmt, omp_context *outer_ctx)
823 omp_context *ctx = XCNEW (omp_context);
825 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
826 (splay_tree_value) ctx);
827 ctx->stmt = stmt;
829 if (outer_ctx)
831 ctx->outer = outer_ctx;
832 ctx->cb = outer_ctx->cb;
833 ctx->cb.block = NULL;
834 ctx->depth = outer_ctx->depth + 1;
836 else
838 ctx->cb.src_fn = current_function_decl;
839 ctx->cb.dst_fn = current_function_decl;
840 ctx->cb.src_node = cgraph_node (current_function_decl);
841 ctx->cb.dst_node = ctx->cb.src_node;
842 ctx->cb.src_cfun = cfun;
843 ctx->cb.copy_decl = omp_copy_decl;
844 ctx->cb.eh_region = -1;
845 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
846 ctx->depth = 1;
849 ctx->cb.decl_map = pointer_map_create ();
851 return ctx;
854 /* Destroy a omp_context data structures. Called through the splay tree
855 value delete callback. */
857 static void
858 delete_omp_context (splay_tree_value value)
860 omp_context *ctx = (omp_context *) value;
862 pointer_map_destroy (ctx->cb.decl_map);
864 if (ctx->field_map)
865 splay_tree_delete (ctx->field_map);
867 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
868 it produces corrupt debug information. */
869 if (ctx->record_type)
871 tree t;
872 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
873 DECL_ABSTRACT_ORIGIN (t) = NULL;
876 XDELETE (ctx);
879 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
880 context. */
882 static void
883 fixup_child_record_type (omp_context *ctx)
885 tree f, type = ctx->record_type;
887 /* ??? It isn't sufficient to just call remap_type here, because
888 variably_modified_type_p doesn't work the way we expect for
889 record types. Testing each field for whether it needs remapping
890 and creating a new record by hand works, however. */
891 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
892 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
893 break;
894 if (f)
896 tree name, new_fields = NULL;
898 type = lang_hooks.types.make_type (RECORD_TYPE);
899 name = DECL_NAME (TYPE_NAME (ctx->record_type));
900 name = build_decl (TYPE_DECL, name, type);
901 TYPE_NAME (type) = name;
903 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
905 tree new_f = copy_node (f);
906 DECL_CONTEXT (new_f) = type;
907 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
908 TREE_CHAIN (new_f) = new_fields;
909 new_fields = new_f;
911 /* Arrange to be able to look up the receiver field
912 given the sender field. */
913 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
914 (splay_tree_value) new_f);
916 TYPE_FIELDS (type) = nreverse (new_fields);
917 layout_type (type);
920 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
923 /* Instantiate decls as necessary in CTX to satisfy the data sharing
924 specified by CLAUSES. */
926 static void
927 scan_sharing_clauses (tree clauses, omp_context *ctx)
929 tree c, decl;
930 bool scan_array_reductions = false;
932 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
934 bool by_ref;
936 switch (OMP_CLAUSE_CODE (c))
938 case OMP_CLAUSE_PRIVATE:
939 decl = OMP_CLAUSE_DECL (c);
940 if (!is_variable_sized (decl))
941 install_var_local (decl, ctx);
942 break;
944 case OMP_CLAUSE_SHARED:
945 gcc_assert (is_parallel_ctx (ctx));
946 decl = OMP_CLAUSE_DECL (c);
947 gcc_assert (!is_variable_sized (decl));
948 by_ref = use_pointer_for_field (decl, true);
949 /* Global variables don't need to be copied,
950 the receiver side will use them directly. */
951 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
952 break;
953 if (! TREE_READONLY (decl)
954 || TREE_ADDRESSABLE (decl)
955 || by_ref
956 || is_reference (decl))
958 install_var_field (decl, by_ref, ctx);
959 install_var_local (decl, ctx);
960 break;
962 /* We don't need to copy const scalar vars back. */
963 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
964 goto do_private;
966 case OMP_CLAUSE_LASTPRIVATE:
967 /* Let the corresponding firstprivate clause create
968 the variable. */
969 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
970 break;
971 /* FALLTHRU */
973 case OMP_CLAUSE_FIRSTPRIVATE:
974 case OMP_CLAUSE_REDUCTION:
975 decl = OMP_CLAUSE_DECL (c);
976 do_private:
977 if (is_variable_sized (decl))
978 break;
979 else if (is_parallel_ctx (ctx)
980 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
981 ctx)))
983 by_ref = use_pointer_for_field (decl, false);
984 install_var_field (decl, by_ref, ctx);
986 install_var_local (decl, ctx);
987 break;
989 case OMP_CLAUSE_COPYPRIVATE:
990 if (ctx->outer)
991 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
992 /* FALLTHRU */
994 case OMP_CLAUSE_COPYIN:
995 decl = OMP_CLAUSE_DECL (c);
996 by_ref = use_pointer_for_field (decl, false);
997 install_var_field (decl, by_ref, ctx);
998 break;
1000 case OMP_CLAUSE_DEFAULT:
1001 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1002 break;
1004 case OMP_CLAUSE_IF:
1005 case OMP_CLAUSE_NUM_THREADS:
1006 case OMP_CLAUSE_SCHEDULE:
1007 if (ctx->outer)
1008 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1009 break;
1011 case OMP_CLAUSE_NOWAIT:
1012 case OMP_CLAUSE_ORDERED:
1013 break;
1015 default:
1016 gcc_unreachable ();
1020 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1022 switch (OMP_CLAUSE_CODE (c))
1024 case OMP_CLAUSE_LASTPRIVATE:
1025 /* Let the corresponding firstprivate clause create
1026 the variable. */
1027 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1028 break;
1029 /* FALLTHRU */
1031 case OMP_CLAUSE_PRIVATE:
1032 case OMP_CLAUSE_FIRSTPRIVATE:
1033 case OMP_CLAUSE_REDUCTION:
1034 decl = OMP_CLAUSE_DECL (c);
1035 if (is_variable_sized (decl))
1036 install_var_local (decl, ctx);
1037 fixup_remapped_decl (decl, ctx,
1038 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1039 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1040 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1041 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1042 scan_array_reductions = true;
1043 break;
1045 case OMP_CLAUSE_SHARED:
1046 decl = OMP_CLAUSE_DECL (c);
1047 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1048 fixup_remapped_decl (decl, ctx, false);
1049 break;
1051 case OMP_CLAUSE_COPYPRIVATE:
1052 case OMP_CLAUSE_COPYIN:
1053 case OMP_CLAUSE_DEFAULT:
1054 case OMP_CLAUSE_IF:
1055 case OMP_CLAUSE_NUM_THREADS:
1056 case OMP_CLAUSE_SCHEDULE:
1057 case OMP_CLAUSE_NOWAIT:
1058 case OMP_CLAUSE_ORDERED:
1059 break;
1061 default:
1062 gcc_unreachable ();
1066 if (scan_array_reductions)
1067 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1069 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1071 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1072 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1076 /* Create a new name for omp child function. Returns an identifier. */
1078 static GTY(()) unsigned int tmp_ompfn_id_num;
1080 static tree
1081 create_omp_child_function_name (void)
1083 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1084 size_t len = IDENTIFIER_LENGTH (name);
1085 char *tmp_name, *prefix;
1087 prefix = alloca (len + sizeof ("_omp_fn"));
1088 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1089 strcpy (prefix + len, "_omp_fn");
1090 #ifndef NO_DOT_IN_LABEL
1091 prefix[len] = '.';
1092 #elif !defined NO_DOLLAR_IN_LABEL
1093 prefix[len] = '$';
1094 #endif
1095 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1096 return get_identifier (tmp_name);
1099 /* Build a decl for the omp child function. It'll not contain a body
1100 yet, just the bare decl. */
1102 static void
1103 create_omp_child_function (omp_context *ctx)
1105 tree decl, type, name, t;
1107 name = create_omp_child_function_name ();
1108 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1110 decl = build_decl (FUNCTION_DECL, name, type);
1111 decl = lang_hooks.decls.pushdecl (decl);
1113 ctx->cb.dst_fn = decl;
1115 TREE_STATIC (decl) = 1;
1116 TREE_USED (decl) = 1;
1117 DECL_ARTIFICIAL (decl) = 1;
1118 DECL_IGNORED_P (decl) = 0;
1119 TREE_PUBLIC (decl) = 0;
1120 DECL_UNINLINABLE (decl) = 1;
1121 DECL_EXTERNAL (decl) = 0;
1122 DECL_CONTEXT (decl) = NULL_TREE;
1123 DECL_INITIAL (decl) = make_node (BLOCK);
1125 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1126 DECL_ARTIFICIAL (t) = 1;
1127 DECL_IGNORED_P (t) = 1;
1128 DECL_RESULT (decl) = t;
1130 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1131 DECL_ARTIFICIAL (t) = 1;
1132 DECL_ARG_TYPE (t) = ptr_type_node;
1133 DECL_CONTEXT (t) = current_function_decl;
1134 TREE_USED (t) = 1;
1135 DECL_ARGUMENTS (decl) = t;
1136 ctx->receiver_decl = t;
1138 /* Allocate memory for the function structure. The call to
1139 allocate_struct_function clobbers CFUN, so we need to restore
1140 it afterward. */
1141 allocate_struct_function (decl);
1142 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1143 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1144 cfun = ctx->cb.src_cfun;
1148 /* Scan an OpenMP parallel directive. */
1150 static void
1151 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1153 omp_context *ctx;
1154 tree name;
1156 /* Ignore parallel directives with empty bodies, unless there
1157 are copyin clauses. */
1158 if (optimize > 0
1159 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1160 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1162 *stmt_p = build_empty_stmt ();
1163 return;
1166 ctx = new_omp_context (*stmt_p, outer_ctx);
1167 if (parallel_nesting_level > 1)
1168 ctx->is_nested = true;
1169 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1170 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1171 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1172 name = create_tmp_var_name (".omp_data_s");
1173 name = build_decl (TYPE_DECL, name, ctx->record_type);
1174 TYPE_NAME (ctx->record_type) = name;
1175 create_omp_child_function (ctx);
1176 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1178 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1179 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1181 if (TYPE_FIELDS (ctx->record_type) == NULL)
1182 ctx->record_type = ctx->receiver_decl = NULL;
1183 else
1185 layout_type (ctx->record_type);
1186 fixup_child_record_type (ctx);
1191 /* Scan an OpenMP loop directive. */
1193 static void
1194 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1196 omp_context *ctx;
1197 tree stmt;
1199 stmt = *stmt_p;
1200 ctx = new_omp_context (stmt, outer_ctx);
1202 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1204 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1205 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1206 scan_omp (&OMP_FOR_COND (stmt), ctx);
1207 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1208 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1211 /* Scan an OpenMP sections directive. */
1213 static void
1214 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1216 tree stmt;
1217 omp_context *ctx;
1219 stmt = *stmt_p;
1220 ctx = new_omp_context (stmt, outer_ctx);
1221 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1222 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1225 /* Scan an OpenMP single directive. */
1227 static void
1228 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1230 tree stmt = *stmt_p;
1231 omp_context *ctx;
1232 tree name;
1234 ctx = new_omp_context (stmt, outer_ctx);
1235 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1236 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1237 name = create_tmp_var_name (".omp_copy_s");
1238 name = build_decl (TYPE_DECL, name, ctx->record_type);
1239 TYPE_NAME (ctx->record_type) = name;
1241 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1242 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1244 if (TYPE_FIELDS (ctx->record_type) == NULL)
1245 ctx->record_type = NULL;
1246 else
1247 layout_type (ctx->record_type);
1251 /* Check OpenMP nesting restrictions. */
1252 static void
1253 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1255 switch (TREE_CODE (t))
1257 case OMP_FOR:
1258 case OMP_SECTIONS:
1259 case OMP_SINGLE:
1260 for (; ctx != NULL; ctx = ctx->outer)
1261 switch (TREE_CODE (ctx->stmt))
1263 case OMP_FOR:
1264 case OMP_SECTIONS:
1265 case OMP_SINGLE:
1266 case OMP_ORDERED:
1267 case OMP_MASTER:
1268 warning (0, "work-sharing region may not be closely nested inside "
1269 "of work-sharing, critical, ordered or master region");
1270 return;
1271 case OMP_PARALLEL:
1272 return;
1273 default:
1274 break;
1276 break;
1277 case OMP_MASTER:
1278 for (; ctx != NULL; ctx = ctx->outer)
1279 switch (TREE_CODE (ctx->stmt))
1281 case OMP_FOR:
1282 case OMP_SECTIONS:
1283 case OMP_SINGLE:
1284 warning (0, "master region may not be closely nested inside "
1285 "of work-sharing region");
1286 return;
1287 case OMP_PARALLEL:
1288 return;
1289 default:
1290 break;
1292 break;
1293 case OMP_ORDERED:
1294 for (; ctx != NULL; ctx = ctx->outer)
1295 switch (TREE_CODE (ctx->stmt))
1297 case OMP_CRITICAL:
1298 warning (0, "ordered region may not be closely nested inside "
1299 "of critical region");
1300 return;
1301 case OMP_FOR:
1302 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1303 OMP_CLAUSE_ORDERED) == NULL)
1304 warning (0, "ordered region must be closely nested inside "
1305 "a loop region with an ordered clause");
1306 return;
1307 case OMP_PARALLEL:
1308 return;
1309 default:
1310 break;
1312 break;
1313 case OMP_CRITICAL:
1314 for (; ctx != NULL; ctx = ctx->outer)
1315 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1316 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1318 warning (0, "critical region may not be nested inside a critical "
1319 "region with the same name");
1320 return;
1322 break;
1323 default:
1324 break;
1329 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1331 static tree
1332 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1334 struct walk_stmt_info *wi = data;
1335 omp_context *ctx = wi->info;
1336 tree t = *tp;
1338 if (EXPR_HAS_LOCATION (t))
1339 input_location = EXPR_LOCATION (t);
1341 /* Check the OpenMP nesting restrictions. */
1342 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1343 check_omp_nesting_restrictions (t, ctx);
1345 *walk_subtrees = 0;
1346 switch (TREE_CODE (t))
1348 case OMP_PARALLEL:
1349 parallel_nesting_level++;
1350 scan_omp_parallel (tp, ctx);
1351 parallel_nesting_level--;
1352 break;
1354 case OMP_FOR:
1355 scan_omp_for (tp, ctx);
1356 break;
1358 case OMP_SECTIONS:
1359 scan_omp_sections (tp, ctx);
1360 break;
1362 case OMP_SINGLE:
1363 scan_omp_single (tp, ctx);
1364 break;
1366 case OMP_SECTION:
1367 case OMP_MASTER:
1368 case OMP_ORDERED:
1369 case OMP_CRITICAL:
1370 ctx = new_omp_context (*tp, ctx);
1371 scan_omp (&OMP_BODY (*tp), ctx);
1372 break;
1374 case BIND_EXPR:
1376 tree var;
1377 *walk_subtrees = 1;
1379 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1380 insert_decl_map (&ctx->cb, var, var);
1382 break;
1384 case VAR_DECL:
1385 case PARM_DECL:
1386 case LABEL_DECL:
1387 case RESULT_DECL:
1388 if (ctx)
1389 *tp = remap_decl (t, &ctx->cb);
1390 break;
1392 default:
1393 if (ctx && TYPE_P (t))
1394 *tp = remap_type (t, &ctx->cb);
1395 else if (!DECL_P (t))
1396 *walk_subtrees = 1;
1397 break;
1400 return NULL_TREE;
1404 /* Scan all the statements starting at STMT_P. CTX contains context
1405 information about the OpenMP directives and clauses found during
1406 the scan. */
1408 static void
1409 scan_omp (tree *stmt_p, omp_context *ctx)
1411 location_t saved_location;
1412 struct walk_stmt_info wi;
1414 memset (&wi, 0, sizeof (wi));
1415 wi.callback = scan_omp_1;
1416 wi.info = ctx;
1417 wi.want_bind_expr = (ctx != NULL);
1418 wi.want_locations = true;
1420 saved_location = input_location;
1421 walk_stmts (&wi, stmt_p);
1422 input_location = saved_location;
1425 /* Re-gimplification and code generation routines. */
1427 /* Build a call to GOMP_barrier. */
1429 static void
1430 build_omp_barrier (tree *stmt_list)
1432 tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1433 gimplify_and_add (t, stmt_list);
1436 /* If a context was created for STMT when it was scanned, return it. */
1438 static omp_context *
1439 maybe_lookup_ctx (tree stmt)
1441 splay_tree_node n;
1442 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1443 return n ? (omp_context *) n->value : NULL;
1447 /* Find the mapping for DECL in CTX or the immediately enclosing
1448 context that has a mapping for DECL.
1450 If CTX is a nested parallel directive, we may have to use the decl
1451 mappings created in CTX's parent context. Suppose that we have the
1452 following parallel nesting (variable UIDs showed for clarity):
1454 iD.1562 = 0;
1455 #omp parallel shared(iD.1562) -> outer parallel
1456 iD.1562 = iD.1562 + 1;
1458 #omp parallel shared (iD.1562) -> inner parallel
1459 iD.1562 = iD.1562 - 1;
1461 Each parallel structure will create a distinct .omp_data_s structure
1462 for copying iD.1562 in/out of the directive:
1464 outer parallel .omp_data_s.1.i -> iD.1562
1465 inner parallel .omp_data_s.2.i -> iD.1562
1467 A shared variable mapping will produce a copy-out operation before
1468 the parallel directive and a copy-in operation after it. So, in
1469 this case we would have:
1471 iD.1562 = 0;
1472 .omp_data_o.1.i = iD.1562;
1473 #omp parallel shared(iD.1562) -> outer parallel
1474 .omp_data_i.1 = &.omp_data_o.1
1475 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1477 .omp_data_o.2.i = iD.1562; -> **
1478 #omp parallel shared(iD.1562) -> inner parallel
1479 .omp_data_i.2 = &.omp_data_o.2
1480 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1483 ** This is a problem. The symbol iD.1562 cannot be referenced
1484 inside the body of the outer parallel region. But since we are
1485 emitting this copy operation while expanding the inner parallel
1486 directive, we need to access the CTX structure of the outer
1487 parallel directive to get the correct mapping:
1489 .omp_data_o.2.i = .omp_data_i.1->i
1491 Since there may be other workshare or parallel directives enclosing
1492 the parallel directive, it may be necessary to walk up the context
1493 parent chain. This is not a problem in general because nested
1494 parallelism happens only rarely. */
1496 static tree
1497 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1499 tree t;
1500 omp_context *up;
1502 gcc_assert (ctx->is_nested);
1504 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1505 t = maybe_lookup_decl (decl, up);
1507 gcc_assert (t || is_global_var (decl));
1509 return t ? t : decl;
1513 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1514 in outer contexts. */
1516 static tree
1517 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1519 tree t = NULL;
1520 omp_context *up;
1522 if (ctx->is_nested)
1523 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1524 t = maybe_lookup_decl (decl, up);
1526 return t ? t : decl;
1530 /* Construct the initialization value for reduction CLAUSE. */
1532 tree
1533 omp_reduction_init (tree clause, tree type)
1535 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1537 case PLUS_EXPR:
1538 case MINUS_EXPR:
1539 case BIT_IOR_EXPR:
1540 case BIT_XOR_EXPR:
1541 case TRUTH_OR_EXPR:
1542 case TRUTH_ORIF_EXPR:
1543 case TRUTH_XOR_EXPR:
1544 case NE_EXPR:
1545 return fold_convert (type, integer_zero_node);
1547 case MULT_EXPR:
1548 case TRUTH_AND_EXPR:
1549 case TRUTH_ANDIF_EXPR:
1550 case EQ_EXPR:
1551 return fold_convert (type, integer_one_node);
1553 case BIT_AND_EXPR:
1554 return fold_convert (type, integer_minus_one_node);
1556 case MAX_EXPR:
1557 if (SCALAR_FLOAT_TYPE_P (type))
1559 REAL_VALUE_TYPE max, min;
1560 if (HONOR_INFINITIES (TYPE_MODE (type)))
1562 real_inf (&max);
1563 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1565 else
1566 real_maxval (&min, 1, TYPE_MODE (type));
1567 return build_real (type, min);
1569 else
1571 gcc_assert (INTEGRAL_TYPE_P (type));
1572 return TYPE_MIN_VALUE (type);
1575 case MIN_EXPR:
1576 if (SCALAR_FLOAT_TYPE_P (type))
1578 REAL_VALUE_TYPE max;
1579 if (HONOR_INFINITIES (TYPE_MODE (type)))
1580 real_inf (&max);
1581 else
1582 real_maxval (&max, 0, TYPE_MODE (type));
1583 return build_real (type, max);
1585 else
1587 gcc_assert (INTEGRAL_TYPE_P (type));
1588 return TYPE_MAX_VALUE (type);
1591 default:
1592 gcc_unreachable ();
1596 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1597 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1598 private variables. Initialization statements go in ILIST, while calls
1599 to destructors go in DLIST. */
1601 static void
1602 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1603 omp_context *ctx)
1605 tree_stmt_iterator diter;
1606 tree c, dtor, copyin_seq, x, ptr;
1607 bool copyin_by_ref = false;
1608 bool lastprivate_firstprivate = false;
1609 int pass;
1611 *dlist = alloc_stmt_list ();
1612 diter = tsi_start (*dlist);
1613 copyin_seq = NULL;
1615 /* Do all the fixed sized types in the first pass, and the variable sized
1616 types in the second pass. This makes sure that the scalar arguments to
1617 the variable sized types are processed before we use them in the
1618 variable sized operations. */
1619 for (pass = 0; pass < 2; ++pass)
1621 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1623 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1624 tree var, new_var;
1625 bool by_ref;
1627 switch (c_kind)
1629 case OMP_CLAUSE_PRIVATE:
1630 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1631 continue;
1632 break;
1633 case OMP_CLAUSE_SHARED:
1634 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1636 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1637 continue;
1639 case OMP_CLAUSE_FIRSTPRIVATE:
1640 case OMP_CLAUSE_COPYIN:
1641 case OMP_CLAUSE_REDUCTION:
1642 break;
1643 case OMP_CLAUSE_LASTPRIVATE:
1644 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1646 lastprivate_firstprivate = true;
1647 if (pass != 0)
1648 continue;
1650 break;
1651 default:
1652 continue;
1655 new_var = var = OMP_CLAUSE_DECL (c);
1656 if (c_kind != OMP_CLAUSE_COPYIN)
1657 new_var = lookup_decl (var, ctx);
1659 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1661 if (pass != 0)
1662 continue;
1664 else if (is_variable_sized (var))
1666 /* For variable sized types, we need to allocate the
1667 actual storage here. Call alloca and store the
1668 result in the pointer decl that we created elsewhere. */
1669 if (pass == 0)
1670 continue;
1672 ptr = DECL_VALUE_EXPR (new_var);
1673 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1674 ptr = TREE_OPERAND (ptr, 0);
1675 gcc_assert (DECL_P (ptr));
1677 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1678 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1679 x = fold_convert (TREE_TYPE (ptr), x);
1680 x = build_gimple_modify_stmt (ptr, x);
1681 gimplify_and_add (x, ilist);
1683 else if (is_reference (var))
1685 /* For references that are being privatized for Fortran,
1686 allocate new backing storage for the new pointer
1687 variable. This allows us to avoid changing all the
1688 code that expects a pointer to something that expects
1689 a direct variable. Note that this doesn't apply to
1690 C++, since reference types are disallowed in data
1691 sharing clauses there, except for NRV optimized
1692 return values. */
1693 if (pass == 0)
1694 continue;
1696 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1697 if (TREE_CONSTANT (x))
1699 const char *name = NULL;
1700 if (DECL_NAME (var))
1701 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1703 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1704 name);
1705 gimple_add_tmp_var (x);
1706 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1708 else
1710 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1711 x = fold_convert (TREE_TYPE (new_var), x);
1714 x = build_gimple_modify_stmt (new_var, x);
1715 gimplify_and_add (x, ilist);
1717 new_var = build_fold_indirect_ref (new_var);
1719 else if (c_kind == OMP_CLAUSE_REDUCTION
1720 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1722 if (pass == 0)
1723 continue;
1725 else if (pass != 0)
1726 continue;
1728 switch (OMP_CLAUSE_CODE (c))
1730 case OMP_CLAUSE_SHARED:
1731 /* Shared global vars are just accessed directly. */
1732 if (is_global_var (new_var))
1733 break;
1734 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1735 needs to be delayed until after fixup_child_record_type so
1736 that we get the correct type during the dereference. */
1737 by_ref = use_pointer_for_field (var, true);
1738 x = build_receiver_ref (var, by_ref, ctx);
1739 SET_DECL_VALUE_EXPR (new_var, x);
1740 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1742 /* ??? If VAR is not passed by reference, and the variable
1743 hasn't been initialized yet, then we'll get a warning for
1744 the store into the omp_data_s structure. Ideally, we'd be
1745 able to notice this and not store anything at all, but
1746 we're generating code too early. Suppress the warning. */
1747 if (!by_ref)
1748 TREE_NO_WARNING (var) = 1;
1749 break;
1751 case OMP_CLAUSE_LASTPRIVATE:
1752 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1753 break;
1754 /* FALLTHRU */
1756 case OMP_CLAUSE_PRIVATE:
1757 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1758 if (x)
1759 gimplify_and_add (x, ilist);
1760 /* FALLTHRU */
1762 do_dtor:
1763 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1764 if (x)
1766 dtor = x;
1767 gimplify_stmt (&dtor);
1768 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1770 break;
1772 case OMP_CLAUSE_FIRSTPRIVATE:
1773 x = build_outer_var_ref (var, ctx);
1774 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1775 gimplify_and_add (x, ilist);
1776 goto do_dtor;
1777 break;
1779 case OMP_CLAUSE_COPYIN:
1780 by_ref = use_pointer_for_field (var, false);
1781 x = build_receiver_ref (var, by_ref, ctx);
1782 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1783 append_to_statement_list (x, &copyin_seq);
1784 copyin_by_ref |= by_ref;
1785 break;
1787 case OMP_CLAUSE_REDUCTION:
1788 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1790 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1791 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1793 else
1795 x = omp_reduction_init (c, TREE_TYPE (new_var));
1796 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1797 x = build_gimple_modify_stmt (new_var, x);
1798 gimplify_and_add (x, ilist);
1800 break;
1802 default:
1803 gcc_unreachable ();
1808 /* The copyin sequence is not to be executed by the main thread, since
1809 that would result in self-copies. Perhaps not visible to scalars,
1810 but it certainly is to C++ operator=. */
1811 if (copyin_seq)
1813 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1814 x = build2 (NE_EXPR, boolean_type_node, x,
1815 build_int_cst (TREE_TYPE (x), 0));
1816 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1817 gimplify_and_add (x, ilist);
1820 /* If any copyin variable is passed by reference, we must ensure the
1821 master thread doesn't modify it before it is copied over in all
1822 threads. Similarly for variables in both firstprivate and
1823 lastprivate clauses we need to ensure the lastprivate copying
1824 happens after firstprivate copying in all threads. */
1825 if (copyin_by_ref || lastprivate_firstprivate)
1826 build_omp_barrier (ilist);
1830 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1831 both parallel and workshare constructs. PREDICATE may be NULL if it's
1832 always true. */
1834 static void
1835 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1836 omp_context *ctx)
1838 tree sub_list, x, c;
1840 /* Early exit if there are no lastprivate clauses. */
1841 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1842 if (clauses == NULL)
1844 /* If this was a workshare clause, see if it had been combined
1845 with its parallel. In that case, look for the clauses on the
1846 parallel statement itself. */
1847 if (is_parallel_ctx (ctx))
1848 return;
1850 ctx = ctx->outer;
1851 if (ctx == NULL || !is_parallel_ctx (ctx))
1852 return;
1854 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1855 OMP_CLAUSE_LASTPRIVATE);
1856 if (clauses == NULL)
1857 return;
1860 sub_list = alloc_stmt_list ();
1862 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1864 tree var, new_var;
1866 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1867 continue;
1869 var = OMP_CLAUSE_DECL (c);
1870 new_var = lookup_decl (var, ctx);
1872 x = build_outer_var_ref (var, ctx);
1873 if (is_reference (var))
1874 new_var = build_fold_indirect_ref (new_var);
1875 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1876 append_to_statement_list (x, &sub_list);
1879 if (predicate)
1880 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1881 else
1882 x = sub_list;
1884 gimplify_and_add (x, stmt_list);
1888 /* Generate code to implement the REDUCTION clauses. */
1890 static void
1891 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1893 tree sub_list = NULL, x, c;
1894 int count = 0;
1896 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1897 update in that case, otherwise use a lock. */
1898 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1899 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1901 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1903 /* Never use OMP_ATOMIC for array reductions. */
1904 count = -1;
1905 break;
1907 count++;
1910 if (count == 0)
1911 return;
1913 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1915 tree var, ref, new_var;
1916 enum tree_code code;
1918 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1919 continue;
1921 var = OMP_CLAUSE_DECL (c);
1922 new_var = lookup_decl (var, ctx);
1923 if (is_reference (var))
1924 new_var = build_fold_indirect_ref (new_var);
1925 ref = build_outer_var_ref (var, ctx);
1926 code = OMP_CLAUSE_REDUCTION_CODE (c);
1928 /* reduction(-:var) sums up the partial results, so it acts
1929 identically to reduction(+:var). */
1930 if (code == MINUS_EXPR)
1931 code = PLUS_EXPR;
1933 if (count == 1)
1935 tree addr = build_fold_addr_expr (ref);
1937 addr = save_expr (addr);
1938 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1939 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1940 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1941 gimplify_and_add (x, stmt_list);
1942 return;
1945 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1947 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1949 if (is_reference (var))
1950 ref = build_fold_addr_expr (ref);
1951 SET_DECL_VALUE_EXPR (placeholder, ref);
1952 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1953 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1954 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1955 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1957 else
1959 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1960 ref = build_outer_var_ref (var, ctx);
1961 x = build_gimple_modify_stmt (ref, x);
1962 append_to_statement_list (x, &sub_list);
1966 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
1967 gimplify_and_add (x, stmt_list);
1969 gimplify_and_add (sub_list, stmt_list);
1971 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
1972 gimplify_and_add (x, stmt_list);
1976 /* Generate code to implement the COPYPRIVATE clauses. */
1978 static void
1979 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1980 omp_context *ctx)
1982 tree c;
1984 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1986 tree var, ref, x;
1987 bool by_ref;
1989 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1990 continue;
1992 var = OMP_CLAUSE_DECL (c);
1993 by_ref = use_pointer_for_field (var, false);
1995 ref = build_sender_ref (var, ctx);
1996 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
1997 x = by_ref ? build_fold_addr_expr (x) : x;
1998 x = build_gimple_modify_stmt (ref, x);
1999 gimplify_and_add (x, slist);
2001 ref = build_receiver_ref (var, by_ref, ctx);
2002 if (is_reference (var))
2004 ref = build_fold_indirect_ref (ref);
2005 var = build_fold_indirect_ref (var);
2007 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2008 gimplify_and_add (x, rlist);
2013 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2014 and REDUCTION from the sender (aka parent) side. */
2016 static void
2017 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2019 tree c;
2021 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2023 tree val, ref, x, var;
2024 bool by_ref, do_in = false, do_out = false;
2026 switch (OMP_CLAUSE_CODE (c))
2028 case OMP_CLAUSE_FIRSTPRIVATE:
2029 case OMP_CLAUSE_COPYIN:
2030 case OMP_CLAUSE_LASTPRIVATE:
2031 case OMP_CLAUSE_REDUCTION:
2032 break;
2033 default:
2034 continue;
2037 var = val = OMP_CLAUSE_DECL (c);
2038 if (ctx->is_nested)
2039 var = lookup_decl_in_outer_ctx (val, ctx);
2041 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2042 && is_global_var (var))
2043 continue;
2044 if (is_variable_sized (val))
2045 continue;
2046 by_ref = use_pointer_for_field (val, false);
2048 switch (OMP_CLAUSE_CODE (c))
2050 case OMP_CLAUSE_FIRSTPRIVATE:
2051 case OMP_CLAUSE_COPYIN:
2052 do_in = true;
2053 break;
2055 case OMP_CLAUSE_LASTPRIVATE:
2056 if (by_ref || is_reference (val))
2058 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2059 continue;
2060 do_in = true;
2062 else
2063 do_out = true;
2064 break;
2066 case OMP_CLAUSE_REDUCTION:
2067 do_in = true;
2068 do_out = !(by_ref || is_reference (val));
2069 break;
2071 default:
2072 gcc_unreachable ();
2075 if (do_in)
2077 ref = build_sender_ref (val, ctx);
2078 x = by_ref ? build_fold_addr_expr (var) : var;
2079 x = build_gimple_modify_stmt (ref, x);
2080 gimplify_and_add (x, ilist);
2083 if (do_out)
2085 ref = build_sender_ref (val, ctx);
2086 x = build_gimple_modify_stmt (var, ref);
2087 gimplify_and_add (x, olist);
2092 /* Generate code to implement SHARED from the sender (aka parent) side.
2093 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2094 got automatically shared. */
2096 static void
2097 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2099 tree var, ovar, nvar, f, x;
2101 if (ctx->record_type == NULL)
2102 return;
2104 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2106 ovar = DECL_ABSTRACT_ORIGIN (f);
2107 nvar = maybe_lookup_decl (ovar, ctx);
2108 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2109 continue;
2111 var = ovar;
2113 /* If CTX is a nested parallel directive. Find the immediately
2114 enclosing parallel or workshare construct that contains a
2115 mapping for OVAR. */
2116 if (ctx->is_nested)
2117 var = lookup_decl_in_outer_ctx (ovar, ctx);
2119 if (use_pointer_for_field (ovar, true))
2121 x = build_sender_ref (ovar, ctx);
2122 var = build_fold_addr_expr (var);
2123 x = build_gimple_modify_stmt (x, var);
2124 gimplify_and_add (x, ilist);
2126 else
2128 x = build_sender_ref (ovar, ctx);
2129 x = build_gimple_modify_stmt (x, var);
2130 gimplify_and_add (x, ilist);
2132 x = build_sender_ref (ovar, ctx);
2133 x = build_gimple_modify_stmt (var, x);
2134 gimplify_and_add (x, olist);
2139 /* Build the function calls to GOMP_parallel_start etc to actually
2140 generate the parallel operation. REGION is the parallel region
2141 being expanded. BB is the block where to insert the code. WS_ARGS
2142 will be set if this is a call to a combined parallel+workshare
2143 construct, it contains the list of additional arguments needed by
2144 the workshare construct. */
2146 static void
2147 expand_parallel_call (struct omp_region *region, basic_block bb,
2148 tree entry_stmt, tree ws_args)
2150 tree t, t1, t2, val, cond, c, list, clauses;
2151 block_stmt_iterator si;
2152 int start_ix;
2154 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2155 push_gimplify_context ();
2157 /* Determine what flavor of GOMP_parallel_start we will be
2158 emitting. */
2159 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2160 if (is_combined_parallel (region))
2162 switch (region->inner->type)
2164 case OMP_FOR:
2165 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2166 + region->inner->sched_kind;
2167 break;
2168 case OMP_SECTIONS:
2169 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2170 break;
2171 default:
2172 gcc_unreachable ();
2176 /* By default, the value of NUM_THREADS is zero (selected at run time)
2177 and there is no conditional. */
2178 cond = NULL_TREE;
2179 val = build_int_cst (unsigned_type_node, 0);
2181 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2182 if (c)
2183 cond = OMP_CLAUSE_IF_EXPR (c);
2185 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2186 if (c)
2187 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2189 /* Ensure 'val' is of the correct type. */
2190 val = fold_convert (unsigned_type_node, val);
2192 /* If we found the clause 'if (cond)', build either
2193 (cond != 0) or (cond ? val : 1u). */
2194 if (cond)
2196 block_stmt_iterator si;
2198 cond = gimple_boolify (cond);
2200 if (integer_zerop (val))
2201 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2202 build_int_cst (TREE_TYPE (cond), 0));
2203 else
2205 basic_block cond_bb, then_bb, else_bb;
2206 edge e;
2207 tree t, tmp;
2209 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2210 e = split_block (bb, NULL);
2211 cond_bb = e->src;
2212 bb = e->dest;
2213 remove_edge (e);
2215 then_bb = create_empty_bb (cond_bb);
2216 else_bb = create_empty_bb (then_bb);
2218 t = build3 (COND_EXPR, void_type_node,
2219 cond, NULL_TREE, NULL_TREE);
2221 si = bsi_start (cond_bb);
2222 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2224 si = bsi_start (then_bb);
2225 t = build_gimple_modify_stmt (tmp, val);
2226 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2228 si = bsi_start (else_bb);
2229 t = build_gimple_modify_stmt (tmp,
2230 build_int_cst (unsigned_type_node, 1));
2231 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2233 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2234 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2235 make_edge (then_bb, bb, EDGE_FALLTHRU);
2236 make_edge (else_bb, bb, EDGE_FALLTHRU);
2238 val = tmp;
2241 list = NULL_TREE;
2242 val = get_formal_tmp_var (val, &list);
2243 si = bsi_start (bb);
2244 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2247 list = NULL_TREE;
2248 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2249 if (t == NULL)
2250 t1 = null_pointer_node;
2251 else
2252 t1 = build_fold_addr_expr (t);
2253 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2255 if (ws_args)
2257 tree args = tree_cons (NULL, t2,
2258 tree_cons (NULL, t1,
2259 tree_cons (NULL, val, ws_args)));
2260 t = build_function_call_expr (built_in_decls[start_ix], args);
2262 else
2263 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2265 gimplify_and_add (t, &list);
2267 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2268 if (t == NULL)
2269 t = null_pointer_node;
2270 else
2271 t = build_fold_addr_expr (t);
2272 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2273 gimplify_and_add (t, &list);
2275 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2276 gimplify_and_add (t, &list);
2278 si = bsi_last (bb);
2279 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2281 pop_gimplify_context (NULL_TREE);
2285 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2286 handler. This prevents programs from violating the structured
2287 block semantics with throws. */
2289 static void
2290 maybe_catch_exception (tree *stmt_p)
2292 tree f, t;
2294 if (!flag_exceptions)
2295 return;
2297 if (lang_protect_cleanup_actions)
2298 t = lang_protect_cleanup_actions ();
2299 else
2300 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2301 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2302 EH_FILTER_MUST_NOT_THROW (f) = 1;
2303 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2305 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2306 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2308 *stmt_p = NULL;
2309 append_to_statement_list (t, stmt_p);
2312 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2314 static tree
2315 list2chain (tree list)
2317 tree t;
2319 for (t = list; t; t = TREE_CHAIN (t))
2321 tree var = TREE_VALUE (t);
2322 if (TREE_CHAIN (t))
2323 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2324 else
2325 TREE_CHAIN (var) = NULL_TREE;
2328 return list ? TREE_VALUE (list) : NULL_TREE;
2332 /* Remove barriers in REGION->EXIT's block. Note that this is only
2333 valid for OMP_PARALLEL regions. Since the end of a parallel region
2334 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2335 left a barrier at the end of the OMP_PARALLEL region can now be
2336 removed. */
2338 static void
2339 remove_exit_barrier (struct omp_region *region)
2341 block_stmt_iterator si;
2342 basic_block exit_bb;
2343 edge_iterator ei;
2344 edge e;
2345 tree t;
2347 exit_bb = region->exit;
2349 /* If the parallel region doesn't return, we don't have REGION->EXIT
2350 block at all. */
2351 if (! exit_bb)
2352 return;
2354 /* The last insn in the block will be the parallel's OMP_RETURN. The
2355 workshare's OMP_RETURN will be in a preceding block. The kinds of
2356 statements that can appear in between are extremely limited -- no
2357 memory operations at all. Here, we allow nothing at all, so the
2358 only thing we allow to precede this OMP_RETURN is a label. */
2359 si = bsi_last (exit_bb);
2360 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2361 bsi_prev (&si);
2362 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2363 return;
2365 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2367 si = bsi_last (e->src);
2368 if (bsi_end_p (si))
2369 continue;
2370 t = bsi_stmt (si);
2371 if (TREE_CODE (t) == OMP_RETURN)
2372 OMP_RETURN_NOWAIT (t) = 1;
2376 static void
2377 remove_exit_barriers (struct omp_region *region)
2379 if (region->type == OMP_PARALLEL)
2380 remove_exit_barrier (region);
2382 if (region->inner)
2384 region = region->inner;
2385 remove_exit_barriers (region);
2386 while (region->next)
2388 region = region->next;
2389 remove_exit_barriers (region);
2394 /* Expand the OpenMP parallel directive starting at REGION. */
2396 static void
2397 expand_omp_parallel (struct omp_region *region)
2399 basic_block entry_bb, exit_bb, new_bb;
2400 struct function *child_cfun, *saved_cfun;
2401 tree child_fn, block, t, ws_args;
2402 block_stmt_iterator si;
2403 tree entry_stmt;
2404 edge e;
2405 bool do_cleanup_cfg = false;
2407 entry_stmt = last_stmt (region->entry);
2408 child_fn = OMP_PARALLEL_FN (entry_stmt);
2409 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2410 saved_cfun = cfun;
2412 entry_bb = region->entry;
2413 exit_bb = region->exit;
2415 if (is_combined_parallel (region))
2416 ws_args = region->ws_args;
2417 else
2418 ws_args = NULL_TREE;
2420 if (child_cfun->cfg)
2422 /* Due to inlining, it may happen that we have already outlined
2423 the region, in which case all we need to do is make the
2424 sub-graph unreachable and emit the parallel call. */
2425 edge entry_succ_e, exit_succ_e;
2426 block_stmt_iterator si;
2428 entry_succ_e = single_succ_edge (entry_bb);
2430 si = bsi_last (entry_bb);
2431 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2432 bsi_remove (&si, true);
2434 new_bb = entry_bb;
2435 remove_edge (entry_succ_e);
2436 if (exit_bb)
2438 exit_succ_e = single_succ_edge (exit_bb);
2439 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2441 do_cleanup_cfg = true;
2443 else
2445 /* If the parallel region needs data sent from the parent
2446 function, then the very first statement (except possible
2447 tree profile counter updates) of the parallel body
2448 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2449 &.OMP_DATA_O is passed as an argument to the child function,
2450 we need to replace it with the argument as seen by the child
2451 function.
2453 In most cases, this will end up being the identity assignment
2454 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2455 a function call that has been inlined, the original PARM_DECL
2456 .OMP_DATA_I may have been converted into a different local
2457 variable. In which case, we need to keep the assignment. */
2458 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2460 basic_block entry_succ_bb = single_succ (entry_bb);
2461 block_stmt_iterator si;
2463 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2465 tree stmt, arg;
2467 gcc_assert (!bsi_end_p (si));
2468 stmt = bsi_stmt (si);
2469 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2470 continue;
2472 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2473 STRIP_NOPS (arg);
2474 if (TREE_CODE (arg) == ADDR_EXPR
2475 && TREE_OPERAND (arg, 0)
2476 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2478 if (GIMPLE_STMT_OPERAND (stmt, 0)
2479 == DECL_ARGUMENTS (child_fn))
2480 bsi_remove (&si, true);
2481 else
2482 GIMPLE_STMT_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2483 break;
2488 /* Declare local variables needed in CHILD_CFUN. */
2489 block = DECL_INITIAL (child_fn);
2490 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2491 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2493 /* Reset DECL_CONTEXT on locals and function arguments. */
2494 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2495 DECL_CONTEXT (t) = child_fn;
2497 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2498 DECL_CONTEXT (t) = child_fn;
2500 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2501 child function. */
2502 si = bsi_last (entry_bb);
2503 t = bsi_stmt (si);
2504 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2505 bsi_remove (&si, true);
2506 e = split_block (entry_bb, t);
2507 entry_bb = e->dest;
2508 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2510 /* Move the parallel region into CHILD_CFUN. We need to reset
2511 dominance information because the expansion of the inner
2512 regions has invalidated it. */
2513 free_dominance_info (CDI_DOMINATORS);
2514 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2515 if (exit_bb)
2516 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2517 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2518 = cfun->curr_properties;
2519 cgraph_add_new_function (child_fn, true);
2521 /* Convert OMP_RETURN into a RETURN_EXPR. */
2522 if (exit_bb)
2524 si = bsi_last (exit_bb);
2525 gcc_assert (!bsi_end_p (si)
2526 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2527 t = build1 (RETURN_EXPR, void_type_node, NULL);
2528 bsi_insert_after (&si, t, BSI_SAME_STMT);
2529 bsi_remove (&si, true);
2533 /* Emit a library call to launch the children threads. */
2534 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2536 if (do_cleanup_cfg)
2538 /* Clean up the unreachable sub-graph we created above. */
2539 free_dominance_info (CDI_DOMINATORS);
2540 free_dominance_info (CDI_POST_DOMINATORS);
2541 cleanup_tree_cfg ();
2546 /* A subroutine of expand_omp_for. Generate code for a parallel
2547 loop with any schedule. Given parameters:
2549 for (V = N1; V cond N2; V += STEP) BODY;
2551 where COND is "<" or ">", we generate pseudocode
2553 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2554 if (more) goto L0; else goto L3;
2556 V = istart0;
2557 iend = iend0;
2559 BODY;
2560 V += STEP;
2561 if (V cond iend) goto L1; else goto L2;
2563 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2566 If this is a combined omp parallel loop, instead of the call to
2567 GOMP_loop_foo_start, we emit 'goto L3'. */
2569 static void
2570 expand_omp_for_generic (struct omp_region *region,
2571 struct omp_for_data *fd,
2572 enum built_in_function start_fn,
2573 enum built_in_function next_fn)
2575 tree type, istart0, iend0, iend;
2576 tree t, list;
2577 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2578 basic_block l2_bb = NULL, l3_bb = NULL;
2579 block_stmt_iterator si;
2580 bool in_combined_parallel = is_combined_parallel (region);
2582 type = TREE_TYPE (fd->v);
2584 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2585 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2586 iend = create_tmp_var (type, NULL);
2587 TREE_ADDRESSABLE (istart0) = 1;
2588 TREE_ADDRESSABLE (iend0) = 1;
2590 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
2592 entry_bb = region->entry;
2593 l0_bb = create_empty_bb (entry_bb);
2594 l1_bb = single_succ (entry_bb);
2596 cont_bb = region->cont;
2597 exit_bb = region->exit;
2598 if (cont_bb)
2600 l2_bb = create_empty_bb (cont_bb);
2601 l3_bb = single_succ (cont_bb);
2604 si = bsi_last (entry_bb);
2605 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2606 if (!in_combined_parallel)
2608 tree t0, t1, t2, t3, t4;
2609 /* If this is not a combined parallel loop, emit a call to
2610 GOMP_loop_foo_start in ENTRY_BB. */
2611 list = alloc_stmt_list ();
2612 t4 = build_fold_addr_expr (iend0);
2613 t3 = build_fold_addr_expr (istart0);
2614 t2 = fold_convert (long_integer_type_node, fd->step);
2615 t1 = fold_convert (long_integer_type_node, fd->n2);
2616 t0 = fold_convert (long_integer_type_node, fd->n1);
2617 if (fd->chunk_size)
2619 t = fold_convert (long_integer_type_node, fd->chunk_size);
2620 t = build_call_expr (built_in_decls[start_fn], 6,
2621 t0, t1, t2, t, t3, t4);
2623 else
2624 t = build_call_expr (built_in_decls[start_fn], 5,
2625 t0, t1, t2, t3, t4);
2626 t = get_formal_tmp_var (t, &list);
2627 if (cont_bb)
2629 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2630 append_to_statement_list (t, &list);
2632 bsi_insert_after (&si, list, BSI_SAME_STMT);
2634 bsi_remove (&si, true);
2636 /* Iteration setup for sequential loop goes in L0_BB. */
2637 list = alloc_stmt_list ();
2638 t = fold_convert (type, istart0);
2639 t = build_gimple_modify_stmt (fd->v, t);
2640 gimplify_and_add (t, &list);
2642 t = fold_convert (type, iend0);
2643 t = build_gimple_modify_stmt (iend, t);
2644 gimplify_and_add (t, &list);
2646 si = bsi_start (l0_bb);
2647 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2649 /* Handle the rare case where BODY doesn't ever return. */
2650 if (cont_bb == NULL)
2652 remove_edge (single_succ_edge (entry_bb));
2653 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
2654 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2655 return;
2658 /* Code to control the increment and predicate for the sequential
2659 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2660 that we can inherit all the edges going out of the loop
2661 body). */
2662 list = alloc_stmt_list ();
2664 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2665 t = build_gimple_modify_stmt (fd->v, t);
2666 gimplify_and_add (t, &list);
2668 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2669 t = get_formal_tmp_var (t, &list);
2670 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2671 append_to_statement_list (t, &list);
2673 si = bsi_last (cont_bb);
2674 bsi_insert_after (&si, list, BSI_SAME_STMT);
2675 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2676 bsi_remove (&si, true);
2678 /* Emit code to get the next parallel iteration in L2_BB. */
2679 list = alloc_stmt_list ();
2681 t = build_call_expr (built_in_decls[next_fn], 2,
2682 build_fold_addr_expr (istart0),
2683 build_fold_addr_expr (iend0));
2684 t = get_formal_tmp_var (t, &list);
2685 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2686 append_to_statement_list (t, &list);
2688 si = bsi_start (l2_bb);
2689 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2691 /* Add the loop cleanup function. */
2692 si = bsi_last (exit_bb);
2693 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2694 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2695 else
2696 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2697 t = build_call_expr (t, 0);
2698 bsi_insert_after (&si, t, BSI_SAME_STMT);
2699 bsi_remove (&si, true);
2701 /* Connect the new blocks. */
2702 remove_edge (single_succ_edge (entry_bb));
2703 if (in_combined_parallel)
2704 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2705 else
2707 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2708 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2711 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2713 remove_edge (single_succ_edge (cont_bb));
2714 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2715 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2717 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2718 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2722 /* A subroutine of expand_omp_for. Generate code for a parallel
2723 loop with static schedule and no specified chunk size. Given
2724 parameters:
2726 for (V = N1; V cond N2; V += STEP) BODY;
2728 where COND is "<" or ">", we generate pseudocode
2730 if (cond is <)
2731 adj = STEP - 1;
2732 else
2733 adj = STEP + 1;
2734 n = (adj + N2 - N1) / STEP;
2735 q = n / nthreads;
2736 q += (q * nthreads != n);
2737 s0 = q * threadid;
2738 e0 = min(s0 + q, n);
2739 if (s0 >= e0) goto L2; else goto L0;
2741 V = s0 * STEP + N1;
2742 e = e0 * STEP + N1;
2744 BODY;
2745 V += STEP;
2746 if (V cond e) goto L1;
2750 static void
2751 expand_omp_for_static_nochunk (struct omp_region *region,
2752 struct omp_for_data *fd)
2754 tree n, q, s0, e0, e, t, nthreads, threadid;
2755 tree type, list;
2756 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2757 basic_block fin_bb;
2758 block_stmt_iterator si;
2760 type = TREE_TYPE (fd->v);
2762 entry_bb = region->entry;
2763 seq_start_bb = create_empty_bb (entry_bb);
2764 body_bb = single_succ (entry_bb);
2765 cont_bb = region->cont;
2766 fin_bb = single_succ (cont_bb);
2767 exit_bb = region->exit;
2769 /* Iteration space partitioning goes in ENTRY_BB. */
2770 list = alloc_stmt_list ();
2772 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2773 t = fold_convert (type, t);
2774 nthreads = get_formal_tmp_var (t, &list);
2776 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2777 t = fold_convert (type, t);
2778 threadid = get_formal_tmp_var (t, &list);
2780 fd->n1 = fold_convert (type, fd->n1);
2781 if (!is_gimple_val (fd->n1))
2782 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2784 fd->n2 = fold_convert (type, fd->n2);
2785 if (!is_gimple_val (fd->n2))
2786 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2788 fd->step = fold_convert (type, fd->step);
2789 if (!is_gimple_val (fd->step))
2790 fd->step = get_formal_tmp_var (fd->step, &list);
2792 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2793 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2794 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2795 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2796 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2797 t = fold_convert (type, t);
2798 if (is_gimple_val (t))
2799 n = t;
2800 else
2801 n = get_formal_tmp_var (t, &list);
2803 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2804 q = get_formal_tmp_var (t, &list);
2806 t = build2 (MULT_EXPR, type, q, nthreads);
2807 t = build2 (NE_EXPR, type, t, n);
2808 t = build2 (PLUS_EXPR, type, q, t);
2809 q = get_formal_tmp_var (t, &list);
2811 t = build2 (MULT_EXPR, type, q, threadid);
2812 s0 = get_formal_tmp_var (t, &list);
2814 t = build2 (PLUS_EXPR, type, s0, q);
2815 t = build2 (MIN_EXPR, type, t, n);
2816 e0 = get_formal_tmp_var (t, &list);
2818 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2819 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2820 append_to_statement_list (t, &list);
2822 si = bsi_last (entry_bb);
2823 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2824 bsi_insert_after (&si, list, BSI_SAME_STMT);
2825 bsi_remove (&si, true);
2827 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2828 list = alloc_stmt_list ();
2830 t = fold_convert (type, s0);
2831 t = build2 (MULT_EXPR, type, t, fd->step);
2832 t = build2 (PLUS_EXPR, type, t, fd->n1);
2833 t = build_gimple_modify_stmt (fd->v, t);
2834 gimplify_and_add (t, &list);
2836 t = fold_convert (type, e0);
2837 t = build2 (MULT_EXPR, type, t, fd->step);
2838 t = build2 (PLUS_EXPR, type, t, fd->n1);
2839 e = get_formal_tmp_var (t, &list);
2841 si = bsi_start (seq_start_bb);
2842 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2844 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2845 list = alloc_stmt_list ();
2847 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2848 t = build_gimple_modify_stmt (fd->v, t);
2849 gimplify_and_add (t, &list);
2851 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2852 t = get_formal_tmp_var (t, &list);
2853 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2854 append_to_statement_list (t, &list);
2856 si = bsi_last (cont_bb);
2857 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2858 bsi_insert_after (&si, list, BSI_SAME_STMT);
2859 bsi_remove (&si, true);
2861 /* Replace the OMP_RETURN with a barrier, or nothing. */
2862 si = bsi_last (exit_bb);
2863 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2865 list = alloc_stmt_list ();
2866 build_omp_barrier (&list);
2867 bsi_insert_after (&si, list, BSI_SAME_STMT);
2869 bsi_remove (&si, true);
2871 /* Connect all the blocks. */
2872 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2874 remove_edge (single_succ_edge (entry_bb));
2875 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2876 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2878 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2879 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2883 /* A subroutine of expand_omp_for. Generate code for a parallel
2884 loop with static schedule and a specified chunk size. Given
2885 parameters:
2887 for (V = N1; V cond N2; V += STEP) BODY;
2889 where COND is "<" or ">", we generate pseudocode
2891 if (cond is <)
2892 adj = STEP - 1;
2893 else
2894 adj = STEP + 1;
2895 n = (adj + N2 - N1) / STEP;
2896 trip = 0;
2898 s0 = (trip * nthreads + threadid) * CHUNK;
2899 e0 = min(s0 + CHUNK, n);
2900 if (s0 < n) goto L1; else goto L4;
2902 V = s0 * STEP + N1;
2903 e = e0 * STEP + N1;
2905 BODY;
2906 V += STEP;
2907 if (V cond e) goto L2; else goto L3;
2909 trip += 1;
2910 goto L0;
2914 static void
2915 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2917 tree n, s0, e0, e, t;
2918 tree trip, nthreads, threadid;
2919 tree type;
2920 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2921 basic_block trip_update_bb, cont_bb, fin_bb;
2922 tree list;
2923 block_stmt_iterator si;
2925 type = TREE_TYPE (fd->v);
2927 entry_bb = region->entry;
2928 iter_part_bb = create_empty_bb (entry_bb);
2929 seq_start_bb = create_empty_bb (iter_part_bb);
2930 body_bb = single_succ (entry_bb);
2931 cont_bb = region->cont;
2932 trip_update_bb = create_empty_bb (cont_bb);
2933 fin_bb = single_succ (cont_bb);
2934 exit_bb = region->exit;
2936 /* Trip and adjustment setup goes in ENTRY_BB. */
2937 list = alloc_stmt_list ();
2939 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2940 t = fold_convert (type, t);
2941 nthreads = get_formal_tmp_var (t, &list);
2943 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2944 t = fold_convert (type, t);
2945 threadid = get_formal_tmp_var (t, &list);
2947 fd->n1 = fold_convert (type, fd->n1);
2948 if (!is_gimple_val (fd->n1))
2949 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2951 fd->n2 = fold_convert (type, fd->n2);
2952 if (!is_gimple_val (fd->n2))
2953 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2955 fd->step = fold_convert (type, fd->step);
2956 if (!is_gimple_val (fd->step))
2957 fd->step = get_formal_tmp_var (fd->step, &list);
2959 fd->chunk_size = fold_convert (type, fd->chunk_size);
2960 if (!is_gimple_val (fd->chunk_size))
2961 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2963 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2964 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2965 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2966 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2967 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2968 t = fold_convert (type, t);
2969 if (is_gimple_val (t))
2970 n = t;
2971 else
2972 n = get_formal_tmp_var (t, &list);
2974 t = build_int_cst (type, 0);
2975 trip = get_initialized_tmp_var (t, &list, NULL);
2977 si = bsi_last (entry_bb);
2978 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2979 bsi_insert_after (&si, list, BSI_SAME_STMT);
2980 bsi_remove (&si, true);
2982 /* Iteration space partitioning goes in ITER_PART_BB. */
2983 list = alloc_stmt_list ();
2985 t = build2 (MULT_EXPR, type, trip, nthreads);
2986 t = build2 (PLUS_EXPR, type, t, threadid);
2987 t = build2 (MULT_EXPR, type, t, fd->chunk_size);
2988 s0 = get_formal_tmp_var (t, &list);
2990 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
2991 t = build2 (MIN_EXPR, type, t, n);
2992 e0 = get_formal_tmp_var (t, &list);
2994 t = build2 (LT_EXPR, boolean_type_node, s0, n);
2995 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2996 append_to_statement_list (t, &list);
2998 si = bsi_start (iter_part_bb);
2999 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3001 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3002 list = alloc_stmt_list ();
3004 t = fold_convert (type, s0);
3005 t = build2 (MULT_EXPR, type, t, fd->step);
3006 t = build2 (PLUS_EXPR, type, t, fd->n1);
3007 t = build_gimple_modify_stmt (fd->v, t);
3008 gimplify_and_add (t, &list);
3010 t = fold_convert (type, e0);
3011 t = build2 (MULT_EXPR, type, t, fd->step);
3012 t = build2 (PLUS_EXPR, type, t, fd->n1);
3013 e = get_formal_tmp_var (t, &list);
3015 si = bsi_start (seq_start_bb);
3016 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3018 /* The code controlling the sequential loop goes in CONT_BB,
3019 replacing the OMP_CONTINUE. */
3020 list = alloc_stmt_list ();
3022 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3023 t = build_gimple_modify_stmt (fd->v, t);
3024 gimplify_and_add (t, &list);
3026 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3027 t = get_formal_tmp_var (t, &list);
3028 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3029 append_to_statement_list (t, &list);
3031 si = bsi_last (cont_bb);
3032 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3033 bsi_insert_after (&si, list, BSI_SAME_STMT);
3034 bsi_remove (&si, true);
3036 /* Trip update code goes into TRIP_UPDATE_BB. */
3037 list = alloc_stmt_list ();
3039 t = build_int_cst (type, 1);
3040 t = build2 (PLUS_EXPR, type, trip, t);
3041 t = build_gimple_modify_stmt (trip, t);
3042 gimplify_and_add (t, &list);
3044 si = bsi_start (trip_update_bb);
3045 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3047 /* Replace the OMP_RETURN with a barrier, or nothing. */
3048 si = bsi_last (exit_bb);
3049 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3051 list = alloc_stmt_list ();
3052 build_omp_barrier (&list);
3053 bsi_insert_after (&si, list, BSI_SAME_STMT);
3055 bsi_remove (&si, true);
3057 /* Connect the new blocks. */
3058 remove_edge (single_succ_edge (entry_bb));
3059 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3061 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3062 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3064 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3066 remove_edge (single_succ_edge (cont_bb));
3067 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3068 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3070 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3074 /* Expand the OpenMP loop defined by REGION. */
3076 static void
3077 expand_omp_for (struct omp_region *region)
3079 struct omp_for_data fd;
3081 push_gimplify_context ();
3083 extract_omp_for_data (last_stmt (region->entry), &fd);
3084 region->sched_kind = fd.sched_kind;
3086 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3087 && !fd.have_ordered
3088 && region->cont
3089 && region->exit)
3091 if (fd.chunk_size == NULL)
3092 expand_omp_for_static_nochunk (region, &fd);
3093 else
3094 expand_omp_for_static_chunk (region, &fd);
3096 else
3098 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3099 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3100 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3101 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3104 pop_gimplify_context (NULL);
3108 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3110 v = GOMP_sections_start (n);
3112 switch (v)
3114 case 0:
3115 goto L2;
3116 case 1:
3117 section 1;
3118 goto L1;
3119 case 2:
3121 case n:
3123 default:
3124 abort ();
3127 v = GOMP_sections_next ();
3128 goto L0;
3130 reduction;
3132 If this is a combined parallel sections, replace the call to
3133 GOMP_sections_start with 'goto L1'. */
3135 static void
3136 expand_omp_sections (struct omp_region *region)
3138 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3139 unsigned i, len;
3140 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3141 block_stmt_iterator si;
3142 struct omp_region *inner;
3143 edge e;
3145 entry_bb = region->entry;
3146 l0_bb = create_empty_bb (entry_bb);
3147 l0 = tree_block_label (l0_bb);
3149 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
3150 l1_bb = region->cont;
3151 if (l1_bb)
3153 l2_bb = single_succ (l1_bb);
3154 default_bb = create_empty_bb (l1_bb->prev_bb);
3156 l1 = tree_block_label (l1_bb);
3158 else
3160 l2_bb = create_empty_bb (l0_bb);
3161 default_bb = l2_bb;
3163 l1 = NULL;
3165 l2 = tree_block_label (l2_bb);
3167 exit_bb = region->exit;
3169 v = create_tmp_var (unsigned_type_node, ".section");
3171 /* We will build a switch() with enough cases for all the
3172 OMP_SECTION regions, a '0' case to handle the end of more work
3173 and a default case to abort if something goes wrong. */
3174 len = EDGE_COUNT (entry_bb->succs);
3175 label_vec = make_tree_vec (len + 2);
3177 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3178 OMP_SECTIONS statement. */
3179 si = bsi_last (entry_bb);
3180 sections_stmt = bsi_stmt (si);
3181 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3182 if (!is_combined_parallel (region))
3184 /* If we are not inside a combined parallel+sections region,
3185 call GOMP_sections_start. */
3186 t = build_int_cst (unsigned_type_node, len);
3187 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3188 t = build_call_expr (u, 1, t);
3189 t = build_gimple_modify_stmt (v, t);
3190 bsi_insert_after (&si, t, BSI_SAME_STMT);
3192 bsi_remove (&si, true);
3194 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
3195 si = bsi_start (l0_bb);
3197 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3198 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3200 t = build3 (CASE_LABEL_EXPR, void_type_node,
3201 build_int_cst (unsigned_type_node, 0), NULL, l2);
3202 TREE_VEC_ELT (label_vec, 0) = t;
3203 make_edge (l0_bb, l2_bb, 0);
3205 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3206 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3208 basic_block s_entry_bb, s_exit_bb;
3210 s_entry_bb = inner->entry;
3211 s_exit_bb = inner->exit;
3213 t = tree_block_label (s_entry_bb);
3214 u = build_int_cst (unsigned_type_node, i);
3215 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3216 TREE_VEC_ELT (label_vec, i) = u;
3218 si = bsi_last (s_entry_bb);
3219 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3220 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3221 bsi_remove (&si, true);
3223 e = single_pred_edge (s_entry_bb);
3224 e->flags = 0;
3225 redirect_edge_pred (e, l0_bb);
3227 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3229 if (s_exit_bb == NULL)
3230 continue;
3232 si = bsi_last (s_exit_bb);
3233 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3234 bsi_remove (&si, true);
3236 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3239 /* Error handling code goes in DEFAULT_BB. */
3240 t = tree_block_label (default_bb);
3241 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3242 TREE_VEC_ELT (label_vec, len + 1) = u;
3243 make_edge (l0_bb, default_bb, 0);
3245 si = bsi_start (default_bb);
3246 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3247 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3249 /* Code to get the next section goes in L1_BB. */
3250 if (l1_bb)
3252 si = bsi_last (l1_bb);
3253 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3255 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3256 t = build_gimple_modify_stmt (v, t);
3257 bsi_insert_after (&si, t, BSI_SAME_STMT);
3258 bsi_remove (&si, true);
3261 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3262 if (exit_bb)
3264 si = bsi_last (exit_bb);
3265 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3266 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3267 else
3268 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3269 t = build_call_expr (t, 0);
3270 bsi_insert_after (&si, t, BSI_SAME_STMT);
3271 bsi_remove (&si, true);
3274 /* Connect the new blocks. */
3275 if (is_combined_parallel (region))
3277 /* If this was a combined parallel+sections region, we did not
3278 emit a GOMP_sections_start in the entry block, so we just
3279 need to jump to L1_BB to get the next section. */
3280 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3282 else
3283 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3285 if (l1_bb)
3287 e = single_succ_edge (l1_bb);
3288 redirect_edge_succ (e, l0_bb);
3289 e->flags = EDGE_FALLTHRU;
3294 /* Expand code for an OpenMP single directive. We've already expanded
3295 much of the code, here we simply place the GOMP_barrier call. */
3297 static void
3298 expand_omp_single (struct omp_region *region)
3300 basic_block entry_bb, exit_bb;
3301 block_stmt_iterator si;
3302 bool need_barrier = false;
3304 entry_bb = region->entry;
3305 exit_bb = region->exit;
3307 si = bsi_last (entry_bb);
3308 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3309 be removed. We need to ensure that the thread that entered the single
3310 does not exit before the data is copied out by the other threads. */
3311 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3312 OMP_CLAUSE_COPYPRIVATE))
3313 need_barrier = true;
3314 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3315 bsi_remove (&si, true);
3316 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3318 si = bsi_last (exit_bb);
3319 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3321 tree t = alloc_stmt_list ();
3322 build_omp_barrier (&t);
3323 bsi_insert_after (&si, t, BSI_SAME_STMT);
3325 bsi_remove (&si, true);
3326 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3330 /* Generic expansion for OpenMP synchronization directives: master,
3331 ordered and critical. All we need to do here is remove the entry
3332 and exit markers for REGION. */
3334 static void
3335 expand_omp_synch (struct omp_region *region)
3337 basic_block entry_bb, exit_bb;
3338 block_stmt_iterator si;
3340 entry_bb = region->entry;
3341 exit_bb = region->exit;
3343 si = bsi_last (entry_bb);
3344 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3345 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3346 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3347 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3348 bsi_remove (&si, true);
3349 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3351 if (exit_bb)
3353 si = bsi_last (exit_bb);
3354 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3355 bsi_remove (&si, true);
3356 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3361 /* Expand the parallel region tree rooted at REGION. Expansion
3362 proceeds in depth-first order. Innermost regions are expanded
3363 first. This way, parallel regions that require a new function to
3364 be created (e.g., OMP_PARALLEL) can be expanded without having any
3365 internal dependencies in their body. */
3367 static void
3368 expand_omp (struct omp_region *region)
3370 while (region)
3372 if (region->inner)
3373 expand_omp (region->inner);
3375 switch (region->type)
3377 case OMP_PARALLEL:
3378 expand_omp_parallel (region);
3379 break;
3381 case OMP_FOR:
3382 expand_omp_for (region);
3383 break;
3385 case OMP_SECTIONS:
3386 expand_omp_sections (region);
3387 break;
3389 case OMP_SECTION:
3390 /* Individual omp sections are handled together with their
3391 parent OMP_SECTIONS region. */
3392 break;
3394 case OMP_SINGLE:
3395 expand_omp_single (region);
3396 break;
3398 case OMP_MASTER:
3399 case OMP_ORDERED:
3400 case OMP_CRITICAL:
3401 expand_omp_synch (region);
3402 break;
3404 default:
3405 gcc_unreachable ();
3408 region = region->next;
3413 /* Helper for build_omp_regions. Scan the dominator tree starting at
3414 block BB. PARENT is the region that contains BB. */
3416 static void
3417 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3419 block_stmt_iterator si;
3420 tree stmt;
3421 basic_block son;
3423 si = bsi_last (bb);
3424 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3426 struct omp_region *region;
3427 enum tree_code code;
3429 stmt = bsi_stmt (si);
3430 code = TREE_CODE (stmt);
3432 if (code == OMP_RETURN)
3434 /* STMT is the return point out of region PARENT. Mark it
3435 as the exit point and make PARENT the immediately
3436 enclosing region. */
3437 gcc_assert (parent);
3438 region = parent;
3439 region->exit = bb;
3440 parent = parent->outer;
3442 /* If REGION is a parallel region, determine whether it is
3443 a combined parallel+workshare region. */
3444 if (region->type == OMP_PARALLEL)
3445 determine_parallel_type (region);
3447 else if (code == OMP_CONTINUE)
3449 gcc_assert (parent);
3450 parent->cont = bb;
3452 else
3454 /* Otherwise, this directive becomes the parent for a new
3455 region. */
3456 region = new_omp_region (bb, code, parent);
3457 parent = region;
3461 for (son = first_dom_son (CDI_DOMINATORS, bb);
3462 son;
3463 son = next_dom_son (CDI_DOMINATORS, son))
3464 build_omp_regions_1 (son, parent);
3468 /* Scan the CFG and build a tree of OMP regions. Return the root of
3469 the OMP region tree. */
3471 static void
3472 build_omp_regions (void)
3474 gcc_assert (root_omp_region == NULL);
3475 calculate_dominance_info (CDI_DOMINATORS);
3476 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3480 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3482 static unsigned int
3483 execute_expand_omp (void)
3485 build_omp_regions ();
3487 if (!root_omp_region)
3488 return 0;
3490 if (dump_file)
3492 fprintf (dump_file, "\nOMP region tree\n\n");
3493 dump_omp_region (dump_file, root_omp_region, 0);
3494 fprintf (dump_file, "\n");
3497 remove_exit_barriers (root_omp_region);
3499 expand_omp (root_omp_region);
3501 free_dominance_info (CDI_DOMINATORS);
3502 free_dominance_info (CDI_POST_DOMINATORS);
3503 cleanup_tree_cfg ();
3505 free_omp_regions ();
3507 return 0;
3510 static bool
3511 gate_expand_omp (void)
3513 return flag_openmp != 0 && errorcount == 0;
3516 struct tree_opt_pass pass_expand_omp =
3518 "ompexp", /* name */
3519 gate_expand_omp, /* gate */
3520 execute_expand_omp, /* execute */
3521 NULL, /* sub */
3522 NULL, /* next */
3523 0, /* static_pass_number */
3524 0, /* tv_id */
3525 PROP_gimple_any, /* properties_required */
3526 PROP_gimple_lomp, /* properties_provided */
3527 0, /* properties_destroyed */
3528 0, /* todo_flags_start */
3529 TODO_dump_func, /* todo_flags_finish */
3530 0 /* letter */
3533 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3535 /* Lower the OpenMP sections directive in *STMT_P. */
3537 static void
3538 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3540 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3541 tree t, dlist;
3542 tree_stmt_iterator tsi;
3543 unsigned i, len;
3545 stmt = *stmt_p;
3547 push_gimplify_context ();
3549 dlist = NULL;
3550 ilist = NULL;
3551 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3553 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3554 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3555 continue;
3557 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3558 body = alloc_stmt_list ();
3559 for (i = 0; i < len; i++, tsi_next (&tsi))
3561 omp_context *sctx;
3562 tree sec_start, sec_end;
3564 sec_start = tsi_stmt (tsi);
3565 sctx = maybe_lookup_ctx (sec_start);
3566 gcc_assert (sctx);
3568 append_to_statement_list (sec_start, &body);
3570 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3571 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3572 OMP_SECTION_BODY (sec_start) = NULL;
3574 if (i == len - 1)
3576 tree l = alloc_stmt_list ();
3577 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3578 &l, ctx);
3579 append_to_statement_list (l, &body);
3580 OMP_SECTION_LAST (sec_start) = 1;
3583 sec_end = make_node (OMP_RETURN);
3584 append_to_statement_list (sec_end, &body);
3587 block = make_node (BLOCK);
3588 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3590 olist = NULL_TREE;
3591 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3593 pop_gimplify_context (NULL_TREE);
3594 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3596 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3597 TREE_SIDE_EFFECTS (new_stmt) = 1;
3599 new_body = alloc_stmt_list ();
3600 append_to_statement_list (ilist, &new_body);
3601 append_to_statement_list (stmt, &new_body);
3602 append_to_statement_list (bind, &new_body);
3604 t = make_node (OMP_CONTINUE);
3605 append_to_statement_list (t, &new_body);
3607 append_to_statement_list (olist, &new_body);
3608 append_to_statement_list (dlist, &new_body);
3610 maybe_catch_exception (&new_body);
3612 t = make_node (OMP_RETURN);
3613 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3614 OMP_CLAUSE_NOWAIT);
3615 append_to_statement_list (t, &new_body);
3617 BIND_EXPR_BODY (new_stmt) = new_body;
3618 OMP_SECTIONS_BODY (stmt) = NULL;
3620 *stmt_p = new_stmt;
3624 /* A subroutine of lower_omp_single. Expand the simple form of
3625 an OMP_SINGLE, without a copyprivate clause:
3627 if (GOMP_single_start ())
3628 BODY;
3629 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3631 FIXME. It may be better to delay expanding the logic of this until
3632 pass_expand_omp. The expanded logic may make the job more difficult
3633 to a synchronization analysis pass. */
3635 static void
3636 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3638 tree t;
3640 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3641 t = build3 (COND_EXPR, void_type_node, t,
3642 OMP_SINGLE_BODY (single_stmt), NULL);
3643 gimplify_and_add (t, pre_p);
3647 /* A subroutine of lower_omp_single. Expand the simple form of
3648 an OMP_SINGLE, with a copyprivate clause:
3650 #pragma omp single copyprivate (a, b, c)
3652 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3655 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3657 BODY;
3658 copyout.a = a;
3659 copyout.b = b;
3660 copyout.c = c;
3661 GOMP_single_copy_end (&copyout);
3663 else
3665 a = copyout_p->a;
3666 b = copyout_p->b;
3667 c = copyout_p->c;
3669 GOMP_barrier ();
3672 FIXME. It may be better to delay expanding the logic of this until
3673 pass_expand_omp. The expanded logic may make the job more difficult
3674 to a synchronization analysis pass. */
3676 static void
3677 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3679 tree ptr_type, t, l0, l1, l2, copyin_seq;
3681 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3683 ptr_type = build_pointer_type (ctx->record_type);
3684 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3686 l0 = create_artificial_label ();
3687 l1 = create_artificial_label ();
3688 l2 = create_artificial_label ();
3690 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3691 t = fold_convert (ptr_type, t);
3692 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3693 gimplify_and_add (t, pre_p);
3695 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3696 build_int_cst (ptr_type, 0));
3697 t = build3 (COND_EXPR, void_type_node, t,
3698 build_and_jump (&l0), build_and_jump (&l1));
3699 gimplify_and_add (t, pre_p);
3701 t = build1 (LABEL_EXPR, void_type_node, l0);
3702 gimplify_and_add (t, pre_p);
3704 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3706 copyin_seq = NULL;
3707 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3708 &copyin_seq, ctx);
3710 t = build_fold_addr_expr (ctx->sender_decl);
3711 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3712 gimplify_and_add (t, pre_p);
3714 t = build_and_jump (&l2);
3715 gimplify_and_add (t, pre_p);
3717 t = build1 (LABEL_EXPR, void_type_node, l1);
3718 gimplify_and_add (t, pre_p);
3720 append_to_statement_list (copyin_seq, pre_p);
3722 t = build1 (LABEL_EXPR, void_type_node, l2);
3723 gimplify_and_add (t, pre_p);
3727 /* Expand code for an OpenMP single directive. */
3729 static void
3730 lower_omp_single (tree *stmt_p, omp_context *ctx)
3732 tree t, bind, block, single_stmt = *stmt_p, dlist;
3734 push_gimplify_context ();
3736 block = make_node (BLOCK);
3737 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3738 TREE_SIDE_EFFECTS (bind) = 1;
3740 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3741 &BIND_EXPR_BODY (bind), &dlist, ctx);
3742 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3744 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3746 if (ctx->record_type)
3747 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3748 else
3749 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3751 OMP_SINGLE_BODY (single_stmt) = NULL;
3753 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3755 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3757 t = make_node (OMP_RETURN);
3758 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3759 OMP_CLAUSE_NOWAIT);
3760 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3762 pop_gimplify_context (bind);
3764 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3765 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3769 /* Expand code for an OpenMP master directive. */
3771 static void
3772 lower_omp_master (tree *stmt_p, omp_context *ctx)
3774 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3776 push_gimplify_context ();
3778 block = make_node (BLOCK);
3779 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3780 TREE_SIDE_EFFECTS (bind) = 1;
3782 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3784 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3785 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3786 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3787 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3789 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3790 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3791 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3792 OMP_MASTER_BODY (stmt) = NULL;
3794 x = build1 (LABEL_EXPR, void_type_node, lab);
3795 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3797 x = make_node (OMP_RETURN);
3798 OMP_RETURN_NOWAIT (x) = 1;
3799 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3801 pop_gimplify_context (bind);
3803 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3804 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3808 /* Expand code for an OpenMP ordered directive. */
3810 static void
3811 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3813 tree bind, block, stmt = *stmt_p, x;
3815 push_gimplify_context ();
3817 block = make_node (BLOCK);
3818 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3819 TREE_SIDE_EFFECTS (bind) = 1;
3821 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3823 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
3824 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3826 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3827 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3828 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3829 OMP_ORDERED_BODY (stmt) = NULL;
3831 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
3832 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3834 x = make_node (OMP_RETURN);
3835 OMP_RETURN_NOWAIT (x) = 1;
3836 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3838 pop_gimplify_context (bind);
3840 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3841 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3845 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3846 substitution of a couple of function calls. But in the NAMED case,
3847 requires that languages coordinate a symbol name. It is therefore
3848 best put here in common code. */
3850 static GTY((param1_is (tree), param2_is (tree)))
3851 splay_tree critical_name_mutexes;
3853 static void
3854 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3856 tree bind, block, stmt = *stmt_p;
3857 tree t, lock, unlock, name;
3859 name = OMP_CRITICAL_NAME (stmt);
3860 if (name)
3862 tree decl;
3863 splay_tree_node n;
3865 if (!critical_name_mutexes)
3866 critical_name_mutexes
3867 = splay_tree_new_ggc (splay_tree_compare_pointers);
3869 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3870 if (n == NULL)
3872 char *new_str;
3874 decl = create_tmp_var_raw (ptr_type_node, NULL);
3876 new_str = ACONCAT ((".gomp_critical_user_",
3877 IDENTIFIER_POINTER (name), NULL));
3878 DECL_NAME (decl) = get_identifier (new_str);
3879 TREE_PUBLIC (decl) = 1;
3880 TREE_STATIC (decl) = 1;
3881 DECL_COMMON (decl) = 1;
3882 DECL_ARTIFICIAL (decl) = 1;
3883 DECL_IGNORED_P (decl) = 1;
3884 varpool_finalize_decl (decl);
3886 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3887 (splay_tree_value) decl);
3889 else
3890 decl = (tree) n->value;
3892 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3893 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
3895 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3896 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
3898 else
3900 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3901 lock = build_call_expr (lock, 0);
3903 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3904 unlock = build_call_expr (unlock, 0);
3907 push_gimplify_context ();
3909 block = make_node (BLOCK);
3910 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3911 TREE_SIDE_EFFECTS (bind) = 1;
3913 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3915 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3917 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3918 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3919 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3920 OMP_CRITICAL_BODY (stmt) = NULL;
3922 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3924 t = make_node (OMP_RETURN);
3925 OMP_RETURN_NOWAIT (t) = 1;
3926 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3928 pop_gimplify_context (bind);
3929 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3930 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3934 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3935 for a lastprivate clause. Given a loop control predicate of (V
3936 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3937 is appended to *DLIST, iterator initialization is appended to
3938 *BODY_P. */
3940 static void
3941 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3942 tree *dlist, struct omp_context *ctx)
3944 tree clauses, cond, stmts, vinit, t;
3945 enum tree_code cond_code;
3947 cond_code = fd->cond_code;
3948 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3950 /* When possible, use a strict equality expression. This can let VRP
3951 type optimizations deduce the value and remove a copy. */
3952 if (host_integerp (fd->step, 0))
3954 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3955 if (step == 1 || step == -1)
3956 cond_code = EQ_EXPR;
3959 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3961 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3962 stmts = NULL;
3963 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
3964 if (stmts != NULL)
3966 append_to_statement_list (stmts, dlist);
3968 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
3969 vinit = fd->n1;
3970 if (cond_code == EQ_EXPR
3971 && host_integerp (fd->n2, 0)
3972 && ! integer_zerop (fd->n2))
3973 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
3975 /* Initialize the iterator variable, so that threads that don't execute
3976 any iterations don't execute the lastprivate clauses by accident. */
3977 t = build_gimple_modify_stmt (fd->v, vinit);
3978 gimplify_and_add (t, body_p);
3983 /* Lower code for an OpenMP loop directive. */
3985 static void
3986 lower_omp_for (tree *stmt_p, omp_context *ctx)
3988 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3989 struct omp_for_data fd;
3991 stmt = *stmt_p;
3993 push_gimplify_context ();
3995 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3996 lower_omp (&OMP_FOR_BODY (stmt), ctx);
3998 /* Move declaration of temporaries in the loop body before we make
3999 it go away. */
4000 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4001 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4003 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4004 TREE_SIDE_EFFECTS (new_stmt) = 1;
4005 body_p = &BIND_EXPR_BODY (new_stmt);
4007 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4008 ilist = NULL;
4009 dlist = NULL;
4010 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4011 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4013 /* Lower the header expressions. At this point, we can assume that
4014 the header is of the form:
4016 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4018 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4019 using the .omp_data_s mapping, if needed. */
4020 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4021 if (!is_gimple_min_invariant (*rhs_p))
4022 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4024 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4025 if (!is_gimple_min_invariant (*rhs_p))
4026 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4028 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4029 if (!is_gimple_min_invariant (*rhs_p))
4030 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4032 /* Once lowered, extract the bounds and clauses. */
4033 extract_omp_for_data (stmt, &fd);
4035 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4037 append_to_statement_list (stmt, body_p);
4039 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4041 t = make_node (OMP_CONTINUE);
4042 append_to_statement_list (t, body_p);
4044 /* After the loop, add exit clauses. */
4045 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4046 append_to_statement_list (dlist, body_p);
4048 maybe_catch_exception (body_p);
4050 /* Region exit marker goes at the end of the loop body. */
4051 t = make_node (OMP_RETURN);
4052 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4053 append_to_statement_list (t, body_p);
4055 pop_gimplify_context (NULL_TREE);
4056 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4058 OMP_FOR_BODY (stmt) = NULL_TREE;
4059 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4060 *stmt_p = new_stmt;
4064 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4065 information for the directive. */
4067 static void
4068 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4070 tree clauses, par_bind, par_body, new_body, bind;
4071 tree olist, ilist, par_olist, par_ilist;
4072 tree stmt, child_fn, t;
4074 stmt = *stmt_p;
4076 clauses = OMP_PARALLEL_CLAUSES (stmt);
4077 par_bind = OMP_PARALLEL_BODY (stmt);
4078 par_body = BIND_EXPR_BODY (par_bind);
4079 child_fn = ctx->cb.dst_fn;
4081 push_gimplify_context ();
4083 par_olist = NULL_TREE;
4084 par_ilist = NULL_TREE;
4085 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4086 lower_omp (&par_body, ctx);
4087 lower_reduction_clauses (clauses, &par_olist, ctx);
4089 /* Declare all the variables created by mapping and the variables
4090 declared in the scope of the parallel body. */
4091 record_vars_into (ctx->block_vars, child_fn);
4092 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4094 if (ctx->record_type)
4096 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4097 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4100 olist = NULL_TREE;
4101 ilist = NULL_TREE;
4102 lower_send_clauses (clauses, &ilist, &olist, ctx);
4103 lower_send_shared_vars (&ilist, &olist, ctx);
4105 /* Once all the expansions are done, sequence all the different
4106 fragments inside OMP_PARALLEL_BODY. */
4107 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4108 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4110 new_body = alloc_stmt_list ();
4112 if (ctx->record_type)
4114 t = build_fold_addr_expr (ctx->sender_decl);
4115 /* fixup_child_record_type might have changed receiver_decl's type. */
4116 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4117 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4118 append_to_statement_list (t, &new_body);
4121 append_to_statement_list (par_ilist, &new_body);
4122 append_to_statement_list (par_body, &new_body);
4123 append_to_statement_list (par_olist, &new_body);
4124 maybe_catch_exception (&new_body);
4125 t = make_node (OMP_RETURN);
4126 append_to_statement_list (t, &new_body);
4127 OMP_PARALLEL_BODY (stmt) = new_body;
4129 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4130 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4132 *stmt_p = bind;
4134 pop_gimplify_context (NULL_TREE);
4138 /* Pass *TP back through the gimplifier within the context determined by WI.
4139 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4140 flags on ADDR_EXPR. */
4142 static void
4143 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4145 enum gimplify_status gs;
4146 tree pre = NULL;
4148 if (wi->is_lhs)
4149 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4150 else if (wi->val_only)
4151 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4152 else
4153 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4154 gcc_assert (gs == GS_ALL_DONE);
4156 if (pre)
4157 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4160 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4162 static tree
4163 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4165 tree t, stmt;
4167 t = create_tmp_var (TREE_TYPE (exp), NULL);
4168 DECL_GIMPLE_REG_P (t) = 1;
4169 stmt = build_gimple_modify_stmt (t, exp);
4170 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4171 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4173 return t;
4176 /* Similarly, but copy from the temporary and insert the statement
4177 after the iterator. */
4179 static tree
4180 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4182 tree t, stmt;
4184 t = create_tmp_var (TREE_TYPE (exp), NULL);
4185 DECL_GIMPLE_REG_P (t) = 1;
4186 stmt = build_gimple_modify_stmt (exp, t);
4187 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4188 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4190 return t;
4193 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4195 static tree
4196 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4198 struct walk_stmt_info *wi = data;
4199 omp_context *ctx = wi->info;
4200 tree t = *tp;
4202 /* If we have issued syntax errors, avoid doing any heavy lifting.
4203 Just replace the OpenMP directives with a NOP to avoid
4204 confusing RTL expansion. */
4205 if (errorcount && OMP_DIRECTIVE_P (*tp))
4207 *tp = build_empty_stmt ();
4208 return NULL_TREE;
4211 *walk_subtrees = 0;
4212 switch (TREE_CODE (*tp))
4214 case OMP_PARALLEL:
4215 ctx = maybe_lookup_ctx (t);
4216 lower_omp_parallel (tp, ctx);
4217 break;
4219 case OMP_FOR:
4220 ctx = maybe_lookup_ctx (t);
4221 gcc_assert (ctx);
4222 lower_omp_for (tp, ctx);
4223 break;
4225 case OMP_SECTIONS:
4226 ctx = maybe_lookup_ctx (t);
4227 gcc_assert (ctx);
4228 lower_omp_sections (tp, ctx);
4229 break;
4231 case OMP_SINGLE:
4232 ctx = maybe_lookup_ctx (t);
4233 gcc_assert (ctx);
4234 lower_omp_single (tp, ctx);
4235 break;
4237 case OMP_MASTER:
4238 ctx = maybe_lookup_ctx (t);
4239 gcc_assert (ctx);
4240 lower_omp_master (tp, ctx);
4241 break;
4243 case OMP_ORDERED:
4244 ctx = maybe_lookup_ctx (t);
4245 gcc_assert (ctx);
4246 lower_omp_ordered (tp, ctx);
4247 break;
4249 case OMP_CRITICAL:
4250 ctx = maybe_lookup_ctx (t);
4251 gcc_assert (ctx);
4252 lower_omp_critical (tp, ctx);
4253 break;
4255 case VAR_DECL:
4256 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4258 lower_regimplify (&t, wi);
4259 if (wi->val_only)
4261 if (wi->is_lhs)
4262 t = save_tmp_var (t, &wi->tsi);
4263 else
4264 t = init_tmp_var (t, &wi->tsi);
4266 *tp = t;
4268 break;
4270 case ADDR_EXPR:
4271 if (ctx)
4272 lower_regimplify (tp, wi);
4273 break;
4275 case ARRAY_REF:
4276 case ARRAY_RANGE_REF:
4277 case REALPART_EXPR:
4278 case IMAGPART_EXPR:
4279 case COMPONENT_REF:
4280 case VIEW_CONVERT_EXPR:
4281 if (ctx)
4282 lower_regimplify (tp, wi);
4283 break;
4285 case INDIRECT_REF:
4286 if (ctx)
4288 wi->is_lhs = false;
4289 wi->val_only = true;
4290 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4292 break;
4294 default:
4295 if (!TYPE_P (t) && !DECL_P (t))
4296 *walk_subtrees = 1;
4297 break;
4300 return NULL_TREE;
4303 static void
4304 lower_omp (tree *stmt_p, omp_context *ctx)
4306 struct walk_stmt_info wi;
4308 memset (&wi, 0, sizeof (wi));
4309 wi.callback = lower_omp_1;
4310 wi.info = ctx;
4311 wi.val_only = true;
4312 wi.want_locations = true;
4314 walk_stmts (&wi, stmt_p);
4317 /* Main entry point. */
4319 static unsigned int
4320 execute_lower_omp (void)
4322 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4323 delete_omp_context);
4325 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4326 gcc_assert (parallel_nesting_level == 0);
4328 if (all_contexts->root)
4329 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4331 if (all_contexts)
4333 splay_tree_delete (all_contexts);
4334 all_contexts = NULL;
4336 return 0;
4339 static bool
4340 gate_lower_omp (void)
4342 return flag_openmp != 0;
4345 struct tree_opt_pass pass_lower_omp =
4347 "omplower", /* name */
4348 gate_lower_omp, /* gate */
4349 execute_lower_omp, /* execute */
4350 NULL, /* sub */
4351 NULL, /* next */
4352 0, /* static_pass_number */
4353 0, /* tv_id */
4354 PROP_gimple_any, /* properties_required */
4355 PROP_gimple_lomp, /* properties_provided */
4356 0, /* properties_destroyed */
4357 0, /* todo_flags_start */
4358 TODO_dump_func, /* todo_flags_finish */
4359 0 /* letter */
4362 /* The following is a utility to diagnose OpenMP structured block violations.
4363 It is not part of the "omplower" pass, as that's invoked too late. It
4364 should be invoked by the respective front ends after gimplification. */
4366 static splay_tree all_labels;
4368 /* Check for mismatched contexts and generate an error if needed. Return
4369 true if an error is detected. */
4371 static bool
4372 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4374 bool exit_p = true;
4376 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4377 return false;
4379 /* Try to avoid confusing the user by producing and error message
4380 with correct "exit" or "enter" verbage. We prefer "exit"
4381 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4382 if (branch_ctx == NULL)
4383 exit_p = false;
4384 else
4386 while (label_ctx)
4388 if (TREE_VALUE (label_ctx) == branch_ctx)
4390 exit_p = false;
4391 break;
4393 label_ctx = TREE_CHAIN (label_ctx);
4397 if (exit_p)
4398 error ("invalid exit from OpenMP structured block");
4399 else
4400 error ("invalid entry to OpenMP structured block");
4402 *stmt_p = build_empty_stmt ();
4403 return true;
4406 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4407 where in the tree each label is found. */
4409 static tree
4410 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4412 struct walk_stmt_info *wi = data;
4413 tree context = (tree) wi->info;
4414 tree inner_context;
4415 tree t = *tp;
4417 *walk_subtrees = 0;
4418 switch (TREE_CODE (t))
4420 case OMP_PARALLEL:
4421 case OMP_SECTIONS:
4422 case OMP_SINGLE:
4423 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4424 /* FALLTHRU */
4425 case OMP_SECTION:
4426 case OMP_MASTER:
4427 case OMP_ORDERED:
4428 case OMP_CRITICAL:
4429 /* The minimal context here is just a tree of statements. */
4430 inner_context = tree_cons (NULL, t, context);
4431 wi->info = inner_context;
4432 walk_stmts (wi, &OMP_BODY (t));
4433 wi->info = context;
4434 break;
4436 case OMP_FOR:
4437 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4438 inner_context = tree_cons (NULL, t, context);
4439 wi->info = inner_context;
4440 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4441 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4442 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4443 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4444 walk_stmts (wi, &OMP_FOR_BODY (t));
4445 wi->info = context;
4446 break;
4448 case LABEL_EXPR:
4449 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4450 (splay_tree_value) context);
4451 break;
4453 default:
4454 break;
4457 return NULL_TREE;
4460 /* Pass 2: Check each branch and see if its context differs from that of
4461 the destination label's context. */
4463 static tree
4464 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4466 struct walk_stmt_info *wi = data;
4467 tree context = (tree) wi->info;
4468 splay_tree_node n;
4469 tree t = *tp;
4471 *walk_subtrees = 0;
4472 switch (TREE_CODE (t))
4474 case OMP_PARALLEL:
4475 case OMP_SECTIONS:
4476 case OMP_SINGLE:
4477 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4478 /* FALLTHRU */
4479 case OMP_SECTION:
4480 case OMP_MASTER:
4481 case OMP_ORDERED:
4482 case OMP_CRITICAL:
4483 wi->info = t;
4484 walk_stmts (wi, &OMP_BODY (t));
4485 wi->info = context;
4486 break;
4488 case OMP_FOR:
4489 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4490 wi->info = t;
4491 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4492 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4493 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4494 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4495 walk_stmts (wi, &OMP_FOR_BODY (t));
4496 wi->info = context;
4497 break;
4499 case GOTO_EXPR:
4501 tree lab = GOTO_DESTINATION (t);
4502 if (TREE_CODE (lab) != LABEL_DECL)
4503 break;
4505 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4506 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4508 break;
4510 case SWITCH_EXPR:
4512 tree vec = SWITCH_LABELS (t);
4513 int i, len = TREE_VEC_LENGTH (vec);
4514 for (i = 0; i < len; ++i)
4516 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4517 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4518 if (diagnose_sb_0 (tp, context, (tree) n->value))
4519 break;
4522 break;
4524 case RETURN_EXPR:
4525 diagnose_sb_0 (tp, context, NULL_TREE);
4526 break;
4528 default:
4529 break;
4532 return NULL_TREE;
4535 void
4536 diagnose_omp_structured_block_errors (tree fndecl)
4538 tree save_current = current_function_decl;
4539 struct walk_stmt_info wi;
4541 current_function_decl = fndecl;
4543 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4545 memset (&wi, 0, sizeof (wi));
4546 wi.callback = diagnose_sb_1;
4547 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4549 memset (&wi, 0, sizeof (wi));
4550 wi.callback = diagnose_sb_2;
4551 wi.want_locations = true;
4552 wi.want_return_expr = true;
4553 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4555 splay_tree_delete (all_labels);
4556 all_labels = NULL;
4558 current_function_decl = save_current;
4561 #include "gt-omp-low.h"