* config/m68k/m68k.md (bungt_rev): New pattern.
[official-gcc.git] / gcc / omp-low.c
blobb76e00ced115e4ffedd32f29370b22f58f604bb3
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 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"
46 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
47 phases. The first phase scans the function looking for OMP statements
48 and then for variables that must be replaced to satisfy data sharing
49 clauses. The second phase expands code for the constructs, as well as
50 re-gimplifying things when variables have been replaced with complex
51 expressions.
53 Final code generation is done by pass_expand_omp. The flowgraph is
54 scanned for parallel regions which are then moved to a new
55 function, to be invoked by the thread library. */
57 /* Context structure. Used to store information about each parallel
58 directive in the code. */
60 typedef struct omp_context
62 /* This field must be at the beginning, as we do "inheritance": Some
63 callback functions for tree-inline.c (e.g., omp_copy_decl)
64 receive a copy_body_data pointer that is up-casted to an
65 omp_context pointer. */
66 copy_body_data cb;
68 /* The tree of contexts corresponding to the encountered constructs. */
69 struct omp_context *outer;
70 tree stmt;
72 /* Map variables to fields in a structure that allows communication
73 between sending and receiving threads. */
74 splay_tree field_map;
75 tree record_type;
76 tree sender_decl;
77 tree receiver_decl;
79 /* A chain of variables to add to the top-level block surrounding the
80 construct. In the case of a parallel, this is in the child function. */
81 tree block_vars;
83 /* What to do with variables with implicitly determined sharing
84 attributes. */
85 enum omp_clause_default_kind default_kind;
87 /* Nesting depth of this context. Used to beautify error messages re
88 invalid gotos. The outermost ctx is depth 1, with depth 0 being
89 reserved for the main body of the function. */
90 int depth;
92 /* True if this parallel directive is nested within another. */
93 bool is_nested;
94 } omp_context;
97 /* A structure describing the main elements of a parallel loop. */
99 struct omp_for_data
101 tree v, n1, n2, step, chunk_size, for_stmt;
102 enum tree_code cond_code;
103 tree pre;
104 bool have_nowait, have_ordered;
105 enum omp_clause_schedule_kind sched_kind;
109 static splay_tree all_contexts;
110 static int parallel_nesting_level;
111 struct omp_region *root_omp_region;
113 static void scan_omp (tree *, omp_context *);
114 static void lower_omp (tree *, omp_context *);
115 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
116 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
118 /* Find an OpenMP clause of type KIND within CLAUSES. */
120 static tree
121 find_omp_clause (tree clauses, enum tree_code kind)
123 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
124 if (OMP_CLAUSE_CODE (clauses) == kind)
125 return clauses;
127 return NULL_TREE;
130 /* Return true if CTX is for an omp parallel. */
132 static inline bool
133 is_parallel_ctx (omp_context *ctx)
135 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
139 /* Return true if REGION is a combined parallel+workshare region. */
141 static inline bool
142 is_combined_parallel (struct omp_region *region)
144 return region->is_combined_parallel;
148 /* Extract the header elements of parallel loop FOR_STMT and store
149 them into *FD. */
151 static void
152 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
154 tree t;
156 fd->for_stmt = for_stmt;
157 fd->pre = NULL;
159 t = OMP_FOR_INIT (for_stmt);
160 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
161 fd->v = TREE_OPERAND (t, 0);
162 gcc_assert (DECL_P (fd->v));
163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
164 fd->n1 = TREE_OPERAND (t, 1);
166 t = OMP_FOR_COND (for_stmt);
167 fd->cond_code = TREE_CODE (t);
168 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
169 fd->n2 = TREE_OPERAND (t, 1);
170 switch (fd->cond_code)
172 case LT_EXPR:
173 case GT_EXPR:
174 break;
175 case LE_EXPR:
176 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
177 build_int_cst (TREE_TYPE (fd->n2), 1));
178 fd->cond_code = LT_EXPR;
179 break;
180 case GE_EXPR:
181 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
182 build_int_cst (TREE_TYPE (fd->n2), 1));
183 fd->cond_code = GT_EXPR;
184 break;
185 default:
186 gcc_unreachable ();
189 t = OMP_FOR_INCR (fd->for_stmt);
190 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
191 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
192 t = TREE_OPERAND (t, 1);
193 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
194 switch (TREE_CODE (t))
196 case PLUS_EXPR:
197 fd->step = TREE_OPERAND (t, 1);
198 break;
199 case MINUS_EXPR:
200 fd->step = TREE_OPERAND (t, 1);
201 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
202 break;
203 default:
204 gcc_unreachable ();
207 fd->have_nowait = fd->have_ordered = false;
208 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
209 fd->chunk_size = NULL_TREE;
211 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
212 switch (OMP_CLAUSE_CODE (t))
214 case OMP_CLAUSE_NOWAIT:
215 fd->have_nowait = true;
216 break;
217 case OMP_CLAUSE_ORDERED:
218 fd->have_ordered = true;
219 break;
220 case OMP_CLAUSE_SCHEDULE:
221 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
222 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
223 break;
224 default:
225 break;
228 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
229 gcc_assert (fd->chunk_size == NULL);
230 else if (fd->chunk_size == NULL)
232 /* We only need to compute a default chunk size for ordered
233 static loops and dynamic loops. */
234 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
235 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
236 ? integer_zero_node : integer_one_node;
241 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
242 is the immediate dominator of PAR_ENTRY_BB, return true if there
243 are no data dependencies that would prevent expanding the parallel
244 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
246 When expanding a combined parallel+workshare region, the call to
247 the child function may need additional arguments in the case of
248 OMP_FOR regions. In some cases, these arguments are computed out
249 of variables passed in from the parent to the child via 'struct
250 .omp_data_s'. For instance:
252 #pragma omp parallel for schedule (guided, i * 4)
253 for (j ...)
255 Is lowered into:
257 # BLOCK 2 (PAR_ENTRY_BB)
258 .omp_data_o.i = i;
259 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
261 # BLOCK 3 (WS_ENTRY_BB)
262 .omp_data_i = &.omp_data_o;
263 D.1667 = .omp_data_i->i;
264 D.1598 = D.1667 * 4;
265 #pragma omp for schedule (guided, D.1598)
267 When we outline the parallel region, the call to the child function
268 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
269 that value is computed *after* the call site. So, in principle we
270 cannot do the transformation.
272 To see whether the code in WS_ENTRY_BB blocks the combined
273 parallel+workshare call, we collect all the variables used in the
274 OMP_FOR header check whether they appear on the LHS of any
275 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
276 call.
278 FIXME. If we had the SSA form built at this point, we could merely
279 hoist the code in block 3 into block 2 and be done with it. But at
280 this point we don't have dataflow information and though we could
281 hack something up here, it is really not worth the aggravation. */
283 static bool
284 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
286 struct omp_for_data fd;
287 tree par_stmt, ws_stmt;
289 par_stmt = last_stmt (par_entry_bb);
290 ws_stmt = last_stmt (ws_entry_bb);
292 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
293 return true;
295 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
297 extract_omp_for_data (ws_stmt, &fd);
299 /* FIXME. We give up too easily here. If any of these arguments
300 are not constants, they will likely involve variables that have
301 been mapped into fields of .omp_data_s for sharing with the child
302 function. With appropriate data flow, it would be possible to
303 see through this. */
304 if (!is_gimple_min_invariant (fd.n1)
305 || !is_gimple_min_invariant (fd.n2)
306 || !is_gimple_min_invariant (fd.step)
307 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
308 return false;
310 return true;
314 /* Collect additional arguments needed to emit a combined
315 parallel+workshare call. WS_STMT is the workshare directive being
316 expanded. */
318 static tree
319 get_ws_args_for (tree ws_stmt)
321 tree t;
323 if (TREE_CODE (ws_stmt) == OMP_FOR)
325 struct omp_for_data fd;
326 tree ws_args;
328 extract_omp_for_data (ws_stmt, &fd);
330 ws_args = NULL_TREE;
331 if (fd.chunk_size)
333 t = fold_convert (long_integer_type_node, fd.chunk_size);
334 ws_args = tree_cons (NULL, t, ws_args);
337 t = fold_convert (long_integer_type_node, fd.step);
338 ws_args = tree_cons (NULL, t, ws_args);
340 t = fold_convert (long_integer_type_node, fd.n2);
341 ws_args = tree_cons (NULL, t, ws_args);
343 t = fold_convert (long_integer_type_node, fd.n1);
344 ws_args = tree_cons (NULL, t, ws_args);
346 return ws_args;
348 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
350 basic_block bb = bb_for_stmt (ws_stmt);
351 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
352 t = tree_cons (NULL, t, NULL);
353 return t;
356 gcc_unreachable ();
360 /* Discover whether REGION is a combined parallel+workshare region. */
362 static void
363 determine_parallel_type (struct omp_region *region)
365 basic_block par_entry_bb, par_exit_bb;
366 basic_block ws_entry_bb, ws_exit_bb;
368 if (region == NULL || region->inner == NULL)
369 return;
371 /* We only support parallel+for and parallel+sections. */
372 if (region->type != OMP_PARALLEL
373 || (region->inner->type != OMP_FOR
374 && region->inner->type != OMP_SECTIONS))
375 return;
377 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
378 WS_EXIT_BB -> PAR_EXIT_BB. */
379 par_entry_bb = region->entry;
380 par_exit_bb = region->exit;
381 ws_entry_bb = region->inner->entry;
382 ws_exit_bb = region->inner->exit;
384 if (single_succ (par_entry_bb) == ws_entry_bb
385 && single_succ (ws_exit_bb) == par_exit_bb
386 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
388 tree ws_stmt = last_stmt (region->inner->entry);
390 if (region->inner->type == OMP_FOR)
392 /* If this is a combined parallel loop, we need to determine
393 whether or not to use the combined library calls. There
394 are two cases where we do not apply the transformation:
395 static loops and any kind of ordered loop. In the first
396 case, we already open code the loop so there is no need
397 to do anything else. In the latter case, the combined
398 parallel loop call would still need extra synchronization
399 to implement ordered semantics, so there would not be any
400 gain in using the combined call. */
401 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
402 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
403 if (c == NULL
404 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
405 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
407 region->is_combined_parallel = false;
408 region->inner->is_combined_parallel = false;
409 return;
413 region->is_combined_parallel = true;
414 region->inner->is_combined_parallel = true;
415 region->ws_args = get_ws_args_for (ws_stmt);
420 /* Return true if EXPR is variable sized. */
422 static inline bool
423 is_variable_sized (tree expr)
425 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
428 /* Return true if DECL is a reference type. */
430 static inline bool
431 is_reference (tree decl)
433 return lang_hooks.decls.omp_privatize_by_reference (decl);
436 /* Lookup variables in the decl or field splay trees. The "maybe" form
437 allows for the variable form to not have been entered, otherwise we
438 assert that the variable must have been entered. */
440 static inline tree
441 lookup_decl (tree var, omp_context *ctx)
443 splay_tree_node n;
444 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
445 return (tree) n->value;
448 static inline tree
449 maybe_lookup_decl (tree var, omp_context *ctx)
451 splay_tree_node n;
452 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
453 return n ? (tree) n->value : NULL_TREE;
456 static inline tree
457 lookup_field (tree var, omp_context *ctx)
459 splay_tree_node n;
460 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
461 return (tree) n->value;
464 static inline tree
465 maybe_lookup_field (tree var, omp_context *ctx)
467 splay_tree_node n;
468 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
469 return n ? (tree) n->value : NULL_TREE;
472 /* Return true if DECL should be copied by pointer. SHARED_P is true
473 if DECL is to be shared. */
475 static bool
476 use_pointer_for_field (tree decl, bool shared_p)
478 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
479 return true;
481 /* We can only use copy-in/copy-out semantics for shared variables
482 when we know the value is not accessible from an outer scope. */
483 if (shared_p)
485 /* ??? Trivially accessible from anywhere. But why would we even
486 be passing an address in this case? Should we simply assert
487 this to be false, or should we have a cleanup pass that removes
488 these from the list of mappings? */
489 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
490 return true;
492 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
493 without analyzing the expression whether or not its location
494 is accessible to anyone else. In the case of nested parallel
495 regions it certainly may be. */
496 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
497 return true;
499 /* Do not use copy-in/copy-out for variables that have their
500 address taken. */
501 if (TREE_ADDRESSABLE (decl))
502 return true;
505 return false;
508 /* Construct a new automatic decl similar to VAR. */
510 static tree
511 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
513 tree copy = build_decl (VAR_DECL, name, type);
515 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
516 DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
517 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
518 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
519 TREE_USED (copy) = 1;
520 DECL_CONTEXT (copy) = current_function_decl;
521 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
523 TREE_CHAIN (copy) = ctx->block_vars;
524 ctx->block_vars = copy;
526 return copy;
529 static tree
530 omp_copy_decl_1 (tree var, omp_context *ctx)
532 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
535 /* Build tree nodes to access the field for VAR on the receiver side. */
537 static tree
538 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
540 tree x, field = lookup_field (var, ctx);
542 /* If the receiver record type was remapped in the child function,
543 remap the field into the new record type. */
544 x = maybe_lookup_field (field, ctx);
545 if (x != NULL)
546 field = x;
548 x = build_fold_indirect_ref (ctx->receiver_decl);
549 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
550 if (by_ref)
551 x = build_fold_indirect_ref (x);
553 return x;
556 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
557 of a parallel, this is a component reference; for workshare constructs
558 this is some variable. */
560 static tree
561 build_outer_var_ref (tree var, omp_context *ctx)
563 tree x;
565 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
566 x = var;
567 else if (is_variable_sized (var))
569 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
570 x = build_outer_var_ref (x, ctx);
571 x = build_fold_indirect_ref (x);
573 else if (is_parallel_ctx (ctx))
575 bool by_ref = use_pointer_for_field (var, false);
576 x = build_receiver_ref (var, by_ref, ctx);
578 else if (ctx->outer)
579 x = lookup_decl (var, ctx->outer);
580 else if (is_reference (var))
581 /* This can happen with orphaned constructs. If var is reference, it is
582 possible it is shared and as such valid. */
583 x = var;
584 else
585 gcc_unreachable ();
587 if (is_reference (var))
588 x = build_fold_indirect_ref (x);
590 return x;
593 /* Build tree nodes to access the field for VAR on the sender side. */
595 static tree
596 build_sender_ref (tree var, omp_context *ctx)
598 tree field = lookup_field (var, ctx);
599 return build3 (COMPONENT_REF, TREE_TYPE (field),
600 ctx->sender_decl, field, NULL);
603 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
605 static void
606 install_var_field (tree var, bool by_ref, omp_context *ctx)
608 tree field, type;
610 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
612 type = TREE_TYPE (var);
613 if (by_ref)
614 type = build_pointer_type (type);
616 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
618 /* Remember what variable this field was created for. This does have a
619 side effect of making dwarf2out ignore this member, so for helpful
620 debugging we clear it later in delete_omp_context. */
621 DECL_ABSTRACT_ORIGIN (field) = var;
623 insert_field_into_struct (ctx->record_type, field);
625 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
626 (splay_tree_value) field);
629 static tree
630 install_var_local (tree var, omp_context *ctx)
632 tree new_var = omp_copy_decl_1 (var, ctx);
633 insert_decl_map (&ctx->cb, var, new_var);
634 return new_var;
637 /* Adjust the replacement for DECL in CTX for the new context. This means
638 copying the DECL_VALUE_EXPR, and fixing up the type. */
640 static void
641 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
643 tree new_decl, size;
645 new_decl = lookup_decl (decl, ctx);
647 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
649 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
650 && DECL_HAS_VALUE_EXPR_P (decl))
652 tree ve = DECL_VALUE_EXPR (decl);
653 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
654 SET_DECL_VALUE_EXPR (new_decl, ve);
655 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
658 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
660 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
661 if (size == error_mark_node)
662 size = TYPE_SIZE (TREE_TYPE (new_decl));
663 DECL_SIZE (new_decl) = size;
665 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
666 if (size == error_mark_node)
667 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
668 DECL_SIZE_UNIT (new_decl) = size;
672 /* The callback for remap_decl. Search all containing contexts for a
673 mapping of the variable; this avoids having to duplicate the splay
674 tree ahead of time. We know a mapping doesn't already exist in the
675 given context. Create new mappings to implement default semantics. */
677 static tree
678 omp_copy_decl (tree var, copy_body_data *cb)
680 omp_context *ctx = (omp_context *) cb;
681 tree new_var;
683 if (TREE_CODE (var) == LABEL_DECL)
685 new_var = create_artificial_label ();
686 DECL_CONTEXT (new_var) = current_function_decl;
687 insert_decl_map (&ctx->cb, var, new_var);
688 return new_var;
691 while (!is_parallel_ctx (ctx))
693 ctx = ctx->outer;
694 if (ctx == NULL)
695 return var;
696 new_var = maybe_lookup_decl (var, ctx);
697 if (new_var)
698 return new_var;
701 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
702 return var;
704 return error_mark_node;
708 /* Return the parallel region associated with STMT. */
710 /* Debugging dumps for parallel regions. */
711 void dump_omp_region (FILE *, struct omp_region *, int);
712 void debug_omp_region (struct omp_region *);
713 void debug_all_omp_regions (void);
715 /* Dump the parallel region tree rooted at REGION. */
717 void
718 dump_omp_region (FILE *file, struct omp_region *region, int indent)
720 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
721 tree_code_name[region->type]);
723 if (region->inner)
724 dump_omp_region (file, region->inner, indent + 4);
726 if (region->cont)
728 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
729 region->cont->index);
732 if (region->exit)
733 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
734 region->exit->index);
735 else
736 fprintf (file, "%*s[no exit marker]\n", indent, "");
738 if (region->next)
739 dump_omp_region (file, region->next, indent);
742 void
743 debug_omp_region (struct omp_region *region)
745 dump_omp_region (stderr, region, 0);
748 void
749 debug_all_omp_regions (void)
751 dump_omp_region (stderr, root_omp_region, 0);
755 /* Create a new parallel region starting at STMT inside region PARENT. */
757 struct omp_region *
758 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
760 struct omp_region *region = xcalloc (1, sizeof (*region));
762 region->outer = parent;
763 region->entry = bb;
764 region->type = type;
766 if (parent)
768 /* This is a nested region. Add it to the list of inner
769 regions in PARENT. */
770 region->next = parent->inner;
771 parent->inner = region;
773 else
775 /* This is a toplevel region. Add it to the list of toplevel
776 regions in ROOT_OMP_REGION. */
777 region->next = root_omp_region;
778 root_omp_region = region;
781 return region;
784 /* Release the memory associated with the region tree rooted at REGION. */
786 static void
787 free_omp_region_1 (struct omp_region *region)
789 struct omp_region *i, *n;
791 for (i = region->inner; i ; i = n)
793 n = i->next;
794 free_omp_region_1 (i);
797 free (region);
800 /* Release the memory for the entire omp region tree. */
802 void
803 free_omp_regions (void)
805 struct omp_region *r, *n;
806 for (r = root_omp_region; r ; r = n)
808 n = r->next;
809 free_omp_region_1 (r);
811 root_omp_region = NULL;
815 /* Create a new context, with OUTER_CTX being the surrounding context. */
817 static omp_context *
818 new_omp_context (tree stmt, omp_context *outer_ctx)
820 omp_context *ctx = XCNEW (omp_context);
822 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
823 (splay_tree_value) ctx);
824 ctx->stmt = stmt;
826 if (outer_ctx)
828 ctx->outer = outer_ctx;
829 ctx->cb = outer_ctx->cb;
830 ctx->cb.block = NULL;
831 ctx->depth = outer_ctx->depth + 1;
833 else
835 ctx->cb.src_fn = current_function_decl;
836 ctx->cb.dst_fn = current_function_decl;
837 ctx->cb.src_node = cgraph_node (current_function_decl);
838 ctx->cb.dst_node = ctx->cb.src_node;
839 ctx->cb.src_cfun = cfun;
840 ctx->cb.copy_decl = omp_copy_decl;
841 ctx->cb.eh_region = -1;
842 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
843 ctx->depth = 1;
846 ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
848 return ctx;
851 /* Destroy a omp_context data structures. Called through the splay tree
852 value delete callback. */
854 static void
855 delete_omp_context (splay_tree_value value)
857 omp_context *ctx = (omp_context *) value;
859 splay_tree_delete (ctx->cb.decl_map);
861 if (ctx->field_map)
862 splay_tree_delete (ctx->field_map);
864 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
865 it produces corrupt debug information. */
866 if (ctx->record_type)
868 tree t;
869 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
870 DECL_ABSTRACT_ORIGIN (t) = NULL;
873 XDELETE (ctx);
876 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
877 context. */
879 static void
880 fixup_child_record_type (omp_context *ctx)
882 tree f, type = ctx->record_type;
884 /* ??? It isn't sufficient to just call remap_type here, because
885 variably_modified_type_p doesn't work the way we expect for
886 record types. Testing each field for whether it needs remapping
887 and creating a new record by hand works, however. */
888 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
889 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
890 break;
891 if (f)
893 tree name, new_fields = NULL;
895 type = lang_hooks.types.make_type (RECORD_TYPE);
896 name = DECL_NAME (TYPE_NAME (ctx->record_type));
897 name = build_decl (TYPE_DECL, name, type);
898 TYPE_NAME (type) = name;
900 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
902 tree new_f = copy_node (f);
903 DECL_CONTEXT (new_f) = type;
904 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
905 TREE_CHAIN (new_f) = new_fields;
906 new_fields = new_f;
908 /* Arrange to be able to look up the receiver field
909 given the sender field. */
910 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
911 (splay_tree_value) new_f);
913 TYPE_FIELDS (type) = nreverse (new_fields);
914 layout_type (type);
917 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
920 /* Instantiate decls as necessary in CTX to satisfy the data sharing
921 specified by CLAUSES. */
923 static void
924 scan_sharing_clauses (tree clauses, omp_context *ctx)
926 tree c, decl;
927 bool scan_array_reductions = false;
929 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
931 bool by_ref;
933 switch (OMP_CLAUSE_CODE (c))
935 case OMP_CLAUSE_PRIVATE:
936 decl = OMP_CLAUSE_DECL (c);
937 if (!is_variable_sized (decl))
938 install_var_local (decl, ctx);
939 break;
941 case OMP_CLAUSE_SHARED:
942 gcc_assert (is_parallel_ctx (ctx));
943 decl = OMP_CLAUSE_DECL (c);
944 gcc_assert (!is_variable_sized (decl));
945 by_ref = use_pointer_for_field (decl, true);
946 /* Global variables don't need to be copied,
947 the receiver side will use them directly. */
948 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
949 break;
950 if (! TREE_READONLY (decl)
951 || TREE_ADDRESSABLE (decl)
952 || by_ref
953 || is_reference (decl))
955 install_var_field (decl, by_ref, ctx);
956 install_var_local (decl, ctx);
957 break;
959 /* We don't need to copy const scalar vars back. */
960 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
961 goto do_private;
963 case OMP_CLAUSE_LASTPRIVATE:
964 /* Let the corresponding firstprivate clause create
965 the variable. */
966 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
967 break;
968 /* FALLTHRU */
970 case OMP_CLAUSE_FIRSTPRIVATE:
971 case OMP_CLAUSE_REDUCTION:
972 decl = OMP_CLAUSE_DECL (c);
973 do_private:
974 if (is_variable_sized (decl))
975 break;
976 else if (is_parallel_ctx (ctx)
977 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
978 ctx)))
980 by_ref = use_pointer_for_field (decl, false);
981 install_var_field (decl, by_ref, ctx);
983 install_var_local (decl, ctx);
984 break;
986 case OMP_CLAUSE_COPYPRIVATE:
987 if (ctx->outer)
988 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
989 /* FALLTHRU */
991 case OMP_CLAUSE_COPYIN:
992 decl = OMP_CLAUSE_DECL (c);
993 by_ref = use_pointer_for_field (decl, false);
994 install_var_field (decl, by_ref, ctx);
995 break;
997 case OMP_CLAUSE_DEFAULT:
998 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
999 break;
1001 case OMP_CLAUSE_IF:
1002 case OMP_CLAUSE_NUM_THREADS:
1003 case OMP_CLAUSE_SCHEDULE:
1004 if (ctx->outer)
1005 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1006 break;
1008 case OMP_CLAUSE_NOWAIT:
1009 case OMP_CLAUSE_ORDERED:
1010 break;
1012 default:
1013 gcc_unreachable ();
1017 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1019 switch (OMP_CLAUSE_CODE (c))
1021 case OMP_CLAUSE_LASTPRIVATE:
1022 /* Let the corresponding firstprivate clause create
1023 the variable. */
1024 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1025 break;
1026 /* FALLTHRU */
1028 case OMP_CLAUSE_PRIVATE:
1029 case OMP_CLAUSE_FIRSTPRIVATE:
1030 case OMP_CLAUSE_REDUCTION:
1031 decl = OMP_CLAUSE_DECL (c);
1032 if (is_variable_sized (decl))
1033 install_var_local (decl, ctx);
1034 fixup_remapped_decl (decl, ctx,
1035 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1036 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1037 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1038 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1039 scan_array_reductions = true;
1040 break;
1042 case OMP_CLAUSE_SHARED:
1043 decl = OMP_CLAUSE_DECL (c);
1044 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1045 fixup_remapped_decl (decl, ctx, false);
1046 break;
1048 case OMP_CLAUSE_COPYPRIVATE:
1049 case OMP_CLAUSE_COPYIN:
1050 case OMP_CLAUSE_DEFAULT:
1051 case OMP_CLAUSE_IF:
1052 case OMP_CLAUSE_NUM_THREADS:
1053 case OMP_CLAUSE_SCHEDULE:
1054 case OMP_CLAUSE_NOWAIT:
1055 case OMP_CLAUSE_ORDERED:
1056 break;
1058 default:
1059 gcc_unreachable ();
1063 if (scan_array_reductions)
1064 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1066 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1068 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1069 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1073 /* Create a new name for omp child function. Returns an identifier. */
1075 static GTY(()) unsigned int tmp_ompfn_id_num;
1077 static tree
1078 create_omp_child_function_name (void)
1080 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1081 size_t len = IDENTIFIER_LENGTH (name);
1082 char *tmp_name, *prefix;
1084 prefix = alloca (len + sizeof ("_omp_fn"));
1085 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1086 strcpy (prefix + len, "_omp_fn");
1087 #ifndef NO_DOT_IN_LABEL
1088 prefix[len] = '.';
1089 #elif !defined NO_DOLLAR_IN_LABEL
1090 prefix[len] = '$';
1091 #endif
1092 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1093 return get_identifier (tmp_name);
1096 /* Build a decl for the omp child function. It'll not contain a body
1097 yet, just the bare decl. */
1099 static void
1100 create_omp_child_function (omp_context *ctx)
1102 tree decl, type, name, t;
1104 name = create_omp_child_function_name ();
1105 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1107 decl = build_decl (FUNCTION_DECL, name, type);
1108 decl = lang_hooks.decls.pushdecl (decl);
1110 ctx->cb.dst_fn = decl;
1112 TREE_STATIC (decl) = 1;
1113 TREE_USED (decl) = 1;
1114 DECL_ARTIFICIAL (decl) = 1;
1115 DECL_IGNORED_P (decl) = 0;
1116 TREE_PUBLIC (decl) = 0;
1117 DECL_UNINLINABLE (decl) = 1;
1118 DECL_EXTERNAL (decl) = 0;
1119 DECL_CONTEXT (decl) = NULL_TREE;
1120 DECL_INITIAL (decl) = make_node (BLOCK);
1122 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1123 DECL_ARTIFICIAL (t) = 1;
1124 DECL_IGNORED_P (t) = 1;
1125 DECL_RESULT (decl) = t;
1127 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1128 DECL_ARTIFICIAL (t) = 1;
1129 DECL_ARG_TYPE (t) = ptr_type_node;
1130 DECL_CONTEXT (t) = current_function_decl;
1131 TREE_USED (t) = 1;
1132 DECL_ARGUMENTS (decl) = t;
1133 ctx->receiver_decl = t;
1135 /* Allocate memory for the function structure. The call to
1136 allocate_struct_function clobbers CFUN, so we need to restore
1137 it afterward. */
1138 allocate_struct_function (decl);
1139 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1140 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1141 cfun = ctx->cb.src_cfun;
1145 /* Scan an OpenMP parallel directive. */
1147 static void
1148 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1150 omp_context *ctx;
1151 tree name;
1153 /* Ignore parallel directives with empty bodies, unless there
1154 are copyin clauses. */
1155 if (optimize > 0
1156 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1157 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1159 *stmt_p = build_empty_stmt ();
1160 return;
1163 ctx = new_omp_context (*stmt_p, outer_ctx);
1164 if (parallel_nesting_level > 1)
1165 ctx->is_nested = true;
1166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1169 name = create_tmp_var_name (".omp_data_s");
1170 name = build_decl (TYPE_DECL, name, ctx->record_type);
1171 TYPE_NAME (ctx->record_type) = name;
1172 create_omp_child_function (ctx);
1173 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1175 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1176 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1178 if (TYPE_FIELDS (ctx->record_type) == NULL)
1179 ctx->record_type = ctx->receiver_decl = NULL;
1180 else
1182 layout_type (ctx->record_type);
1183 fixup_child_record_type (ctx);
1188 /* Scan an OpenMP loop directive. */
1190 static void
1191 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1193 omp_context *ctx;
1194 tree stmt;
1196 stmt = *stmt_p;
1197 ctx = new_omp_context (stmt, outer_ctx);
1199 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1201 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1202 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1203 scan_omp (&OMP_FOR_COND (stmt), ctx);
1204 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1205 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1208 /* Scan an OpenMP sections directive. */
1210 static void
1211 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1213 tree stmt;
1214 omp_context *ctx;
1216 stmt = *stmt_p;
1217 ctx = new_omp_context (stmt, outer_ctx);
1218 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1219 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1222 /* Scan an OpenMP single directive. */
1224 static void
1225 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1227 tree stmt = *stmt_p;
1228 omp_context *ctx;
1229 tree name;
1231 ctx = new_omp_context (stmt, outer_ctx);
1232 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1233 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1234 name = create_tmp_var_name (".omp_copy_s");
1235 name = build_decl (TYPE_DECL, name, ctx->record_type);
1236 TYPE_NAME (ctx->record_type) = name;
1238 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1239 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1241 if (TYPE_FIELDS (ctx->record_type) == NULL)
1242 ctx->record_type = NULL;
1243 else
1244 layout_type (ctx->record_type);
1248 /* Check OpenMP nesting restrictions. */
1249 static void
1250 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1252 switch (TREE_CODE (t))
1254 case OMP_FOR:
1255 case OMP_SECTIONS:
1256 case OMP_SINGLE:
1257 for (; ctx != NULL; ctx = ctx->outer)
1258 switch (TREE_CODE (ctx->stmt))
1260 case OMP_FOR:
1261 case OMP_SECTIONS:
1262 case OMP_SINGLE:
1263 case OMP_ORDERED:
1264 case OMP_MASTER:
1265 warning (0, "work-sharing region may not be closely nested inside "
1266 "of work-sharing, critical, ordered or master region");
1267 return;
1268 case OMP_PARALLEL:
1269 return;
1270 default:
1271 break;
1273 break;
1274 case OMP_MASTER:
1275 for (; ctx != NULL; ctx = ctx->outer)
1276 switch (TREE_CODE (ctx->stmt))
1278 case OMP_FOR:
1279 case OMP_SECTIONS:
1280 case OMP_SINGLE:
1281 warning (0, "master region may not be closely nested inside "
1282 "of work-sharing region");
1283 return;
1284 case OMP_PARALLEL:
1285 return;
1286 default:
1287 break;
1289 break;
1290 case OMP_ORDERED:
1291 for (; ctx != NULL; ctx = ctx->outer)
1292 switch (TREE_CODE (ctx->stmt))
1294 case OMP_CRITICAL:
1295 warning (0, "ordered region may not be closely nested inside "
1296 "of critical region");
1297 return;
1298 case OMP_FOR:
1299 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1300 OMP_CLAUSE_ORDERED) == NULL)
1301 warning (0, "ordered region must be closely nested inside "
1302 "a loop region with an ordered clause");
1303 return;
1304 case OMP_PARALLEL:
1305 return;
1306 default:
1307 break;
1309 break;
1310 case OMP_CRITICAL:
1311 for (; ctx != NULL; ctx = ctx->outer)
1312 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1313 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1315 warning (0, "critical region may not be nested inside a critical "
1316 "region with the same name");
1317 return;
1319 break;
1320 default:
1321 break;
1326 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1328 static tree
1329 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1331 struct walk_stmt_info *wi = data;
1332 omp_context *ctx = wi->info;
1333 tree t = *tp;
1335 if (EXPR_HAS_LOCATION (t))
1336 input_location = EXPR_LOCATION (t);
1338 /* Check the OpenMP nesting restrictions. */
1339 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1340 check_omp_nesting_restrictions (t, ctx);
1342 *walk_subtrees = 0;
1343 switch (TREE_CODE (t))
1345 case OMP_PARALLEL:
1346 parallel_nesting_level++;
1347 scan_omp_parallel (tp, ctx);
1348 parallel_nesting_level--;
1349 break;
1351 case OMP_FOR:
1352 scan_omp_for (tp, ctx);
1353 break;
1355 case OMP_SECTIONS:
1356 scan_omp_sections (tp, ctx);
1357 break;
1359 case OMP_SINGLE:
1360 scan_omp_single (tp, ctx);
1361 break;
1363 case OMP_SECTION:
1364 case OMP_MASTER:
1365 case OMP_ORDERED:
1366 case OMP_CRITICAL:
1367 ctx = new_omp_context (*tp, ctx);
1368 scan_omp (&OMP_BODY (*tp), ctx);
1369 break;
1371 case BIND_EXPR:
1373 tree var;
1374 *walk_subtrees = 1;
1376 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1377 insert_decl_map (&ctx->cb, var, var);
1379 break;
1381 case VAR_DECL:
1382 case PARM_DECL:
1383 case LABEL_DECL:
1384 case RESULT_DECL:
1385 if (ctx)
1386 *tp = remap_decl (t, &ctx->cb);
1387 break;
1389 default:
1390 if (ctx && TYPE_P (t))
1391 *tp = remap_type (t, &ctx->cb);
1392 else if (!DECL_P (t))
1393 *walk_subtrees = 1;
1394 break;
1397 return NULL_TREE;
1401 /* Scan all the statements starting at STMT_P. CTX contains context
1402 information about the OpenMP directives and clauses found during
1403 the scan. */
1405 static void
1406 scan_omp (tree *stmt_p, omp_context *ctx)
1408 location_t saved_location;
1409 struct walk_stmt_info wi;
1411 memset (&wi, 0, sizeof (wi));
1412 wi.callback = scan_omp_1;
1413 wi.info = ctx;
1414 wi.want_bind_expr = (ctx != NULL);
1415 wi.want_locations = true;
1417 saved_location = input_location;
1418 walk_stmts (&wi, stmt_p);
1419 input_location = saved_location;
1422 /* Re-gimplification and code generation routines. */
1424 /* Build a call to GOMP_barrier. */
1426 static void
1427 build_omp_barrier (tree *stmt_list)
1429 tree t;
1431 t = built_in_decls[BUILT_IN_GOMP_BARRIER];
1432 t = build_function_call_expr (t, NULL);
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);
1509 return t;
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, args, 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 args = tree_cons (NULL, x, NULL);
1679 x = built_in_decls[BUILT_IN_ALLOCA];
1680 x = build_function_call_expr (x, args);
1681 x = fold_convert (TREE_TYPE (ptr), x);
1682 x = build2 (MODIFY_EXPR, void_type_node, ptr, x);
1683 gimplify_and_add (x, ilist);
1685 else if (is_reference (var))
1687 /* For references that are being privatized for Fortran,
1688 allocate new backing storage for the new pointer
1689 variable. This allows us to avoid changing all the
1690 code that expects a pointer to something that expects
1691 a direct variable. Note that this doesn't apply to
1692 C++, since reference types are disallowed in data
1693 sharing clauses there, except for NRV optimized
1694 return values. */
1695 if (pass == 0)
1696 continue;
1698 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1699 if (TREE_CONSTANT (x))
1701 const char *name = NULL;
1702 if (DECL_NAME (var))
1703 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1705 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1706 name);
1707 gimple_add_tmp_var (x);
1708 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1710 else
1712 args = tree_cons (NULL, x, NULL);
1713 x = built_in_decls[BUILT_IN_ALLOCA];
1714 x = build_function_call_expr (x, args);
1715 x = fold_convert (TREE_TYPE (new_var), x);
1718 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1719 gimplify_and_add (x, ilist);
1721 new_var = build_fold_indirect_ref (new_var);
1723 else if (c_kind == OMP_CLAUSE_REDUCTION
1724 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1726 if (pass == 0)
1727 continue;
1729 else if (pass != 0)
1730 continue;
1732 switch (OMP_CLAUSE_CODE (c))
1734 case OMP_CLAUSE_SHARED:
1735 /* Shared global vars are just accessed directly. */
1736 if (is_global_var (new_var))
1737 break;
1738 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1739 needs to be delayed until after fixup_child_record_type so
1740 that we get the correct type during the dereference. */
1741 by_ref = use_pointer_for_field (var, true);
1742 x = build_receiver_ref (var, by_ref, ctx);
1743 SET_DECL_VALUE_EXPR (new_var, x);
1744 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1746 /* ??? If VAR is not passed by reference, and the variable
1747 hasn't been initialized yet, then we'll get a warning for
1748 the store into the omp_data_s structure. Ideally, we'd be
1749 able to notice this and not store anything at all, but
1750 we're generating code too early. Suppress the warning. */
1751 if (!by_ref)
1752 TREE_NO_WARNING (var) = 1;
1753 break;
1755 case OMP_CLAUSE_LASTPRIVATE:
1756 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1757 break;
1758 /* FALLTHRU */
1760 case OMP_CLAUSE_PRIVATE:
1761 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1762 if (x)
1763 gimplify_and_add (x, ilist);
1764 /* FALLTHRU */
1766 do_dtor:
1767 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1768 if (x)
1770 dtor = x;
1771 gimplify_stmt (&dtor);
1772 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1774 break;
1776 case OMP_CLAUSE_FIRSTPRIVATE:
1777 x = build_outer_var_ref (var, ctx);
1778 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1779 gimplify_and_add (x, ilist);
1780 goto do_dtor;
1781 break;
1783 case OMP_CLAUSE_COPYIN:
1784 by_ref = use_pointer_for_field (var, false);
1785 x = build_receiver_ref (var, by_ref, ctx);
1786 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1787 append_to_statement_list (x, &copyin_seq);
1788 copyin_by_ref |= by_ref;
1789 break;
1791 case OMP_CLAUSE_REDUCTION:
1792 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1794 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1795 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1797 else
1799 x = omp_reduction_init (c, TREE_TYPE (new_var));
1800 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1801 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1802 gimplify_and_add (x, ilist);
1804 break;
1806 default:
1807 gcc_unreachable ();
1812 /* The copyin sequence is not to be executed by the main thread, since
1813 that would result in self-copies. Perhaps not visible to scalars,
1814 but it certainly is to C++ operator=. */
1815 if (copyin_seq)
1817 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
1818 x = build_function_call_expr (x, NULL);
1819 x = build2 (NE_EXPR, boolean_type_node, x,
1820 build_int_cst (TREE_TYPE (x), 0));
1821 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1822 gimplify_and_add (x, ilist);
1825 /* If any copyin variable is passed by reference, we must ensure the
1826 master thread doesn't modify it before it is copied over in all
1827 threads. Similarly for variables in both firstprivate and
1828 lastprivate clauses we need to ensure the lastprivate copying
1829 happens after firstprivate copying in all threads. */
1830 if (copyin_by_ref || lastprivate_firstprivate)
1831 build_omp_barrier (ilist);
1835 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1836 both parallel and workshare constructs. PREDICATE may be NULL if it's
1837 always true. */
1839 static void
1840 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1841 omp_context *ctx)
1843 tree sub_list, x, c;
1845 /* Early exit if there are no lastprivate clauses. */
1846 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1847 if (clauses == NULL)
1849 /* If this was a workshare clause, see if it had been combined
1850 with its parallel. In that case, look for the clauses on the
1851 parallel statement itself. */
1852 if (is_parallel_ctx (ctx))
1853 return;
1855 ctx = ctx->outer;
1856 if (ctx == NULL || !is_parallel_ctx (ctx))
1857 return;
1859 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1860 OMP_CLAUSE_LASTPRIVATE);
1861 if (clauses == NULL)
1862 return;
1865 sub_list = alloc_stmt_list ();
1867 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1869 tree var, new_var;
1871 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1872 continue;
1874 var = OMP_CLAUSE_DECL (c);
1875 new_var = lookup_decl (var, ctx);
1877 x = build_outer_var_ref (var, ctx);
1878 if (is_reference (var))
1879 new_var = build_fold_indirect_ref (new_var);
1880 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1881 append_to_statement_list (x, &sub_list);
1884 if (predicate)
1885 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1886 else
1887 x = sub_list;
1889 gimplify_and_add (x, stmt_list);
1893 /* Generate code to implement the REDUCTION clauses. */
1895 static void
1896 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1898 tree sub_list = NULL, x, c;
1899 int count = 0;
1901 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1902 update in that case, otherwise use a lock. */
1903 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1904 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1906 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1908 /* Never use OMP_ATOMIC for array reductions. */
1909 count = -1;
1910 break;
1912 count++;
1915 if (count == 0)
1916 return;
1918 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1920 tree var, ref, new_var;
1921 enum tree_code code;
1923 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1924 continue;
1926 var = OMP_CLAUSE_DECL (c);
1927 new_var = lookup_decl (var, ctx);
1928 if (is_reference (var))
1929 new_var = build_fold_indirect_ref (new_var);
1930 ref = build_outer_var_ref (var, ctx);
1931 code = OMP_CLAUSE_REDUCTION_CODE (c);
1933 /* reduction(-:var) sums up the partial results, so it acts
1934 identically to reduction(+:var). */
1935 if (code == MINUS_EXPR)
1936 code = PLUS_EXPR;
1938 if (count == 1)
1940 tree addr = build_fold_addr_expr (ref);
1942 addr = save_expr (addr);
1943 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1944 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1945 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1946 gimplify_and_add (x, stmt_list);
1947 return;
1950 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1952 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1954 if (is_reference (var))
1955 ref = build_fold_addr_expr (ref);
1956 SET_DECL_VALUE_EXPR (placeholder, ref);
1957 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1958 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1959 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1960 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1962 else
1964 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1965 ref = build_outer_var_ref (var, ctx);
1966 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1967 append_to_statement_list (x, &sub_list);
1971 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
1972 x = build_function_call_expr (x, NULL);
1973 gimplify_and_add (x, stmt_list);
1975 gimplify_and_add (sub_list, stmt_list);
1977 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
1978 x = build_function_call_expr (x, NULL);
1979 gimplify_and_add (x, stmt_list);
1983 /* Generate code to implement the COPYPRIVATE clauses. */
1985 static void
1986 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1987 omp_context *ctx)
1989 tree c;
1991 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1993 tree var, ref, x;
1994 bool by_ref;
1996 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1997 continue;
1999 var = OMP_CLAUSE_DECL (c);
2000 by_ref = use_pointer_for_field (var, false);
2002 ref = build_sender_ref (var, ctx);
2003 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
2004 x = by_ref ? build_fold_addr_expr (x) : x;
2005 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
2006 gimplify_and_add (x, slist);
2008 ref = build_receiver_ref (var, by_ref, ctx);
2009 if (is_reference (var))
2011 ref = build_fold_indirect_ref (ref);
2012 var = build_fold_indirect_ref (var);
2014 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2015 gimplify_and_add (x, rlist);
2020 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2021 and REDUCTION from the sender (aka parent) side. */
2023 static void
2024 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2026 tree c;
2028 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2030 tree val, ref, x, var;
2031 bool by_ref, do_in = false, do_out = false;
2033 switch (OMP_CLAUSE_CODE (c))
2035 case OMP_CLAUSE_FIRSTPRIVATE:
2036 case OMP_CLAUSE_COPYIN:
2037 case OMP_CLAUSE_LASTPRIVATE:
2038 case OMP_CLAUSE_REDUCTION:
2039 break;
2040 default:
2041 continue;
2044 var = val = OMP_CLAUSE_DECL (c);
2045 if (ctx->is_nested)
2046 var = lookup_decl_in_outer_ctx (val, ctx);
2048 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2049 && is_global_var (var))
2050 continue;
2051 if (is_variable_sized (val))
2052 continue;
2053 by_ref = use_pointer_for_field (val, false);
2055 switch (OMP_CLAUSE_CODE (c))
2057 case OMP_CLAUSE_FIRSTPRIVATE:
2058 case OMP_CLAUSE_COPYIN:
2059 do_in = true;
2060 break;
2062 case OMP_CLAUSE_LASTPRIVATE:
2063 if (by_ref || is_reference (val))
2065 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2066 continue;
2067 do_in = true;
2069 else
2070 do_out = true;
2071 break;
2073 case OMP_CLAUSE_REDUCTION:
2074 do_in = true;
2075 do_out = !(by_ref || is_reference (val));
2076 break;
2078 default:
2079 gcc_unreachable ();
2082 if (do_in)
2084 ref = build_sender_ref (val, ctx);
2085 x = by_ref ? build_fold_addr_expr (var) : var;
2086 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
2087 gimplify_and_add (x, ilist);
2090 if (do_out)
2092 ref = build_sender_ref (val, ctx);
2093 x = build2 (MODIFY_EXPR, void_type_node, var, ref);
2094 gimplify_and_add (x, olist);
2099 /* Generate code to implement SHARED from the sender (aka parent) side.
2100 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2101 got automatically shared. */
2103 static void
2104 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2106 tree var, ovar, nvar, f, x;
2108 if (ctx->record_type == NULL)
2109 return;
2111 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2113 ovar = DECL_ABSTRACT_ORIGIN (f);
2114 nvar = maybe_lookup_decl (ovar, ctx);
2115 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2116 continue;
2118 var = ovar;
2120 /* If CTX is a nested parallel directive. Find the immediately
2121 enclosing parallel or workshare construct that contains a
2122 mapping for OVAR. */
2123 if (ctx->is_nested)
2124 var = lookup_decl_in_outer_ctx (ovar, ctx);
2126 if (use_pointer_for_field (ovar, true))
2128 x = build_sender_ref (ovar, ctx);
2129 var = build_fold_addr_expr (var);
2130 x = build2 (MODIFY_EXPR, void_type_node, x, var);
2131 gimplify_and_add (x, ilist);
2133 else
2135 x = build_sender_ref (ovar, ctx);
2136 x = build2 (MODIFY_EXPR, void_type_node, x, var);
2137 gimplify_and_add (x, ilist);
2139 x = build_sender_ref (ovar, ctx);
2140 x = build2 (MODIFY_EXPR, void_type_node, var, x);
2141 gimplify_and_add (x, olist);
2146 /* Build the function calls to GOMP_parallel_start etc to actually
2147 generate the parallel operation. REGION is the parallel region
2148 being expanded. BB is the block where to insert the code. WS_ARGS
2149 will be set if this is a call to a combined parallel+workshare
2150 construct, it contains the list of additional arguments needed by
2151 the workshare construct. */
2153 static void
2154 expand_parallel_call (struct omp_region *region, basic_block bb,
2155 tree entry_stmt, tree ws_args)
2157 tree t, args, val, cond, c, list, clauses;
2158 block_stmt_iterator si;
2159 int start_ix;
2161 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2162 push_gimplify_context ();
2164 /* Determine what flavor of GOMP_parallel_start we will be
2165 emitting. */
2166 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2167 if (is_combined_parallel (region))
2169 switch (region->inner->type)
2171 case OMP_FOR:
2172 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2173 + region->inner->sched_kind;
2174 break;
2175 case OMP_SECTIONS:
2176 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2177 break;
2178 default:
2179 gcc_unreachable ();
2183 /* By default, the value of NUM_THREADS is zero (selected at run time)
2184 and there is no conditional. */
2185 cond = NULL_TREE;
2186 val = build_int_cst (unsigned_type_node, 0);
2188 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2189 if (c)
2190 cond = OMP_CLAUSE_IF_EXPR (c);
2192 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2193 if (c)
2194 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2196 /* Ensure 'val' is of the correct type. */
2197 val = fold_convert (unsigned_type_node, val);
2199 /* If we found the clause 'if (cond)', build either
2200 (cond != 0) or (cond ? val : 1u). */
2201 if (cond)
2203 block_stmt_iterator si;
2205 cond = gimple_boolify (cond);
2207 if (integer_zerop (val))
2208 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2209 build_int_cst (TREE_TYPE (cond), 0));
2210 else
2212 basic_block cond_bb, then_bb, else_bb;
2213 edge e;
2214 tree t, then_lab, else_lab, tmp;
2216 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2217 e = split_block (bb, NULL);
2218 cond_bb = e->src;
2219 bb = e->dest;
2220 remove_edge (e);
2222 then_bb = create_empty_bb (cond_bb);
2223 else_bb = create_empty_bb (then_bb);
2224 then_lab = create_artificial_label ();
2225 else_lab = create_artificial_label ();
2227 t = build3 (COND_EXPR, void_type_node,
2228 cond,
2229 build_and_jump (&then_lab),
2230 build_and_jump (&else_lab));
2232 si = bsi_start (cond_bb);
2233 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2235 si = bsi_start (then_bb);
2236 t = build1 (LABEL_EXPR, void_type_node, then_lab);
2237 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2238 t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
2239 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2241 si = bsi_start (else_bb);
2242 t = build1 (LABEL_EXPR, void_type_node, else_lab);
2243 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2244 t = build2 (MODIFY_EXPR, void_type_node, tmp,
2245 build_int_cst (unsigned_type_node, 1));
2246 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2248 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2249 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2250 make_edge (then_bb, bb, EDGE_FALLTHRU);
2251 make_edge (else_bb, bb, EDGE_FALLTHRU);
2253 val = tmp;
2256 list = NULL_TREE;
2257 val = get_formal_tmp_var (val, &list);
2258 si = bsi_start (bb);
2259 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2262 list = NULL_TREE;
2263 args = tree_cons (NULL, val, NULL);
2264 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2265 if (t == NULL)
2266 t = null_pointer_node;
2267 else
2268 t = build_fold_addr_expr (t);
2269 args = tree_cons (NULL, t, args);
2270 t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2271 args = tree_cons (NULL, t, args);
2273 if (ws_args)
2274 args = chainon (args, ws_args);
2276 t = built_in_decls[start_ix];
2277 t = build_function_call_expr (t, args);
2278 gimplify_and_add (t, &list);
2280 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2281 if (t == NULL)
2282 t = null_pointer_node;
2283 else
2284 t = build_fold_addr_expr (t);
2285 args = tree_cons (NULL, t, NULL);
2286 t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
2287 gimplify_and_add (t, &list);
2289 t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
2290 t = build_function_call_expr (t, NULL);
2291 gimplify_and_add (t, &list);
2293 si = bsi_last (bb);
2294 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2296 pop_gimplify_context (NULL_TREE);
2300 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2301 handler. This prevents programs from violating the structured
2302 block semantics with throws. */
2304 static void
2305 maybe_catch_exception (tree *stmt_p)
2307 tree f, t;
2309 if (!flag_exceptions)
2310 return;
2312 if (lang_protect_cleanup_actions)
2313 t = lang_protect_cleanup_actions ();
2314 else
2316 t = built_in_decls[BUILT_IN_TRAP];
2317 t = build_function_call_expr (t, NULL);
2319 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2320 EH_FILTER_MUST_NOT_THROW (f) = 1;
2321 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2323 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2324 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2326 *stmt_p = NULL;
2327 append_to_statement_list (t, stmt_p);
2330 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2332 static tree
2333 list2chain (tree list)
2335 tree t;
2337 for (t = list; t; t = TREE_CHAIN (t))
2339 tree var = TREE_VALUE (t);
2340 if (TREE_CHAIN (t))
2341 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2342 else
2343 TREE_CHAIN (var) = NULL_TREE;
2346 return list ? TREE_VALUE (list) : NULL_TREE;
2350 /* Remove barriers in REGION->EXIT's block. Note that this is only
2351 valid for OMP_PARALLEL regions. Since the end of a parallel region
2352 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2353 left a barrier at the end of the OMP_PARALLEL region can now be
2354 removed. */
2356 static void
2357 remove_exit_barrier (struct omp_region *region)
2359 block_stmt_iterator si;
2360 basic_block exit_bb;
2361 edge_iterator ei;
2362 edge e;
2363 tree t;
2365 exit_bb = region->exit;
2367 /* If the parallel region doesn't return, we don't have REGION->EXIT
2368 block at all. */
2369 if (! exit_bb)
2370 return;
2372 /* The last insn in the block will be the parallel's OMP_RETURN. The
2373 workshare's OMP_RETURN will be in a preceding block. The kinds of
2374 statements that can appear in between are extremely limited -- no
2375 memory operations at all. Here, we allow nothing at all, so the
2376 only thing we allow to precede this OMP_RETURN is a label. */
2377 si = bsi_last (exit_bb);
2378 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2379 bsi_prev (&si);
2380 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2381 return;
2383 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2385 si = bsi_last (e->src);
2386 if (bsi_end_p (si))
2387 continue;
2388 t = bsi_stmt (si);
2389 if (TREE_CODE (t) == OMP_RETURN)
2390 OMP_RETURN_NOWAIT (t) = 1;
2394 static void
2395 remove_exit_barriers (struct omp_region *region)
2397 if (region->type == OMP_PARALLEL)
2398 remove_exit_barrier (region);
2400 if (region->inner)
2402 region = region->inner;
2403 remove_exit_barriers (region);
2404 while (region->next)
2406 region = region->next;
2407 remove_exit_barriers (region);
2412 /* Expand the OpenMP parallel directive starting at REGION. */
2414 static void
2415 expand_omp_parallel (struct omp_region *region)
2417 basic_block entry_bb, exit_bb, new_bb;
2418 struct function *child_cfun, *saved_cfun;
2419 tree child_fn, block, t, ws_args;
2420 block_stmt_iterator si;
2421 tree entry_stmt;
2422 edge e;
2424 entry_stmt = last_stmt (region->entry);
2425 child_fn = OMP_PARALLEL_FN (entry_stmt);
2426 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2427 saved_cfun = cfun;
2429 entry_bb = region->entry;
2430 exit_bb = region->exit;
2432 if (is_combined_parallel (region))
2433 ws_args = region->ws_args;
2434 else
2435 ws_args = NULL_TREE;
2437 if (child_cfun->cfg)
2439 /* Due to inlining, it may happen that we have already outlined
2440 the region, in which case all we need to do is make the
2441 sub-graph unreachable and emit the parallel call. */
2442 edge entry_succ_e, exit_succ_e;
2443 block_stmt_iterator si;
2445 entry_succ_e = single_succ_edge (entry_bb);
2446 exit_succ_e = single_succ_edge (exit_bb);
2448 si = bsi_last (entry_bb);
2449 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2450 bsi_remove (&si, true);
2452 new_bb = entry_bb;
2453 remove_edge (entry_succ_e);
2454 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2456 else
2458 /* If the parallel region needs data sent from the parent
2459 function, then the very first statement (except possible
2460 tree profile counter updates) of the parallel body
2461 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2462 &.OMP_DATA_O is passed as an argument to the child function,
2463 we need to replace it with the argument as seen by the child
2464 function.
2466 In most cases, this will end up being the identity assignment
2467 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2468 a function call that has been inlined, the original PARM_DECL
2469 .OMP_DATA_I may have been converted into a different local
2470 variable. In which case, we need to keep the assignment. */
2471 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2473 basic_block entry_succ_bb = single_succ (entry_bb);
2474 block_stmt_iterator si;
2476 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2478 tree stmt, arg;
2480 gcc_assert (!bsi_end_p (si));
2481 stmt = bsi_stmt (si);
2482 if (TREE_CODE (stmt) != MODIFY_EXPR)
2483 continue;
2485 arg = TREE_OPERAND (stmt, 1);
2486 STRIP_NOPS (arg);
2487 if (TREE_CODE (arg) == ADDR_EXPR
2488 && TREE_OPERAND (arg, 0)
2489 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2491 if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
2492 bsi_remove (&si, true);
2493 else
2494 TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2495 break;
2500 /* Declare local variables needed in CHILD_CFUN. */
2501 block = DECL_INITIAL (child_fn);
2502 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2503 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
2505 /* Reset DECL_CONTEXT on locals and function arguments. */
2506 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2507 DECL_CONTEXT (t) = child_fn;
2509 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2510 DECL_CONTEXT (t) = child_fn;
2512 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2513 child function. */
2514 si = bsi_last (entry_bb);
2515 t = bsi_stmt (si);
2516 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2517 bsi_remove (&si, true);
2518 e = split_block (entry_bb, t);
2519 entry_bb = e->dest;
2520 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2522 /* Move the parallel region into CHILD_CFUN. We need to reset
2523 dominance information because the expansion of the inner
2524 regions has invalidated it. */
2525 free_dominance_info (CDI_DOMINATORS);
2526 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2527 if (exit_bb)
2528 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2529 cgraph_add_new_function (child_fn);
2531 /* Convert OMP_RETURN into a RETURN_EXPR. */
2532 if (exit_bb)
2534 si = bsi_last (exit_bb);
2535 gcc_assert (!bsi_end_p (si)
2536 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2537 t = build1 (RETURN_EXPR, void_type_node, NULL);
2538 bsi_insert_after (&si, t, TSI_SAME_STMT);
2539 bsi_remove (&si, true);
2543 /* Emit a library call to launch the children threads. */
2544 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2548 /* A subroutine of expand_omp_for. Generate code for a parallel
2549 loop with any schedule. Given parameters:
2551 for (V = N1; V cond N2; V += STEP) BODY;
2553 where COND is "<" or ">", we generate pseudocode
2555 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2556 if (more) goto L0; else goto L3;
2558 V = istart0;
2559 iend = iend0;
2561 BODY;
2562 V += STEP;
2563 if (V cond iend) goto L1; else goto L2;
2565 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2568 If this is a combined omp parallel loop, instead of the call to
2569 GOMP_loop_foo_start, we emit 'goto L3'. */
2571 static void
2572 expand_omp_for_generic (struct omp_region *region,
2573 struct omp_for_data *fd,
2574 enum built_in_function start_fn,
2575 enum built_in_function next_fn)
2577 tree l0, l1, l2, l3;
2578 tree type, istart0, iend0, iend;
2579 tree t, args, list;
2580 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l3_bb;
2581 block_stmt_iterator si;
2582 bool in_combined_parallel = is_combined_parallel (region);
2584 type = TREE_TYPE (fd->v);
2586 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2587 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2588 iend = create_tmp_var (type, NULL);
2589 TREE_ADDRESSABLE (istart0) = 1;
2590 TREE_ADDRESSABLE (iend0) = 1;
2592 entry_bb = region->entry;
2593 l0_bb = create_empty_bb (entry_bb);
2594 l1_bb = single_succ (entry_bb);
2595 cont_bb = region->cont;
2596 l2_bb = create_empty_bb (cont_bb);
2597 l3_bb = single_succ (cont_bb);
2598 exit_bb = region->exit;
2600 l0 = tree_block_label (l0_bb);
2601 l1 = tree_block_label (l1_bb);
2602 l2 = tree_block_label (l2_bb);
2603 l3 = tree_block_label (l3_bb);
2605 si = bsi_last (entry_bb);
2606 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2607 if (!in_combined_parallel)
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 t = build_fold_addr_expr (iend0);
2613 args = tree_cons (NULL, t, NULL);
2614 t = build_fold_addr_expr (istart0);
2615 args = tree_cons (NULL, t, args);
2616 if (fd->chunk_size)
2618 t = fold_convert (long_integer_type_node, fd->chunk_size);
2619 args = tree_cons (NULL, t, args);
2621 t = fold_convert (long_integer_type_node, fd->step);
2622 args = tree_cons (NULL, t, args);
2623 t = fold_convert (long_integer_type_node, fd->n2);
2624 args = tree_cons (NULL, t, args);
2625 t = fold_convert (long_integer_type_node, fd->n1);
2626 args = tree_cons (NULL, t, args);
2627 t = build_function_call_expr (built_in_decls[start_fn], args);
2628 t = get_formal_tmp_var (t, &list);
2629 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2630 build_and_jump (&l3));
2631 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 = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2640 gimplify_and_add (t, &list);
2642 t = fold_convert (type, iend0);
2643 t = build2 (MODIFY_EXPR, void_type_node, iend, t);
2644 gimplify_and_add (t, &list);
2646 si = bsi_start (l0_bb);
2647 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2649 /* Code to control the increment and predicate for the sequential
2650 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2651 that we can inherit all the edges going out of the loop
2652 body). */
2653 list = alloc_stmt_list ();
2655 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2656 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2657 gimplify_and_add (t, &list);
2659 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2660 t = get_formal_tmp_var (t, &list);
2661 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2662 build_and_jump (&l2));
2663 append_to_statement_list (t, &list);
2665 si = bsi_last (cont_bb);
2666 bsi_insert_after (&si, list, BSI_SAME_STMT);
2667 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2668 bsi_remove (&si, true);
2670 /* Emit code to get the next parallel iteration in L2_BB. */
2671 list = alloc_stmt_list ();
2673 t = build_fold_addr_expr (iend0);
2674 args = tree_cons (NULL, t, NULL);
2675 t = build_fold_addr_expr (istart0);
2676 args = tree_cons (NULL, t, args);
2677 t = build_function_call_expr (built_in_decls[next_fn], args);
2678 t = get_formal_tmp_var (t, &list);
2679 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2680 build_and_jump (&l3));
2681 append_to_statement_list (t, &list);
2683 si = bsi_start (l2_bb);
2684 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2686 /* Add the loop cleanup function. */
2687 si = bsi_last (exit_bb);
2688 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2689 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2690 else
2691 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2692 t = build_function_call_expr (t, NULL);
2693 bsi_insert_after (&si, t, BSI_SAME_STMT);
2694 bsi_remove (&si, true);
2696 /* Connect the new blocks. */
2697 remove_edge (single_succ_edge (entry_bb));
2698 if (in_combined_parallel)
2699 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2700 else
2702 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2703 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2706 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2708 remove_edge (single_succ_edge (cont_bb));
2709 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2710 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2712 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2713 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2717 /* A subroutine of expand_omp_for. Generate code for a parallel
2718 loop with static schedule and no specified chunk size. Given
2719 parameters:
2721 for (V = N1; V cond N2; V += STEP) BODY;
2723 where COND is "<" or ">", we generate pseudocode
2725 if (cond is <)
2726 adj = STEP - 1;
2727 else
2728 adj = STEP + 1;
2729 n = (adj + N2 - N1) / STEP;
2730 q = n / nthreads;
2731 q += (q * nthreads != n);
2732 s0 = q * threadid;
2733 e0 = min(s0 + q, n);
2734 if (s0 >= e0) goto L2; else goto L0;
2736 V = s0 * STEP + N1;
2737 e = e0 * STEP + N1;
2739 BODY;
2740 V += STEP;
2741 if (V cond e) goto L1;
2745 static void
2746 expand_omp_for_static_nochunk (struct omp_region *region,
2747 struct omp_for_data *fd)
2749 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
2750 tree type, utype, list;
2751 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2752 basic_block fin_bb;
2753 block_stmt_iterator si;
2755 type = TREE_TYPE (fd->v);
2756 utype = lang_hooks.types.unsigned_type (type);
2758 entry_bb = region->entry;
2759 seq_start_bb = create_empty_bb (entry_bb);
2760 body_bb = single_succ (entry_bb);
2761 cont_bb = region->cont;
2762 fin_bb = single_succ (cont_bb);
2763 exit_bb = region->exit;
2765 l0 = tree_block_label (seq_start_bb);
2766 l1 = tree_block_label (body_bb);
2767 l2 = tree_block_label (fin_bb);
2769 /* Iteration space partitioning goes in ENTRY_BB. */
2770 list = alloc_stmt_list ();
2772 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2773 t = build_function_call_expr (t, NULL);
2774 t = fold_convert (utype, t);
2775 nthreads = get_formal_tmp_var (t, &list);
2777 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2778 t = build_function_call_expr (t, NULL);
2779 t = fold_convert (utype, t);
2780 threadid = get_formal_tmp_var (t, &list);
2782 fd->n1 = fold_convert (type, fd->n1);
2783 if (!is_gimple_val (fd->n1))
2784 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2786 fd->n2 = fold_convert (type, fd->n2);
2787 if (!is_gimple_val (fd->n2))
2788 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2790 fd->step = fold_convert (type, fd->step);
2791 if (!is_gimple_val (fd->step))
2792 fd->step = get_formal_tmp_var (fd->step, &list);
2794 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2795 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2796 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2797 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2798 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2799 t = fold_convert (utype, t);
2800 if (is_gimple_val (t))
2801 n = t;
2802 else
2803 n = get_formal_tmp_var (t, &list);
2805 t = build2 (TRUNC_DIV_EXPR, utype, n, nthreads);
2806 q = get_formal_tmp_var (t, &list);
2808 t = build2 (MULT_EXPR, utype, q, nthreads);
2809 t = build2 (NE_EXPR, utype, t, n);
2810 t = build2 (PLUS_EXPR, utype, q, t);
2811 q = get_formal_tmp_var (t, &list);
2813 t = build2 (MULT_EXPR, utype, q, threadid);
2814 s0 = get_formal_tmp_var (t, &list);
2816 t = build2 (PLUS_EXPR, utype, s0, q);
2817 t = build2 (MIN_EXPR, utype, t, n);
2818 e0 = get_formal_tmp_var (t, &list);
2820 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2821 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
2822 build_and_jump (&l0));
2823 append_to_statement_list (t, &list);
2825 si = bsi_last (entry_bb);
2826 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2827 bsi_insert_after (&si, list, BSI_SAME_STMT);
2828 bsi_remove (&si, true);
2830 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2831 list = alloc_stmt_list ();
2833 t = fold_convert (type, s0);
2834 t = build2 (MULT_EXPR, type, t, fd->step);
2835 t = build2 (PLUS_EXPR, type, t, fd->n1);
2836 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2837 gimplify_and_add (t, &list);
2839 t = fold_convert (type, e0);
2840 t = build2 (MULT_EXPR, type, t, fd->step);
2841 t = build2 (PLUS_EXPR, type, t, fd->n1);
2842 e = get_formal_tmp_var (t, &list);
2844 si = bsi_start (seq_start_bb);
2845 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2847 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2848 list = alloc_stmt_list ();
2850 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2851 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2852 gimplify_and_add (t, &list);
2854 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2855 t = get_formal_tmp_var (t, &list);
2856 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2857 build_and_jump (&l2));
2858 append_to_statement_list (t, &list);
2860 si = bsi_last (cont_bb);
2861 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2862 bsi_insert_after (&si, list, BSI_SAME_STMT);
2863 bsi_remove (&si, true);
2865 /* Replace the OMP_RETURN with a barrier, or nothing. */
2866 si = bsi_last (exit_bb);
2867 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2869 list = alloc_stmt_list ();
2870 build_omp_barrier (&list);
2871 bsi_insert_after (&si, list, BSI_SAME_STMT);
2873 bsi_remove (&si, true);
2875 /* Connect all the blocks. */
2876 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2878 remove_edge (single_succ_edge (entry_bb));
2879 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2880 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2882 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2883 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2887 /* A subroutine of expand_omp_for. Generate code for a parallel
2888 loop with static schedule and a specified chunk size. Given
2889 parameters:
2891 for (V = N1; V cond N2; V += STEP) BODY;
2893 where COND is "<" or ">", we generate pseudocode
2895 if (cond is <)
2896 adj = STEP - 1;
2897 else
2898 adj = STEP + 1;
2899 n = (adj + N2 - N1) / STEP;
2900 trip = 0;
2902 s0 = (trip * nthreads + threadid) * CHUNK;
2903 e0 = min(s0 + CHUNK, n);
2904 if (s0 < n) goto L1; else goto L4;
2906 V = s0 * STEP + N1;
2907 e = e0 * STEP + N1;
2909 BODY;
2910 V += STEP;
2911 if (V cond e) goto L2; else goto L3;
2913 trip += 1;
2914 goto L0;
2918 static void
2919 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2921 tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
2922 tree trip, nthreads, threadid;
2923 tree type, utype;
2924 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2925 basic_block trip_update_bb, cont_bb, fin_bb;
2926 tree list;
2927 block_stmt_iterator si;
2929 type = TREE_TYPE (fd->v);
2930 utype = lang_hooks.types.unsigned_type (type);
2932 entry_bb = region->entry;
2933 iter_part_bb = create_empty_bb (entry_bb);
2934 seq_start_bb = create_empty_bb (iter_part_bb);
2935 body_bb = single_succ (entry_bb);
2936 cont_bb = region->cont;
2937 trip_update_bb = create_empty_bb (cont_bb);
2938 fin_bb = single_succ (cont_bb);
2939 exit_bb = region->exit;
2941 l0 = tree_block_label (iter_part_bb);
2942 l1 = tree_block_label (seq_start_bb);
2943 l2 = tree_block_label (body_bb);
2944 l3 = tree_block_label (trip_update_bb);
2945 l4 = tree_block_label (fin_bb);
2947 /* Trip and adjustment setup goes in ENTRY_BB. */
2948 list = alloc_stmt_list ();
2950 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2951 t = build_function_call_expr (t, NULL);
2952 t = fold_convert (utype, t);
2953 nthreads = get_formal_tmp_var (t, &list);
2955 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2956 t = build_function_call_expr (t, NULL);
2957 t = fold_convert (utype, t);
2958 threadid = get_formal_tmp_var (t, &list);
2960 fd->n1 = fold_convert (type, fd->n1);
2961 if (!is_gimple_val (fd->n1))
2962 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2964 fd->n2 = fold_convert (type, fd->n2);
2965 if (!is_gimple_val (fd->n2))
2966 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2968 fd->step = fold_convert (type, fd->step);
2969 if (!is_gimple_val (fd->step))
2970 fd->step = get_formal_tmp_var (fd->step, &list);
2972 fd->chunk_size = fold_convert (utype, fd->chunk_size);
2973 if (!is_gimple_val (fd->chunk_size))
2974 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2976 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2977 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2978 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2979 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2980 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2981 t = fold_convert (utype, t);
2982 if (is_gimple_val (t))
2983 n = t;
2984 else
2985 n = get_formal_tmp_var (t, &list);
2987 t = build_int_cst (utype, 0);
2988 trip = get_initialized_tmp_var (t, &list, NULL);
2990 si = bsi_last (entry_bb);
2991 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2992 bsi_insert_after (&si, list, BSI_SAME_STMT);
2993 bsi_remove (&si, true);
2995 /* Iteration space partitioning goes in ITER_PART_BB. */
2996 list = alloc_stmt_list ();
2998 t = build2 (MULT_EXPR, utype, trip, nthreads);
2999 t = build2 (PLUS_EXPR, utype, t, threadid);
3000 t = build2 (MULT_EXPR, utype, t, fd->chunk_size);
3001 s0 = get_formal_tmp_var (t, &list);
3003 t = build2 (PLUS_EXPR, utype, s0, fd->chunk_size);
3004 t = build2 (MIN_EXPR, utype, t, n);
3005 e0 = get_formal_tmp_var (t, &list);
3007 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3008 t = build3 (COND_EXPR, void_type_node, t,
3009 build_and_jump (&l1), build_and_jump (&l4));
3010 append_to_statement_list (t, &list);
3012 si = bsi_start (iter_part_bb);
3013 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3015 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3016 list = alloc_stmt_list ();
3018 t = fold_convert (type, s0);
3019 t = build2 (MULT_EXPR, type, t, fd->step);
3020 t = build2 (PLUS_EXPR, type, t, fd->n1);
3021 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
3022 gimplify_and_add (t, &list);
3024 t = fold_convert (type, e0);
3025 t = build2 (MULT_EXPR, type, t, fd->step);
3026 t = build2 (PLUS_EXPR, type, t, fd->n1);
3027 e = get_formal_tmp_var (t, &list);
3029 si = bsi_start (seq_start_bb);
3030 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3032 /* The code controlling the sequential loop goes in CONT_BB,
3033 replacing the OMP_CONTINUE. */
3034 list = alloc_stmt_list ();
3036 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3037 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
3038 gimplify_and_add (t, &list);
3040 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3041 t = get_formal_tmp_var (t, &list);
3042 t = build3 (COND_EXPR, void_type_node, t,
3043 build_and_jump (&l2), build_and_jump (&l3));
3044 append_to_statement_list (t, &list);
3046 si = bsi_last (cont_bb);
3047 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3048 bsi_insert_after (&si, list, BSI_SAME_STMT);
3049 bsi_remove (&si, true);
3051 /* Trip update code goes into TRIP_UPDATE_BB. */
3052 list = alloc_stmt_list ();
3054 t = build_int_cst (utype, 1);
3055 t = build2 (PLUS_EXPR, utype, trip, t);
3056 t = build2 (MODIFY_EXPR, void_type_node, trip, t);
3057 gimplify_and_add (t, &list);
3059 si = bsi_start (trip_update_bb);
3060 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3062 /* Replace the OMP_RETURN with a barrier, or nothing. */
3063 si = bsi_last (exit_bb);
3064 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3066 list = alloc_stmt_list ();
3067 build_omp_barrier (&list);
3068 bsi_insert_after (&si, list, BSI_SAME_STMT);
3070 bsi_remove (&si, true);
3072 /* Connect the new blocks. */
3073 remove_edge (single_succ_edge (entry_bb));
3074 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3076 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3077 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3079 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3081 remove_edge (single_succ_edge (cont_bb));
3082 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3083 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3085 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3089 /* Expand the OpenMP loop defined by REGION. */
3091 static void
3092 expand_omp_for (struct omp_region *region)
3094 struct omp_for_data fd;
3096 push_gimplify_context ();
3098 extract_omp_for_data (last_stmt (region->entry), &fd);
3099 region->sched_kind = fd.sched_kind;
3101 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered)
3103 if (fd.chunk_size == NULL)
3104 expand_omp_for_static_nochunk (region, &fd);
3105 else
3106 expand_omp_for_static_chunk (region, &fd);
3108 else
3110 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3111 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3112 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3113 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3116 pop_gimplify_context (NULL);
3120 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3122 v = GOMP_sections_start (n);
3124 switch (v)
3126 case 0:
3127 goto L2;
3128 case 1:
3129 section 1;
3130 goto L1;
3131 case 2:
3133 case n:
3135 default:
3136 abort ();
3139 v = GOMP_sections_next ();
3140 goto L0;
3142 reduction;
3144 If this is a combined parallel sections, replace the call to
3145 GOMP_sections_start with 'goto L1'. */
3147 static void
3148 expand_omp_sections (struct omp_region *region)
3150 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3151 unsigned i, len;
3152 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3153 block_stmt_iterator si;
3154 struct omp_region *inner;
3155 edge e;
3157 entry_bb = region->entry;
3158 l0_bb = create_empty_bb (entry_bb);
3159 l1_bb = region->cont;
3160 l2_bb = single_succ (l1_bb);
3161 default_bb = create_empty_bb (l1_bb->prev_bb);
3162 exit_bb = region->exit;
3164 l0 = tree_block_label (l0_bb);
3165 l1 = tree_block_label (l1_bb);
3166 l2 = tree_block_label (l2_bb);
3168 v = create_tmp_var (unsigned_type_node, ".section");
3170 /* We will build a switch() with enough cases for all the
3171 OMP_SECTION regions, a '0' case to handle the end of more work
3172 and a default case to abort if something goes wrong. */
3173 len = EDGE_COUNT (entry_bb->succs);
3174 label_vec = make_tree_vec (len + 2);
3176 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3177 OMP_SECTIONS statement. */
3178 si = bsi_last (entry_bb);
3179 sections_stmt = bsi_stmt (si);
3180 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3181 if (!is_combined_parallel (region))
3183 /* If we are not inside a combined parallel+sections region,
3184 call GOMP_sections_start. */
3185 t = build_int_cst (unsigned_type_node, len);
3186 t = tree_cons (NULL, t, NULL);
3187 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3188 t = build_function_call_expr (u, t);
3189 t = build2 (MODIFY_EXPR, void_type_node, 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 si = bsi_last (s_exit_bb);
3224 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3225 bsi_remove (&si, true);
3227 e = single_pred_edge (s_entry_bb);
3228 e->flags = 0;
3229 redirect_edge_pred (e, l0_bb);
3231 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3232 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3235 /* Error handling code goes in DEFAULT_BB. */
3236 t = tree_block_label (default_bb);
3237 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3238 TREE_VEC_ELT (label_vec, len + 1) = u;
3239 make_edge (l0_bb, default_bb, 0);
3241 si = bsi_start (default_bb);
3242 t = built_in_decls[BUILT_IN_TRAP];
3243 t = build_function_call_expr (t, NULL);
3244 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3246 /* Code to get the next section goes in L1_BB. */
3247 si = bsi_last (l1_bb);
3248 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3250 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3251 t = build_function_call_expr (t, NULL);
3252 t = build2 (MODIFY_EXPR, void_type_node, v, t);
3253 bsi_insert_after (&si, t, BSI_SAME_STMT);
3254 bsi_remove (&si, true);
3256 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3257 si = bsi_last (exit_bb);
3258 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3259 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3260 else
3261 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3262 t = build_function_call_expr (t, NULL);
3263 bsi_insert_after (&si, t, BSI_SAME_STMT);
3264 bsi_remove (&si, true);
3266 /* Connect the new blocks. */
3267 if (is_combined_parallel (region))
3269 /* If this was a combined parallel+sections region, we did not
3270 emit a GOMP_sections_start in the entry block, so we just
3271 need to jump to L1_BB to get the next section. */
3272 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3274 else
3275 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3277 e = single_succ_edge (l1_bb);
3278 redirect_edge_succ (e, l0_bb);
3279 e->flags = EDGE_FALLTHRU;
3283 /* Expand code for an OpenMP single directive. We've already expanded
3284 much of the code, here we simply place the GOMP_barrier call. */
3286 static void
3287 expand_omp_single (struct omp_region *region)
3289 basic_block entry_bb, exit_bb;
3290 block_stmt_iterator si;
3291 bool need_barrier = false;
3293 entry_bb = region->entry;
3294 exit_bb = region->exit;
3296 si = bsi_last (entry_bb);
3297 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3298 be removed. We need to ensure that the thread that entered the single
3299 does not exit before the data is copied out by the other threads. */
3300 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3301 OMP_CLAUSE_COPYPRIVATE))
3302 need_barrier = true;
3303 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3304 bsi_remove (&si, true);
3305 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3307 si = bsi_last (exit_bb);
3308 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3310 tree t = alloc_stmt_list ();
3311 build_omp_barrier (&t);
3312 bsi_insert_after (&si, t, BSI_SAME_STMT);
3314 bsi_remove (&si, true);
3315 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3319 /* Generic expansion for OpenMP synchronization directives: master,
3320 ordered and critical. All we need to do here is remove the entry
3321 and exit markers for REGION. */
3323 static void
3324 expand_omp_synch (struct omp_region *region)
3326 basic_block entry_bb, exit_bb;
3327 block_stmt_iterator si;
3329 entry_bb = region->entry;
3330 exit_bb = region->exit;
3332 si = bsi_last (entry_bb);
3333 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3334 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3335 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3336 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3337 bsi_remove (&si, true);
3338 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3340 si = bsi_last (exit_bb);
3341 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3342 bsi_remove (&si, true);
3343 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3347 /* Expand the parallel region tree rooted at REGION. Expansion
3348 proceeds in depth-first order. Innermost regions are expanded
3349 first. This way, parallel regions that require a new function to
3350 be created (e.g., OMP_PARALLEL) can be expanded without having any
3351 internal dependencies in their body. */
3353 static void
3354 expand_omp (struct omp_region *region)
3356 while (region)
3358 if (region->inner)
3359 expand_omp (region->inner);
3361 switch (region->type)
3363 case OMP_PARALLEL:
3364 expand_omp_parallel (region);
3365 break;
3367 case OMP_FOR:
3368 expand_omp_for (region);
3369 break;
3371 case OMP_SECTIONS:
3372 expand_omp_sections (region);
3373 break;
3375 case OMP_SECTION:
3376 /* Individual omp sections are handled together with their
3377 parent OMP_SECTIONS region. */
3378 break;
3380 case OMP_SINGLE:
3381 expand_omp_single (region);
3382 break;
3384 case OMP_MASTER:
3385 case OMP_ORDERED:
3386 case OMP_CRITICAL:
3387 expand_omp_synch (region);
3388 break;
3390 default:
3391 gcc_unreachable ();
3394 region = region->next;
3399 /* Helper for build_omp_regions. Scan the dominator tree starting at
3400 block BB. PARENT is the region that contains BB. */
3402 static void
3403 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3405 block_stmt_iterator si;
3406 tree stmt;
3407 basic_block son;
3409 si = bsi_last (bb);
3410 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3412 struct omp_region *region;
3413 enum tree_code code;
3415 stmt = bsi_stmt (si);
3416 code = TREE_CODE (stmt);
3418 if (code == OMP_RETURN)
3420 /* STMT is the return point out of region PARENT. Mark it
3421 as the exit point and make PARENT the immediately
3422 enclosing region. */
3423 gcc_assert (parent);
3424 region = parent;
3425 region->exit = bb;
3426 parent = parent->outer;
3428 /* If REGION is a parallel region, determine whether it is
3429 a combined parallel+workshare region. */
3430 if (region->type == OMP_PARALLEL)
3431 determine_parallel_type (region);
3433 else if (code == OMP_CONTINUE)
3435 gcc_assert (parent);
3436 parent->cont = bb;
3438 else
3440 /* Otherwise, this directive becomes the parent for a new
3441 region. */
3442 region = new_omp_region (bb, code, parent);
3443 parent = region;
3447 for (son = first_dom_son (CDI_DOMINATORS, bb);
3448 son;
3449 son = next_dom_son (CDI_DOMINATORS, son))
3450 build_omp_regions_1 (son, parent);
3454 /* Scan the CFG and build a tree of OMP regions. Return the root of
3455 the OMP region tree. */
3457 static void
3458 build_omp_regions (void)
3460 gcc_assert (root_omp_region == NULL);
3461 calculate_dominance_info (CDI_DOMINATORS);
3462 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3466 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3468 static unsigned int
3469 execute_expand_omp (void)
3471 build_omp_regions ();
3473 if (!root_omp_region)
3474 return 0;
3476 if (dump_file)
3478 fprintf (dump_file, "\nOMP region tree\n\n");
3479 dump_omp_region (dump_file, root_omp_region, 0);
3480 fprintf (dump_file, "\n");
3483 remove_exit_barriers (root_omp_region);
3485 expand_omp (root_omp_region);
3487 free_dominance_info (CDI_DOMINATORS);
3488 free_dominance_info (CDI_POST_DOMINATORS);
3489 cleanup_tree_cfg ();
3491 free_omp_regions ();
3493 return 0;
3496 static bool
3497 gate_expand_omp (void)
3499 return flag_openmp != 0 && errorcount == 0;
3502 struct tree_opt_pass pass_expand_omp =
3504 "ompexp", /* name */
3505 gate_expand_omp, /* gate */
3506 execute_expand_omp, /* execute */
3507 NULL, /* sub */
3508 NULL, /* next */
3509 0, /* static_pass_number */
3510 0, /* tv_id */
3511 PROP_gimple_any, /* properties_required */
3512 PROP_gimple_lomp, /* properties_provided */
3513 0, /* properties_destroyed */
3514 0, /* todo_flags_start */
3515 TODO_dump_func, /* todo_flags_finish */
3516 0 /* letter */
3519 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3521 /* Lower the OpenMP sections directive in *STMT_P. */
3523 static void
3524 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3526 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3527 tree t, dlist;
3528 tree_stmt_iterator tsi;
3529 unsigned i, len;
3531 stmt = *stmt_p;
3533 push_gimplify_context ();
3535 dlist = NULL;
3536 ilist = NULL;
3537 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3539 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3540 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3541 continue;
3543 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3544 body = alloc_stmt_list ();
3545 for (i = 0; i < len; i++, tsi_next (&tsi))
3547 omp_context *sctx;
3548 tree sec_start, sec_end;
3550 sec_start = tsi_stmt (tsi);
3551 sctx = maybe_lookup_ctx (sec_start);
3552 gcc_assert (sctx);
3554 append_to_statement_list (sec_start, &body);
3556 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3557 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3558 OMP_SECTION_BODY (sec_start) = NULL;
3560 if (i == len - 1)
3562 tree l = alloc_stmt_list ();
3563 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3564 &l, ctx);
3565 append_to_statement_list (l, &body);
3566 OMP_SECTION_LAST (sec_start) = 1;
3569 sec_end = make_node (OMP_RETURN);
3570 append_to_statement_list (sec_end, &body);
3573 block = make_node (BLOCK);
3574 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3576 olist = NULL_TREE;
3577 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3579 pop_gimplify_context (NULL_TREE);
3580 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3582 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3583 TREE_SIDE_EFFECTS (new_stmt) = 1;
3585 new_body = alloc_stmt_list ();
3586 append_to_statement_list (ilist, &new_body);
3587 append_to_statement_list (stmt, &new_body);
3588 append_to_statement_list (bind, &new_body);
3590 t = make_node (OMP_CONTINUE);
3591 append_to_statement_list (t, &new_body);
3593 append_to_statement_list (olist, &new_body);
3594 append_to_statement_list (dlist, &new_body);
3596 maybe_catch_exception (&new_body);
3598 t = make_node (OMP_RETURN);
3599 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3600 OMP_CLAUSE_NOWAIT);
3601 append_to_statement_list (t, &new_body);
3603 BIND_EXPR_BODY (new_stmt) = new_body;
3604 OMP_SECTIONS_BODY (stmt) = NULL;
3606 *stmt_p = new_stmt;
3610 /* A subroutine of lower_omp_single. Expand the simple form of
3611 an OMP_SINGLE, without a copyprivate clause:
3613 if (GOMP_single_start ())
3614 BODY;
3615 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3617 FIXME. It may be better to delay expanding the logic of this until
3618 pass_expand_omp. The expanded logic may make the job more difficult
3619 to a synchronization analysis pass. */
3621 static void
3622 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3624 tree t;
3626 t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
3627 t = build_function_call_expr (t, NULL);
3628 t = build3 (COND_EXPR, void_type_node, t,
3629 OMP_SINGLE_BODY (single_stmt), NULL);
3630 gimplify_and_add (t, pre_p);
3634 /* A subroutine of lower_omp_single. Expand the simple form of
3635 an OMP_SINGLE, with a copyprivate clause:
3637 #pragma omp single copyprivate (a, b, c)
3639 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3642 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3644 BODY;
3645 copyout.a = a;
3646 copyout.b = b;
3647 copyout.c = c;
3648 GOMP_single_copy_end (&copyout);
3650 else
3652 a = copyout_p->a;
3653 b = copyout_p->b;
3654 c = copyout_p->c;
3656 GOMP_barrier ();
3659 FIXME. It may be better to delay expanding the logic of this until
3660 pass_expand_omp. The expanded logic may make the job more difficult
3661 to a synchronization analysis pass. */
3663 static void
3664 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3666 tree ptr_type, t, args, l0, l1, l2, copyin_seq;
3668 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3670 ptr_type = build_pointer_type (ctx->record_type);
3671 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3673 l0 = create_artificial_label ();
3674 l1 = create_artificial_label ();
3675 l2 = create_artificial_label ();
3677 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
3678 t = build_function_call_expr (t, NULL);
3679 t = fold_convert (ptr_type, t);
3680 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
3681 gimplify_and_add (t, pre_p);
3683 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3684 build_int_cst (ptr_type, 0));
3685 t = build3 (COND_EXPR, void_type_node, t,
3686 build_and_jump (&l0), build_and_jump (&l1));
3687 gimplify_and_add (t, pre_p);
3689 t = build1 (LABEL_EXPR, void_type_node, l0);
3690 gimplify_and_add (t, pre_p);
3692 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3694 copyin_seq = NULL;
3695 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3696 &copyin_seq, ctx);
3698 t = build_fold_addr_expr (ctx->sender_decl);
3699 args = tree_cons (NULL, t, NULL);
3700 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
3701 t = build_function_call_expr (t, args);
3702 gimplify_and_add (t, pre_p);
3704 t = build_and_jump (&l2);
3705 gimplify_and_add (t, pre_p);
3707 t = build1 (LABEL_EXPR, void_type_node, l1);
3708 gimplify_and_add (t, pre_p);
3710 append_to_statement_list (copyin_seq, pre_p);
3712 t = build1 (LABEL_EXPR, void_type_node, l2);
3713 gimplify_and_add (t, pre_p);
3717 /* Expand code for an OpenMP single directive. */
3719 static void
3720 lower_omp_single (tree *stmt_p, omp_context *ctx)
3722 tree t, bind, block, single_stmt = *stmt_p, dlist;
3724 push_gimplify_context ();
3726 block = make_node (BLOCK);
3727 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3728 TREE_SIDE_EFFECTS (bind) = 1;
3730 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3731 &BIND_EXPR_BODY (bind), &dlist, ctx);
3732 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3734 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3736 if (ctx->record_type)
3737 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3738 else
3739 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3741 OMP_SINGLE_BODY (single_stmt) = NULL;
3743 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3745 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3747 t = make_node (OMP_RETURN);
3748 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3749 OMP_CLAUSE_NOWAIT);
3750 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3752 pop_gimplify_context (bind);
3754 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3755 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3759 /* Expand code for an OpenMP master directive. */
3761 static void
3762 lower_omp_master (tree *stmt_p, omp_context *ctx)
3764 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3766 push_gimplify_context ();
3768 block = make_node (BLOCK);
3769 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3770 TREE_SIDE_EFFECTS (bind) = 1;
3772 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3774 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
3775 x = build_function_call_expr (x, NULL);
3776 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3777 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3778 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3780 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3781 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3782 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3783 OMP_MASTER_BODY (stmt) = NULL;
3785 x = build1 (LABEL_EXPR, void_type_node, lab);
3786 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3788 x = make_node (OMP_RETURN);
3789 OMP_RETURN_NOWAIT (x) = 1;
3790 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3792 pop_gimplify_context (bind);
3794 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3795 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3799 /* Expand code for an OpenMP ordered directive. */
3801 static void
3802 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3804 tree bind, block, stmt = *stmt_p, x;
3806 push_gimplify_context ();
3808 block = make_node (BLOCK);
3809 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3810 TREE_SIDE_EFFECTS (bind) = 1;
3812 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3814 x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
3815 x = build_function_call_expr (x, NULL);
3816 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3818 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3819 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3820 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3821 OMP_ORDERED_BODY (stmt) = NULL;
3823 x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
3824 x = build_function_call_expr (x, NULL);
3825 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3827 x = make_node (OMP_RETURN);
3828 OMP_RETURN_NOWAIT (x) = 1;
3829 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3831 pop_gimplify_context (bind);
3833 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3834 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3838 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3839 substitution of a couple of function calls. But in the NAMED case,
3840 requires that languages coordinate a symbol name. It is therefore
3841 best put here in common code. */
3843 static GTY((param1_is (tree), param2_is (tree)))
3844 splay_tree critical_name_mutexes;
3846 static void
3847 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3849 tree bind, block, stmt = *stmt_p;
3850 tree t, lock, unlock, name;
3852 name = OMP_CRITICAL_NAME (stmt);
3853 if (name)
3855 tree decl, args;
3856 splay_tree_node n;
3858 if (!critical_name_mutexes)
3859 critical_name_mutexes
3860 = splay_tree_new_ggc (splay_tree_compare_pointers);
3862 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3863 if (n == NULL)
3865 char *new_str;
3867 decl = create_tmp_var_raw (ptr_type_node, NULL);
3869 new_str = ACONCAT ((".gomp_critical_user_",
3870 IDENTIFIER_POINTER (name), NULL));
3871 DECL_NAME (decl) = get_identifier (new_str);
3872 TREE_PUBLIC (decl) = 1;
3873 TREE_STATIC (decl) = 1;
3874 DECL_COMMON (decl) = 1;
3875 DECL_ARTIFICIAL (decl) = 1;
3876 DECL_IGNORED_P (decl) = 1;
3877 cgraph_varpool_finalize_decl (decl);
3879 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3880 (splay_tree_value) decl);
3882 else
3883 decl = (tree) n->value;
3885 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3886 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3887 lock = build_function_call_expr (lock, args);
3889 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3890 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3891 unlock = build_function_call_expr (unlock, args);
3893 else
3895 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3896 lock = build_function_call_expr (lock, NULL);
3898 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3899 unlock = build_function_call_expr (unlock, NULL);
3902 push_gimplify_context ();
3904 block = make_node (BLOCK);
3905 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3906 TREE_SIDE_EFFECTS (bind) = 1;
3908 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3910 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3912 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3913 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3914 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3915 OMP_CRITICAL_BODY (stmt) = NULL;
3917 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3919 t = make_node (OMP_RETURN);
3920 OMP_RETURN_NOWAIT (t) = 1;
3921 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3923 pop_gimplify_context (bind);
3924 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3925 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3929 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3930 for a lastprivate clause. Given a loop control predicate of (V
3931 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3932 is appended to *BODY_P. */
3934 static void
3935 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3936 struct omp_context *ctx)
3938 tree clauses, cond;
3939 enum tree_code cond_code;
3941 cond_code = fd->cond_code;
3942 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3944 /* When possible, use a strict equality expression. This can let VRP
3945 type optimizations deduce the value and remove a copy. */
3946 if (host_integerp (fd->step, 0))
3948 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3949 if (step == 1 || step == -1)
3950 cond_code = EQ_EXPR;
3953 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3955 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3956 lower_lastprivate_clauses (clauses, cond, body_p, ctx);
3960 /* Lower code for an OpenMP loop directive. */
3962 static void
3963 lower_omp_for (tree *stmt_p, omp_context *ctx)
3965 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3966 struct omp_for_data fd;
3968 stmt = *stmt_p;
3970 push_gimplify_context ();
3972 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3973 lower_omp (&OMP_FOR_BODY (stmt), ctx);
3975 /* Move declaration of temporaries in the loop body before we make
3976 it go away. */
3977 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
3978 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
3980 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3981 TREE_SIDE_EFFECTS (new_stmt) = 1;
3982 body_p = &BIND_EXPR_BODY (new_stmt);
3984 /* The pre-body and input clauses go before the lowered OMP_FOR. */
3985 ilist = NULL;
3986 dlist = NULL;
3987 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
3988 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
3990 /* Lower the header expressions. At this point, we can assume that
3991 the header is of the form:
3993 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
3995 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
3996 using the .omp_data_s mapping, if needed. */
3997 rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1);
3998 if (!is_gimple_min_invariant (*rhs_p))
3999 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4001 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4002 if (!is_gimple_min_invariant (*rhs_p))
4003 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4005 rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4006 if (!is_gimple_min_invariant (*rhs_p))
4007 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4009 /* Once lowered, extract the bounds and clauses. */
4010 extract_omp_for_data (stmt, &fd);
4012 append_to_statement_list (stmt, body_p);
4014 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4016 t = make_node (OMP_CONTINUE);
4017 append_to_statement_list (t, body_p);
4019 /* After the loop, add exit clauses. */
4020 lower_omp_for_lastprivate (&fd, &dlist, ctx);
4021 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4022 append_to_statement_list (dlist, body_p);
4024 maybe_catch_exception (body_p);
4026 /* Region exit marker goes at the end of the loop body. */
4027 t = make_node (OMP_RETURN);
4028 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4029 append_to_statement_list (t, body_p);
4031 pop_gimplify_context (NULL_TREE);
4032 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4034 OMP_FOR_BODY (stmt) = NULL_TREE;
4035 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4036 *stmt_p = new_stmt;
4040 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4041 information for the directive. */
4043 static void
4044 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4046 tree clauses, par_bind, par_body, new_body, bind;
4047 tree olist, ilist, par_olist, par_ilist;
4048 tree stmt, child_fn, t;
4050 stmt = *stmt_p;
4052 clauses = OMP_PARALLEL_CLAUSES (stmt);
4053 par_bind = OMP_PARALLEL_BODY (stmt);
4054 par_body = BIND_EXPR_BODY (par_bind);
4055 child_fn = ctx->cb.dst_fn;
4057 push_gimplify_context ();
4059 par_olist = NULL_TREE;
4060 par_ilist = NULL_TREE;
4061 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4062 lower_omp (&par_body, ctx);
4063 lower_reduction_clauses (clauses, &par_olist, ctx);
4065 /* Declare all the variables created by mapping and the variables
4066 declared in the scope of the parallel body. */
4067 record_vars_into (ctx->block_vars, child_fn);
4068 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4070 if (ctx->record_type)
4072 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4073 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4076 olist = NULL_TREE;
4077 ilist = NULL_TREE;
4078 lower_send_clauses (clauses, &ilist, &olist, ctx);
4079 lower_send_shared_vars (&ilist, &olist, ctx);
4081 /* Once all the expansions are done, sequence all the different
4082 fragments inside OMP_PARALLEL_BODY. */
4083 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4084 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4086 new_body = alloc_stmt_list ();
4088 if (ctx->record_type)
4090 t = build_fold_addr_expr (ctx->sender_decl);
4091 /* fixup_child_record_type might have changed receiver_decl's type. */
4092 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4093 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
4094 append_to_statement_list (t, &new_body);
4097 append_to_statement_list (par_ilist, &new_body);
4098 append_to_statement_list (par_body, &new_body);
4099 append_to_statement_list (par_olist, &new_body);
4100 maybe_catch_exception (&new_body);
4101 t = make_node (OMP_RETURN);
4102 append_to_statement_list (t, &new_body);
4103 OMP_PARALLEL_BODY (stmt) = new_body;
4105 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4106 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4108 *stmt_p = bind;
4110 pop_gimplify_context (NULL_TREE);
4114 /* Pass *TP back through the gimplifier within the context determined by WI.
4115 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4116 flags on ADDR_EXPR. */
4118 static void
4119 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4121 enum gimplify_status gs;
4122 tree pre = NULL;
4124 if (wi->is_lhs)
4125 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4126 else if (wi->val_only)
4127 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4128 else
4129 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4130 gcc_assert (gs == GS_ALL_DONE);
4132 if (pre)
4133 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4137 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4139 static tree
4140 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4142 struct walk_stmt_info *wi = data;
4143 omp_context *ctx = wi->info;
4144 tree t = *tp;
4146 /* If we have issued syntax errors, avoid doing any heavy lifting.
4147 Just replace the OpenMP directives with a NOP to avoid
4148 confusing RTL expansion. */
4149 if (errorcount && OMP_DIRECTIVE_P (*tp))
4151 *tp = build_empty_stmt ();
4152 return NULL_TREE;
4155 *walk_subtrees = 0;
4156 switch (TREE_CODE (*tp))
4158 case OMP_PARALLEL:
4159 ctx = maybe_lookup_ctx (t);
4160 lower_omp_parallel (tp, ctx);
4161 break;
4163 case OMP_FOR:
4164 ctx = maybe_lookup_ctx (t);
4165 gcc_assert (ctx);
4166 lower_omp_for (tp, ctx);
4167 break;
4169 case OMP_SECTIONS:
4170 ctx = maybe_lookup_ctx (t);
4171 gcc_assert (ctx);
4172 lower_omp_sections (tp, ctx);
4173 break;
4175 case OMP_SINGLE:
4176 ctx = maybe_lookup_ctx (t);
4177 gcc_assert (ctx);
4178 lower_omp_single (tp, ctx);
4179 break;
4181 case OMP_MASTER:
4182 ctx = maybe_lookup_ctx (t);
4183 gcc_assert (ctx);
4184 lower_omp_master (tp, ctx);
4185 break;
4187 case OMP_ORDERED:
4188 ctx = maybe_lookup_ctx (t);
4189 gcc_assert (ctx);
4190 lower_omp_ordered (tp, ctx);
4191 break;
4193 case OMP_CRITICAL:
4194 ctx = maybe_lookup_ctx (t);
4195 gcc_assert (ctx);
4196 lower_omp_critical (tp, ctx);
4197 break;
4199 case VAR_DECL:
4200 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4201 lower_regimplify (tp, wi);
4202 break;
4204 case ADDR_EXPR:
4205 if (ctx)
4206 lower_regimplify (tp, wi);
4207 break;
4209 case ARRAY_REF:
4210 case ARRAY_RANGE_REF:
4211 case REALPART_EXPR:
4212 case IMAGPART_EXPR:
4213 case COMPONENT_REF:
4214 case VIEW_CONVERT_EXPR:
4215 if (ctx)
4216 lower_regimplify (tp, wi);
4217 break;
4219 case INDIRECT_REF:
4220 if (ctx)
4222 wi->is_lhs = false;
4223 wi->val_only = true;
4224 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4226 break;
4228 default:
4229 if (!TYPE_P (t) && !DECL_P (t))
4230 *walk_subtrees = 1;
4231 break;
4234 return NULL_TREE;
4237 static void
4238 lower_omp (tree *stmt_p, omp_context *ctx)
4240 struct walk_stmt_info wi;
4242 memset (&wi, 0, sizeof (wi));
4243 wi.callback = lower_omp_1;
4244 wi.info = ctx;
4245 wi.val_only = true;
4246 wi.want_locations = true;
4248 walk_stmts (&wi, stmt_p);
4251 /* Main entry point. */
4253 static unsigned int
4254 execute_lower_omp (void)
4256 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4257 delete_omp_context);
4259 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4260 gcc_assert (parallel_nesting_level == 0);
4262 if (all_contexts->root)
4263 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4265 if (all_contexts)
4267 splay_tree_delete (all_contexts);
4268 all_contexts = NULL;
4270 return 0;
4273 static bool
4274 gate_lower_omp (void)
4276 return flag_openmp != 0;
4279 struct tree_opt_pass pass_lower_omp =
4281 "omplower", /* name */
4282 gate_lower_omp, /* gate */
4283 execute_lower_omp, /* execute */
4284 NULL, /* sub */
4285 NULL, /* next */
4286 0, /* static_pass_number */
4287 0, /* tv_id */
4288 PROP_gimple_any, /* properties_required */
4289 PROP_gimple_lomp, /* properties_provided */
4290 0, /* properties_destroyed */
4291 0, /* todo_flags_start */
4292 TODO_dump_func, /* todo_flags_finish */
4293 0 /* letter */
4296 /* The following is a utility to diagnose OpenMP structured block violations.
4297 It is not part of the "omplower" pass, as that's invoked too late. It
4298 should be invoked by the respective front ends after gimplification. */
4300 static splay_tree all_labels;
4302 /* Check for mismatched contexts and generate an error if needed. Return
4303 true if an error is detected. */
4305 static bool
4306 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4308 bool exit_p = true;
4310 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4311 return false;
4313 /* Try to avoid confusing the user by producing and error message
4314 with correct "exit" or "enter" verbage. We prefer "exit"
4315 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4316 if (branch_ctx == NULL)
4317 exit_p = false;
4318 else
4320 while (label_ctx)
4322 if (TREE_VALUE (label_ctx) == branch_ctx)
4324 exit_p = false;
4325 break;
4327 label_ctx = TREE_CHAIN (label_ctx);
4331 if (exit_p)
4332 error ("invalid exit from OpenMP structured block");
4333 else
4334 error ("invalid entry to OpenMP structured block");
4336 *stmt_p = build_empty_stmt ();
4337 return true;
4340 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4341 where in the tree each label is found. */
4343 static tree
4344 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4346 struct walk_stmt_info *wi = data;
4347 tree context = (tree) wi->info;
4348 tree inner_context;
4349 tree t = *tp;
4351 *walk_subtrees = 0;
4352 switch (TREE_CODE (t))
4354 case OMP_PARALLEL:
4355 case OMP_SECTIONS:
4356 case OMP_SINGLE:
4357 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4358 /* FALLTHRU */
4359 case OMP_SECTION:
4360 case OMP_MASTER:
4361 case OMP_ORDERED:
4362 case OMP_CRITICAL:
4363 /* The minimal context here is just a tree of statements. */
4364 inner_context = tree_cons (NULL, t, context);
4365 wi->info = inner_context;
4366 walk_stmts (wi, &OMP_BODY (t));
4367 wi->info = context;
4368 break;
4370 case OMP_FOR:
4371 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4372 inner_context = tree_cons (NULL, t, context);
4373 wi->info = inner_context;
4374 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4375 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4376 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4377 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4378 walk_stmts (wi, &OMP_FOR_BODY (t));
4379 wi->info = context;
4380 break;
4382 case LABEL_EXPR:
4383 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4384 (splay_tree_value) context);
4385 break;
4387 default:
4388 break;
4391 return NULL_TREE;
4394 /* Pass 2: Check each branch and see if its context differs from that of
4395 the destination label's context. */
4397 static tree
4398 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4400 struct walk_stmt_info *wi = data;
4401 tree context = (tree) wi->info;
4402 splay_tree_node n;
4403 tree t = *tp;
4405 *walk_subtrees = 0;
4406 switch (TREE_CODE (t))
4408 case OMP_PARALLEL:
4409 case OMP_SECTIONS:
4410 case OMP_SINGLE:
4411 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4412 /* FALLTHRU */
4413 case OMP_SECTION:
4414 case OMP_MASTER:
4415 case OMP_ORDERED:
4416 case OMP_CRITICAL:
4417 wi->info = t;
4418 walk_stmts (wi, &OMP_BODY (t));
4419 wi->info = context;
4420 break;
4422 case OMP_FOR:
4423 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4424 wi->info = t;
4425 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4426 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4427 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4428 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4429 walk_stmts (wi, &OMP_FOR_BODY (t));
4430 wi->info = context;
4431 break;
4433 case GOTO_EXPR:
4435 tree lab = GOTO_DESTINATION (t);
4436 if (TREE_CODE (lab) != LABEL_DECL)
4437 break;
4439 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4440 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4442 break;
4444 case SWITCH_EXPR:
4446 tree vec = SWITCH_LABELS (t);
4447 int i, len = TREE_VEC_LENGTH (vec);
4448 for (i = 0; i < len; ++i)
4450 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4451 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4452 if (diagnose_sb_0 (tp, context, (tree) n->value))
4453 break;
4456 break;
4458 case RETURN_EXPR:
4459 diagnose_sb_0 (tp, context, NULL_TREE);
4460 break;
4462 default:
4463 break;
4466 return NULL_TREE;
4469 void
4470 diagnose_omp_structured_block_errors (tree fndecl)
4472 tree save_current = current_function_decl;
4473 struct walk_stmt_info wi;
4475 current_function_decl = fndecl;
4477 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4479 memset (&wi, 0, sizeof (wi));
4480 wi.callback = diagnose_sb_1;
4481 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4483 memset (&wi, 0, sizeof (wi));
4484 wi.callback = diagnose_sb_2;
4485 wi.want_locations = true;
4486 wi.want_return_expr = true;
4487 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4489 splay_tree_delete (all_labels);
4490 all_labels = NULL;
4492 current_function_decl = save_current;
4495 #include "gt-omp-low.h"