* config/bfin/bfin.md (reload_outpdi, reload_inpdi): New patterns.
[official-gcc/alias-decl.git] / gcc / omp-low.c
blob57f36509c67db749ec475043851a9fd19e330e5e
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, 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 COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "tree-gimple.h"
31 #include "tree-inline.h"
32 #include "langhooks.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
35 #include "timevar.h"
36 #include "flags.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "toplev.h"
40 #include "tree-pass.h"
41 #include "ggc.h"
42 #include "except.h"
43 #include "splay-tree.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 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, var;
156 fd->for_stmt = for_stmt;
157 fd->pre = NULL;
159 t = OMP_FOR_INIT (for_stmt);
160 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
161 fd->v = GIMPLE_STMT_OPERAND (t, 0);
162 gcc_assert (SSA_VAR_P (fd->v));
163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
164 var = TREE_CODE (fd->v) == SSA_NAME ? SSA_NAME_VAR (fd->v) : fd->v;
165 fd->n1 = GIMPLE_STMT_OPERAND (t, 1);
167 t = OMP_FOR_COND (for_stmt);
168 fd->cond_code = TREE_CODE (t);
169 gcc_assert (TREE_OPERAND (t, 0) == var);
170 fd->n2 = TREE_OPERAND (t, 1);
171 switch (fd->cond_code)
173 case LT_EXPR:
174 case GT_EXPR:
175 break;
176 case LE_EXPR:
177 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
178 build_int_cst (TREE_TYPE (fd->n2), 1));
179 fd->cond_code = LT_EXPR;
180 break;
181 case GE_EXPR:
182 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
183 build_int_cst (TREE_TYPE (fd->n2), 1));
184 fd->cond_code = GT_EXPR;
185 break;
186 default:
187 gcc_unreachable ();
190 t = OMP_FOR_INCR (fd->for_stmt);
191 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
192 gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == var);
193 t = GIMPLE_STMT_OPERAND (t, 1);
194 gcc_assert (TREE_OPERAND (t, 0) == var);
195 switch (TREE_CODE (t))
197 case PLUS_EXPR:
198 fd->step = TREE_OPERAND (t, 1);
199 break;
200 case MINUS_EXPR:
201 fd->step = TREE_OPERAND (t, 1);
202 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
203 break;
204 default:
205 gcc_unreachable ();
208 fd->have_nowait = fd->have_ordered = false;
209 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
210 fd->chunk_size = NULL_TREE;
212 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
213 switch (OMP_CLAUSE_CODE (t))
215 case OMP_CLAUSE_NOWAIT:
216 fd->have_nowait = true;
217 break;
218 case OMP_CLAUSE_ORDERED:
219 fd->have_ordered = true;
220 break;
221 case OMP_CLAUSE_SCHEDULE:
222 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
223 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
224 break;
225 default:
226 break;
229 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
230 gcc_assert (fd->chunk_size == NULL);
231 else if (fd->chunk_size == NULL)
233 /* We only need to compute a default chunk size for ordered
234 static loops and dynamic loops. */
235 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
236 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
237 ? integer_zero_node : integer_one_node;
242 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
243 is the immediate dominator of PAR_ENTRY_BB, return true if there
244 are no data dependencies that would prevent expanding the parallel
245 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
247 When expanding a combined parallel+workshare region, the call to
248 the child function may need additional arguments in the case of
249 OMP_FOR regions. In some cases, these arguments are computed out
250 of variables passed in from the parent to the child via 'struct
251 .omp_data_s'. For instance:
253 #pragma omp parallel for schedule (guided, i * 4)
254 for (j ...)
256 Is lowered into:
258 # BLOCK 2 (PAR_ENTRY_BB)
259 .omp_data_o.i = i;
260 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
262 # BLOCK 3 (WS_ENTRY_BB)
263 .omp_data_i = &.omp_data_o;
264 D.1667 = .omp_data_i->i;
265 D.1598 = D.1667 * 4;
266 #pragma omp for schedule (guided, D.1598)
268 When we outline the parallel region, the call to the child function
269 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
270 that value is computed *after* the call site. So, in principle we
271 cannot do the transformation.
273 To see whether the code in WS_ENTRY_BB blocks the combined
274 parallel+workshare call, we collect all the variables used in the
275 OMP_FOR header check whether they appear on the LHS of any
276 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
277 call.
279 FIXME. If we had the SSA form built at this point, we could merely
280 hoist the code in block 3 into block 2 and be done with it. But at
281 this point we don't have dataflow information and though we could
282 hack something up here, it is really not worth the aggravation. */
284 static bool
285 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
287 struct omp_for_data fd;
288 tree par_stmt, ws_stmt;
290 par_stmt = last_stmt (par_entry_bb);
291 ws_stmt = last_stmt (ws_entry_bb);
293 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
294 return true;
296 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
298 extract_omp_for_data (ws_stmt, &fd);
300 /* FIXME. We give up too easily here. If any of these arguments
301 are not constants, they will likely involve variables that have
302 been mapped into fields of .omp_data_s for sharing with the child
303 function. With appropriate data flow, it would be possible to
304 see through this. */
305 if (!is_gimple_min_invariant (fd.n1)
306 || !is_gimple_min_invariant (fd.n2)
307 || !is_gimple_min_invariant (fd.step)
308 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
309 return false;
311 return true;
315 /* Collect additional arguments needed to emit a combined
316 parallel+workshare call. WS_STMT is the workshare directive being
317 expanded. */
319 static tree
320 get_ws_args_for (tree ws_stmt)
322 tree t;
324 if (TREE_CODE (ws_stmt) == OMP_FOR)
326 struct omp_for_data fd;
327 tree ws_args;
329 extract_omp_for_data (ws_stmt, &fd);
331 ws_args = NULL_TREE;
332 if (fd.chunk_size)
334 t = fold_convert (long_integer_type_node, fd.chunk_size);
335 ws_args = tree_cons (NULL, t, ws_args);
338 t = fold_convert (long_integer_type_node, fd.step);
339 ws_args = tree_cons (NULL, t, ws_args);
341 t = fold_convert (long_integer_type_node, fd.n2);
342 ws_args = tree_cons (NULL, t, ws_args);
344 t = fold_convert (long_integer_type_node, fd.n1);
345 ws_args = tree_cons (NULL, t, ws_args);
347 return ws_args;
349 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
351 /* Number of sections is equal to the number of edges from the
352 OMP_SECTIONS_SWITCH statement, except for the one to the exit
353 of the sections region. */
354 basic_block bb = single_succ (bb_for_stmt (ws_stmt));
355 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
356 t = tree_cons (NULL, t, NULL);
357 return t;
360 gcc_unreachable ();
364 /* Discover whether REGION is a combined parallel+workshare region. */
366 static void
367 determine_parallel_type (struct omp_region *region)
369 basic_block par_entry_bb, par_exit_bb;
370 basic_block ws_entry_bb, ws_exit_bb;
372 if (region == NULL || region->inner == NULL
373 || region->exit == NULL || region->inner->exit == NULL
374 || region->inner->cont == NULL)
375 return;
377 /* We only support parallel+for and parallel+sections. */
378 if (region->type != OMP_PARALLEL
379 || (region->inner->type != OMP_FOR
380 && region->inner->type != OMP_SECTIONS))
381 return;
383 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
384 WS_EXIT_BB -> PAR_EXIT_BB. */
385 par_entry_bb = region->entry;
386 par_exit_bb = region->exit;
387 ws_entry_bb = region->inner->entry;
388 ws_exit_bb = region->inner->exit;
390 if (single_succ (par_entry_bb) == ws_entry_bb
391 && single_succ (ws_exit_bb) == par_exit_bb
392 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
393 && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
394 || (last_and_only_stmt (ws_entry_bb)
395 && last_and_only_stmt (par_exit_bb))))
397 tree ws_stmt = last_stmt (ws_entry_bb);
399 if (region->inner->type == OMP_FOR)
401 /* If this is a combined parallel loop, we need to determine
402 whether or not to use the combined library calls. There
403 are two cases where we do not apply the transformation:
404 static loops and any kind of ordered loop. In the first
405 case, we already open code the loop so there is no need
406 to do anything else. In the latter case, the combined
407 parallel loop call would still need extra synchronization
408 to implement ordered semantics, so there would not be any
409 gain in using the combined call. */
410 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
411 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
412 if (c == NULL
413 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
414 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
416 region->is_combined_parallel = false;
417 region->inner->is_combined_parallel = false;
418 return;
422 region->is_combined_parallel = true;
423 region->inner->is_combined_parallel = true;
424 region->ws_args = get_ws_args_for (ws_stmt);
429 /* Return true if EXPR is variable sized. */
431 static inline bool
432 is_variable_sized (const_tree expr)
434 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
437 /* Return true if DECL is a reference type. */
439 static inline bool
440 is_reference (tree decl)
442 return lang_hooks.decls.omp_privatize_by_reference (decl);
445 /* Lookup variables in the decl or field splay trees. The "maybe" form
446 allows for the variable form to not have been entered, otherwise we
447 assert that the variable must have been entered. */
449 static inline tree
450 lookup_decl (tree var, omp_context *ctx)
452 tree *n;
453 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
454 return *n;
457 static inline tree
458 maybe_lookup_decl (tree var, omp_context *ctx)
460 tree *n;
461 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
462 return n ? *n : NULL_TREE;
465 static inline tree
466 lookup_field (tree var, omp_context *ctx)
468 splay_tree_node n;
469 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
470 return (tree) n->value;
473 static inline tree
474 maybe_lookup_field (tree var, omp_context *ctx)
476 splay_tree_node n;
477 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
478 return n ? (tree) n->value : NULL_TREE;
481 /* Return true if DECL should be copied by pointer. SHARED_P is true
482 if DECL is to be shared. */
484 static bool
485 use_pointer_for_field (const_tree decl, bool shared_p)
487 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
488 return true;
490 /* We can only use copy-in/copy-out semantics for shared variables
491 when we know the value is not accessible from an outer scope. */
492 if (shared_p)
494 /* ??? Trivially accessible from anywhere. But why would we even
495 be passing an address in this case? Should we simply assert
496 this to be false, or should we have a cleanup pass that removes
497 these from the list of mappings? */
498 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
499 return true;
501 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
502 without analyzing the expression whether or not its location
503 is accessible to anyone else. In the case of nested parallel
504 regions it certainly may be. */
505 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
506 return true;
508 /* Do not use copy-in/copy-out for variables that have their
509 address taken. */
510 if (TREE_ADDRESSABLE (decl))
511 return true;
514 return false;
517 /* Create a new VAR_DECL and copy information from VAR to it. */
519 tree
520 copy_var_decl (tree var, tree name, tree type)
522 tree copy = build_decl (VAR_DECL, name, type);
524 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
525 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
526 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
527 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
528 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
529 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
530 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
531 TREE_USED (copy) = 1;
532 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
534 return copy;
537 /* Construct a new automatic decl similar to VAR. */
539 static tree
540 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
542 tree copy = copy_var_decl (var, name, type);
544 DECL_CONTEXT (copy) = current_function_decl;
545 TREE_CHAIN (copy) = ctx->block_vars;
546 ctx->block_vars = copy;
548 return copy;
551 static tree
552 omp_copy_decl_1 (tree var, omp_context *ctx)
554 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
557 /* Build tree nodes to access the field for VAR on the receiver side. */
559 static tree
560 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
562 tree x, field = lookup_field (var, ctx);
564 /* If the receiver record type was remapped in the child function,
565 remap the field into the new record type. */
566 x = maybe_lookup_field (field, ctx);
567 if (x != NULL)
568 field = x;
570 x = build_fold_indirect_ref (ctx->receiver_decl);
571 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
572 if (by_ref)
573 x = build_fold_indirect_ref (x);
575 return x;
578 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
579 of a parallel, this is a component reference; for workshare constructs
580 this is some variable. */
582 static tree
583 build_outer_var_ref (tree var, omp_context *ctx)
585 tree x;
587 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
588 x = var;
589 else if (is_variable_sized (var))
591 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
592 x = build_outer_var_ref (x, ctx);
593 x = build_fold_indirect_ref (x);
595 else if (is_parallel_ctx (ctx))
597 bool by_ref = use_pointer_for_field (var, false);
598 x = build_receiver_ref (var, by_ref, ctx);
600 else if (ctx->outer)
601 x = lookup_decl (var, ctx->outer);
602 else if (is_reference (var))
603 /* This can happen with orphaned constructs. If var is reference, it is
604 possible it is shared and as such valid. */
605 x = var;
606 else
607 gcc_unreachable ();
609 if (is_reference (var))
610 x = build_fold_indirect_ref (x);
612 return x;
615 /* Build tree nodes to access the field for VAR on the sender side. */
617 static tree
618 build_sender_ref (tree var, omp_context *ctx)
620 tree field = lookup_field (var, ctx);
621 return build3 (COMPONENT_REF, TREE_TYPE (field),
622 ctx->sender_decl, field, NULL);
625 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
627 static void
628 install_var_field (tree var, bool by_ref, omp_context *ctx)
630 tree field, type;
632 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
634 type = TREE_TYPE (var);
635 if (by_ref)
636 type = build_pointer_type (type);
638 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
640 /* Remember what variable this field was created for. This does have a
641 side effect of making dwarf2out ignore this member, so for helpful
642 debugging we clear it later in delete_omp_context. */
643 DECL_ABSTRACT_ORIGIN (field) = var;
645 insert_field_into_struct (ctx->record_type, field);
647 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
648 (splay_tree_value) field);
651 static tree
652 install_var_local (tree var, omp_context *ctx)
654 tree new_var = omp_copy_decl_1 (var, ctx);
655 insert_decl_map (&ctx->cb, var, new_var);
656 return new_var;
659 /* Adjust the replacement for DECL in CTX for the new context. This means
660 copying the DECL_VALUE_EXPR, and fixing up the type. */
662 static void
663 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
665 tree new_decl, size;
667 new_decl = lookup_decl (decl, ctx);
669 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
671 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
672 && DECL_HAS_VALUE_EXPR_P (decl))
674 tree ve = DECL_VALUE_EXPR (decl);
675 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
676 SET_DECL_VALUE_EXPR (new_decl, ve);
677 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
680 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
682 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
683 if (size == error_mark_node)
684 size = TYPE_SIZE (TREE_TYPE (new_decl));
685 DECL_SIZE (new_decl) = size;
687 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
688 if (size == error_mark_node)
689 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
690 DECL_SIZE_UNIT (new_decl) = size;
694 /* The callback for remap_decl. Search all containing contexts for a
695 mapping of the variable; this avoids having to duplicate the splay
696 tree ahead of time. We know a mapping doesn't already exist in the
697 given context. Create new mappings to implement default semantics. */
699 static tree
700 omp_copy_decl (tree var, copy_body_data *cb)
702 omp_context *ctx = (omp_context *) cb;
703 tree new_var;
705 if (TREE_CODE (var) == LABEL_DECL)
707 new_var = create_artificial_label ();
708 DECL_CONTEXT (new_var) = current_function_decl;
709 insert_decl_map (&ctx->cb, var, new_var);
710 return new_var;
713 while (!is_parallel_ctx (ctx))
715 ctx = ctx->outer;
716 if (ctx == NULL)
717 return var;
718 new_var = maybe_lookup_decl (var, ctx);
719 if (new_var)
720 return new_var;
723 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
724 return var;
726 return error_mark_node;
730 /* Return the parallel region associated with STMT. */
732 /* Debugging dumps for parallel regions. */
733 void dump_omp_region (FILE *, struct omp_region *, int);
734 void debug_omp_region (struct omp_region *);
735 void debug_all_omp_regions (void);
737 /* Dump the parallel region tree rooted at REGION. */
739 void
740 dump_omp_region (FILE *file, struct omp_region *region, int indent)
742 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
743 tree_code_name[region->type]);
745 if (region->inner)
746 dump_omp_region (file, region->inner, indent + 4);
748 if (region->cont)
750 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
751 region->cont->index);
754 if (region->exit)
755 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
756 region->exit->index);
757 else
758 fprintf (file, "%*s[no exit marker]\n", indent, "");
760 if (region->next)
761 dump_omp_region (file, region->next, indent);
764 void
765 debug_omp_region (struct omp_region *region)
767 dump_omp_region (stderr, region, 0);
770 void
771 debug_all_omp_regions (void)
773 dump_omp_region (stderr, root_omp_region, 0);
777 /* Create a new parallel region starting at STMT inside region PARENT. */
779 struct omp_region *
780 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
782 struct omp_region *region = xcalloc (1, sizeof (*region));
784 region->outer = parent;
785 region->entry = bb;
786 region->type = type;
788 if (parent)
790 /* This is a nested region. Add it to the list of inner
791 regions in PARENT. */
792 region->next = parent->inner;
793 parent->inner = region;
795 else
797 /* This is a toplevel region. Add it to the list of toplevel
798 regions in ROOT_OMP_REGION. */
799 region->next = root_omp_region;
800 root_omp_region = region;
803 return region;
806 /* Release the memory associated with the region tree rooted at REGION. */
808 static void
809 free_omp_region_1 (struct omp_region *region)
811 struct omp_region *i, *n;
813 for (i = region->inner; i ; i = n)
815 n = i->next;
816 free_omp_region_1 (i);
819 free (region);
822 /* Release the memory for the entire omp region tree. */
824 void
825 free_omp_regions (void)
827 struct omp_region *r, *n;
828 for (r = root_omp_region; r ; r = n)
830 n = r->next;
831 free_omp_region_1 (r);
833 root_omp_region = NULL;
837 /* Create a new context, with OUTER_CTX being the surrounding context. */
839 static omp_context *
840 new_omp_context (tree stmt, omp_context *outer_ctx)
842 omp_context *ctx = XCNEW (omp_context);
844 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
845 (splay_tree_value) ctx);
846 ctx->stmt = stmt;
848 if (outer_ctx)
850 ctx->outer = outer_ctx;
851 ctx->cb = outer_ctx->cb;
852 ctx->cb.block = NULL;
853 ctx->depth = outer_ctx->depth + 1;
855 else
857 ctx->cb.src_fn = current_function_decl;
858 ctx->cb.dst_fn = current_function_decl;
859 ctx->cb.src_node = cgraph_node (current_function_decl);
860 ctx->cb.dst_node = ctx->cb.src_node;
861 ctx->cb.src_cfun = cfun;
862 ctx->cb.copy_decl = omp_copy_decl;
863 ctx->cb.eh_region = -1;
864 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
865 ctx->depth = 1;
868 ctx->cb.decl_map = pointer_map_create ();
870 return ctx;
873 /* Destroy a omp_context data structures. Called through the splay tree
874 value delete callback. */
876 static void
877 delete_omp_context (splay_tree_value value)
879 omp_context *ctx = (omp_context *) value;
881 pointer_map_destroy (ctx->cb.decl_map);
883 if (ctx->field_map)
884 splay_tree_delete (ctx->field_map);
886 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
887 it produces corrupt debug information. */
888 if (ctx->record_type)
890 tree t;
891 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
892 DECL_ABSTRACT_ORIGIN (t) = NULL;
895 XDELETE (ctx);
898 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
899 context. */
901 static void
902 fixup_child_record_type (omp_context *ctx)
904 tree f, type = ctx->record_type;
906 /* ??? It isn't sufficient to just call remap_type here, because
907 variably_modified_type_p doesn't work the way we expect for
908 record types. Testing each field for whether it needs remapping
909 and creating a new record by hand works, however. */
910 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
911 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
912 break;
913 if (f)
915 tree name, new_fields = NULL;
917 type = lang_hooks.types.make_type (RECORD_TYPE);
918 name = DECL_NAME (TYPE_NAME (ctx->record_type));
919 name = build_decl (TYPE_DECL, name, type);
920 TYPE_NAME (type) = name;
922 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
924 tree new_f = copy_node (f);
925 DECL_CONTEXT (new_f) = type;
926 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
927 TREE_CHAIN (new_f) = new_fields;
928 new_fields = new_f;
930 /* Arrange to be able to look up the receiver field
931 given the sender field. */
932 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
933 (splay_tree_value) new_f);
935 TYPE_FIELDS (type) = nreverse (new_fields);
936 layout_type (type);
939 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
942 /* Instantiate decls as necessary in CTX to satisfy the data sharing
943 specified by CLAUSES. */
945 static void
946 scan_sharing_clauses (tree clauses, omp_context *ctx)
948 tree c, decl;
949 bool scan_array_reductions = false;
951 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
953 bool by_ref;
955 switch (OMP_CLAUSE_CODE (c))
957 case OMP_CLAUSE_PRIVATE:
958 decl = OMP_CLAUSE_DECL (c);
959 if (!is_variable_sized (decl))
960 install_var_local (decl, ctx);
961 break;
963 case OMP_CLAUSE_SHARED:
964 gcc_assert (is_parallel_ctx (ctx));
965 decl = OMP_CLAUSE_DECL (c);
966 gcc_assert (!is_variable_sized (decl));
967 by_ref = use_pointer_for_field (decl, true);
968 /* Global variables don't need to be copied,
969 the receiver side will use them directly. */
970 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
971 break;
972 if (! TREE_READONLY (decl)
973 || TREE_ADDRESSABLE (decl)
974 || by_ref
975 || is_reference (decl))
977 install_var_field (decl, by_ref, ctx);
978 install_var_local (decl, ctx);
979 break;
981 /* We don't need to copy const scalar vars back. */
982 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
983 goto do_private;
985 case OMP_CLAUSE_LASTPRIVATE:
986 /* Let the corresponding firstprivate clause create
987 the variable. */
988 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
989 break;
990 /* FALLTHRU */
992 case OMP_CLAUSE_FIRSTPRIVATE:
993 case OMP_CLAUSE_REDUCTION:
994 decl = OMP_CLAUSE_DECL (c);
995 do_private:
996 if (is_variable_sized (decl))
997 break;
998 else if (is_parallel_ctx (ctx)
999 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
1000 ctx)))
1002 by_ref = use_pointer_for_field (decl, false);
1003 install_var_field (decl, by_ref, ctx);
1005 install_var_local (decl, ctx);
1006 break;
1008 case OMP_CLAUSE_COPYPRIVATE:
1009 if (ctx->outer)
1010 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
1011 /* FALLTHRU */
1013 case OMP_CLAUSE_COPYIN:
1014 decl = OMP_CLAUSE_DECL (c);
1015 by_ref = use_pointer_for_field (decl, false);
1016 install_var_field (decl, by_ref, ctx);
1017 break;
1019 case OMP_CLAUSE_DEFAULT:
1020 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1021 break;
1023 case OMP_CLAUSE_IF:
1024 case OMP_CLAUSE_NUM_THREADS:
1025 case OMP_CLAUSE_SCHEDULE:
1026 if (ctx->outer)
1027 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1028 break;
1030 case OMP_CLAUSE_NOWAIT:
1031 case OMP_CLAUSE_ORDERED:
1032 break;
1034 default:
1035 gcc_unreachable ();
1039 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1041 switch (OMP_CLAUSE_CODE (c))
1043 case OMP_CLAUSE_LASTPRIVATE:
1044 /* Let the corresponding firstprivate clause create
1045 the variable. */
1046 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1047 break;
1048 /* FALLTHRU */
1050 case OMP_CLAUSE_PRIVATE:
1051 case OMP_CLAUSE_FIRSTPRIVATE:
1052 case OMP_CLAUSE_REDUCTION:
1053 decl = OMP_CLAUSE_DECL (c);
1054 if (is_variable_sized (decl))
1055 install_var_local (decl, ctx);
1056 fixup_remapped_decl (decl, ctx,
1057 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1058 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1059 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1060 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1061 scan_array_reductions = true;
1062 break;
1064 case OMP_CLAUSE_SHARED:
1065 decl = OMP_CLAUSE_DECL (c);
1066 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1067 fixup_remapped_decl (decl, ctx, false);
1068 break;
1070 case OMP_CLAUSE_COPYPRIVATE:
1071 case OMP_CLAUSE_COPYIN:
1072 case OMP_CLAUSE_DEFAULT:
1073 case OMP_CLAUSE_IF:
1074 case OMP_CLAUSE_NUM_THREADS:
1075 case OMP_CLAUSE_SCHEDULE:
1076 case OMP_CLAUSE_NOWAIT:
1077 case OMP_CLAUSE_ORDERED:
1078 break;
1080 default:
1081 gcc_unreachable ();
1085 if (scan_array_reductions)
1086 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1087 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1088 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1090 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1091 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1095 /* Create a new name for omp child function. Returns an identifier. */
1097 static GTY(()) unsigned int tmp_ompfn_id_num;
1099 static tree
1100 create_omp_child_function_name (void)
1102 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1103 size_t len = IDENTIFIER_LENGTH (name);
1104 char *tmp_name, *prefix;
1106 prefix = alloca (len + sizeof ("_omp_fn"));
1107 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1108 strcpy (prefix + len, "_omp_fn");
1109 #ifndef NO_DOT_IN_LABEL
1110 prefix[len] = '.';
1111 #elif !defined NO_DOLLAR_IN_LABEL
1112 prefix[len] = '$';
1113 #endif
1114 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1115 return get_identifier (tmp_name);
1118 /* Build a decl for the omp child function. It'll not contain a body
1119 yet, just the bare decl. */
1121 static void
1122 create_omp_child_function (omp_context *ctx)
1124 tree decl, type, name, t;
1126 name = create_omp_child_function_name ();
1127 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1129 decl = build_decl (FUNCTION_DECL, name, type);
1130 decl = lang_hooks.decls.pushdecl (decl);
1132 ctx->cb.dst_fn = decl;
1134 TREE_STATIC (decl) = 1;
1135 TREE_USED (decl) = 1;
1136 DECL_ARTIFICIAL (decl) = 1;
1137 DECL_IGNORED_P (decl) = 0;
1138 TREE_PUBLIC (decl) = 0;
1139 DECL_UNINLINABLE (decl) = 1;
1140 DECL_EXTERNAL (decl) = 0;
1141 DECL_CONTEXT (decl) = NULL_TREE;
1142 DECL_INITIAL (decl) = make_node (BLOCK);
1144 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1145 DECL_ARTIFICIAL (t) = 1;
1146 DECL_IGNORED_P (t) = 1;
1147 DECL_RESULT (decl) = t;
1149 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1150 DECL_ARTIFICIAL (t) = 1;
1151 DECL_ARG_TYPE (t) = ptr_type_node;
1152 DECL_CONTEXT (t) = current_function_decl;
1153 TREE_USED (t) = 1;
1154 DECL_ARGUMENTS (decl) = t;
1155 ctx->receiver_decl = t;
1157 /* Allocate memory for the function structure. The call to
1158 allocate_struct_function clobbers CFUN, so we need to restore
1159 it afterward. */
1160 push_struct_function (decl);
1161 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1162 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1163 pop_cfun ();
1167 /* Scan an OpenMP parallel directive. */
1169 static void
1170 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1172 omp_context *ctx;
1173 tree name;
1175 /* Ignore parallel directives with empty bodies, unless there
1176 are copyin clauses. */
1177 if (optimize > 0
1178 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1179 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1181 *stmt_p = build_empty_stmt ();
1182 return;
1185 ctx = new_omp_context (*stmt_p, outer_ctx);
1186 if (parallel_nesting_level > 1)
1187 ctx->is_nested = true;
1188 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1189 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1190 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1191 name = create_tmp_var_name (".omp_data_s");
1192 name = build_decl (TYPE_DECL, name, ctx->record_type);
1193 TYPE_NAME (ctx->record_type) = name;
1194 create_omp_child_function (ctx);
1195 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1197 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1198 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1200 if (TYPE_FIELDS (ctx->record_type) == NULL)
1201 ctx->record_type = ctx->receiver_decl = NULL;
1202 else
1204 layout_type (ctx->record_type);
1205 fixup_child_record_type (ctx);
1210 /* Scan an OpenMP loop directive. */
1212 static void
1213 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1215 omp_context *ctx;
1216 tree stmt;
1218 stmt = *stmt_p;
1219 ctx = new_omp_context (stmt, outer_ctx);
1221 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1223 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1224 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1225 scan_omp (&OMP_FOR_COND (stmt), ctx);
1226 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1227 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1230 /* Scan an OpenMP sections directive. */
1232 static void
1233 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1235 tree stmt;
1236 omp_context *ctx;
1238 stmt = *stmt_p;
1239 ctx = new_omp_context (stmt, outer_ctx);
1240 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1241 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1244 /* Scan an OpenMP single directive. */
1246 static void
1247 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1249 tree stmt = *stmt_p;
1250 omp_context *ctx;
1251 tree name;
1253 ctx = new_omp_context (stmt, outer_ctx);
1254 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1255 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1256 name = create_tmp_var_name (".omp_copy_s");
1257 name = build_decl (TYPE_DECL, name, ctx->record_type);
1258 TYPE_NAME (ctx->record_type) = name;
1260 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1261 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1263 if (TYPE_FIELDS (ctx->record_type) == NULL)
1264 ctx->record_type = NULL;
1265 else
1266 layout_type (ctx->record_type);
1270 /* Check OpenMP nesting restrictions. */
1271 static void
1272 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1274 switch (TREE_CODE (t))
1276 case OMP_FOR:
1277 case OMP_SECTIONS:
1278 case OMP_SINGLE:
1279 for (; ctx != NULL; ctx = ctx->outer)
1280 switch (TREE_CODE (ctx->stmt))
1282 case OMP_FOR:
1283 case OMP_SECTIONS:
1284 case OMP_SINGLE:
1285 case OMP_ORDERED:
1286 case OMP_MASTER:
1287 warning (0, "work-sharing region may not be closely nested inside "
1288 "of work-sharing, critical, ordered or master region");
1289 return;
1290 case OMP_PARALLEL:
1291 return;
1292 default:
1293 break;
1295 break;
1296 case OMP_MASTER:
1297 for (; ctx != NULL; ctx = ctx->outer)
1298 switch (TREE_CODE (ctx->stmt))
1300 case OMP_FOR:
1301 case OMP_SECTIONS:
1302 case OMP_SINGLE:
1303 warning (0, "master region may not be closely nested inside "
1304 "of work-sharing region");
1305 return;
1306 case OMP_PARALLEL:
1307 return;
1308 default:
1309 break;
1311 break;
1312 case OMP_ORDERED:
1313 for (; ctx != NULL; ctx = ctx->outer)
1314 switch (TREE_CODE (ctx->stmt))
1316 case OMP_CRITICAL:
1317 warning (0, "ordered region may not be closely nested inside "
1318 "of critical region");
1319 return;
1320 case OMP_FOR:
1321 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1322 OMP_CLAUSE_ORDERED) == NULL)
1323 warning (0, "ordered region must be closely nested inside "
1324 "a loop region with an ordered clause");
1325 return;
1326 case OMP_PARALLEL:
1327 return;
1328 default:
1329 break;
1331 break;
1332 case OMP_CRITICAL:
1333 for (; ctx != NULL; ctx = ctx->outer)
1334 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1335 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1337 warning (0, "critical region may not be nested inside a critical "
1338 "region with the same name");
1339 return;
1341 break;
1342 default:
1343 break;
1348 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1350 static tree
1351 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1353 struct walk_stmt_info *wi = data;
1354 omp_context *ctx = wi->info;
1355 tree t = *tp;
1357 if (EXPR_HAS_LOCATION (t))
1358 input_location = EXPR_LOCATION (t);
1360 /* Check the OpenMP nesting restrictions. */
1361 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1362 check_omp_nesting_restrictions (t, ctx);
1364 *walk_subtrees = 0;
1365 switch (TREE_CODE (t))
1367 case OMP_PARALLEL:
1368 parallel_nesting_level++;
1369 scan_omp_parallel (tp, ctx);
1370 parallel_nesting_level--;
1371 break;
1373 case OMP_FOR:
1374 scan_omp_for (tp, ctx);
1375 break;
1377 case OMP_SECTIONS:
1378 scan_omp_sections (tp, ctx);
1379 break;
1381 case OMP_SINGLE:
1382 scan_omp_single (tp, ctx);
1383 break;
1385 case OMP_SECTION:
1386 case OMP_MASTER:
1387 case OMP_ORDERED:
1388 case OMP_CRITICAL:
1389 ctx = new_omp_context (*tp, ctx);
1390 scan_omp (&OMP_BODY (*tp), ctx);
1391 break;
1393 case BIND_EXPR:
1395 tree var;
1396 *walk_subtrees = 1;
1398 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1399 insert_decl_map (&ctx->cb, var, var);
1401 break;
1403 case VAR_DECL:
1404 case PARM_DECL:
1405 case LABEL_DECL:
1406 case RESULT_DECL:
1407 if (ctx)
1408 *tp = remap_decl (t, &ctx->cb);
1409 break;
1411 default:
1412 if (ctx && TYPE_P (t))
1413 *tp = remap_type (t, &ctx->cb);
1414 else if (!DECL_P (t))
1415 *walk_subtrees = 1;
1416 break;
1419 return NULL_TREE;
1423 /* Scan all the statements starting at STMT_P. CTX contains context
1424 information about the OpenMP directives and clauses found during
1425 the scan. */
1427 static void
1428 scan_omp (tree *stmt_p, omp_context *ctx)
1430 location_t saved_location;
1431 struct walk_stmt_info wi;
1433 memset (&wi, 0, sizeof (wi));
1434 wi.callback = scan_omp_1;
1435 wi.info = ctx;
1436 wi.want_bind_expr = (ctx != NULL);
1437 wi.want_locations = true;
1439 saved_location = input_location;
1440 walk_stmts (&wi, stmt_p);
1441 input_location = saved_location;
1444 /* Re-gimplification and code generation routines. */
1446 /* Build a call to GOMP_barrier. */
1448 static tree
1449 build_omp_barrier (void)
1451 return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1454 /* If a context was created for STMT when it was scanned, return it. */
1456 static omp_context *
1457 maybe_lookup_ctx (tree stmt)
1459 splay_tree_node n;
1460 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1461 return n ? (omp_context *) n->value : NULL;
1465 /* Find the mapping for DECL in CTX or the immediately enclosing
1466 context that has a mapping for DECL.
1468 If CTX is a nested parallel directive, we may have to use the decl
1469 mappings created in CTX's parent context. Suppose that we have the
1470 following parallel nesting (variable UIDs showed for clarity):
1472 iD.1562 = 0;
1473 #omp parallel shared(iD.1562) -> outer parallel
1474 iD.1562 = iD.1562 + 1;
1476 #omp parallel shared (iD.1562) -> inner parallel
1477 iD.1562 = iD.1562 - 1;
1479 Each parallel structure will create a distinct .omp_data_s structure
1480 for copying iD.1562 in/out of the directive:
1482 outer parallel .omp_data_s.1.i -> iD.1562
1483 inner parallel .omp_data_s.2.i -> iD.1562
1485 A shared variable mapping will produce a copy-out operation before
1486 the parallel directive and a copy-in operation after it. So, in
1487 this case we would have:
1489 iD.1562 = 0;
1490 .omp_data_o.1.i = iD.1562;
1491 #omp parallel shared(iD.1562) -> outer parallel
1492 .omp_data_i.1 = &.omp_data_o.1
1493 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1495 .omp_data_o.2.i = iD.1562; -> **
1496 #omp parallel shared(iD.1562) -> inner parallel
1497 .omp_data_i.2 = &.omp_data_o.2
1498 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1501 ** This is a problem. The symbol iD.1562 cannot be referenced
1502 inside the body of the outer parallel region. But since we are
1503 emitting this copy operation while expanding the inner parallel
1504 directive, we need to access the CTX structure of the outer
1505 parallel directive to get the correct mapping:
1507 .omp_data_o.2.i = .omp_data_i.1->i
1509 Since there may be other workshare or parallel directives enclosing
1510 the parallel directive, it may be necessary to walk up the context
1511 parent chain. This is not a problem in general because nested
1512 parallelism happens only rarely. */
1514 static tree
1515 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1517 tree t;
1518 omp_context *up;
1520 gcc_assert (ctx->is_nested);
1522 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1523 t = maybe_lookup_decl (decl, up);
1525 gcc_assert (t || is_global_var (decl));
1527 return t ? t : decl;
1531 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1532 in outer contexts. */
1534 static tree
1535 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1537 tree t = NULL;
1538 omp_context *up;
1540 if (ctx->is_nested)
1541 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1542 t = maybe_lookup_decl (decl, up);
1544 return t ? t : decl;
1548 /* Construct the initialization value for reduction CLAUSE. */
1550 tree
1551 omp_reduction_init (tree clause, tree type)
1553 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1555 case PLUS_EXPR:
1556 case MINUS_EXPR:
1557 case BIT_IOR_EXPR:
1558 case BIT_XOR_EXPR:
1559 case TRUTH_OR_EXPR:
1560 case TRUTH_ORIF_EXPR:
1561 case TRUTH_XOR_EXPR:
1562 case NE_EXPR:
1563 return fold_convert (type, integer_zero_node);
1565 case MULT_EXPR:
1566 case TRUTH_AND_EXPR:
1567 case TRUTH_ANDIF_EXPR:
1568 case EQ_EXPR:
1569 return fold_convert (type, integer_one_node);
1571 case BIT_AND_EXPR:
1572 return fold_convert (type, integer_minus_one_node);
1574 case MAX_EXPR:
1575 if (SCALAR_FLOAT_TYPE_P (type))
1577 REAL_VALUE_TYPE max, min;
1578 if (HONOR_INFINITIES (TYPE_MODE (type)))
1580 real_inf (&max);
1581 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1583 else
1584 real_maxval (&min, 1, TYPE_MODE (type));
1585 return build_real (type, min);
1587 else
1589 gcc_assert (INTEGRAL_TYPE_P (type));
1590 return TYPE_MIN_VALUE (type);
1593 case MIN_EXPR:
1594 if (SCALAR_FLOAT_TYPE_P (type))
1596 REAL_VALUE_TYPE max;
1597 if (HONOR_INFINITIES (TYPE_MODE (type)))
1598 real_inf (&max);
1599 else
1600 real_maxval (&max, 0, TYPE_MODE (type));
1601 return build_real (type, max);
1603 else
1605 gcc_assert (INTEGRAL_TYPE_P (type));
1606 return TYPE_MAX_VALUE (type);
1609 default:
1610 gcc_unreachable ();
1614 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1615 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1616 private variables. Initialization statements go in ILIST, while calls
1617 to destructors go in DLIST. */
1619 static void
1620 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1621 omp_context *ctx)
1623 tree_stmt_iterator diter;
1624 tree c, dtor, copyin_seq, x, ptr;
1625 bool copyin_by_ref = false;
1626 bool lastprivate_firstprivate = false;
1627 int pass;
1629 *dlist = alloc_stmt_list ();
1630 diter = tsi_start (*dlist);
1631 copyin_seq = NULL;
1633 /* Do all the fixed sized types in the first pass, and the variable sized
1634 types in the second pass. This makes sure that the scalar arguments to
1635 the variable sized types are processed before we use them in the
1636 variable sized operations. */
1637 for (pass = 0; pass < 2; ++pass)
1639 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1641 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1642 tree var, new_var;
1643 bool by_ref;
1645 switch (c_kind)
1647 case OMP_CLAUSE_PRIVATE:
1648 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1649 continue;
1650 break;
1651 case OMP_CLAUSE_SHARED:
1652 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1654 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1655 continue;
1657 case OMP_CLAUSE_FIRSTPRIVATE:
1658 case OMP_CLAUSE_COPYIN:
1659 case OMP_CLAUSE_REDUCTION:
1660 break;
1661 case OMP_CLAUSE_LASTPRIVATE:
1662 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1664 lastprivate_firstprivate = true;
1665 if (pass != 0)
1666 continue;
1668 break;
1669 default:
1670 continue;
1673 new_var = var = OMP_CLAUSE_DECL (c);
1674 if (c_kind != OMP_CLAUSE_COPYIN)
1675 new_var = lookup_decl (var, ctx);
1677 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1679 if (pass != 0)
1680 continue;
1682 else if (is_variable_sized (var))
1684 /* For variable sized types, we need to allocate the
1685 actual storage here. Call alloca and store the
1686 result in the pointer decl that we created elsewhere. */
1687 if (pass == 0)
1688 continue;
1690 ptr = DECL_VALUE_EXPR (new_var);
1691 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1692 ptr = TREE_OPERAND (ptr, 0);
1693 gcc_assert (DECL_P (ptr));
1695 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1696 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1697 x = fold_convert (TREE_TYPE (ptr), x);
1698 x = build_gimple_modify_stmt (ptr, x);
1699 gimplify_and_add (x, ilist);
1701 else if (is_reference (var))
1703 /* For references that are being privatized for Fortran,
1704 allocate new backing storage for the new pointer
1705 variable. This allows us to avoid changing all the
1706 code that expects a pointer to something that expects
1707 a direct variable. Note that this doesn't apply to
1708 C++, since reference types are disallowed in data
1709 sharing clauses there, except for NRV optimized
1710 return values. */
1711 if (pass == 0)
1712 continue;
1714 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1715 if (TREE_CONSTANT (x))
1717 const char *name = NULL;
1718 if (DECL_NAME (var))
1719 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1721 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1722 name);
1723 gimple_add_tmp_var (x);
1724 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1726 else
1728 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1729 x = fold_convert (TREE_TYPE (new_var), x);
1732 x = build_gimple_modify_stmt (new_var, x);
1733 gimplify_and_add (x, ilist);
1735 new_var = build_fold_indirect_ref (new_var);
1737 else if (c_kind == OMP_CLAUSE_REDUCTION
1738 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1740 if (pass == 0)
1741 continue;
1743 else if (pass != 0)
1744 continue;
1746 switch (OMP_CLAUSE_CODE (c))
1748 case OMP_CLAUSE_SHARED:
1749 /* Shared global vars are just accessed directly. */
1750 if (is_global_var (new_var))
1751 break;
1752 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1753 needs to be delayed until after fixup_child_record_type so
1754 that we get the correct type during the dereference. */
1755 by_ref = use_pointer_for_field (var, true);
1756 x = build_receiver_ref (var, by_ref, ctx);
1757 SET_DECL_VALUE_EXPR (new_var, x);
1758 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1760 /* ??? If VAR is not passed by reference, and the variable
1761 hasn't been initialized yet, then we'll get a warning for
1762 the store into the omp_data_s structure. Ideally, we'd be
1763 able to notice this and not store anything at all, but
1764 we're generating code too early. Suppress the warning. */
1765 if (!by_ref)
1766 TREE_NO_WARNING (var) = 1;
1767 break;
1769 case OMP_CLAUSE_LASTPRIVATE:
1770 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1771 break;
1772 /* FALLTHRU */
1774 case OMP_CLAUSE_PRIVATE:
1775 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1776 if (x)
1777 gimplify_and_add (x, ilist);
1778 /* FALLTHRU */
1780 do_dtor:
1781 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1782 if (x)
1784 dtor = x;
1785 gimplify_stmt (&dtor);
1786 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1788 break;
1790 case OMP_CLAUSE_FIRSTPRIVATE:
1791 x = build_outer_var_ref (var, ctx);
1792 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1793 gimplify_and_add (x, ilist);
1794 goto do_dtor;
1795 break;
1797 case OMP_CLAUSE_COPYIN:
1798 by_ref = use_pointer_for_field (var, false);
1799 x = build_receiver_ref (var, by_ref, ctx);
1800 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1801 append_to_statement_list (x, &copyin_seq);
1802 copyin_by_ref |= by_ref;
1803 break;
1805 case OMP_CLAUSE_REDUCTION:
1806 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1808 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1809 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1811 else
1813 x = omp_reduction_init (c, TREE_TYPE (new_var));
1814 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1815 x = build_gimple_modify_stmt (new_var, x);
1816 gimplify_and_add (x, ilist);
1818 break;
1820 default:
1821 gcc_unreachable ();
1826 /* The copyin sequence is not to be executed by the main thread, since
1827 that would result in self-copies. Perhaps not visible to scalars,
1828 but it certainly is to C++ operator=. */
1829 if (copyin_seq)
1831 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1832 x = build2 (NE_EXPR, boolean_type_node, x,
1833 build_int_cst (TREE_TYPE (x), 0));
1834 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1835 gimplify_and_add (x, ilist);
1838 /* If any copyin variable is passed by reference, we must ensure the
1839 master thread doesn't modify it before it is copied over in all
1840 threads. Similarly for variables in both firstprivate and
1841 lastprivate clauses we need to ensure the lastprivate copying
1842 happens after firstprivate copying in all threads. */
1843 if (copyin_by_ref || lastprivate_firstprivate)
1844 gimplify_and_add (build_omp_barrier (), ilist);
1848 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1849 both parallel and workshare constructs. PREDICATE may be NULL if it's
1850 always true. */
1852 static void
1853 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1854 omp_context *ctx)
1856 tree sub_list, x, c;
1858 /* Early exit if there are no lastprivate clauses. */
1859 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1860 if (clauses == NULL)
1862 /* If this was a workshare clause, see if it had been combined
1863 with its parallel. In that case, look for the clauses on the
1864 parallel statement itself. */
1865 if (is_parallel_ctx (ctx))
1866 return;
1868 ctx = ctx->outer;
1869 if (ctx == NULL || !is_parallel_ctx (ctx))
1870 return;
1872 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1873 OMP_CLAUSE_LASTPRIVATE);
1874 if (clauses == NULL)
1875 return;
1878 sub_list = alloc_stmt_list ();
1880 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1882 tree var, new_var;
1884 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1885 continue;
1887 var = OMP_CLAUSE_DECL (c);
1888 new_var = lookup_decl (var, ctx);
1890 x = build_outer_var_ref (var, ctx);
1891 if (is_reference (var))
1892 new_var = build_fold_indirect_ref (new_var);
1893 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1894 append_to_statement_list (x, &sub_list);
1897 if (predicate)
1898 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1899 else
1900 x = sub_list;
1902 gimplify_and_add (x, stmt_list);
1906 /* Generate code to implement the REDUCTION clauses. */
1908 static void
1909 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1911 tree sub_list = NULL, x, c;
1912 int count = 0;
1914 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1915 update in that case, otherwise use a lock. */
1916 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1917 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1919 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1921 /* Never use OMP_ATOMIC for array reductions. */
1922 count = -1;
1923 break;
1925 count++;
1928 if (count == 0)
1929 return;
1931 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1933 tree var, ref, new_var;
1934 enum tree_code code;
1936 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1937 continue;
1939 var = OMP_CLAUSE_DECL (c);
1940 new_var = lookup_decl (var, ctx);
1941 if (is_reference (var))
1942 new_var = build_fold_indirect_ref (new_var);
1943 ref = build_outer_var_ref (var, ctx);
1944 code = OMP_CLAUSE_REDUCTION_CODE (c);
1946 /* reduction(-:var) sums up the partial results, so it acts
1947 identically to reduction(+:var). */
1948 if (code == MINUS_EXPR)
1949 code = PLUS_EXPR;
1951 if (count == 1)
1953 tree addr = build_fold_addr_expr (ref);
1955 addr = save_expr (addr);
1956 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1957 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1958 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1959 gimplify_and_add (x, stmt_list);
1960 return;
1963 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1965 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1967 if (is_reference (var))
1968 ref = build_fold_addr_expr (ref);
1969 SET_DECL_VALUE_EXPR (placeholder, ref);
1970 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1971 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1972 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1973 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1975 else
1977 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1978 ref = build_outer_var_ref (var, ctx);
1979 x = build_gimple_modify_stmt (ref, x);
1980 append_to_statement_list (x, &sub_list);
1984 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
1985 gimplify_and_add (x, stmt_list);
1987 gimplify_and_add (sub_list, stmt_list);
1989 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
1990 gimplify_and_add (x, stmt_list);
1994 /* Generate code to implement the COPYPRIVATE clauses. */
1996 static void
1997 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1998 omp_context *ctx)
2000 tree c;
2002 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2004 tree var, ref, x;
2005 bool by_ref;
2007 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2008 continue;
2010 var = OMP_CLAUSE_DECL (c);
2011 by_ref = use_pointer_for_field (var, false);
2013 ref = build_sender_ref (var, ctx);
2014 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
2015 x = by_ref ? build_fold_addr_expr (x) : x;
2016 x = build_gimple_modify_stmt (ref, x);
2017 gimplify_and_add (x, slist);
2019 ref = build_receiver_ref (var, by_ref, ctx);
2020 if (is_reference (var))
2022 ref = build_fold_indirect_ref (ref);
2023 var = build_fold_indirect_ref (var);
2025 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2026 gimplify_and_add (x, rlist);
2031 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2032 and REDUCTION from the sender (aka parent) side. */
2034 static void
2035 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2037 tree c;
2039 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2041 tree val, ref, x, var;
2042 bool by_ref, do_in = false, do_out = false;
2044 switch (OMP_CLAUSE_CODE (c))
2046 case OMP_CLAUSE_FIRSTPRIVATE:
2047 case OMP_CLAUSE_COPYIN:
2048 case OMP_CLAUSE_LASTPRIVATE:
2049 case OMP_CLAUSE_REDUCTION:
2050 break;
2051 default:
2052 continue;
2055 var = val = OMP_CLAUSE_DECL (c);
2056 if (ctx->is_nested)
2057 var = lookup_decl_in_outer_ctx (val, ctx);
2059 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2060 && is_global_var (var))
2061 continue;
2062 if (is_variable_sized (val))
2063 continue;
2064 by_ref = use_pointer_for_field (val, false);
2066 switch (OMP_CLAUSE_CODE (c))
2068 case OMP_CLAUSE_FIRSTPRIVATE:
2069 case OMP_CLAUSE_COPYIN:
2070 do_in = true;
2071 break;
2073 case OMP_CLAUSE_LASTPRIVATE:
2074 if (by_ref || is_reference (val))
2076 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2077 continue;
2078 do_in = true;
2080 else
2081 do_out = true;
2082 break;
2084 case OMP_CLAUSE_REDUCTION:
2085 do_in = true;
2086 do_out = !(by_ref || is_reference (val));
2087 break;
2089 default:
2090 gcc_unreachable ();
2093 if (do_in)
2095 ref = build_sender_ref (val, ctx);
2096 x = by_ref ? build_fold_addr_expr (var) : var;
2097 x = build_gimple_modify_stmt (ref, x);
2098 gimplify_and_add (x, ilist);
2101 if (do_out)
2103 ref = build_sender_ref (val, ctx);
2104 x = build_gimple_modify_stmt (var, ref);
2105 gimplify_and_add (x, olist);
2110 /* Generate code to implement SHARED from the sender (aka parent) side.
2111 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2112 got automatically shared. */
2114 static void
2115 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2117 tree var, ovar, nvar, f, x;
2119 if (ctx->record_type == NULL)
2120 return;
2122 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2124 ovar = DECL_ABSTRACT_ORIGIN (f);
2125 nvar = maybe_lookup_decl (ovar, ctx);
2126 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2127 continue;
2129 var = ovar;
2131 /* If CTX is a nested parallel directive. Find the immediately
2132 enclosing parallel or workshare construct that contains a
2133 mapping for OVAR. */
2134 if (ctx->is_nested)
2135 var = lookup_decl_in_outer_ctx (ovar, ctx);
2137 if (use_pointer_for_field (ovar, true))
2139 x = build_sender_ref (ovar, ctx);
2140 var = build_fold_addr_expr (var);
2141 x = build_gimple_modify_stmt (x, var);
2142 gimplify_and_add (x, ilist);
2144 else
2146 x = build_sender_ref (ovar, ctx);
2147 x = build_gimple_modify_stmt (x, var);
2148 gimplify_and_add (x, ilist);
2150 x = build_sender_ref (ovar, ctx);
2151 x = build_gimple_modify_stmt (var, x);
2152 gimplify_and_add (x, olist);
2157 /* Build the function calls to GOMP_parallel_start etc to actually
2158 generate the parallel operation. REGION is the parallel region
2159 being expanded. BB is the block where to insert the code. WS_ARGS
2160 will be set if this is a call to a combined parallel+workshare
2161 construct, it contains the list of additional arguments needed by
2162 the workshare construct. */
2164 static void
2165 expand_parallel_call (struct omp_region *region, basic_block bb,
2166 tree entry_stmt, tree ws_args)
2168 tree t, t1, t2, val, cond, c, clauses;
2169 block_stmt_iterator si;
2170 int start_ix;
2172 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2174 /* Determine what flavor of GOMP_parallel_start we will be
2175 emitting. */
2176 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2177 if (is_combined_parallel (region))
2179 switch (region->inner->type)
2181 case OMP_FOR:
2182 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2183 + region->inner->sched_kind;
2184 break;
2185 case OMP_SECTIONS:
2186 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2187 break;
2188 default:
2189 gcc_unreachable ();
2193 /* By default, the value of NUM_THREADS is zero (selected at run time)
2194 and there is no conditional. */
2195 cond = NULL_TREE;
2196 val = build_int_cst (unsigned_type_node, 0);
2198 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2199 if (c)
2200 cond = OMP_CLAUSE_IF_EXPR (c);
2202 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2203 if (c)
2204 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2206 /* Ensure 'val' is of the correct type. */
2207 val = fold_convert (unsigned_type_node, val);
2209 /* If we found the clause 'if (cond)', build either
2210 (cond != 0) or (cond ? val : 1u). */
2211 if (cond)
2213 block_stmt_iterator si;
2215 cond = gimple_boolify (cond);
2217 if (integer_zerop (val))
2218 val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
2219 build_int_cst (TREE_TYPE (cond), 0));
2220 else
2222 basic_block cond_bb, then_bb, else_bb;
2223 edge e, e_then, e_else;
2224 tree t, tmp_then, tmp_else, tmp_join, tmp_var;
2226 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
2227 if (gimple_in_ssa_p (cfun))
2229 tmp_then = make_ssa_name (tmp_var, NULL_TREE);
2230 tmp_else = make_ssa_name (tmp_var, NULL_TREE);
2231 tmp_join = make_ssa_name (tmp_var, NULL_TREE);
2233 else
2235 tmp_then = tmp_var;
2236 tmp_else = tmp_var;
2237 tmp_join = tmp_var;
2240 e = split_block (bb, NULL);
2241 cond_bb = e->src;
2242 bb = e->dest;
2243 remove_edge (e);
2245 then_bb = create_empty_bb (cond_bb);
2246 else_bb = create_empty_bb (then_bb);
2247 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
2248 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
2250 t = build3 (COND_EXPR, void_type_node,
2251 cond, NULL_TREE, NULL_TREE);
2253 si = bsi_start (cond_bb);
2254 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2256 si = bsi_start (then_bb);
2257 t = build_gimple_modify_stmt (tmp_then, val);
2258 if (gimple_in_ssa_p (cfun))
2259 SSA_NAME_DEF_STMT (tmp_then) = t;
2260 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2262 si = bsi_start (else_bb);
2263 t = build_gimple_modify_stmt (tmp_else,
2264 build_int_cst (unsigned_type_node, 1));
2265 if (gimple_in_ssa_p (cfun))
2266 SSA_NAME_DEF_STMT (tmp_else) = t;
2267 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2269 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2270 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2271 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
2272 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
2274 if (gimple_in_ssa_p (cfun))
2276 tree phi = create_phi_node (tmp_join, bb);
2277 SSA_NAME_DEF_STMT (tmp_join) = phi;
2278 add_phi_arg (phi, tmp_then, e_then);
2279 add_phi_arg (phi, tmp_else, e_else);
2282 val = tmp_join;
2285 si = bsi_start (bb);
2286 val = force_gimple_operand_bsi (&si, val, true, NULL_TREE,
2287 false, BSI_CONTINUE_LINKING);
2290 si = bsi_last (bb);
2291 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2292 if (t == NULL)
2293 t1 = null_pointer_node;
2294 else
2295 t1 = build_fold_addr_expr (t);
2296 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2298 if (ws_args)
2300 tree args = tree_cons (NULL, t2,
2301 tree_cons (NULL, t1,
2302 tree_cons (NULL, val, ws_args)));
2303 t = build_function_call_expr (built_in_decls[start_ix], args);
2305 else
2306 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2308 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2309 false, BSI_CONTINUE_LINKING);
2311 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2312 if (t == NULL)
2313 t = null_pointer_node;
2314 else
2315 t = build_fold_addr_expr (t);
2316 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2317 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2318 false, BSI_CONTINUE_LINKING);
2320 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2321 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2322 false, BSI_CONTINUE_LINKING);
2326 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2327 handler. This prevents programs from violating the structured
2328 block semantics with throws. */
2330 static void
2331 maybe_catch_exception (tree *stmt_p)
2333 tree f, t;
2335 if (!flag_exceptions)
2336 return;
2338 if (lang_protect_cleanup_actions)
2339 t = lang_protect_cleanup_actions ();
2340 else
2341 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2342 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2343 EH_FILTER_MUST_NOT_THROW (f) = 1;
2344 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2346 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2347 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2349 *stmt_p = NULL;
2350 append_to_statement_list (t, stmt_p);
2353 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2355 static tree
2356 list2chain (tree list)
2358 tree t;
2360 for (t = list; t; t = TREE_CHAIN (t))
2362 tree var = TREE_VALUE (t);
2363 if (TREE_CHAIN (t))
2364 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2365 else
2366 TREE_CHAIN (var) = NULL_TREE;
2369 return list ? TREE_VALUE (list) : NULL_TREE;
2373 /* Remove barriers in REGION->EXIT's block. Note that this is only
2374 valid for OMP_PARALLEL regions. Since the end of a parallel region
2375 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2376 left a barrier at the end of the OMP_PARALLEL region can now be
2377 removed. */
2379 static void
2380 remove_exit_barrier (struct omp_region *region)
2382 block_stmt_iterator si;
2383 basic_block exit_bb;
2384 edge_iterator ei;
2385 edge e;
2386 tree t;
2388 exit_bb = region->exit;
2390 /* If the parallel region doesn't return, we don't have REGION->EXIT
2391 block at all. */
2392 if (! exit_bb)
2393 return;
2395 /* The last insn in the block will be the parallel's OMP_RETURN. The
2396 workshare's OMP_RETURN will be in a preceding block. The kinds of
2397 statements that can appear in between are extremely limited -- no
2398 memory operations at all. Here, we allow nothing at all, so the
2399 only thing we allow to precede this OMP_RETURN is a label. */
2400 si = bsi_last (exit_bb);
2401 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2402 bsi_prev (&si);
2403 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2404 return;
2406 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2408 si = bsi_last (e->src);
2409 if (bsi_end_p (si))
2410 continue;
2411 t = bsi_stmt (si);
2412 if (TREE_CODE (t) == OMP_RETURN)
2413 OMP_RETURN_NOWAIT (t) = 1;
2417 static void
2418 remove_exit_barriers (struct omp_region *region)
2420 if (region->type == OMP_PARALLEL)
2421 remove_exit_barrier (region);
2423 if (region->inner)
2425 region = region->inner;
2426 remove_exit_barriers (region);
2427 while (region->next)
2429 region = region->next;
2430 remove_exit_barriers (region);
2435 /* Expand the OpenMP parallel directive starting at REGION. */
2437 static void
2438 expand_omp_parallel (struct omp_region *region)
2440 basic_block entry_bb, exit_bb, new_bb;
2441 struct function *child_cfun;
2442 tree child_fn, block, t, ws_args;
2443 block_stmt_iterator si;
2444 tree entry_stmt;
2445 edge e;
2447 entry_stmt = last_stmt (region->entry);
2448 child_fn = OMP_PARALLEL_FN (entry_stmt);
2449 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2451 entry_bb = region->entry;
2452 exit_bb = region->exit;
2454 if (is_combined_parallel (region))
2455 ws_args = region->ws_args;
2456 else
2457 ws_args = NULL_TREE;
2459 if (child_cfun->cfg)
2461 /* Due to inlining, it may happen that we have already outlined
2462 the region, in which case all we need to do is make the
2463 sub-graph unreachable and emit the parallel call. */
2464 edge entry_succ_e, exit_succ_e;
2465 block_stmt_iterator si;
2467 entry_succ_e = single_succ_edge (entry_bb);
2469 si = bsi_last (entry_bb);
2470 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2471 bsi_remove (&si, true);
2473 new_bb = entry_bb;
2474 if (exit_bb)
2476 exit_succ_e = single_succ_edge (exit_bb);
2477 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2479 remove_edge_and_dominated_blocks (entry_succ_e);
2481 else
2483 /* If the parallel region needs data sent from the parent
2484 function, then the very first statement (except possible
2485 tree profile counter updates) of the parallel body
2486 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2487 &.OMP_DATA_O is passed as an argument to the child function,
2488 we need to replace it with the argument as seen by the child
2489 function.
2491 In most cases, this will end up being the identity assignment
2492 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2493 a function call that has been inlined, the original PARM_DECL
2494 .OMP_DATA_I may have been converted into a different local
2495 variable. In which case, we need to keep the assignment. */
2496 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2498 basic_block entry_succ_bb = single_succ (entry_bb);
2499 block_stmt_iterator si;
2500 tree parcopy_stmt = NULL_TREE, arg, narg;
2502 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2504 tree stmt, arg;
2506 gcc_assert (!bsi_end_p (si));
2507 stmt = bsi_stmt (si);
2508 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2509 continue;
2511 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2512 STRIP_NOPS (arg);
2513 if (TREE_CODE (arg) == ADDR_EXPR
2514 && TREE_OPERAND (arg, 0)
2515 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2517 parcopy_stmt = stmt;
2518 break;
2522 gcc_assert (parcopy_stmt != NULL_TREE);
2523 arg = DECL_ARGUMENTS (child_fn);
2525 if (!gimple_in_ssa_p (cfun))
2527 if (GIMPLE_STMT_OPERAND (parcopy_stmt, 0) == arg)
2528 bsi_remove (&si, true);
2529 else
2530 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = arg;
2532 else
2534 /* If we are in ssa form, we must load the value from the default
2535 definition of the argument. That should not be defined now,
2536 since the argument is not used uninitialized. */
2537 gcc_assert (gimple_default_def (cfun, arg) == NULL);
2538 narg = make_ssa_name (arg, build_empty_stmt ());
2539 set_default_def (arg, narg);
2540 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = narg;
2541 update_stmt (parcopy_stmt);
2545 /* Declare local variables needed in CHILD_CFUN. */
2546 block = DECL_INITIAL (child_fn);
2547 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2548 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2550 /* Reset DECL_CONTEXT on function arguments. */
2551 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2552 DECL_CONTEXT (t) = child_fn;
2554 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2555 child function. */
2556 si = bsi_last (entry_bb);
2557 t = bsi_stmt (si);
2558 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2559 bsi_remove (&si, true);
2560 e = split_block (entry_bb, t);
2561 entry_bb = e->dest;
2562 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2564 /* Convert OMP_RETURN into a RETURN_EXPR. */
2565 if (exit_bb)
2567 si = bsi_last (exit_bb);
2568 gcc_assert (!bsi_end_p (si)
2569 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2570 t = build1 (RETURN_EXPR, void_type_node, NULL);
2571 bsi_insert_after (&si, t, BSI_SAME_STMT);
2572 bsi_remove (&si, true);
2575 /* Move the parallel region into CHILD_CFUN. */
2577 if (gimple_in_ssa_p (cfun))
2579 push_cfun (child_cfun);
2580 init_tree_ssa ();
2581 init_ssa_operands ();
2582 cfun->gimple_df->in_ssa_p = true;
2583 pop_cfun ();
2585 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2586 if (exit_bb)
2587 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2589 /* Inform the callgraph about the new function. */
2590 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2591 = cfun->curr_properties;
2592 cgraph_add_new_function (child_fn, true);
2594 /* Fix the callgraph edges for child_cfun. Those for cfun will be
2595 fixed in a following pass. */
2596 push_cfun (child_cfun);
2597 rebuild_cgraph_edges ();
2598 pop_cfun ();
2601 /* Emit a library call to launch the children threads. */
2602 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2606 /* A subroutine of expand_omp_for. Generate code for a parallel
2607 loop with any schedule. Given parameters:
2609 for (V = N1; V cond N2; V += STEP) BODY;
2611 where COND is "<" or ">", we generate pseudocode
2613 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2614 if (more) goto L0; else goto L3;
2616 V = istart0;
2617 iend = iend0;
2619 BODY;
2620 V += STEP;
2621 if (V cond iend) goto L1; else goto L2;
2623 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2626 If this is a combined omp parallel loop, instead of the call to
2627 GOMP_loop_foo_start, we call GOMP_loop_foo_next. */
2629 static void
2630 expand_omp_for_generic (struct omp_region *region,
2631 struct omp_for_data *fd,
2632 enum built_in_function start_fn,
2633 enum built_in_function next_fn)
2635 tree type, istart0, iend0, iend, phi;
2636 tree t, vmain, vback;
2637 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2638 basic_block l2_bb = NULL, l3_bb = NULL;
2639 block_stmt_iterator si;
2640 bool in_combined_parallel = is_combined_parallel (region);
2641 bool broken_loop = region->cont == NULL;
2642 edge e, ne;
2644 gcc_assert (!broken_loop || !in_combined_parallel);
2646 type = TREE_TYPE (fd->v);
2648 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2649 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2650 TREE_ADDRESSABLE (istart0) = 1;
2651 TREE_ADDRESSABLE (iend0) = 1;
2652 if (gimple_in_ssa_p (cfun))
2654 add_referenced_var (istart0);
2655 add_referenced_var (iend0);
2658 entry_bb = region->entry;
2659 cont_bb = region->cont;
2660 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2661 gcc_assert (broken_loop
2662 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2663 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2664 l1_bb = single_succ (l0_bb);
2665 if (!broken_loop)
2667 l2_bb = create_empty_bb (cont_bb);
2668 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
2669 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2671 else
2672 l2_bb = NULL;
2673 l3_bb = BRANCH_EDGE (entry_bb)->dest;
2674 exit_bb = region->exit;
2676 si = bsi_last (entry_bb);
2677 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2678 if (in_combined_parallel)
2680 /* In a combined parallel loop, emit a call to
2681 GOMP_loop_foo_next. */
2682 t = build_call_expr (built_in_decls[next_fn], 2,
2683 build_fold_addr_expr (istart0),
2684 build_fold_addr_expr (iend0));
2686 else
2688 tree t0, t1, t2, t3, t4;
2689 /* If this is not a combined parallel loop, emit a call to
2690 GOMP_loop_foo_start in ENTRY_BB. */
2691 t4 = build_fold_addr_expr (iend0);
2692 t3 = build_fold_addr_expr (istart0);
2693 t2 = fold_convert (long_integer_type_node, fd->step);
2694 t1 = fold_convert (long_integer_type_node, fd->n2);
2695 t0 = fold_convert (long_integer_type_node, fd->n1);
2696 if (fd->chunk_size)
2698 t = fold_convert (long_integer_type_node, fd->chunk_size);
2699 t = build_call_expr (built_in_decls[start_fn], 6,
2700 t0, t1, t2, t, t3, t4);
2702 else
2703 t = build_call_expr (built_in_decls[start_fn], 5,
2704 t0, t1, t2, t3, t4);
2706 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2707 true, BSI_SAME_STMT);
2708 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2709 bsi_insert_after (&si, t, BSI_SAME_STMT);
2711 /* V may be used outside of the loop (e.g., to handle lastprivate clause).
2712 If this is the case, its value is undefined if the loop is not entered
2713 at all. To handle this case, set its initial value to N1. */
2714 if (gimple_in_ssa_p (cfun))
2716 e = find_edge (entry_bb, l3_bb);
2717 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
2718 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == fd->v)
2719 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), fd->n1);
2721 else
2723 t = build_gimple_modify_stmt (fd->v, fd->n1);
2724 bsi_insert_before (&si, t, BSI_SAME_STMT);
2727 /* Remove the OMP_FOR statement. */
2728 bsi_remove (&si, true);
2730 /* Iteration setup for sequential loop goes in L0_BB. */
2731 si = bsi_start (l0_bb);
2732 t = fold_convert (type, istart0);
2733 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2734 false, BSI_CONTINUE_LINKING);
2735 t = build_gimple_modify_stmt (fd->v, t);
2736 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2737 if (gimple_in_ssa_p (cfun))
2738 SSA_NAME_DEF_STMT (fd->v) = t;
2740 t = fold_convert (type, iend0);
2741 iend = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2742 false, BSI_CONTINUE_LINKING);
2744 if (!broken_loop)
2746 /* Code to control the increment and predicate for the sequential
2747 loop goes in the CONT_BB. */
2748 si = bsi_last (cont_bb);
2749 t = bsi_stmt (si);
2750 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
2751 vmain = TREE_OPERAND (t, 1);
2752 vback = TREE_OPERAND (t, 0);
2754 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
2755 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2756 true, BSI_SAME_STMT);
2757 t = build_gimple_modify_stmt (vback, t);
2758 bsi_insert_before (&si, t, BSI_SAME_STMT);
2759 if (gimple_in_ssa_p (cfun))
2760 SSA_NAME_DEF_STMT (vback) = t;
2762 t = build2 (fd->cond_code, boolean_type_node, vback, iend);
2763 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2764 bsi_insert_before (&si, t, BSI_SAME_STMT);
2766 /* Remove OMP_CONTINUE. */
2767 bsi_remove (&si, true);
2769 /* Emit code to get the next parallel iteration in L2_BB. */
2770 si = bsi_start (l2_bb);
2772 t = build_call_expr (built_in_decls[next_fn], 2,
2773 build_fold_addr_expr (istart0),
2774 build_fold_addr_expr (iend0));
2775 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2776 false, BSI_CONTINUE_LINKING);
2777 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2778 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2781 /* Add the loop cleanup function. */
2782 si = bsi_last (exit_bb);
2783 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2784 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2785 else
2786 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2787 t = build_call_expr (t, 0);
2788 bsi_insert_after (&si, t, BSI_SAME_STMT);
2789 bsi_remove (&si, true);
2791 /* Connect the new blocks. */
2792 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
2793 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
2795 if (!broken_loop)
2797 e = find_edge (cont_bb, l3_bb);
2798 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2800 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
2801 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
2802 PHI_ARG_DEF_FROM_EDGE (phi, e));
2803 remove_edge (e);
2805 find_edge (cont_bb, l1_bb)->flags = EDGE_TRUE_VALUE;
2806 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2807 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2809 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
2810 recompute_dominator (CDI_DOMINATORS, l2_bb));
2811 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
2812 recompute_dominator (CDI_DOMINATORS, l3_bb));
2813 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
2814 recompute_dominator (CDI_DOMINATORS, l0_bb));
2815 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
2816 recompute_dominator (CDI_DOMINATORS, l1_bb));
2821 /* A subroutine of expand_omp_for. Generate code for a parallel
2822 loop with static schedule and no specified chunk size. Given
2823 parameters:
2825 for (V = N1; V cond N2; V += STEP) BODY;
2827 where COND is "<" or ">", we generate pseudocode
2829 if (cond is <)
2830 adj = STEP - 1;
2831 else
2832 adj = STEP + 1;
2833 n = (adj + N2 - N1) / STEP;
2834 q = n / nthreads;
2835 q += (q * nthreads != n);
2836 s0 = q * threadid;
2837 e0 = min(s0 + q, n);
2838 V = s0 * STEP + N1;
2839 if (s0 >= e0) goto L2; else goto L0;
2841 e = e0 * STEP + N1;
2843 BODY;
2844 V += STEP;
2845 if (V cond e) goto L1;
2849 static void
2850 expand_omp_for_static_nochunk (struct omp_region *region,
2851 struct omp_for_data *fd)
2853 tree n, q, s0, e0, e, t, nthreads, threadid;
2854 tree type, vmain, vback;
2855 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2856 basic_block fin_bb;
2857 block_stmt_iterator si;
2859 type = TREE_TYPE (fd->v);
2861 entry_bb = region->entry;
2862 cont_bb = region->cont;
2863 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2864 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2865 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2866 body_bb = single_succ (seq_start_bb);
2867 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
2868 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2869 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
2870 exit_bb = region->exit;
2872 /* Iteration space partitioning goes in ENTRY_BB. */
2873 si = bsi_last (entry_bb);
2874 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2876 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2877 t = fold_convert (type, t);
2878 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2879 true, BSI_SAME_STMT);
2881 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2882 t = fold_convert (type, t);
2883 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2884 true, BSI_SAME_STMT);
2886 fd->n1 = force_gimple_operand_bsi (&si,
2887 fold_convert (type, fd->n1),
2888 true, NULL_TREE,
2889 true, BSI_SAME_STMT);
2891 fd->n2 = force_gimple_operand_bsi (&si,
2892 fold_convert (type, fd->n2),
2893 true, NULL_TREE,
2894 true, BSI_SAME_STMT);
2896 fd->step = force_gimple_operand_bsi (&si,
2897 fold_convert (type, fd->step),
2898 true, NULL_TREE,
2899 true, BSI_SAME_STMT);
2901 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2902 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2903 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2904 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2905 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2906 t = fold_convert (type, t);
2907 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2909 t = fold_build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2910 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2912 t = fold_build2 (MULT_EXPR, type, q, nthreads);
2913 t = fold_build2 (NE_EXPR, type, t, n);
2914 t = fold_build2 (PLUS_EXPR, type, q, t);
2915 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2917 t = build2 (MULT_EXPR, type, q, threadid);
2918 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2920 t = fold_build2 (PLUS_EXPR, type, s0, q);
2921 t = fold_build2 (MIN_EXPR, type, t, n);
2922 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2924 t = fold_convert (type, s0);
2925 t = fold_build2 (MULT_EXPR, type, t, fd->step);
2926 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
2927 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2928 true, BSI_SAME_STMT);
2929 t = build_gimple_modify_stmt (fd->v, t);
2930 bsi_insert_before (&si, t, BSI_SAME_STMT);
2931 if (gimple_in_ssa_p (cfun))
2932 SSA_NAME_DEF_STMT (fd->v) = t;
2934 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2935 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2936 bsi_insert_before (&si, t, BSI_SAME_STMT);
2938 /* Remove the OMP_FOR statement. */
2939 bsi_remove (&si, true);
2941 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2942 si = bsi_start (seq_start_bb);
2944 t = fold_convert (type, e0);
2945 t = fold_build2 (MULT_EXPR, type, t, fd->step);
2946 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
2947 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2948 false, BSI_CONTINUE_LINKING);
2950 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2951 si = bsi_last (cont_bb);
2952 t = bsi_stmt (si);
2953 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
2954 vmain = TREE_OPERAND (t, 1);
2955 vback = TREE_OPERAND (t, 0);
2957 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
2958 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2959 true, BSI_SAME_STMT);
2960 t = build_gimple_modify_stmt (vback, t);
2961 bsi_insert_before (&si, t, BSI_SAME_STMT);
2962 if (gimple_in_ssa_p (cfun))
2963 SSA_NAME_DEF_STMT (vback) = t;
2965 t = build2 (fd->cond_code, boolean_type_node, vback, e);
2966 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2967 bsi_insert_before (&si, t, BSI_SAME_STMT);
2969 /* Remove the OMP_CONTINUE statement. */
2970 bsi_remove (&si, true);
2972 /* Replace the OMP_RETURN with a barrier, or nothing. */
2973 si = bsi_last (exit_bb);
2974 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2975 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
2976 false, BSI_SAME_STMT);
2977 bsi_remove (&si, true);
2979 /* Connect all the blocks. */
2980 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
2981 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
2983 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
2984 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2986 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
2987 set_immediate_dominator (CDI_DOMINATORS, body_bb,
2988 recompute_dominator (CDI_DOMINATORS, body_bb));
2989 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
2990 recompute_dominator (CDI_DOMINATORS, fin_bb));
2994 /* A subroutine of expand_omp_for. Generate code for a parallel
2995 loop with static schedule and a specified chunk size. Given
2996 parameters:
2998 for (V = N1; V cond N2; V += STEP) BODY;
3000 where COND is "<" or ">", we generate pseudocode
3002 if (cond is <)
3003 adj = STEP - 1;
3004 else
3005 adj = STEP + 1;
3006 n = (adj + N2 - N1) / STEP;
3007 trip = 0;
3008 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
3009 here so that V is defined
3010 if the loop is not entered
3012 s0 = (trip * nthreads + threadid) * CHUNK;
3013 e0 = min(s0 + CHUNK, n);
3014 if (s0 < n) goto L1; else goto L4;
3016 V = s0 * STEP + N1;
3017 e = e0 * STEP + N1;
3019 BODY;
3020 V += STEP;
3021 if (V cond e) goto L2; else goto L3;
3023 trip += 1;
3024 goto L0;
3028 static void
3029 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
3031 tree n, s0, e0, e, t, phi, nphi, args;
3032 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
3033 tree type, cont, v_main, v_back, v_extra;
3034 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
3035 basic_block trip_update_bb, cont_bb, fin_bb;
3036 block_stmt_iterator si;
3037 edge se, re, ene;
3039 type = TREE_TYPE (fd->v);
3041 entry_bb = region->entry;
3042 se = split_block (entry_bb, last_stmt (entry_bb));
3043 entry_bb = se->src;
3044 iter_part_bb = se->dest;
3045 cont_bb = region->cont;
3046 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
3047 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
3048 == FALLTHRU_EDGE (cont_bb)->dest);
3049 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
3050 body_bb = single_succ (seq_start_bb);
3051 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
3052 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3053 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
3054 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
3055 exit_bb = region->exit;
3057 /* Trip and adjustment setup goes in ENTRY_BB. */
3058 si = bsi_last (entry_bb);
3059 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3061 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
3062 t = fold_convert (type, t);
3063 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3064 true, BSI_SAME_STMT);
3066 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3067 t = fold_convert (type, t);
3068 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3069 true, BSI_SAME_STMT);
3071 fd->n1 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n1),
3072 true, NULL_TREE,
3073 true, BSI_SAME_STMT);
3074 fd->n2 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n2),
3075 true, NULL_TREE,
3076 true, BSI_SAME_STMT);
3077 fd->step = force_gimple_operand_bsi (&si, fold_convert (type, fd->step),
3078 true, NULL_TREE,
3079 true, BSI_SAME_STMT);
3080 fd->chunk_size
3081 = force_gimple_operand_bsi (&si, fold_convert (type,
3082 fd->chunk_size),
3083 true, NULL_TREE,
3084 true, BSI_SAME_STMT);
3086 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
3087 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
3088 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
3089 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
3090 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
3091 t = fold_convert (type, t);
3092 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3093 true, BSI_SAME_STMT);
3095 trip_var = create_tmp_var (type, ".trip");
3096 if (gimple_in_ssa_p (cfun))
3098 add_referenced_var (trip_var);
3099 trip_init = make_ssa_name (trip_var, NULL_TREE);
3100 trip_main = make_ssa_name (trip_var, NULL_TREE);
3101 trip_back = make_ssa_name (trip_var, NULL_TREE);
3103 else
3105 trip_init = trip_var;
3106 trip_main = trip_var;
3107 trip_back = trip_var;
3110 t = build_gimple_modify_stmt (trip_init, build_int_cst (type, 0));
3111 bsi_insert_before (&si, t, BSI_SAME_STMT);
3112 if (gimple_in_ssa_p (cfun))
3113 SSA_NAME_DEF_STMT (trip_init) = t;
3115 t = fold_build2 (MULT_EXPR, type, threadid, fd->chunk_size);
3116 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3117 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3118 v_extra = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3119 true, BSI_SAME_STMT);
3121 /* Remove the OMP_FOR. */
3122 bsi_remove (&si, true);
3124 /* Iteration space partitioning goes in ITER_PART_BB. */
3125 si = bsi_last (iter_part_bb);
3127 t = fold_build2 (MULT_EXPR, type, trip_main, nthreads);
3128 t = fold_build2 (PLUS_EXPR, type, t, threadid);
3129 t = fold_build2 (MULT_EXPR, type, t, fd->chunk_size);
3130 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3131 false, BSI_CONTINUE_LINKING);
3133 t = fold_build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3134 t = fold_build2 (MIN_EXPR, type, t, n);
3135 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3136 false, BSI_CONTINUE_LINKING);
3138 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3139 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3140 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3142 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3143 si = bsi_start (seq_start_bb);
3145 t = fold_convert (type, s0);
3146 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3147 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3148 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3149 false, BSI_CONTINUE_LINKING);
3150 t = build_gimple_modify_stmt (fd->v, t);
3151 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3152 if (gimple_in_ssa_p (cfun))
3153 SSA_NAME_DEF_STMT (fd->v) = t;
3155 t = fold_convert (type, e0);
3156 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3157 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3158 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3159 false, BSI_CONTINUE_LINKING);
3161 /* The code controlling the sequential loop goes in CONT_BB,
3162 replacing the OMP_CONTINUE. */
3163 si = bsi_last (cont_bb);
3164 cont = bsi_stmt (si);
3165 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3166 v_main = TREE_OPERAND (cont, 1);
3167 v_back = TREE_OPERAND (cont, 0);
3169 t = build2 (PLUS_EXPR, type, v_main, fd->step);
3170 t = build_gimple_modify_stmt (v_back, t);
3171 bsi_insert_before (&si, t, BSI_SAME_STMT);
3172 if (gimple_in_ssa_p (cfun))
3173 SSA_NAME_DEF_STMT (v_back) = t;
3175 t = build2 (fd->cond_code, boolean_type_node, v_back, e);
3176 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3177 bsi_insert_before (&si, t, BSI_SAME_STMT);
3179 /* Remove OMP_CONTINUE. */
3180 bsi_remove (&si, true);
3182 /* Trip update code goes into TRIP_UPDATE_BB. */
3183 si = bsi_start (trip_update_bb);
3185 t = build_int_cst (type, 1);
3186 t = build2 (PLUS_EXPR, type, trip_main, t);
3187 t = build_gimple_modify_stmt (trip_back, t);
3188 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3189 if (gimple_in_ssa_p (cfun))
3190 SSA_NAME_DEF_STMT (trip_back) = t;
3192 /* Replace the OMP_RETURN with a barrier, or nothing. */
3193 si = bsi_last (exit_bb);
3194 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3195 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3196 false, BSI_SAME_STMT);
3197 bsi_remove (&si, true);
3199 /* Connect the new blocks. */
3200 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
3201 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
3203 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3204 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
3206 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
3208 if (gimple_in_ssa_p (cfun))
3210 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
3211 remove arguments of the phi nodes in fin_bb. We need to create
3212 appropriate phi nodes in iter_part_bb instead. */
3213 se = single_pred_edge (fin_bb);
3214 re = single_succ_edge (trip_update_bb);
3215 ene = single_succ_edge (entry_bb);
3217 args = PENDING_STMT (re);
3218 PENDING_STMT (re) = NULL_TREE;
3219 for (phi = phi_nodes (fin_bb);
3220 phi && args;
3221 phi = PHI_CHAIN (phi), args = TREE_CHAIN (args))
3223 t = PHI_RESULT (phi);
3224 gcc_assert (t == TREE_PURPOSE (args));
3225 nphi = create_phi_node (t, iter_part_bb);
3226 SSA_NAME_DEF_STMT (t) = nphi;
3228 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
3229 /* A special case -- fd->v is not yet computed in iter_part_bb, we
3230 need to use v_extra instead. */
3231 if (t == fd->v)
3232 t = v_extra;
3233 add_phi_arg (nphi, t, ene);
3234 add_phi_arg (nphi, TREE_VALUE (args), re);
3236 gcc_assert (!phi && !args);
3237 while ((phi = phi_nodes (fin_bb)) != NULL_TREE)
3238 remove_phi_node (phi, NULL_TREE, false);
3240 /* Make phi node for trip. */
3241 phi = create_phi_node (trip_main, iter_part_bb);
3242 SSA_NAME_DEF_STMT (trip_main) = phi;
3243 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
3244 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
3247 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
3248 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
3249 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
3250 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
3251 recompute_dominator (CDI_DOMINATORS, fin_bb));
3252 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
3253 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
3254 set_immediate_dominator (CDI_DOMINATORS, body_bb,
3255 recompute_dominator (CDI_DOMINATORS, body_bb));
3259 /* Expand the OpenMP loop defined by REGION. */
3261 static void
3262 expand_omp_for (struct omp_region *region)
3264 struct omp_for_data fd;
3266 extract_omp_for_data (last_stmt (region->entry), &fd);
3267 region->sched_kind = fd.sched_kind;
3269 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3270 && !fd.have_ordered
3271 && region->cont != NULL)
3273 if (fd.chunk_size == NULL)
3274 expand_omp_for_static_nochunk (region, &fd);
3275 else
3276 expand_omp_for_static_chunk (region, &fd);
3278 else
3280 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3281 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3282 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3283 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3288 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3290 v = GOMP_sections_start (n);
3292 switch (v)
3294 case 0:
3295 goto L2;
3296 case 1:
3297 section 1;
3298 goto L1;
3299 case 2:
3301 case n:
3303 default:
3304 abort ();
3307 v = GOMP_sections_next ();
3308 goto L0;
3310 reduction;
3312 If this is a combined parallel sections, replace the call to
3313 GOMP_sections_start with call to GOMP_sections_next. */
3315 static void
3316 expand_omp_sections (struct omp_region *region)
3318 tree label_vec, l1, l2, t, u, sections_stmt, vin, vmain, vnext, cont;
3319 unsigned i, casei, len;
3320 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
3321 block_stmt_iterator si;
3322 struct omp_region *inner;
3323 bool exit_reachable = region->cont != NULL;
3325 gcc_assert (exit_reachable == (region->exit != NULL));
3326 entry_bb = region->entry;
3327 l0_bb = single_succ (entry_bb);
3328 l1_bb = region->cont;
3329 l2_bb = region->exit;
3330 if (exit_reachable)
3332 gcc_assert (single_pred (l2_bb) == l0_bb);
3333 default_bb = create_empty_bb (l1_bb->prev_bb);
3334 l1 = tree_block_label (l1_bb);
3335 l2 = tree_block_label (l2_bb);
3337 else
3339 default_bb = create_empty_bb (l0_bb);
3340 l1 = NULL_TREE;
3341 l2 = tree_block_label (default_bb);
3344 /* We will build a switch() with enough cases for all the
3345 OMP_SECTION regions, a '0' case to handle the end of more work
3346 and a default case to abort if something goes wrong. */
3347 len = EDGE_COUNT (l0_bb->succs);
3348 label_vec = make_tree_vec (len + 1);
3350 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3351 OMP_SECTIONS statement. */
3352 si = bsi_last (entry_bb);
3353 sections_stmt = bsi_stmt (si);
3354 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3355 vin = OMP_SECTIONS_CONTROL (sections_stmt);
3356 if (!is_combined_parallel (region))
3358 /* If we are not inside a combined parallel+sections region,
3359 call GOMP_sections_start. */
3360 t = build_int_cst (unsigned_type_node,
3361 exit_reachable ? len - 1 : len);
3362 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3363 t = build_call_expr (u, 1, t);
3365 else
3367 /* Otherwise, call GOMP_sections_next. */
3368 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3369 t = build_call_expr (u, 0);
3371 t = build_gimple_modify_stmt (vin, t);
3372 bsi_insert_after (&si, t, BSI_SAME_STMT);
3373 if (gimple_in_ssa_p (cfun))
3374 SSA_NAME_DEF_STMT (vin) = t;
3375 bsi_remove (&si, true);
3377 /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB. */
3378 si = bsi_last (l0_bb);
3379 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
3380 if (exit_reachable)
3382 cont = last_stmt (l1_bb);
3383 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3384 vmain = TREE_OPERAND (cont, 1);
3385 vnext = TREE_OPERAND (cont, 0);
3387 else
3389 vmain = vin;
3390 vnext = NULL_TREE;
3393 t = build3 (SWITCH_EXPR, void_type_node, vmain, NULL, label_vec);
3394 bsi_insert_after (&si, t, BSI_SAME_STMT);
3395 bsi_remove (&si, true);
3397 i = 0;
3398 if (exit_reachable)
3400 t = build3 (CASE_LABEL_EXPR, void_type_node,
3401 build_int_cst (unsigned_type_node, 0), NULL, l2);
3402 TREE_VEC_ELT (label_vec, 0) = t;
3403 i++;
3406 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3407 for (inner = region->inner, casei = 1;
3408 inner;
3409 inner = inner->next, i++, casei++)
3411 basic_block s_entry_bb, s_exit_bb;
3413 s_entry_bb = inner->entry;
3414 s_exit_bb = inner->exit;
3416 t = tree_block_label (s_entry_bb);
3417 u = build_int_cst (unsigned_type_node, casei);
3418 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3419 TREE_VEC_ELT (label_vec, i) = u;
3421 si = bsi_last (s_entry_bb);
3422 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3423 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3424 bsi_remove (&si, true);
3425 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3427 if (s_exit_bb == NULL)
3428 continue;
3430 si = bsi_last (s_exit_bb);
3431 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3432 bsi_remove (&si, true);
3434 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3437 /* Error handling code goes in DEFAULT_BB. */
3438 t = tree_block_label (default_bb);
3439 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3440 TREE_VEC_ELT (label_vec, len) = u;
3441 make_edge (l0_bb, default_bb, 0);
3443 si = bsi_start (default_bb);
3444 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3445 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3447 if (exit_reachable)
3449 /* Code to get the next section goes in L1_BB. */
3450 si = bsi_last (l1_bb);
3451 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3453 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3454 t = build_gimple_modify_stmt (vnext, t);
3455 bsi_insert_after (&si, t, BSI_SAME_STMT);
3456 if (gimple_in_ssa_p (cfun))
3457 SSA_NAME_DEF_STMT (vnext) = t;
3458 bsi_remove (&si, true);
3460 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
3462 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3463 si = bsi_last (l2_bb);
3464 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3465 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3466 else
3467 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3468 t = build_call_expr (t, 0);
3469 bsi_insert_after (&si, t, BSI_SAME_STMT);
3470 bsi_remove (&si, true);
3473 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
3477 /* Expand code for an OpenMP single directive. We've already expanded
3478 much of the code, here we simply place the GOMP_barrier call. */
3480 static void
3481 expand_omp_single (struct omp_region *region)
3483 basic_block entry_bb, exit_bb;
3484 block_stmt_iterator si;
3485 bool need_barrier = false;
3487 entry_bb = region->entry;
3488 exit_bb = region->exit;
3490 si = bsi_last (entry_bb);
3491 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3492 be removed. We need to ensure that the thread that entered the single
3493 does not exit before the data is copied out by the other threads. */
3494 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3495 OMP_CLAUSE_COPYPRIVATE))
3496 need_barrier = true;
3497 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3498 bsi_remove (&si, true);
3499 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3501 si = bsi_last (exit_bb);
3502 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3503 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3504 false, BSI_SAME_STMT);
3505 bsi_remove (&si, true);
3506 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3510 /* Generic expansion for OpenMP synchronization directives: master,
3511 ordered and critical. All we need to do here is remove the entry
3512 and exit markers for REGION. */
3514 static void
3515 expand_omp_synch (struct omp_region *region)
3517 basic_block entry_bb, exit_bb;
3518 block_stmt_iterator si;
3520 entry_bb = region->entry;
3521 exit_bb = region->exit;
3523 si = bsi_last (entry_bb);
3524 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3525 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3526 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3527 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3528 bsi_remove (&si, true);
3529 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3531 if (exit_bb)
3533 si = bsi_last (exit_bb);
3534 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3535 bsi_remove (&si, true);
3536 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3541 /* Expand the parallel region tree rooted at REGION. Expansion
3542 proceeds in depth-first order. Innermost regions are expanded
3543 first. This way, parallel regions that require a new function to
3544 be created (e.g., OMP_PARALLEL) can be expanded without having any
3545 internal dependencies in their body. */
3547 static void
3548 expand_omp (struct omp_region *region)
3550 while (region)
3552 if (region->inner)
3553 expand_omp (region->inner);
3555 switch (region->type)
3557 case OMP_PARALLEL:
3558 expand_omp_parallel (region);
3559 break;
3561 case OMP_FOR:
3562 expand_omp_for (region);
3563 break;
3565 case OMP_SECTIONS:
3566 expand_omp_sections (region);
3567 break;
3569 case OMP_SECTION:
3570 /* Individual omp sections are handled together with their
3571 parent OMP_SECTIONS region. */
3572 break;
3574 case OMP_SINGLE:
3575 expand_omp_single (region);
3576 break;
3578 case OMP_MASTER:
3579 case OMP_ORDERED:
3580 case OMP_CRITICAL:
3581 expand_omp_synch (region);
3582 break;
3584 default:
3585 gcc_unreachable ();
3588 region = region->next;
3593 /* Helper for build_omp_regions. Scan the dominator tree starting at
3594 block BB. PARENT is the region that contains BB. */
3596 static void
3597 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3599 block_stmt_iterator si;
3600 tree stmt;
3601 basic_block son;
3603 si = bsi_last (bb);
3604 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3606 struct omp_region *region;
3607 enum tree_code code;
3609 stmt = bsi_stmt (si);
3610 code = TREE_CODE (stmt);
3612 if (code == OMP_RETURN)
3614 /* STMT is the return point out of region PARENT. Mark it
3615 as the exit point and make PARENT the immediately
3616 enclosing region. */
3617 gcc_assert (parent);
3618 region = parent;
3619 region->exit = bb;
3620 parent = parent->outer;
3622 /* If REGION is a parallel region, determine whether it is
3623 a combined parallel+workshare region. */
3624 if (region->type == OMP_PARALLEL)
3625 determine_parallel_type (region);
3627 else if (code == OMP_CONTINUE)
3629 gcc_assert (parent);
3630 parent->cont = bb;
3632 else if (code == OMP_SECTIONS_SWITCH)
3634 /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
3635 it. */
3637 else
3639 /* Otherwise, this directive becomes the parent for a new
3640 region. */
3641 region = new_omp_region (bb, code, parent);
3642 parent = region;
3646 for (son = first_dom_son (CDI_DOMINATORS, bb);
3647 son;
3648 son = next_dom_son (CDI_DOMINATORS, son))
3649 build_omp_regions_1 (son, parent);
3653 /* Scan the CFG and build a tree of OMP regions. Return the root of
3654 the OMP region tree. */
3656 static void
3657 build_omp_regions (void)
3659 gcc_assert (root_omp_region == NULL);
3660 calculate_dominance_info (CDI_DOMINATORS);
3661 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3665 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3667 static unsigned int
3668 execute_expand_omp (void)
3670 build_omp_regions ();
3672 if (!root_omp_region)
3673 return 0;
3675 if (dump_file)
3677 fprintf (dump_file, "\nOMP region tree\n\n");
3678 dump_omp_region (dump_file, root_omp_region, 0);
3679 fprintf (dump_file, "\n");
3682 remove_exit_barriers (root_omp_region);
3684 expand_omp (root_omp_region);
3686 cleanup_tree_cfg ();
3688 free_omp_regions ();
3690 return 0;
3693 /* OMP expansion in SSA form. For testing purposes only. */
3695 static bool
3696 gate_expand_omp_ssa (void)
3698 return flag_openmp_ssa && flag_openmp != 0 && errorcount == 0;
3701 struct tree_opt_pass pass_expand_omp_ssa =
3703 "ompexpssa", /* name */
3704 gate_expand_omp_ssa, /* gate */
3705 execute_expand_omp, /* execute */
3706 NULL, /* sub */
3707 NULL, /* next */
3708 0, /* static_pass_number */
3709 0, /* tv_id */
3710 PROP_gimple_any, /* properties_required */
3711 PROP_gimple_lomp, /* properties_provided */
3712 0, /* properties_destroyed */
3713 0, /* todo_flags_start */
3714 TODO_dump_func, /* todo_flags_finish */
3715 0 /* letter */
3718 /* OMP expansion -- the default pass, run before creation of SSA form. */
3720 static bool
3721 gate_expand_omp (void)
3723 return ((!flag_openmp_ssa || !optimize)
3724 && flag_openmp != 0 && errorcount == 0);
3727 struct tree_opt_pass pass_expand_omp =
3729 "ompexp", /* name */
3730 gate_expand_omp, /* gate */
3731 execute_expand_omp, /* execute */
3732 NULL, /* sub */
3733 NULL, /* next */
3734 0, /* static_pass_number */
3735 0, /* tv_id */
3736 PROP_gimple_any, /* properties_required */
3737 PROP_gimple_lomp, /* properties_provided */
3738 0, /* properties_destroyed */
3739 0, /* todo_flags_start */
3740 TODO_dump_func, /* todo_flags_finish */
3741 0 /* letter */
3744 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3746 /* Lower the OpenMP sections directive in *STMT_P. */
3748 static void
3749 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3751 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body, control;
3752 tree t, dlist;
3753 tree_stmt_iterator tsi;
3754 unsigned i, len;
3756 stmt = *stmt_p;
3758 push_gimplify_context ();
3760 dlist = NULL;
3761 ilist = NULL;
3762 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3764 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3765 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3766 continue;
3768 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3769 body = alloc_stmt_list ();
3770 for (i = 0; i < len; i++, tsi_next (&tsi))
3772 omp_context *sctx;
3773 tree sec_start, sec_end;
3775 sec_start = tsi_stmt (tsi);
3776 sctx = maybe_lookup_ctx (sec_start);
3777 gcc_assert (sctx);
3779 append_to_statement_list (sec_start, &body);
3781 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3782 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3783 OMP_SECTION_BODY (sec_start) = NULL;
3785 if (i == len - 1)
3787 tree l = alloc_stmt_list ();
3788 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3789 &l, ctx);
3790 append_to_statement_list (l, &body);
3791 OMP_SECTION_LAST (sec_start) = 1;
3794 sec_end = make_node (OMP_RETURN);
3795 append_to_statement_list (sec_end, &body);
3798 block = make_node (BLOCK);
3799 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3801 olist = NULL_TREE;
3802 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3804 pop_gimplify_context (NULL_TREE);
3805 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3807 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3808 TREE_SIDE_EFFECTS (new_stmt) = 1;
3810 new_body = alloc_stmt_list ();
3811 append_to_statement_list (ilist, &new_body);
3812 append_to_statement_list (stmt, &new_body);
3813 append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
3814 append_to_statement_list (bind, &new_body);
3816 control = create_tmp_var (unsigned_type_node, ".section");
3817 t = build2 (OMP_CONTINUE, void_type_node, control, control);
3818 OMP_SECTIONS_CONTROL (stmt) = control;
3819 append_to_statement_list (t, &new_body);
3821 append_to_statement_list (olist, &new_body);
3822 append_to_statement_list (dlist, &new_body);
3824 maybe_catch_exception (&new_body);
3826 t = make_node (OMP_RETURN);
3827 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3828 OMP_CLAUSE_NOWAIT);
3829 append_to_statement_list (t, &new_body);
3831 BIND_EXPR_BODY (new_stmt) = new_body;
3832 OMP_SECTIONS_BODY (stmt) = NULL;
3834 *stmt_p = new_stmt;
3838 /* A subroutine of lower_omp_single. Expand the simple form of
3839 an OMP_SINGLE, without a copyprivate clause:
3841 if (GOMP_single_start ())
3842 BODY;
3843 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3845 FIXME. It may be better to delay expanding the logic of this until
3846 pass_expand_omp. The expanded logic may make the job more difficult
3847 to a synchronization analysis pass. */
3849 static void
3850 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3852 tree t;
3854 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3855 t = build3 (COND_EXPR, void_type_node, t,
3856 OMP_SINGLE_BODY (single_stmt), NULL);
3857 gimplify_and_add (t, pre_p);
3861 /* A subroutine of lower_omp_single. Expand the simple form of
3862 an OMP_SINGLE, with a copyprivate clause:
3864 #pragma omp single copyprivate (a, b, c)
3866 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3869 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3871 BODY;
3872 copyout.a = a;
3873 copyout.b = b;
3874 copyout.c = c;
3875 GOMP_single_copy_end (&copyout);
3877 else
3879 a = copyout_p->a;
3880 b = copyout_p->b;
3881 c = copyout_p->c;
3883 GOMP_barrier ();
3886 FIXME. It may be better to delay expanding the logic of this until
3887 pass_expand_omp. The expanded logic may make the job more difficult
3888 to a synchronization analysis pass. */
3890 static void
3891 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3893 tree ptr_type, t, l0, l1, l2, copyin_seq;
3895 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3897 ptr_type = build_pointer_type (ctx->record_type);
3898 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3900 l0 = create_artificial_label ();
3901 l1 = create_artificial_label ();
3902 l2 = create_artificial_label ();
3904 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3905 t = fold_convert (ptr_type, t);
3906 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3907 gimplify_and_add (t, pre_p);
3909 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3910 build_int_cst (ptr_type, 0));
3911 t = build3 (COND_EXPR, void_type_node, t,
3912 build_and_jump (&l0), build_and_jump (&l1));
3913 gimplify_and_add (t, pre_p);
3915 t = build1 (LABEL_EXPR, void_type_node, l0);
3916 gimplify_and_add (t, pre_p);
3918 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3920 copyin_seq = NULL;
3921 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3922 &copyin_seq, ctx);
3924 t = build_fold_addr_expr (ctx->sender_decl);
3925 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3926 gimplify_and_add (t, pre_p);
3928 t = build_and_jump (&l2);
3929 gimplify_and_add (t, pre_p);
3931 t = build1 (LABEL_EXPR, void_type_node, l1);
3932 gimplify_and_add (t, pre_p);
3934 append_to_statement_list (copyin_seq, pre_p);
3936 t = build1 (LABEL_EXPR, void_type_node, l2);
3937 gimplify_and_add (t, pre_p);
3941 /* Expand code for an OpenMP single directive. */
3943 static void
3944 lower_omp_single (tree *stmt_p, omp_context *ctx)
3946 tree t, bind, block, single_stmt = *stmt_p, dlist;
3948 push_gimplify_context ();
3950 block = make_node (BLOCK);
3951 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3952 TREE_SIDE_EFFECTS (bind) = 1;
3954 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3955 &BIND_EXPR_BODY (bind), &dlist, ctx);
3956 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3958 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3960 if (ctx->record_type)
3961 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3962 else
3963 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3965 OMP_SINGLE_BODY (single_stmt) = NULL;
3967 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3969 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3971 t = make_node (OMP_RETURN);
3972 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3973 OMP_CLAUSE_NOWAIT);
3974 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3976 pop_gimplify_context (bind);
3978 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3979 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3983 /* Expand code for an OpenMP master directive. */
3985 static void
3986 lower_omp_master (tree *stmt_p, omp_context *ctx)
3988 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3990 push_gimplify_context ();
3992 block = make_node (BLOCK);
3993 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3994 TREE_SIDE_EFFECTS (bind) = 1;
3996 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3998 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3999 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
4000 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
4001 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4003 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
4004 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
4005 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
4006 OMP_MASTER_BODY (stmt) = NULL;
4008 x = build1 (LABEL_EXPR, void_type_node, lab);
4009 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4011 x = make_node (OMP_RETURN);
4012 OMP_RETURN_NOWAIT (x) = 1;
4013 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4015 pop_gimplify_context (bind);
4017 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4018 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4022 /* Expand code for an OpenMP ordered directive. */
4024 static void
4025 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
4027 tree bind, block, stmt = *stmt_p, x;
4029 push_gimplify_context ();
4031 block = make_node (BLOCK);
4032 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4033 TREE_SIDE_EFFECTS (bind) = 1;
4035 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4037 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
4038 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4040 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
4041 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
4042 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
4043 OMP_ORDERED_BODY (stmt) = NULL;
4045 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
4046 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4048 x = make_node (OMP_RETURN);
4049 OMP_RETURN_NOWAIT (x) = 1;
4050 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4052 pop_gimplify_context (bind);
4054 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4055 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4059 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
4060 substitution of a couple of function calls. But in the NAMED case,
4061 requires that languages coordinate a symbol name. It is therefore
4062 best put here in common code. */
4064 static GTY((param1_is (tree), param2_is (tree)))
4065 splay_tree critical_name_mutexes;
4067 static void
4068 lower_omp_critical (tree *stmt_p, omp_context *ctx)
4070 tree bind, block, stmt = *stmt_p;
4071 tree t, lock, unlock, name;
4073 name = OMP_CRITICAL_NAME (stmt);
4074 if (name)
4076 tree decl;
4077 splay_tree_node n;
4079 if (!critical_name_mutexes)
4080 critical_name_mutexes
4081 = splay_tree_new_ggc (splay_tree_compare_pointers);
4083 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
4084 if (n == NULL)
4086 char *new_str;
4088 decl = create_tmp_var_raw (ptr_type_node, NULL);
4090 new_str = ACONCAT ((".gomp_critical_user_",
4091 IDENTIFIER_POINTER (name), NULL));
4092 DECL_NAME (decl) = get_identifier (new_str);
4093 TREE_PUBLIC (decl) = 1;
4094 TREE_STATIC (decl) = 1;
4095 DECL_COMMON (decl) = 1;
4096 DECL_ARTIFICIAL (decl) = 1;
4097 DECL_IGNORED_P (decl) = 1;
4098 varpool_finalize_decl (decl);
4100 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
4101 (splay_tree_value) decl);
4103 else
4104 decl = (tree) n->value;
4106 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
4107 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
4109 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
4110 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
4112 else
4114 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
4115 lock = build_call_expr (lock, 0);
4117 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
4118 unlock = build_call_expr (unlock, 0);
4121 push_gimplify_context ();
4123 block = make_node (BLOCK);
4124 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4125 TREE_SIDE_EFFECTS (bind) = 1;
4127 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4129 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
4131 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
4132 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
4133 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
4134 OMP_CRITICAL_BODY (stmt) = NULL;
4136 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
4138 t = make_node (OMP_RETURN);
4139 OMP_RETURN_NOWAIT (t) = 1;
4140 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4142 pop_gimplify_context (bind);
4143 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4144 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4148 /* A subroutine of lower_omp_for. Generate code to emit the predicate
4149 for a lastprivate clause. Given a loop control predicate of (V
4150 cond N2), we gate the clause on (!(V cond N2)). The lowered form
4151 is appended to *DLIST, iterator initialization is appended to
4152 *BODY_P. */
4154 static void
4155 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
4156 tree *dlist, struct omp_context *ctx)
4158 tree clauses, cond, stmts, vinit, t;
4159 enum tree_code cond_code;
4161 cond_code = fd->cond_code;
4162 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
4164 /* When possible, use a strict equality expression. This can let VRP
4165 type optimizations deduce the value and remove a copy. */
4166 if (host_integerp (fd->step, 0))
4168 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
4169 if (step == 1 || step == -1)
4170 cond_code = EQ_EXPR;
4173 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
4175 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
4176 stmts = NULL;
4177 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
4178 if (stmts != NULL)
4180 append_to_statement_list (stmts, dlist);
4182 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
4183 vinit = fd->n1;
4184 if (cond_code == EQ_EXPR
4185 && host_integerp (fd->n2, 0)
4186 && ! integer_zerop (fd->n2))
4187 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
4189 /* Initialize the iterator variable, so that threads that don't execute
4190 any iterations don't execute the lastprivate clauses by accident. */
4191 t = build_gimple_modify_stmt (fd->v, vinit);
4192 gimplify_and_add (t, body_p);
4197 /* Lower code for an OpenMP loop directive. */
4199 static void
4200 lower_omp_for (tree *stmt_p, omp_context *ctx)
4202 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
4203 struct omp_for_data fd;
4205 stmt = *stmt_p;
4207 push_gimplify_context ();
4209 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4210 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4212 /* Move declaration of temporaries in the loop body before we make
4213 it go away. */
4214 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4215 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4217 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4218 TREE_SIDE_EFFECTS (new_stmt) = 1;
4219 body_p = &BIND_EXPR_BODY (new_stmt);
4221 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4222 ilist = NULL;
4223 dlist = NULL;
4224 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4225 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4227 /* Lower the header expressions. At this point, we can assume that
4228 the header is of the form:
4230 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4232 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4233 using the .omp_data_s mapping, if needed. */
4234 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4235 if (!is_gimple_min_invariant (*rhs_p))
4236 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4238 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4239 if (!is_gimple_min_invariant (*rhs_p))
4240 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4242 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4243 if (!is_gimple_min_invariant (*rhs_p))
4244 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4246 /* Once lowered, extract the bounds and clauses. */
4247 extract_omp_for_data (stmt, &fd);
4249 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4251 append_to_statement_list (stmt, body_p);
4253 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4255 t = build2 (OMP_CONTINUE, void_type_node, fd.v, fd.v);
4256 append_to_statement_list (t, body_p);
4258 /* After the loop, add exit clauses. */
4259 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4260 append_to_statement_list (dlist, body_p);
4262 maybe_catch_exception (body_p);
4264 /* Region exit marker goes at the end of the loop body. */
4265 t = make_node (OMP_RETURN);
4266 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4267 append_to_statement_list (t, body_p);
4269 pop_gimplify_context (NULL_TREE);
4270 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4272 OMP_FOR_BODY (stmt) = NULL_TREE;
4273 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4274 *stmt_p = new_stmt;
4277 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
4278 or OMP_PARALLEL. */
4280 static tree
4281 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4283 struct walk_stmt_info *wi = data;
4284 int *info = wi->info;
4286 *walk_subtrees = 0;
4287 switch (TREE_CODE (*tp))
4289 case OMP_FOR:
4290 case OMP_SECTIONS:
4291 *info = *info == 0 ? 1 : -1;
4292 break;
4293 default:
4294 *info = -1;
4295 break;
4297 return NULL;
4300 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4301 information for the directive. */
4303 static void
4304 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4306 tree clauses, par_bind, par_body, new_body, bind;
4307 tree olist, ilist, par_olist, par_ilist;
4308 tree stmt, child_fn, t;
4310 stmt = *stmt_p;
4312 clauses = OMP_PARALLEL_CLAUSES (stmt);
4313 par_bind = OMP_PARALLEL_BODY (stmt);
4314 par_body = BIND_EXPR_BODY (par_bind);
4315 child_fn = ctx->cb.dst_fn;
4316 if (!OMP_PARALLEL_COMBINED (stmt))
4318 struct walk_stmt_info wi;
4319 int ws_num = 0;
4321 memset (&wi, 0, sizeof (wi));
4322 wi.callback = check_combined_parallel;
4323 wi.info = &ws_num;
4324 wi.val_only = true;
4325 walk_stmts (&wi, &par_bind);
4326 if (ws_num == 1)
4327 OMP_PARALLEL_COMBINED (stmt) = 1;
4330 push_gimplify_context ();
4332 par_olist = NULL_TREE;
4333 par_ilist = NULL_TREE;
4334 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4335 lower_omp (&par_body, ctx);
4336 lower_reduction_clauses (clauses, &par_olist, ctx);
4338 /* Declare all the variables created by mapping and the variables
4339 declared in the scope of the parallel body. */
4340 record_vars_into (ctx->block_vars, child_fn);
4341 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4343 if (ctx->record_type)
4345 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4346 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4349 olist = NULL_TREE;
4350 ilist = NULL_TREE;
4351 lower_send_clauses (clauses, &ilist, &olist, ctx);
4352 lower_send_shared_vars (&ilist, &olist, ctx);
4354 /* Once all the expansions are done, sequence all the different
4355 fragments inside OMP_PARALLEL_BODY. */
4356 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4357 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4359 new_body = alloc_stmt_list ();
4361 if (ctx->record_type)
4363 t = build_fold_addr_expr (ctx->sender_decl);
4364 /* fixup_child_record_type might have changed receiver_decl's type. */
4365 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4366 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4367 append_to_statement_list (t, &new_body);
4370 append_to_statement_list (par_ilist, &new_body);
4371 append_to_statement_list (par_body, &new_body);
4372 append_to_statement_list (par_olist, &new_body);
4373 maybe_catch_exception (&new_body);
4374 t = make_node (OMP_RETURN);
4375 append_to_statement_list (t, &new_body);
4376 OMP_PARALLEL_BODY (stmt) = new_body;
4378 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4379 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4381 *stmt_p = bind;
4383 pop_gimplify_context (NULL_TREE);
4387 /* Pass *TP back through the gimplifier within the context determined by WI.
4388 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4389 flags on ADDR_EXPR. */
4391 static void
4392 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4394 enum gimplify_status gs;
4395 tree pre = NULL;
4397 if (wi->is_lhs)
4398 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4399 else if (wi->val_only)
4400 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4401 else
4402 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4403 gcc_assert (gs == GS_ALL_DONE);
4405 if (pre)
4406 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4409 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4411 static tree
4412 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4414 tree t, stmt;
4416 t = create_tmp_var (TREE_TYPE (exp), NULL);
4417 DECL_GIMPLE_REG_P (t) = 1;
4418 stmt = build_gimple_modify_stmt (t, exp);
4419 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4420 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4422 return t;
4425 /* Similarly, but copy from the temporary and insert the statement
4426 after the iterator. */
4428 static tree
4429 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4431 tree t, stmt;
4433 t = create_tmp_var (TREE_TYPE (exp), NULL);
4434 DECL_GIMPLE_REG_P (t) = 1;
4435 stmt = build_gimple_modify_stmt (exp, t);
4436 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4437 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4439 return t;
4442 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4444 static tree
4445 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4447 struct walk_stmt_info *wi = data;
4448 omp_context *ctx = wi->info;
4449 tree t = *tp;
4451 /* If we have issued syntax errors, avoid doing any heavy lifting.
4452 Just replace the OpenMP directives with a NOP to avoid
4453 confusing RTL expansion. */
4454 if (errorcount && OMP_DIRECTIVE_P (*tp))
4456 *tp = build_empty_stmt ();
4457 return NULL_TREE;
4460 *walk_subtrees = 0;
4461 switch (TREE_CODE (*tp))
4463 case OMP_PARALLEL:
4464 ctx = maybe_lookup_ctx (t);
4465 lower_omp_parallel (tp, ctx);
4466 break;
4468 case OMP_FOR:
4469 ctx = maybe_lookup_ctx (t);
4470 gcc_assert (ctx);
4471 lower_omp_for (tp, ctx);
4472 break;
4474 case OMP_SECTIONS:
4475 ctx = maybe_lookup_ctx (t);
4476 gcc_assert (ctx);
4477 lower_omp_sections (tp, ctx);
4478 break;
4480 case OMP_SINGLE:
4481 ctx = maybe_lookup_ctx (t);
4482 gcc_assert (ctx);
4483 lower_omp_single (tp, ctx);
4484 break;
4486 case OMP_MASTER:
4487 ctx = maybe_lookup_ctx (t);
4488 gcc_assert (ctx);
4489 lower_omp_master (tp, ctx);
4490 break;
4492 case OMP_ORDERED:
4493 ctx = maybe_lookup_ctx (t);
4494 gcc_assert (ctx);
4495 lower_omp_ordered (tp, ctx);
4496 break;
4498 case OMP_CRITICAL:
4499 ctx = maybe_lookup_ctx (t);
4500 gcc_assert (ctx);
4501 lower_omp_critical (tp, ctx);
4502 break;
4504 case VAR_DECL:
4505 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4507 lower_regimplify (&t, wi);
4508 if (wi->val_only)
4510 if (wi->is_lhs)
4511 t = save_tmp_var (t, &wi->tsi);
4512 else
4513 t = init_tmp_var (t, &wi->tsi);
4515 *tp = t;
4517 break;
4519 case ADDR_EXPR:
4520 if (ctx)
4521 lower_regimplify (tp, wi);
4522 break;
4524 case ARRAY_REF:
4525 case ARRAY_RANGE_REF:
4526 case REALPART_EXPR:
4527 case IMAGPART_EXPR:
4528 case COMPONENT_REF:
4529 case VIEW_CONVERT_EXPR:
4530 if (ctx)
4531 lower_regimplify (tp, wi);
4532 break;
4534 case INDIRECT_REF:
4535 if (ctx)
4537 wi->is_lhs = false;
4538 wi->val_only = true;
4539 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4541 break;
4543 default:
4544 if (!TYPE_P (t) && !DECL_P (t))
4545 *walk_subtrees = 1;
4546 break;
4549 return NULL_TREE;
4552 static void
4553 lower_omp (tree *stmt_p, omp_context *ctx)
4555 struct walk_stmt_info wi;
4557 memset (&wi, 0, sizeof (wi));
4558 wi.callback = lower_omp_1;
4559 wi.info = ctx;
4560 wi.val_only = true;
4561 wi.want_locations = true;
4563 walk_stmts (&wi, stmt_p);
4566 /* Main entry point. */
4568 static unsigned int
4569 execute_lower_omp (void)
4571 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4572 delete_omp_context);
4574 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4575 gcc_assert (parallel_nesting_level == 0);
4577 if (all_contexts->root)
4578 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4580 if (all_contexts)
4582 splay_tree_delete (all_contexts);
4583 all_contexts = NULL;
4585 return 0;
4588 static bool
4589 gate_lower_omp (void)
4591 return flag_openmp != 0;
4594 struct tree_opt_pass pass_lower_omp =
4596 "omplower", /* name */
4597 gate_lower_omp, /* gate */
4598 execute_lower_omp, /* execute */
4599 NULL, /* sub */
4600 NULL, /* next */
4601 0, /* static_pass_number */
4602 0, /* tv_id */
4603 PROP_gimple_any, /* properties_required */
4604 PROP_gimple_lomp, /* properties_provided */
4605 0, /* properties_destroyed */
4606 0, /* todo_flags_start */
4607 TODO_dump_func, /* todo_flags_finish */
4608 0 /* letter */
4611 /* The following is a utility to diagnose OpenMP structured block violations.
4612 It is not part of the "omplower" pass, as that's invoked too late. It
4613 should be invoked by the respective front ends after gimplification. */
4615 static splay_tree all_labels;
4617 /* Check for mismatched contexts and generate an error if needed. Return
4618 true if an error is detected. */
4620 static bool
4621 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4623 bool exit_p = true;
4625 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4626 return false;
4628 /* Try to avoid confusing the user by producing and error message
4629 with correct "exit" or "enter" verbage. We prefer "exit"
4630 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4631 if (branch_ctx == NULL)
4632 exit_p = false;
4633 else
4635 while (label_ctx)
4637 if (TREE_VALUE (label_ctx) == branch_ctx)
4639 exit_p = false;
4640 break;
4642 label_ctx = TREE_CHAIN (label_ctx);
4646 if (exit_p)
4647 error ("invalid exit from OpenMP structured block");
4648 else
4649 error ("invalid entry to OpenMP structured block");
4651 *stmt_p = build_empty_stmt ();
4652 return true;
4655 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4656 where in the tree each label is found. */
4658 static tree
4659 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4661 struct walk_stmt_info *wi = data;
4662 tree context = (tree) wi->info;
4663 tree inner_context;
4664 tree t = *tp;
4666 *walk_subtrees = 0;
4667 switch (TREE_CODE (t))
4669 case OMP_PARALLEL:
4670 case OMP_SECTIONS:
4671 case OMP_SINGLE:
4672 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4673 /* FALLTHRU */
4674 case OMP_SECTION:
4675 case OMP_MASTER:
4676 case OMP_ORDERED:
4677 case OMP_CRITICAL:
4678 /* The minimal context here is just a tree of statements. */
4679 inner_context = tree_cons (NULL, t, context);
4680 wi->info = inner_context;
4681 walk_stmts (wi, &OMP_BODY (t));
4682 wi->info = context;
4683 break;
4685 case OMP_FOR:
4686 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4687 inner_context = tree_cons (NULL, t, context);
4688 wi->info = inner_context;
4689 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4690 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4691 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4692 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4693 walk_stmts (wi, &OMP_FOR_BODY (t));
4694 wi->info = context;
4695 break;
4697 case LABEL_EXPR:
4698 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4699 (splay_tree_value) context);
4700 break;
4702 default:
4703 break;
4706 return NULL_TREE;
4709 /* Pass 2: Check each branch and see if its context differs from that of
4710 the destination label's context. */
4712 static tree
4713 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4715 struct walk_stmt_info *wi = data;
4716 tree context = (tree) wi->info;
4717 splay_tree_node n;
4718 tree t = *tp;
4720 *walk_subtrees = 0;
4721 switch (TREE_CODE (t))
4723 case OMP_PARALLEL:
4724 case OMP_SECTIONS:
4725 case OMP_SINGLE:
4726 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4727 /* FALLTHRU */
4728 case OMP_SECTION:
4729 case OMP_MASTER:
4730 case OMP_ORDERED:
4731 case OMP_CRITICAL:
4732 wi->info = t;
4733 walk_stmts (wi, &OMP_BODY (t));
4734 wi->info = context;
4735 break;
4737 case OMP_FOR:
4738 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4739 wi->info = t;
4740 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4741 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4742 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4743 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4744 walk_stmts (wi, &OMP_FOR_BODY (t));
4745 wi->info = context;
4746 break;
4748 case GOTO_EXPR:
4750 tree lab = GOTO_DESTINATION (t);
4751 if (TREE_CODE (lab) != LABEL_DECL)
4752 break;
4754 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4755 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4757 break;
4759 case SWITCH_EXPR:
4761 tree vec = SWITCH_LABELS (t);
4762 int i, len = TREE_VEC_LENGTH (vec);
4763 for (i = 0; i < len; ++i)
4765 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4766 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4767 if (diagnose_sb_0 (tp, context, (tree) n->value))
4768 break;
4771 break;
4773 case RETURN_EXPR:
4774 diagnose_sb_0 (tp, context, NULL_TREE);
4775 break;
4777 default:
4778 break;
4781 return NULL_TREE;
4784 void
4785 diagnose_omp_structured_block_errors (tree fndecl)
4787 tree save_current = current_function_decl;
4788 struct walk_stmt_info wi;
4790 current_function_decl = fndecl;
4792 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4794 memset (&wi, 0, sizeof (wi));
4795 wi.callback = diagnose_sb_1;
4796 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4798 memset (&wi, 0, sizeof (wi));
4799 wi.callback = diagnose_sb_2;
4800 wi.want_locations = true;
4801 wi.want_return_expr = true;
4802 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4804 splay_tree_delete (all_labels);
4805 all_labels = NULL;
4807 current_function_decl = save_current;
4810 #include "gt-omp-low.h"