2007-10-02 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / omp-low.c
blob421b5c62863b709e2ece9ac1d4fa00bde16644a0
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);
2603 update_ssa (TODO_update_ssa_only_virtuals);
2607 /* A subroutine of expand_omp_for. Generate code for a parallel
2608 loop with any schedule. Given parameters:
2610 for (V = N1; V cond N2; V += STEP) BODY;
2612 where COND is "<" or ">", we generate pseudocode
2614 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2615 if (more) goto L0; else goto L3;
2617 V = istart0;
2618 iend = iend0;
2620 BODY;
2621 V += STEP;
2622 if (V cond iend) goto L1; else goto L2;
2624 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2627 If this is a combined omp parallel loop, instead of the call to
2628 GOMP_loop_foo_start, we call GOMP_loop_foo_next. */
2630 static void
2631 expand_omp_for_generic (struct omp_region *region,
2632 struct omp_for_data *fd,
2633 enum built_in_function start_fn,
2634 enum built_in_function next_fn)
2636 tree type, istart0, iend0, iend, phi;
2637 tree t, vmain, vback;
2638 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2639 basic_block l2_bb = NULL, l3_bb = NULL;
2640 block_stmt_iterator si;
2641 bool in_combined_parallel = is_combined_parallel (region);
2642 bool broken_loop = region->cont == NULL;
2643 edge e, ne;
2645 gcc_assert (!broken_loop || !in_combined_parallel);
2647 type = TREE_TYPE (fd->v);
2649 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2650 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2651 TREE_ADDRESSABLE (istart0) = 1;
2652 TREE_ADDRESSABLE (iend0) = 1;
2653 if (gimple_in_ssa_p (cfun))
2655 add_referenced_var (istart0);
2656 add_referenced_var (iend0);
2659 entry_bb = region->entry;
2660 cont_bb = region->cont;
2661 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2662 gcc_assert (broken_loop
2663 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2664 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2665 l1_bb = single_succ (l0_bb);
2666 if (!broken_loop)
2668 l2_bb = create_empty_bb (cont_bb);
2669 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
2670 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2672 else
2673 l2_bb = NULL;
2674 l3_bb = BRANCH_EDGE (entry_bb)->dest;
2675 exit_bb = region->exit;
2677 si = bsi_last (entry_bb);
2678 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2679 if (in_combined_parallel)
2681 /* In a combined parallel loop, emit a call to
2682 GOMP_loop_foo_next. */
2683 t = build_call_expr (built_in_decls[next_fn], 2,
2684 build_fold_addr_expr (istart0),
2685 build_fold_addr_expr (iend0));
2687 else
2689 tree t0, t1, t2, t3, t4;
2690 /* If this is not a combined parallel loop, emit a call to
2691 GOMP_loop_foo_start in ENTRY_BB. */
2692 t4 = build_fold_addr_expr (iend0);
2693 t3 = build_fold_addr_expr (istart0);
2694 t2 = fold_convert (long_integer_type_node, fd->step);
2695 t1 = fold_convert (long_integer_type_node, fd->n2);
2696 t0 = fold_convert (long_integer_type_node, fd->n1);
2697 if (fd->chunk_size)
2699 t = fold_convert (long_integer_type_node, fd->chunk_size);
2700 t = build_call_expr (built_in_decls[start_fn], 6,
2701 t0, t1, t2, t, t3, t4);
2703 else
2704 t = build_call_expr (built_in_decls[start_fn], 5,
2705 t0, t1, t2, t3, t4);
2707 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2708 true, BSI_SAME_STMT);
2709 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2710 bsi_insert_after (&si, t, BSI_SAME_STMT);
2712 /* V may be used outside of the loop (e.g., to handle lastprivate clause).
2713 If this is the case, its value is undefined if the loop is not entered
2714 at all. To handle this case, set its initial value to N1. */
2715 if (gimple_in_ssa_p (cfun))
2717 e = find_edge (entry_bb, l3_bb);
2718 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
2719 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == fd->v)
2720 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), fd->n1);
2722 else
2724 t = build_gimple_modify_stmt (fd->v, fd->n1);
2725 bsi_insert_before (&si, t, BSI_SAME_STMT);
2728 /* Remove the OMP_FOR statement. */
2729 bsi_remove (&si, true);
2731 /* Iteration setup for sequential loop goes in L0_BB. */
2732 si = bsi_start (l0_bb);
2733 t = fold_convert (type, istart0);
2734 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2735 false, BSI_CONTINUE_LINKING);
2736 t = build_gimple_modify_stmt (fd->v, t);
2737 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2738 if (gimple_in_ssa_p (cfun))
2739 SSA_NAME_DEF_STMT (fd->v) = t;
2741 t = fold_convert (type, iend0);
2742 iend = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2743 false, BSI_CONTINUE_LINKING);
2745 if (!broken_loop)
2747 /* Code to control the increment and predicate for the sequential
2748 loop goes in the CONT_BB. */
2749 si = bsi_last (cont_bb);
2750 t = bsi_stmt (si);
2751 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
2752 vmain = TREE_OPERAND (t, 1);
2753 vback = TREE_OPERAND (t, 0);
2755 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
2756 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2757 true, BSI_SAME_STMT);
2758 t = build_gimple_modify_stmt (vback, t);
2759 bsi_insert_before (&si, t, BSI_SAME_STMT);
2760 if (gimple_in_ssa_p (cfun))
2761 SSA_NAME_DEF_STMT (vback) = t;
2763 t = build2 (fd->cond_code, boolean_type_node, vback, iend);
2764 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2765 bsi_insert_before (&si, t, BSI_SAME_STMT);
2767 /* Remove OMP_CONTINUE. */
2768 bsi_remove (&si, true);
2770 /* Emit code to get the next parallel iteration in L2_BB. */
2771 si = bsi_start (l2_bb);
2773 t = build_call_expr (built_in_decls[next_fn], 2,
2774 build_fold_addr_expr (istart0),
2775 build_fold_addr_expr (iend0));
2776 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2777 false, BSI_CONTINUE_LINKING);
2778 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2779 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2782 /* Add the loop cleanup function. */
2783 si = bsi_last (exit_bb);
2784 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2785 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2786 else
2787 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2788 t = build_call_expr (t, 0);
2789 bsi_insert_after (&si, t, BSI_SAME_STMT);
2790 bsi_remove (&si, true);
2792 /* Connect the new blocks. */
2793 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
2794 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
2796 if (!broken_loop)
2798 e = find_edge (cont_bb, l3_bb);
2799 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2801 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
2802 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
2803 PHI_ARG_DEF_FROM_EDGE (phi, e));
2804 remove_edge (e);
2806 find_edge (cont_bb, l1_bb)->flags = EDGE_TRUE_VALUE;
2807 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2808 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2810 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
2811 recompute_dominator (CDI_DOMINATORS, l2_bb));
2812 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
2813 recompute_dominator (CDI_DOMINATORS, l3_bb));
2814 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
2815 recompute_dominator (CDI_DOMINATORS, l0_bb));
2816 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
2817 recompute_dominator (CDI_DOMINATORS, l1_bb));
2822 /* A subroutine of expand_omp_for. Generate code for a parallel
2823 loop with static schedule and no specified chunk size. Given
2824 parameters:
2826 for (V = N1; V cond N2; V += STEP) BODY;
2828 where COND is "<" or ">", we generate pseudocode
2830 if (cond is <)
2831 adj = STEP - 1;
2832 else
2833 adj = STEP + 1;
2834 n = (adj + N2 - N1) / STEP;
2835 q = n / nthreads;
2836 q += (q * nthreads != n);
2837 s0 = q * threadid;
2838 e0 = min(s0 + q, n);
2839 V = s0 * STEP + N1;
2840 if (s0 >= e0) goto L2; else goto L0;
2842 e = e0 * STEP + N1;
2844 BODY;
2845 V += STEP;
2846 if (V cond e) goto L1;
2850 static void
2851 expand_omp_for_static_nochunk (struct omp_region *region,
2852 struct omp_for_data *fd)
2854 tree n, q, s0, e0, e, t, nthreads, threadid;
2855 tree type, vmain, vback;
2856 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2857 basic_block fin_bb;
2858 block_stmt_iterator si;
2860 type = TREE_TYPE (fd->v);
2862 entry_bb = region->entry;
2863 cont_bb = region->cont;
2864 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2865 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2866 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2867 body_bb = single_succ (seq_start_bb);
2868 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
2869 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2870 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
2871 exit_bb = region->exit;
2873 /* Iteration space partitioning goes in ENTRY_BB. */
2874 si = bsi_last (entry_bb);
2875 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2877 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2878 t = fold_convert (type, t);
2879 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2880 true, BSI_SAME_STMT);
2882 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2883 t = fold_convert (type, t);
2884 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2885 true, BSI_SAME_STMT);
2887 fd->n1 = force_gimple_operand_bsi (&si,
2888 fold_convert (type, fd->n1),
2889 true, NULL_TREE,
2890 true, BSI_SAME_STMT);
2892 fd->n2 = force_gimple_operand_bsi (&si,
2893 fold_convert (type, fd->n2),
2894 true, NULL_TREE,
2895 true, BSI_SAME_STMT);
2897 fd->step = force_gimple_operand_bsi (&si,
2898 fold_convert (type, fd->step),
2899 true, NULL_TREE,
2900 true, BSI_SAME_STMT);
2902 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2903 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2904 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2905 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2906 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2907 t = fold_convert (type, t);
2908 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2910 t = fold_build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2911 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2913 t = fold_build2 (MULT_EXPR, type, q, nthreads);
2914 t = fold_build2 (NE_EXPR, type, t, n);
2915 t = fold_build2 (PLUS_EXPR, type, q, t);
2916 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2918 t = build2 (MULT_EXPR, type, q, threadid);
2919 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2921 t = fold_build2 (PLUS_EXPR, type, s0, q);
2922 t = fold_build2 (MIN_EXPR, type, t, n);
2923 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2925 t = fold_convert (type, s0);
2926 t = fold_build2 (MULT_EXPR, type, t, fd->step);
2927 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
2928 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2929 true, BSI_SAME_STMT);
2930 t = build_gimple_modify_stmt (fd->v, t);
2931 bsi_insert_before (&si, t, BSI_SAME_STMT);
2932 if (gimple_in_ssa_p (cfun))
2933 SSA_NAME_DEF_STMT (fd->v) = t;
2935 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2936 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2937 bsi_insert_before (&si, t, BSI_SAME_STMT);
2939 /* Remove the OMP_FOR statement. */
2940 bsi_remove (&si, true);
2942 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2943 si = bsi_start (seq_start_bb);
2945 t = fold_convert (type, e0);
2946 t = fold_build2 (MULT_EXPR, type, t, fd->step);
2947 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
2948 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2949 false, BSI_CONTINUE_LINKING);
2951 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2952 si = bsi_last (cont_bb);
2953 t = bsi_stmt (si);
2954 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
2955 vmain = TREE_OPERAND (t, 1);
2956 vback = TREE_OPERAND (t, 0);
2958 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
2959 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2960 true, BSI_SAME_STMT);
2961 t = build_gimple_modify_stmt (vback, t);
2962 bsi_insert_before (&si, t, BSI_SAME_STMT);
2963 if (gimple_in_ssa_p (cfun))
2964 SSA_NAME_DEF_STMT (vback) = t;
2966 t = build2 (fd->cond_code, boolean_type_node, vback, e);
2967 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2968 bsi_insert_before (&si, t, BSI_SAME_STMT);
2970 /* Remove the OMP_CONTINUE statement. */
2971 bsi_remove (&si, true);
2973 /* Replace the OMP_RETURN with a barrier, or nothing. */
2974 si = bsi_last (exit_bb);
2975 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2976 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
2977 false, BSI_SAME_STMT);
2978 bsi_remove (&si, true);
2980 /* Connect all the blocks. */
2981 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
2982 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
2984 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
2985 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2987 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
2988 set_immediate_dominator (CDI_DOMINATORS, body_bb,
2989 recompute_dominator (CDI_DOMINATORS, body_bb));
2990 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
2991 recompute_dominator (CDI_DOMINATORS, fin_bb));
2995 /* A subroutine of expand_omp_for. Generate code for a parallel
2996 loop with static schedule and a specified chunk size. Given
2997 parameters:
2999 for (V = N1; V cond N2; V += STEP) BODY;
3001 where COND is "<" or ">", we generate pseudocode
3003 if (cond is <)
3004 adj = STEP - 1;
3005 else
3006 adj = STEP + 1;
3007 n = (adj + N2 - N1) / STEP;
3008 trip = 0;
3009 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
3010 here so that V is defined
3011 if the loop is not entered
3013 s0 = (trip * nthreads + threadid) * CHUNK;
3014 e0 = min(s0 + CHUNK, n);
3015 if (s0 < n) goto L1; else goto L4;
3017 V = s0 * STEP + N1;
3018 e = e0 * STEP + N1;
3020 BODY;
3021 V += STEP;
3022 if (V cond e) goto L2; else goto L3;
3024 trip += 1;
3025 goto L0;
3029 static void
3030 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
3032 tree n, s0, e0, e, t, phi, nphi, args;
3033 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
3034 tree type, cont, v_main, v_back, v_extra;
3035 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
3036 basic_block trip_update_bb, cont_bb, fin_bb;
3037 block_stmt_iterator si;
3038 edge se, re, ene;
3040 type = TREE_TYPE (fd->v);
3042 entry_bb = region->entry;
3043 se = split_block (entry_bb, last_stmt (entry_bb));
3044 entry_bb = se->src;
3045 iter_part_bb = se->dest;
3046 cont_bb = region->cont;
3047 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
3048 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
3049 == FALLTHRU_EDGE (cont_bb)->dest);
3050 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
3051 body_bb = single_succ (seq_start_bb);
3052 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
3053 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3054 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
3055 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
3056 exit_bb = region->exit;
3058 /* Trip and adjustment setup goes in ENTRY_BB. */
3059 si = bsi_last (entry_bb);
3060 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3062 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
3063 t = fold_convert (type, t);
3064 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3065 true, BSI_SAME_STMT);
3067 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3068 t = fold_convert (type, t);
3069 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3070 true, BSI_SAME_STMT);
3072 fd->n1 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n1),
3073 true, NULL_TREE,
3074 true, BSI_SAME_STMT);
3075 fd->n2 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n2),
3076 true, NULL_TREE,
3077 true, BSI_SAME_STMT);
3078 fd->step = force_gimple_operand_bsi (&si, fold_convert (type, fd->step),
3079 true, NULL_TREE,
3080 true, BSI_SAME_STMT);
3081 fd->chunk_size
3082 = force_gimple_operand_bsi (&si, fold_convert (type,
3083 fd->chunk_size),
3084 true, NULL_TREE,
3085 true, BSI_SAME_STMT);
3087 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
3088 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
3089 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
3090 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
3091 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
3092 t = fold_convert (type, t);
3093 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3094 true, BSI_SAME_STMT);
3096 trip_var = create_tmp_var (type, ".trip");
3097 if (gimple_in_ssa_p (cfun))
3099 add_referenced_var (trip_var);
3100 trip_init = make_ssa_name (trip_var, NULL_TREE);
3101 trip_main = make_ssa_name (trip_var, NULL_TREE);
3102 trip_back = make_ssa_name (trip_var, NULL_TREE);
3104 else
3106 trip_init = trip_var;
3107 trip_main = trip_var;
3108 trip_back = trip_var;
3111 t = build_gimple_modify_stmt (trip_init, build_int_cst (type, 0));
3112 bsi_insert_before (&si, t, BSI_SAME_STMT);
3113 if (gimple_in_ssa_p (cfun))
3114 SSA_NAME_DEF_STMT (trip_init) = t;
3116 t = fold_build2 (MULT_EXPR, type, threadid, fd->chunk_size);
3117 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3118 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3119 v_extra = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3120 true, BSI_SAME_STMT);
3122 /* Remove the OMP_FOR. */
3123 bsi_remove (&si, true);
3125 /* Iteration space partitioning goes in ITER_PART_BB. */
3126 si = bsi_last (iter_part_bb);
3128 t = fold_build2 (MULT_EXPR, type, trip_main, nthreads);
3129 t = fold_build2 (PLUS_EXPR, type, t, threadid);
3130 t = fold_build2 (MULT_EXPR, type, t, fd->chunk_size);
3131 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3132 false, BSI_CONTINUE_LINKING);
3134 t = fold_build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3135 t = fold_build2 (MIN_EXPR, type, t, n);
3136 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3137 false, BSI_CONTINUE_LINKING);
3139 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3140 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3141 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3143 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3144 si = bsi_start (seq_start_bb);
3146 t = fold_convert (type, s0);
3147 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3148 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3149 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3150 false, BSI_CONTINUE_LINKING);
3151 t = build_gimple_modify_stmt (fd->v, t);
3152 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3153 if (gimple_in_ssa_p (cfun))
3154 SSA_NAME_DEF_STMT (fd->v) = t;
3156 t = fold_convert (type, e0);
3157 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3158 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3159 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3160 false, BSI_CONTINUE_LINKING);
3162 /* The code controlling the sequential loop goes in CONT_BB,
3163 replacing the OMP_CONTINUE. */
3164 si = bsi_last (cont_bb);
3165 cont = bsi_stmt (si);
3166 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3167 v_main = TREE_OPERAND (cont, 1);
3168 v_back = TREE_OPERAND (cont, 0);
3170 t = build2 (PLUS_EXPR, type, v_main, fd->step);
3171 t = build_gimple_modify_stmt (v_back, t);
3172 bsi_insert_before (&si, t, BSI_SAME_STMT);
3173 if (gimple_in_ssa_p (cfun))
3174 SSA_NAME_DEF_STMT (v_back) = t;
3176 t = build2 (fd->cond_code, boolean_type_node, v_back, e);
3177 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3178 bsi_insert_before (&si, t, BSI_SAME_STMT);
3180 /* Remove OMP_CONTINUE. */
3181 bsi_remove (&si, true);
3183 /* Trip update code goes into TRIP_UPDATE_BB. */
3184 si = bsi_start (trip_update_bb);
3186 t = build_int_cst (type, 1);
3187 t = build2 (PLUS_EXPR, type, trip_main, t);
3188 t = build_gimple_modify_stmt (trip_back, t);
3189 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3190 if (gimple_in_ssa_p (cfun))
3191 SSA_NAME_DEF_STMT (trip_back) = t;
3193 /* Replace the OMP_RETURN with a barrier, or nothing. */
3194 si = bsi_last (exit_bb);
3195 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3196 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3197 false, BSI_SAME_STMT);
3198 bsi_remove (&si, true);
3200 /* Connect the new blocks. */
3201 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
3202 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
3204 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3205 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
3207 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
3209 if (gimple_in_ssa_p (cfun))
3211 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
3212 remove arguments of the phi nodes in fin_bb. We need to create
3213 appropriate phi nodes in iter_part_bb instead. */
3214 se = single_pred_edge (fin_bb);
3215 re = single_succ_edge (trip_update_bb);
3216 ene = single_succ_edge (entry_bb);
3218 args = PENDING_STMT (re);
3219 PENDING_STMT (re) = NULL_TREE;
3220 for (phi = phi_nodes (fin_bb);
3221 phi && args;
3222 phi = PHI_CHAIN (phi), args = TREE_CHAIN (args))
3224 t = PHI_RESULT (phi);
3225 gcc_assert (t == TREE_PURPOSE (args));
3226 nphi = create_phi_node (t, iter_part_bb);
3227 SSA_NAME_DEF_STMT (t) = nphi;
3229 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
3230 /* A special case -- fd->v is not yet computed in iter_part_bb, we
3231 need to use v_extra instead. */
3232 if (t == fd->v)
3233 t = v_extra;
3234 add_phi_arg (nphi, t, ene);
3235 add_phi_arg (nphi, TREE_VALUE (args), re);
3237 gcc_assert (!phi && !args);
3238 while ((phi = phi_nodes (fin_bb)) != NULL_TREE)
3239 remove_phi_node (phi, NULL_TREE, false);
3241 /* Make phi node for trip. */
3242 phi = create_phi_node (trip_main, iter_part_bb);
3243 SSA_NAME_DEF_STMT (trip_main) = phi;
3244 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
3245 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
3248 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
3249 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
3250 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
3251 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
3252 recompute_dominator (CDI_DOMINATORS, fin_bb));
3253 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
3254 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
3255 set_immediate_dominator (CDI_DOMINATORS, body_bb,
3256 recompute_dominator (CDI_DOMINATORS, body_bb));
3260 /* Expand the OpenMP loop defined by REGION. */
3262 static void
3263 expand_omp_for (struct omp_region *region)
3265 struct omp_for_data fd;
3267 extract_omp_for_data (last_stmt (region->entry), &fd);
3268 region->sched_kind = fd.sched_kind;
3270 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3271 && !fd.have_ordered
3272 && region->cont != NULL)
3274 if (fd.chunk_size == NULL)
3275 expand_omp_for_static_nochunk (region, &fd);
3276 else
3277 expand_omp_for_static_chunk (region, &fd);
3279 else
3281 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3282 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3283 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3284 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3287 update_ssa (TODO_update_ssa_only_virtuals);
3291 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3293 v = GOMP_sections_start (n);
3295 switch (v)
3297 case 0:
3298 goto L2;
3299 case 1:
3300 section 1;
3301 goto L1;
3302 case 2:
3304 case n:
3306 default:
3307 abort ();
3310 v = GOMP_sections_next ();
3311 goto L0;
3313 reduction;
3315 If this is a combined parallel sections, replace the call to
3316 GOMP_sections_start with call to GOMP_sections_next. */
3318 static void
3319 expand_omp_sections (struct omp_region *region)
3321 tree label_vec, l1, l2, t, u, sections_stmt, vin, vmain, vnext, cont;
3322 unsigned i, casei, len;
3323 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
3324 block_stmt_iterator si;
3325 struct omp_region *inner;
3326 bool exit_reachable = region->cont != NULL;
3328 gcc_assert (exit_reachable == (region->exit != NULL));
3329 entry_bb = region->entry;
3330 l0_bb = single_succ (entry_bb);
3331 l1_bb = region->cont;
3332 l2_bb = region->exit;
3333 if (exit_reachable)
3335 gcc_assert (single_pred (l2_bb) == l0_bb);
3336 default_bb = create_empty_bb (l1_bb->prev_bb);
3337 l1 = tree_block_label (l1_bb);
3338 l2 = tree_block_label (l2_bb);
3340 else
3342 default_bb = create_empty_bb (l0_bb);
3343 l1 = NULL_TREE;
3344 l2 = tree_block_label (default_bb);
3347 /* We will build a switch() with enough cases for all the
3348 OMP_SECTION regions, a '0' case to handle the end of more work
3349 and a default case to abort if something goes wrong. */
3350 len = EDGE_COUNT (l0_bb->succs);
3351 label_vec = make_tree_vec (len + 1);
3353 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3354 OMP_SECTIONS statement. */
3355 si = bsi_last (entry_bb);
3356 sections_stmt = bsi_stmt (si);
3357 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3358 vin = OMP_SECTIONS_CONTROL (sections_stmt);
3359 if (!is_combined_parallel (region))
3361 /* If we are not inside a combined parallel+sections region,
3362 call GOMP_sections_start. */
3363 t = build_int_cst (unsigned_type_node,
3364 exit_reachable ? len - 1 : len);
3365 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3366 t = build_call_expr (u, 1, t);
3368 else
3370 /* Otherwise, call GOMP_sections_next. */
3371 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3372 t = build_call_expr (u, 0);
3374 t = build_gimple_modify_stmt (vin, t);
3375 bsi_insert_after (&si, t, BSI_SAME_STMT);
3376 if (gimple_in_ssa_p (cfun))
3377 SSA_NAME_DEF_STMT (vin) = t;
3378 bsi_remove (&si, true);
3380 /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB. */
3381 si = bsi_last (l0_bb);
3382 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
3383 if (exit_reachable)
3385 cont = last_stmt (l1_bb);
3386 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3387 vmain = TREE_OPERAND (cont, 1);
3388 vnext = TREE_OPERAND (cont, 0);
3390 else
3392 vmain = vin;
3393 vnext = NULL_TREE;
3396 t = build3 (SWITCH_EXPR, void_type_node, vmain, NULL, label_vec);
3397 bsi_insert_after (&si, t, BSI_SAME_STMT);
3398 bsi_remove (&si, true);
3400 i = 0;
3401 if (exit_reachable)
3403 t = build3 (CASE_LABEL_EXPR, void_type_node,
3404 build_int_cst (unsigned_type_node, 0), NULL, l2);
3405 TREE_VEC_ELT (label_vec, 0) = t;
3406 i++;
3409 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3410 for (inner = region->inner, casei = 1;
3411 inner;
3412 inner = inner->next, i++, casei++)
3414 basic_block s_entry_bb, s_exit_bb;
3416 s_entry_bb = inner->entry;
3417 s_exit_bb = inner->exit;
3419 t = tree_block_label (s_entry_bb);
3420 u = build_int_cst (unsigned_type_node, casei);
3421 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3422 TREE_VEC_ELT (label_vec, i) = u;
3424 si = bsi_last (s_entry_bb);
3425 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3426 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3427 bsi_remove (&si, true);
3428 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3430 if (s_exit_bb == NULL)
3431 continue;
3433 si = bsi_last (s_exit_bb);
3434 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3435 bsi_remove (&si, true);
3437 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3440 /* Error handling code goes in DEFAULT_BB. */
3441 t = tree_block_label (default_bb);
3442 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3443 TREE_VEC_ELT (label_vec, len) = u;
3444 make_edge (l0_bb, default_bb, 0);
3446 si = bsi_start (default_bb);
3447 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3448 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3450 if (exit_reachable)
3452 /* Code to get the next section goes in L1_BB. */
3453 si = bsi_last (l1_bb);
3454 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3456 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3457 t = build_gimple_modify_stmt (vnext, t);
3458 bsi_insert_after (&si, t, BSI_SAME_STMT);
3459 if (gimple_in_ssa_p (cfun))
3460 SSA_NAME_DEF_STMT (vnext) = t;
3461 bsi_remove (&si, true);
3463 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
3465 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3466 si = bsi_last (l2_bb);
3467 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3468 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3469 else
3470 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3471 t = build_call_expr (t, 0);
3472 bsi_insert_after (&si, t, BSI_SAME_STMT);
3473 bsi_remove (&si, true);
3476 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
3480 /* Expand code for an OpenMP single directive. We've already expanded
3481 much of the code, here we simply place the GOMP_barrier call. */
3483 static void
3484 expand_omp_single (struct omp_region *region)
3486 basic_block entry_bb, exit_bb;
3487 block_stmt_iterator si;
3488 bool need_barrier = false;
3490 entry_bb = region->entry;
3491 exit_bb = region->exit;
3493 si = bsi_last (entry_bb);
3494 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3495 be removed. We need to ensure that the thread that entered the single
3496 does not exit before the data is copied out by the other threads. */
3497 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3498 OMP_CLAUSE_COPYPRIVATE))
3499 need_barrier = true;
3500 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3501 bsi_remove (&si, true);
3502 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3504 si = bsi_last (exit_bb);
3505 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3506 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3507 false, BSI_SAME_STMT);
3508 bsi_remove (&si, true);
3509 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3513 /* Generic expansion for OpenMP synchronization directives: master,
3514 ordered and critical. All we need to do here is remove the entry
3515 and exit markers for REGION. */
3517 static void
3518 expand_omp_synch (struct omp_region *region)
3520 basic_block entry_bb, exit_bb;
3521 block_stmt_iterator si;
3523 entry_bb = region->entry;
3524 exit_bb = region->exit;
3526 si = bsi_last (entry_bb);
3527 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3528 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3529 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3530 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3531 bsi_remove (&si, true);
3532 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3534 if (exit_bb)
3536 si = bsi_last (exit_bb);
3537 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3538 bsi_remove (&si, true);
3539 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3544 /* Expand the parallel region tree rooted at REGION. Expansion
3545 proceeds in depth-first order. Innermost regions are expanded
3546 first. This way, parallel regions that require a new function to
3547 be created (e.g., OMP_PARALLEL) can be expanded without having any
3548 internal dependencies in their body. */
3550 static void
3551 expand_omp (struct omp_region *region)
3553 while (region)
3555 if (region->inner)
3556 expand_omp (region->inner);
3558 switch (region->type)
3560 case OMP_PARALLEL:
3561 expand_omp_parallel (region);
3562 break;
3564 case OMP_FOR:
3565 expand_omp_for (region);
3566 break;
3568 case OMP_SECTIONS:
3569 expand_omp_sections (region);
3570 break;
3572 case OMP_SECTION:
3573 /* Individual omp sections are handled together with their
3574 parent OMP_SECTIONS region. */
3575 break;
3577 case OMP_SINGLE:
3578 expand_omp_single (region);
3579 break;
3581 case OMP_MASTER:
3582 case OMP_ORDERED:
3583 case OMP_CRITICAL:
3584 expand_omp_synch (region);
3585 break;
3587 default:
3588 gcc_unreachable ();
3591 region = region->next;
3596 /* Helper for build_omp_regions. Scan the dominator tree starting at
3597 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
3598 true, the function ends once a single tree is built (otherwise, whole
3599 forest of OMP constructs may be built). */
3601 static void
3602 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
3603 bool single_tree)
3605 block_stmt_iterator si;
3606 tree stmt;
3607 basic_block son;
3609 si = bsi_last (bb);
3610 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3612 struct omp_region *region;
3613 enum tree_code code;
3615 stmt = bsi_stmt (si);
3616 code = TREE_CODE (stmt);
3618 if (code == OMP_RETURN)
3620 /* STMT is the return point out of region PARENT. Mark it
3621 as the exit point and make PARENT the immediately
3622 enclosing region. */
3623 gcc_assert (parent);
3624 region = parent;
3625 region->exit = bb;
3626 parent = parent->outer;
3628 /* If REGION is a parallel region, determine whether it is
3629 a combined parallel+workshare region. */
3630 if (region->type == OMP_PARALLEL)
3631 determine_parallel_type (region);
3633 else if (code == OMP_CONTINUE)
3635 gcc_assert (parent);
3636 parent->cont = bb;
3638 else if (code == OMP_SECTIONS_SWITCH)
3640 /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
3641 it. */
3643 else
3645 /* Otherwise, this directive becomes the parent for a new
3646 region. */
3647 region = new_omp_region (bb, code, parent);
3648 parent = region;
3652 if (single_tree && !parent)
3653 return;
3655 for (son = first_dom_son (CDI_DOMINATORS, bb);
3656 son;
3657 son = next_dom_son (CDI_DOMINATORS, son))
3658 build_omp_regions_1 (son, parent, single_tree);
3661 /* Builds the tree of OMP regions rooted at ROOT, storing it to
3662 root_omp_region. */
3664 static void
3665 build_omp_regions_root (basic_block root)
3667 gcc_assert (root_omp_region == NULL);
3668 build_omp_regions_1 (root, NULL, true);
3669 gcc_assert (root_omp_region != NULL);
3672 /* Expands omp construct (and its subconstructs) starting in HEAD. */
3674 void
3675 omp_expand_local (basic_block head)
3677 build_omp_regions_root (head);
3678 if (dump_file && (dump_flags & TDF_DETAILS))
3680 fprintf (dump_file, "\nOMP region tree\n\n");
3681 dump_omp_region (dump_file, root_omp_region, 0);
3682 fprintf (dump_file, "\n");
3685 remove_exit_barriers (root_omp_region);
3686 expand_omp (root_omp_region);
3688 free_omp_regions ();
3691 /* Scan the CFG and build a tree of OMP regions. Return the root of
3692 the OMP region tree. */
3694 static void
3695 build_omp_regions (void)
3697 gcc_assert (root_omp_region == NULL);
3698 calculate_dominance_info (CDI_DOMINATORS);
3699 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
3703 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3705 static unsigned int
3706 execute_expand_omp (void)
3708 build_omp_regions ();
3710 if (!root_omp_region)
3711 return 0;
3713 if (dump_file)
3715 fprintf (dump_file, "\nOMP region tree\n\n");
3716 dump_omp_region (dump_file, root_omp_region, 0);
3717 fprintf (dump_file, "\n");
3720 remove_exit_barriers (root_omp_region);
3722 expand_omp (root_omp_region);
3724 cleanup_tree_cfg ();
3726 free_omp_regions ();
3728 return 0;
3731 /* OMP expansion in SSA form. For testing purposes only. */
3733 static bool
3734 gate_expand_omp_ssa (void)
3736 return flag_openmp_ssa && flag_openmp != 0 && errorcount == 0;
3739 struct tree_opt_pass pass_expand_omp_ssa =
3741 "ompexpssa", /* name */
3742 gate_expand_omp_ssa, /* gate */
3743 execute_expand_omp, /* execute */
3744 NULL, /* sub */
3745 NULL, /* next */
3746 0, /* static_pass_number */
3747 0, /* tv_id */
3748 PROP_gimple_any, /* properties_required */
3749 PROP_gimple_lomp, /* properties_provided */
3750 0, /* properties_destroyed */
3751 0, /* todo_flags_start */
3752 TODO_dump_func, /* todo_flags_finish */
3753 0 /* letter */
3756 /* OMP expansion -- the default pass, run before creation of SSA form. */
3758 static bool
3759 gate_expand_omp (void)
3761 return ((!flag_openmp_ssa || !optimize)
3762 && flag_openmp != 0 && errorcount == 0);
3765 struct tree_opt_pass pass_expand_omp =
3767 "ompexp", /* name */
3768 gate_expand_omp, /* gate */
3769 execute_expand_omp, /* execute */
3770 NULL, /* sub */
3771 NULL, /* next */
3772 0, /* static_pass_number */
3773 0, /* tv_id */
3774 PROP_gimple_any, /* properties_required */
3775 PROP_gimple_lomp, /* properties_provided */
3776 0, /* properties_destroyed */
3777 0, /* todo_flags_start */
3778 TODO_dump_func, /* todo_flags_finish */
3779 0 /* letter */
3782 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3784 /* Lower the OpenMP sections directive in *STMT_P. */
3786 static void
3787 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3789 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body, control;
3790 tree t, dlist;
3791 tree_stmt_iterator tsi;
3792 unsigned i, len;
3794 stmt = *stmt_p;
3796 push_gimplify_context ();
3798 dlist = NULL;
3799 ilist = NULL;
3800 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3802 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3803 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3804 continue;
3806 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3807 body = alloc_stmt_list ();
3808 for (i = 0; i < len; i++, tsi_next (&tsi))
3810 omp_context *sctx;
3811 tree sec_start, sec_end;
3813 sec_start = tsi_stmt (tsi);
3814 sctx = maybe_lookup_ctx (sec_start);
3815 gcc_assert (sctx);
3817 append_to_statement_list (sec_start, &body);
3819 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3820 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3821 OMP_SECTION_BODY (sec_start) = NULL;
3823 if (i == len - 1)
3825 tree l = alloc_stmt_list ();
3826 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3827 &l, ctx);
3828 append_to_statement_list (l, &body);
3829 OMP_SECTION_LAST (sec_start) = 1;
3832 sec_end = make_node (OMP_RETURN);
3833 append_to_statement_list (sec_end, &body);
3836 block = make_node (BLOCK);
3837 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3839 olist = NULL_TREE;
3840 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3842 pop_gimplify_context (NULL_TREE);
3843 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3845 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3846 TREE_SIDE_EFFECTS (new_stmt) = 1;
3848 new_body = alloc_stmt_list ();
3849 append_to_statement_list (ilist, &new_body);
3850 append_to_statement_list (stmt, &new_body);
3851 append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
3852 append_to_statement_list (bind, &new_body);
3854 control = create_tmp_var (unsigned_type_node, ".section");
3855 t = build2 (OMP_CONTINUE, void_type_node, control, control);
3856 OMP_SECTIONS_CONTROL (stmt) = control;
3857 append_to_statement_list (t, &new_body);
3859 append_to_statement_list (olist, &new_body);
3860 append_to_statement_list (dlist, &new_body);
3862 maybe_catch_exception (&new_body);
3864 t = make_node (OMP_RETURN);
3865 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3866 OMP_CLAUSE_NOWAIT);
3867 append_to_statement_list (t, &new_body);
3869 BIND_EXPR_BODY (new_stmt) = new_body;
3870 OMP_SECTIONS_BODY (stmt) = NULL;
3872 *stmt_p = new_stmt;
3876 /* A subroutine of lower_omp_single. Expand the simple form of
3877 an OMP_SINGLE, without a copyprivate clause:
3879 if (GOMP_single_start ())
3880 BODY;
3881 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3883 FIXME. It may be better to delay expanding the logic of this until
3884 pass_expand_omp. The expanded logic may make the job more difficult
3885 to a synchronization analysis pass. */
3887 static void
3888 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3890 tree t;
3892 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3893 t = build3 (COND_EXPR, void_type_node, t,
3894 OMP_SINGLE_BODY (single_stmt), NULL);
3895 gimplify_and_add (t, pre_p);
3899 /* A subroutine of lower_omp_single. Expand the simple form of
3900 an OMP_SINGLE, with a copyprivate clause:
3902 #pragma omp single copyprivate (a, b, c)
3904 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3907 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3909 BODY;
3910 copyout.a = a;
3911 copyout.b = b;
3912 copyout.c = c;
3913 GOMP_single_copy_end (&copyout);
3915 else
3917 a = copyout_p->a;
3918 b = copyout_p->b;
3919 c = copyout_p->c;
3921 GOMP_barrier ();
3924 FIXME. It may be better to delay expanding the logic of this until
3925 pass_expand_omp. The expanded logic may make the job more difficult
3926 to a synchronization analysis pass. */
3928 static void
3929 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3931 tree ptr_type, t, l0, l1, l2, copyin_seq;
3933 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3935 ptr_type = build_pointer_type (ctx->record_type);
3936 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3938 l0 = create_artificial_label ();
3939 l1 = create_artificial_label ();
3940 l2 = create_artificial_label ();
3942 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3943 t = fold_convert (ptr_type, t);
3944 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3945 gimplify_and_add (t, pre_p);
3947 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3948 build_int_cst (ptr_type, 0));
3949 t = build3 (COND_EXPR, void_type_node, t,
3950 build_and_jump (&l0), build_and_jump (&l1));
3951 gimplify_and_add (t, pre_p);
3953 t = build1 (LABEL_EXPR, void_type_node, l0);
3954 gimplify_and_add (t, pre_p);
3956 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3958 copyin_seq = NULL;
3959 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3960 &copyin_seq, ctx);
3962 t = build_fold_addr_expr (ctx->sender_decl);
3963 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3964 gimplify_and_add (t, pre_p);
3966 t = build_and_jump (&l2);
3967 gimplify_and_add (t, pre_p);
3969 t = build1 (LABEL_EXPR, void_type_node, l1);
3970 gimplify_and_add (t, pre_p);
3972 append_to_statement_list (copyin_seq, pre_p);
3974 t = build1 (LABEL_EXPR, void_type_node, l2);
3975 gimplify_and_add (t, pre_p);
3979 /* Expand code for an OpenMP single directive. */
3981 static void
3982 lower_omp_single (tree *stmt_p, omp_context *ctx)
3984 tree t, bind, block, single_stmt = *stmt_p, dlist;
3986 push_gimplify_context ();
3988 block = make_node (BLOCK);
3989 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3990 TREE_SIDE_EFFECTS (bind) = 1;
3992 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3993 &BIND_EXPR_BODY (bind), &dlist, ctx);
3994 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3996 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3998 if (ctx->record_type)
3999 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
4000 else
4001 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
4003 OMP_SINGLE_BODY (single_stmt) = NULL;
4005 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
4007 maybe_catch_exception (&BIND_EXPR_BODY (bind));
4009 t = make_node (OMP_RETURN);
4010 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
4011 OMP_CLAUSE_NOWAIT);
4012 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4014 pop_gimplify_context (bind);
4016 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4017 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4021 /* Expand code for an OpenMP master directive. */
4023 static void
4024 lower_omp_master (tree *stmt_p, omp_context *ctx)
4026 tree bind, block, stmt = *stmt_p, lab = NULL, x;
4028 push_gimplify_context ();
4030 block = make_node (BLOCK);
4031 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4032 TREE_SIDE_EFFECTS (bind) = 1;
4034 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4036 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
4037 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
4038 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
4039 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4041 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
4042 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
4043 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
4044 OMP_MASTER_BODY (stmt) = NULL;
4046 x = build1 (LABEL_EXPR, void_type_node, lab);
4047 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4049 x = make_node (OMP_RETURN);
4050 OMP_RETURN_NOWAIT (x) = 1;
4051 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4053 pop_gimplify_context (bind);
4055 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4056 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4060 /* Expand code for an OpenMP ordered directive. */
4062 static void
4063 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
4065 tree bind, block, stmt = *stmt_p, x;
4067 push_gimplify_context ();
4069 block = make_node (BLOCK);
4070 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4071 TREE_SIDE_EFFECTS (bind) = 1;
4073 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4075 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
4076 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4078 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
4079 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
4080 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
4081 OMP_ORDERED_BODY (stmt) = NULL;
4083 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
4084 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4086 x = make_node (OMP_RETURN);
4087 OMP_RETURN_NOWAIT (x) = 1;
4088 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4090 pop_gimplify_context (bind);
4092 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4093 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4097 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
4098 substitution of a couple of function calls. But in the NAMED case,
4099 requires that languages coordinate a symbol name. It is therefore
4100 best put here in common code. */
4102 static GTY((param1_is (tree), param2_is (tree)))
4103 splay_tree critical_name_mutexes;
4105 static void
4106 lower_omp_critical (tree *stmt_p, omp_context *ctx)
4108 tree bind, block, stmt = *stmt_p;
4109 tree t, lock, unlock, name;
4111 name = OMP_CRITICAL_NAME (stmt);
4112 if (name)
4114 tree decl;
4115 splay_tree_node n;
4117 if (!critical_name_mutexes)
4118 critical_name_mutexes
4119 = splay_tree_new_ggc (splay_tree_compare_pointers);
4121 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
4122 if (n == NULL)
4124 char *new_str;
4126 decl = create_tmp_var_raw (ptr_type_node, NULL);
4128 new_str = ACONCAT ((".gomp_critical_user_",
4129 IDENTIFIER_POINTER (name), NULL));
4130 DECL_NAME (decl) = get_identifier (new_str);
4131 TREE_PUBLIC (decl) = 1;
4132 TREE_STATIC (decl) = 1;
4133 DECL_COMMON (decl) = 1;
4134 DECL_ARTIFICIAL (decl) = 1;
4135 DECL_IGNORED_P (decl) = 1;
4136 varpool_finalize_decl (decl);
4138 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
4139 (splay_tree_value) decl);
4141 else
4142 decl = (tree) n->value;
4144 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
4145 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
4147 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
4148 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
4150 else
4152 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
4153 lock = build_call_expr (lock, 0);
4155 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
4156 unlock = build_call_expr (unlock, 0);
4159 push_gimplify_context ();
4161 block = make_node (BLOCK);
4162 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4163 TREE_SIDE_EFFECTS (bind) = 1;
4165 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4167 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
4169 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
4170 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
4171 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
4172 OMP_CRITICAL_BODY (stmt) = NULL;
4174 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
4176 t = make_node (OMP_RETURN);
4177 OMP_RETURN_NOWAIT (t) = 1;
4178 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4180 pop_gimplify_context (bind);
4181 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4182 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4186 /* A subroutine of lower_omp_for. Generate code to emit the predicate
4187 for a lastprivate clause. Given a loop control predicate of (V
4188 cond N2), we gate the clause on (!(V cond N2)). The lowered form
4189 is appended to *DLIST, iterator initialization is appended to
4190 *BODY_P. */
4192 static void
4193 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
4194 tree *dlist, struct omp_context *ctx)
4196 tree clauses, cond, stmts, vinit, t;
4197 enum tree_code cond_code;
4199 cond_code = fd->cond_code;
4200 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
4202 /* When possible, use a strict equality expression. This can let VRP
4203 type optimizations deduce the value and remove a copy. */
4204 if (host_integerp (fd->step, 0))
4206 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
4207 if (step == 1 || step == -1)
4208 cond_code = EQ_EXPR;
4211 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
4213 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
4214 stmts = NULL;
4215 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
4216 if (stmts != NULL)
4218 append_to_statement_list (stmts, dlist);
4220 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
4221 vinit = fd->n1;
4222 if (cond_code == EQ_EXPR
4223 && host_integerp (fd->n2, 0)
4224 && ! integer_zerop (fd->n2))
4225 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
4227 /* Initialize the iterator variable, so that threads that don't execute
4228 any iterations don't execute the lastprivate clauses by accident. */
4229 t = build_gimple_modify_stmt (fd->v, vinit);
4230 gimplify_and_add (t, body_p);
4235 /* Lower code for an OpenMP loop directive. */
4237 static void
4238 lower_omp_for (tree *stmt_p, omp_context *ctx)
4240 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
4241 struct omp_for_data fd;
4243 stmt = *stmt_p;
4245 push_gimplify_context ();
4247 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4248 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4250 /* Move declaration of temporaries in the loop body before we make
4251 it go away. */
4252 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4253 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4255 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4256 TREE_SIDE_EFFECTS (new_stmt) = 1;
4257 body_p = &BIND_EXPR_BODY (new_stmt);
4259 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4260 ilist = NULL;
4261 dlist = NULL;
4262 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4263 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4265 /* Lower the header expressions. At this point, we can assume that
4266 the header is of the form:
4268 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4270 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4271 using the .omp_data_s mapping, if needed. */
4272 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4273 if (!is_gimple_min_invariant (*rhs_p))
4274 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4276 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4277 if (!is_gimple_min_invariant (*rhs_p))
4278 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4280 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4281 if (!is_gimple_min_invariant (*rhs_p))
4282 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4284 /* Once lowered, extract the bounds and clauses. */
4285 extract_omp_for_data (stmt, &fd);
4287 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4289 append_to_statement_list (stmt, body_p);
4291 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4293 t = build2 (OMP_CONTINUE, void_type_node, fd.v, fd.v);
4294 append_to_statement_list (t, body_p);
4296 /* After the loop, add exit clauses. */
4297 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4298 append_to_statement_list (dlist, body_p);
4300 maybe_catch_exception (body_p);
4302 /* Region exit marker goes at the end of the loop body. */
4303 t = make_node (OMP_RETURN);
4304 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4305 append_to_statement_list (t, body_p);
4307 pop_gimplify_context (NULL_TREE);
4308 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4310 OMP_FOR_BODY (stmt) = NULL_TREE;
4311 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4312 *stmt_p = new_stmt;
4315 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
4316 or OMP_PARALLEL. */
4318 static tree
4319 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4321 struct walk_stmt_info *wi = data;
4322 int *info = wi->info;
4324 *walk_subtrees = 0;
4325 switch (TREE_CODE (*tp))
4327 case OMP_FOR:
4328 case OMP_SECTIONS:
4329 *info = *info == 0 ? 1 : -1;
4330 break;
4331 default:
4332 *info = -1;
4333 break;
4335 return NULL;
4338 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4339 information for the directive. */
4341 static void
4342 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4344 tree clauses, par_bind, par_body, new_body, bind;
4345 tree olist, ilist, par_olist, par_ilist;
4346 tree stmt, child_fn, t;
4348 stmt = *stmt_p;
4350 clauses = OMP_PARALLEL_CLAUSES (stmt);
4351 par_bind = OMP_PARALLEL_BODY (stmt);
4352 par_body = BIND_EXPR_BODY (par_bind);
4353 child_fn = ctx->cb.dst_fn;
4354 if (!OMP_PARALLEL_COMBINED (stmt))
4356 struct walk_stmt_info wi;
4357 int ws_num = 0;
4359 memset (&wi, 0, sizeof (wi));
4360 wi.callback = check_combined_parallel;
4361 wi.info = &ws_num;
4362 wi.val_only = true;
4363 walk_stmts (&wi, &par_bind);
4364 if (ws_num == 1)
4365 OMP_PARALLEL_COMBINED (stmt) = 1;
4368 push_gimplify_context ();
4370 par_olist = NULL_TREE;
4371 par_ilist = NULL_TREE;
4372 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4373 lower_omp (&par_body, ctx);
4374 lower_reduction_clauses (clauses, &par_olist, ctx);
4376 /* Declare all the variables created by mapping and the variables
4377 declared in the scope of the parallel body. */
4378 record_vars_into (ctx->block_vars, child_fn);
4379 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4381 if (ctx->record_type)
4383 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4384 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4387 olist = NULL_TREE;
4388 ilist = NULL_TREE;
4389 lower_send_clauses (clauses, &ilist, &olist, ctx);
4390 lower_send_shared_vars (&ilist, &olist, ctx);
4392 /* Once all the expansions are done, sequence all the different
4393 fragments inside OMP_PARALLEL_BODY. */
4394 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4395 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4397 new_body = alloc_stmt_list ();
4399 if (ctx->record_type)
4401 t = build_fold_addr_expr (ctx->sender_decl);
4402 /* fixup_child_record_type might have changed receiver_decl's type. */
4403 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4404 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4405 append_to_statement_list (t, &new_body);
4408 append_to_statement_list (par_ilist, &new_body);
4409 append_to_statement_list (par_body, &new_body);
4410 append_to_statement_list (par_olist, &new_body);
4411 maybe_catch_exception (&new_body);
4412 t = make_node (OMP_RETURN);
4413 append_to_statement_list (t, &new_body);
4414 OMP_PARALLEL_BODY (stmt) = new_body;
4416 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4417 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4419 *stmt_p = bind;
4421 pop_gimplify_context (NULL_TREE);
4425 /* Pass *TP back through the gimplifier within the context determined by WI.
4426 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4427 flags on ADDR_EXPR. */
4429 static void
4430 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4432 enum gimplify_status gs;
4433 tree pre = NULL;
4435 if (wi->is_lhs)
4436 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4437 else if (wi->val_only)
4438 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4439 else
4440 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4441 gcc_assert (gs == GS_ALL_DONE);
4443 if (pre)
4444 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4447 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4449 static tree
4450 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4452 tree t, stmt;
4454 t = create_tmp_var (TREE_TYPE (exp), NULL);
4455 DECL_GIMPLE_REG_P (t) = 1;
4456 stmt = build_gimple_modify_stmt (t, exp);
4457 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4458 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4460 return t;
4463 /* Similarly, but copy from the temporary and insert the statement
4464 after the iterator. */
4466 static tree
4467 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4469 tree t, stmt;
4471 t = create_tmp_var (TREE_TYPE (exp), NULL);
4472 DECL_GIMPLE_REG_P (t) = 1;
4473 stmt = build_gimple_modify_stmt (exp, t);
4474 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4475 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4477 return t;
4480 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4482 static tree
4483 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4485 struct walk_stmt_info *wi = data;
4486 omp_context *ctx = wi->info;
4487 tree t = *tp;
4489 /* If we have issued syntax errors, avoid doing any heavy lifting.
4490 Just replace the OpenMP directives with a NOP to avoid
4491 confusing RTL expansion. */
4492 if (errorcount && OMP_DIRECTIVE_P (*tp))
4494 *tp = build_empty_stmt ();
4495 return NULL_TREE;
4498 *walk_subtrees = 0;
4499 switch (TREE_CODE (*tp))
4501 case OMP_PARALLEL:
4502 ctx = maybe_lookup_ctx (t);
4503 lower_omp_parallel (tp, ctx);
4504 break;
4506 case OMP_FOR:
4507 ctx = maybe_lookup_ctx (t);
4508 gcc_assert (ctx);
4509 lower_omp_for (tp, ctx);
4510 break;
4512 case OMP_SECTIONS:
4513 ctx = maybe_lookup_ctx (t);
4514 gcc_assert (ctx);
4515 lower_omp_sections (tp, ctx);
4516 break;
4518 case OMP_SINGLE:
4519 ctx = maybe_lookup_ctx (t);
4520 gcc_assert (ctx);
4521 lower_omp_single (tp, ctx);
4522 break;
4524 case OMP_MASTER:
4525 ctx = maybe_lookup_ctx (t);
4526 gcc_assert (ctx);
4527 lower_omp_master (tp, ctx);
4528 break;
4530 case OMP_ORDERED:
4531 ctx = maybe_lookup_ctx (t);
4532 gcc_assert (ctx);
4533 lower_omp_ordered (tp, ctx);
4534 break;
4536 case OMP_CRITICAL:
4537 ctx = maybe_lookup_ctx (t);
4538 gcc_assert (ctx);
4539 lower_omp_critical (tp, ctx);
4540 break;
4542 case VAR_DECL:
4543 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4545 lower_regimplify (&t, wi);
4546 if (wi->val_only)
4548 if (wi->is_lhs)
4549 t = save_tmp_var (t, &wi->tsi);
4550 else
4551 t = init_tmp_var (t, &wi->tsi);
4553 *tp = t;
4555 break;
4557 case ADDR_EXPR:
4558 if (ctx)
4559 lower_regimplify (tp, wi);
4560 break;
4562 case ARRAY_REF:
4563 case ARRAY_RANGE_REF:
4564 case REALPART_EXPR:
4565 case IMAGPART_EXPR:
4566 case COMPONENT_REF:
4567 case VIEW_CONVERT_EXPR:
4568 if (ctx)
4569 lower_regimplify (tp, wi);
4570 break;
4572 case INDIRECT_REF:
4573 if (ctx)
4575 wi->is_lhs = false;
4576 wi->val_only = true;
4577 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4579 break;
4581 default:
4582 if (!TYPE_P (t) && !DECL_P (t))
4583 *walk_subtrees = 1;
4584 break;
4587 return NULL_TREE;
4590 static void
4591 lower_omp (tree *stmt_p, omp_context *ctx)
4593 struct walk_stmt_info wi;
4595 memset (&wi, 0, sizeof (wi));
4596 wi.callback = lower_omp_1;
4597 wi.info = ctx;
4598 wi.val_only = true;
4599 wi.want_locations = true;
4601 walk_stmts (&wi, stmt_p);
4604 /* Main entry point. */
4606 static unsigned int
4607 execute_lower_omp (void)
4609 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4610 delete_omp_context);
4612 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4613 gcc_assert (parallel_nesting_level == 0);
4615 if (all_contexts->root)
4616 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4618 if (all_contexts)
4620 splay_tree_delete (all_contexts);
4621 all_contexts = NULL;
4623 return 0;
4626 static bool
4627 gate_lower_omp (void)
4629 return flag_openmp != 0;
4632 struct tree_opt_pass pass_lower_omp =
4634 "omplower", /* name */
4635 gate_lower_omp, /* gate */
4636 execute_lower_omp, /* execute */
4637 NULL, /* sub */
4638 NULL, /* next */
4639 0, /* static_pass_number */
4640 0, /* tv_id */
4641 PROP_gimple_any, /* properties_required */
4642 PROP_gimple_lomp, /* properties_provided */
4643 0, /* properties_destroyed */
4644 0, /* todo_flags_start */
4645 TODO_dump_func, /* todo_flags_finish */
4646 0 /* letter */
4649 /* The following is a utility to diagnose OpenMP structured block violations.
4650 It is not part of the "omplower" pass, as that's invoked too late. It
4651 should be invoked by the respective front ends after gimplification. */
4653 static splay_tree all_labels;
4655 /* Check for mismatched contexts and generate an error if needed. Return
4656 true if an error is detected. */
4658 static bool
4659 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4661 bool exit_p = true;
4663 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4664 return false;
4666 /* Try to avoid confusing the user by producing and error message
4667 with correct "exit" or "enter" verbage. We prefer "exit"
4668 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4669 if (branch_ctx == NULL)
4670 exit_p = false;
4671 else
4673 while (label_ctx)
4675 if (TREE_VALUE (label_ctx) == branch_ctx)
4677 exit_p = false;
4678 break;
4680 label_ctx = TREE_CHAIN (label_ctx);
4684 if (exit_p)
4685 error ("invalid exit from OpenMP structured block");
4686 else
4687 error ("invalid entry to OpenMP structured block");
4689 *stmt_p = build_empty_stmt ();
4690 return true;
4693 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4694 where in the tree each label is found. */
4696 static tree
4697 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4699 struct walk_stmt_info *wi = data;
4700 tree context = (tree) wi->info;
4701 tree inner_context;
4702 tree t = *tp;
4704 *walk_subtrees = 0;
4705 switch (TREE_CODE (t))
4707 case OMP_PARALLEL:
4708 case OMP_SECTIONS:
4709 case OMP_SINGLE:
4710 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4711 /* FALLTHRU */
4712 case OMP_SECTION:
4713 case OMP_MASTER:
4714 case OMP_ORDERED:
4715 case OMP_CRITICAL:
4716 /* The minimal context here is just a tree of statements. */
4717 inner_context = tree_cons (NULL, t, context);
4718 wi->info = inner_context;
4719 walk_stmts (wi, &OMP_BODY (t));
4720 wi->info = context;
4721 break;
4723 case OMP_FOR:
4724 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4725 inner_context = tree_cons (NULL, t, context);
4726 wi->info = inner_context;
4727 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4728 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4729 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4730 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4731 walk_stmts (wi, &OMP_FOR_BODY (t));
4732 wi->info = context;
4733 break;
4735 case LABEL_EXPR:
4736 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4737 (splay_tree_value) context);
4738 break;
4740 default:
4741 break;
4744 return NULL_TREE;
4747 /* Pass 2: Check each branch and see if its context differs from that of
4748 the destination label's context. */
4750 static tree
4751 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4753 struct walk_stmt_info *wi = data;
4754 tree context = (tree) wi->info;
4755 splay_tree_node n;
4756 tree t = *tp;
4758 *walk_subtrees = 0;
4759 switch (TREE_CODE (t))
4761 case OMP_PARALLEL:
4762 case OMP_SECTIONS:
4763 case OMP_SINGLE:
4764 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4765 /* FALLTHRU */
4766 case OMP_SECTION:
4767 case OMP_MASTER:
4768 case OMP_ORDERED:
4769 case OMP_CRITICAL:
4770 wi->info = t;
4771 walk_stmts (wi, &OMP_BODY (t));
4772 wi->info = context;
4773 break;
4775 case OMP_FOR:
4776 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4777 wi->info = t;
4778 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4779 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4780 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4781 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4782 walk_stmts (wi, &OMP_FOR_BODY (t));
4783 wi->info = context;
4784 break;
4786 case GOTO_EXPR:
4788 tree lab = GOTO_DESTINATION (t);
4789 if (TREE_CODE (lab) != LABEL_DECL)
4790 break;
4792 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4793 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4795 break;
4797 case SWITCH_EXPR:
4799 tree vec = SWITCH_LABELS (t);
4800 int i, len = TREE_VEC_LENGTH (vec);
4801 for (i = 0; i < len; ++i)
4803 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4804 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4805 if (diagnose_sb_0 (tp, context, (tree) n->value))
4806 break;
4809 break;
4811 case RETURN_EXPR:
4812 diagnose_sb_0 (tp, context, NULL_TREE);
4813 break;
4815 default:
4816 break;
4819 return NULL_TREE;
4822 void
4823 diagnose_omp_structured_block_errors (tree fndecl)
4825 tree save_current = current_function_decl;
4826 struct walk_stmt_info wi;
4828 current_function_decl = fndecl;
4830 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4832 memset (&wi, 0, sizeof (wi));
4833 wi.callback = diagnose_sb_1;
4834 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4836 memset (&wi, 0, sizeof (wi));
4837 wi.callback = diagnose_sb_2;
4838 wi.want_locations = true;
4839 wi.want_return_expr = true;
4840 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4842 splay_tree_delete (all_labels);
4843 all_labels = NULL;
4845 current_function_decl = save_current;
4848 #include "gt-omp-low.h"