Daily bump.
[official-gcc.git] / gcc / omp-low.c
blob45602c24d748b704e04404cae2f536c40c709213
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, 2008 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"
44 #include "optabs.h"
45 #include "cfgloop.h"
47 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
48 phases. The first phase scans the function looking for OMP statements
49 and then for variables that must be replaced to satisfy data sharing
50 clauses. The second phase expands code for the constructs, as well as
51 re-gimplifying things when variables have been replaced with complex
52 expressions.
54 Final code generation is done by pass_expand_omp. The flowgraph is
55 scanned for parallel regions which are then moved to a new
56 function, to be invoked by the thread library. */
58 /* Context structure. Used to store information about each parallel
59 directive in the code. */
61 typedef struct omp_context
63 /* This field must be at the beginning, as we do "inheritance": Some
64 callback functions for tree-inline.c (e.g., omp_copy_decl)
65 receive a copy_body_data pointer that is up-casted to an
66 omp_context pointer. */
67 copy_body_data cb;
69 /* The tree of contexts corresponding to the encountered constructs. */
70 struct omp_context *outer;
71 tree stmt;
73 /* Map variables to fields in a structure that allows communication
74 between sending and receiving threads. */
75 splay_tree field_map;
76 tree record_type;
77 tree sender_decl;
78 tree receiver_decl;
80 /* A chain of variables to add to the top-level block surrounding the
81 construct. In the case of a parallel, this is in the child function. */
82 tree block_vars;
84 /* What to do with variables with implicitly determined sharing
85 attributes. */
86 enum omp_clause_default_kind default_kind;
88 /* Nesting depth of this context. Used to beautify error messages re
89 invalid gotos. The outermost ctx is depth 1, with depth 0 being
90 reserved for the main body of the function. */
91 int depth;
93 /* True if this parallel directive is nested within another. */
94 bool is_nested;
95 } omp_context;
98 /* A structure describing the main elements of a parallel loop. */
100 struct omp_for_data
102 tree v, n1, n2, step, chunk_size, for_stmt;
103 enum tree_code cond_code;
104 tree pre;
105 bool have_nowait, have_ordered;
106 enum omp_clause_schedule_kind sched_kind;
110 static splay_tree all_contexts;
111 static int parallel_nesting_level;
112 struct omp_region *root_omp_region;
114 static void scan_omp (tree *, omp_context *);
115 static void lower_omp (tree *, omp_context *);
116 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
117 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
119 /* Find an OpenMP clause of type KIND within CLAUSES. */
121 tree
122 find_omp_clause (tree clauses, enum tree_code kind)
124 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
125 if (OMP_CLAUSE_CODE (clauses) == kind)
126 return clauses;
128 return NULL_TREE;
131 /* Return true if CTX is for an omp parallel. */
133 static inline bool
134 is_parallel_ctx (omp_context *ctx)
136 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
140 /* Return true if REGION is a combined parallel+workshare region. */
142 static inline bool
143 is_combined_parallel (struct omp_region *region)
145 return region->is_combined_parallel;
149 /* Extract the header elements of parallel loop FOR_STMT and store
150 them into *FD. */
152 static void
153 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
155 tree t, var;
157 fd->for_stmt = for_stmt;
158 fd->pre = NULL;
160 t = OMP_FOR_INIT (for_stmt);
161 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
162 fd->v = GIMPLE_STMT_OPERAND (t, 0);
163 gcc_assert (SSA_VAR_P (fd->v));
164 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
165 var = TREE_CODE (fd->v) == SSA_NAME ? SSA_NAME_VAR (fd->v) : fd->v;
166 fd->n1 = GIMPLE_STMT_OPERAND (t, 1);
168 t = OMP_FOR_COND (for_stmt);
169 fd->cond_code = TREE_CODE (t);
170 gcc_assert (TREE_OPERAND (t, 0) == var);
171 fd->n2 = TREE_OPERAND (t, 1);
172 switch (fd->cond_code)
174 case LT_EXPR:
175 case GT_EXPR:
176 break;
177 case LE_EXPR:
178 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
179 build_int_cst (TREE_TYPE (fd->n2), 1));
180 fd->cond_code = LT_EXPR;
181 break;
182 case GE_EXPR:
183 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
184 build_int_cst (TREE_TYPE (fd->n2), 1));
185 fd->cond_code = GT_EXPR;
186 break;
187 default:
188 gcc_unreachable ();
191 t = OMP_FOR_INCR (fd->for_stmt);
192 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
193 gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == var);
194 t = GIMPLE_STMT_OPERAND (t, 1);
195 gcc_assert (TREE_OPERAND (t, 0) == var);
196 switch (TREE_CODE (t))
198 case PLUS_EXPR:
199 fd->step = TREE_OPERAND (t, 1);
200 break;
201 case MINUS_EXPR:
202 fd->step = TREE_OPERAND (t, 1);
203 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
204 break;
205 default:
206 gcc_unreachable ();
209 fd->have_nowait = fd->have_ordered = false;
210 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
211 fd->chunk_size = NULL_TREE;
213 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
214 switch (OMP_CLAUSE_CODE (t))
216 case OMP_CLAUSE_NOWAIT:
217 fd->have_nowait = true;
218 break;
219 case OMP_CLAUSE_ORDERED:
220 fd->have_ordered = true;
221 break;
222 case OMP_CLAUSE_SCHEDULE:
223 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
224 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
225 break;
226 default:
227 break;
230 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
231 gcc_assert (fd->chunk_size == NULL);
232 else if (fd->chunk_size == NULL)
234 /* We only need to compute a default chunk size for ordered
235 static loops and dynamic loops. */
236 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
237 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
238 ? integer_zero_node : integer_one_node;
243 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
244 is the immediate dominator of PAR_ENTRY_BB, return true if there
245 are no data dependencies that would prevent expanding the parallel
246 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
248 When expanding a combined parallel+workshare region, the call to
249 the child function may need additional arguments in the case of
250 OMP_FOR regions. In some cases, these arguments are computed out
251 of variables passed in from the parent to the child via 'struct
252 .omp_data_s'. For instance:
254 #pragma omp parallel for schedule (guided, i * 4)
255 for (j ...)
257 Is lowered into:
259 # BLOCK 2 (PAR_ENTRY_BB)
260 .omp_data_o.i = i;
261 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
263 # BLOCK 3 (WS_ENTRY_BB)
264 .omp_data_i = &.omp_data_o;
265 D.1667 = .omp_data_i->i;
266 D.1598 = D.1667 * 4;
267 #pragma omp for schedule (guided, D.1598)
269 When we outline the parallel region, the call to the child function
270 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
271 that value is computed *after* the call site. So, in principle we
272 cannot do the transformation.
274 To see whether the code in WS_ENTRY_BB blocks the combined
275 parallel+workshare call, we collect all the variables used in the
276 OMP_FOR header check whether they appear on the LHS of any
277 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
278 call.
280 FIXME. If we had the SSA form built at this point, we could merely
281 hoist the code in block 3 into block 2 and be done with it. But at
282 this point we don't have dataflow information and though we could
283 hack something up here, it is really not worth the aggravation. */
285 static bool
286 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
288 struct omp_for_data fd;
289 tree par_stmt, ws_stmt;
291 par_stmt = last_stmt (par_entry_bb);
292 ws_stmt = last_stmt (ws_entry_bb);
294 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
295 return true;
297 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
299 extract_omp_for_data (ws_stmt, &fd);
301 /* FIXME. We give up too easily here. If any of these arguments
302 are not constants, they will likely involve variables that have
303 been mapped into fields of .omp_data_s for sharing with the child
304 function. With appropriate data flow, it would be possible to
305 see through this. */
306 if (!is_gimple_min_invariant (fd.n1)
307 || !is_gimple_min_invariant (fd.n2)
308 || !is_gimple_min_invariant (fd.step)
309 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
310 return false;
312 return true;
316 /* Collect additional arguments needed to emit a combined
317 parallel+workshare call. WS_STMT is the workshare directive being
318 expanded. */
320 static tree
321 get_ws_args_for (tree ws_stmt)
323 tree t;
325 if (TREE_CODE (ws_stmt) == OMP_FOR)
327 struct omp_for_data fd;
328 tree ws_args;
330 extract_omp_for_data (ws_stmt, &fd);
332 ws_args = NULL_TREE;
333 if (fd.chunk_size)
335 t = fold_convert (long_integer_type_node, fd.chunk_size);
336 ws_args = tree_cons (NULL, t, ws_args);
339 t = fold_convert (long_integer_type_node, fd.step);
340 ws_args = tree_cons (NULL, t, ws_args);
342 t = fold_convert (long_integer_type_node, fd.n2);
343 ws_args = tree_cons (NULL, t, ws_args);
345 t = fold_convert (long_integer_type_node, fd.n1);
346 ws_args = tree_cons (NULL, t, ws_args);
348 return ws_args;
350 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
352 /* Number of sections is equal to the number of edges from the
353 OMP_SECTIONS_SWITCH statement, except for the one to the exit
354 of the sections region. */
355 basic_block bb = single_succ (bb_for_stmt (ws_stmt));
356 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
357 t = tree_cons (NULL, t, NULL);
358 return t;
361 gcc_unreachable ();
365 /* Discover whether REGION is a combined parallel+workshare region. */
367 static void
368 determine_parallel_type (struct omp_region *region)
370 basic_block par_entry_bb, par_exit_bb;
371 basic_block ws_entry_bb, ws_exit_bb;
373 if (region == NULL || region->inner == NULL
374 || region->exit == NULL || region->inner->exit == NULL
375 || region->inner->cont == NULL)
376 return;
378 /* We only support parallel+for and parallel+sections. */
379 if (region->type != OMP_PARALLEL
380 || (region->inner->type != OMP_FOR
381 && region->inner->type != OMP_SECTIONS))
382 return;
384 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
385 WS_EXIT_BB -> PAR_EXIT_BB. */
386 par_entry_bb = region->entry;
387 par_exit_bb = region->exit;
388 ws_entry_bb = region->inner->entry;
389 ws_exit_bb = region->inner->exit;
391 if (single_succ (par_entry_bb) == ws_entry_bb
392 && single_succ (ws_exit_bb) == par_exit_bb
393 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
394 && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
395 || (last_and_only_stmt (ws_entry_bb)
396 && last_and_only_stmt (par_exit_bb))))
398 tree ws_stmt = last_stmt (ws_entry_bb);
400 if (region->inner->type == OMP_FOR)
402 /* If this is a combined parallel loop, we need to determine
403 whether or not to use the combined library calls. There
404 are two cases where we do not apply the transformation:
405 static loops and any kind of ordered loop. In the first
406 case, we already open code the loop so there is no need
407 to do anything else. In the latter case, the combined
408 parallel loop call would still need extra synchronization
409 to implement ordered semantics, so there would not be any
410 gain in using the combined call. */
411 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
412 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
413 if (c == NULL
414 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
415 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
417 region->is_combined_parallel = false;
418 region->inner->is_combined_parallel = false;
419 return;
423 region->is_combined_parallel = true;
424 region->inner->is_combined_parallel = true;
425 region->ws_args = get_ws_args_for (ws_stmt);
430 /* Return true if EXPR is variable sized. */
432 static inline bool
433 is_variable_sized (const_tree expr)
435 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
438 /* Return true if DECL is a reference type. */
440 static inline bool
441 is_reference (tree decl)
443 return lang_hooks.decls.omp_privatize_by_reference (decl);
446 /* Lookup variables in the decl or field splay trees. The "maybe" form
447 allows for the variable form to not have been entered, otherwise we
448 assert that the variable must have been entered. */
450 static inline tree
451 lookup_decl (tree var, omp_context *ctx)
453 tree *n;
454 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
455 return *n;
458 static inline tree
459 maybe_lookup_decl (const_tree var, omp_context *ctx)
461 tree *n;
462 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
463 return n ? *n : NULL_TREE;
466 static inline tree
467 lookup_field (tree var, omp_context *ctx)
469 splay_tree_node n;
470 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
471 return (tree) n->value;
474 static inline tree
475 maybe_lookup_field (tree var, omp_context *ctx)
477 splay_tree_node n;
478 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
479 return n ? (tree) n->value : NULL_TREE;
482 /* Return true if DECL should be copied by pointer. SHARED_CTX is
483 the parallel context if DECL is to be shared. */
485 static bool
486 use_pointer_for_field (const_tree decl, omp_context *shared_ctx)
488 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
489 return true;
491 /* We can only use copy-in/copy-out semantics for shared variables
492 when we know the value is not accessible from an outer scope. */
493 if (shared_ctx)
495 /* ??? Trivially accessible from anywhere. But why would we even
496 be passing an address in this case? Should we simply assert
497 this to be false, or should we have a cleanup pass that removes
498 these from the list of mappings? */
499 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
500 return true;
502 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
503 without analyzing the expression whether or not its location
504 is accessible to anyone else. In the case of nested parallel
505 regions it certainly may be. */
506 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
507 return true;
509 /* Do not use copy-in/copy-out for variables that have their
510 address taken. */
511 if (TREE_ADDRESSABLE (decl))
512 return true;
514 /* Disallow copy-in/out in nested parallel if
515 decl is shared in outer parallel, otherwise
516 each thread could store the shared variable
517 in its own copy-in location, making the
518 variable no longer really shared. */
519 if (!TREE_READONLY (decl) && shared_ctx->is_nested)
521 omp_context *up;
523 for (up = shared_ctx->outer; up; up = up->outer)
524 if (maybe_lookup_decl (decl, up))
525 break;
527 if (up && is_parallel_ctx (up))
529 tree c;
531 for (c = OMP_PARALLEL_CLAUSES (up->stmt);
532 c; c = OMP_CLAUSE_CHAIN (c))
533 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
534 && OMP_CLAUSE_DECL (c) == decl)
535 break;
537 if (c)
538 return true;
543 return false;
546 /* Create a new VAR_DECL and copy information from VAR to it. */
548 tree
549 copy_var_decl (tree var, tree name, tree type)
551 tree copy = build_decl (VAR_DECL, name, type);
553 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
554 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
555 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
556 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
557 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
558 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
559 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
560 DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (var);
561 TREE_USED (copy) = 1;
562 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
564 return copy;
567 /* Construct a new automatic decl similar to VAR. */
569 static tree
570 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
572 tree copy = copy_var_decl (var, name, type);
574 DECL_CONTEXT (copy) = current_function_decl;
575 TREE_CHAIN (copy) = ctx->block_vars;
576 ctx->block_vars = copy;
578 return copy;
581 static tree
582 omp_copy_decl_1 (tree var, omp_context *ctx)
584 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
587 /* Build tree nodes to access the field for VAR on the receiver side. */
589 static tree
590 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
592 tree x, field = lookup_field (var, ctx);
594 /* If the receiver record type was remapped in the child function,
595 remap the field into the new record type. */
596 x = maybe_lookup_field (field, ctx);
597 if (x != NULL)
598 field = x;
600 x = build_fold_indirect_ref (ctx->receiver_decl);
601 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
602 if (by_ref)
603 x = build_fold_indirect_ref (x);
605 return x;
608 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
609 of a parallel, this is a component reference; for workshare constructs
610 this is some variable. */
612 static tree
613 build_outer_var_ref (tree var, omp_context *ctx)
615 tree x;
617 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
618 x = var;
619 else if (is_variable_sized (var))
621 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
622 x = build_outer_var_ref (x, ctx);
623 x = build_fold_indirect_ref (x);
625 else if (is_parallel_ctx (ctx))
627 bool by_ref = use_pointer_for_field (var, NULL);
628 x = build_receiver_ref (var, by_ref, ctx);
630 else if (ctx->outer)
631 x = lookup_decl (var, ctx->outer);
632 else if (is_reference (var))
633 /* This can happen with orphaned constructs. If var is reference, it is
634 possible it is shared and as such valid. */
635 x = var;
636 else
637 gcc_unreachable ();
639 if (is_reference (var))
640 x = build_fold_indirect_ref (x);
642 return x;
645 /* Build tree nodes to access the field for VAR on the sender side. */
647 static tree
648 build_sender_ref (tree var, omp_context *ctx)
650 tree field = lookup_field (var, ctx);
651 return build3 (COMPONENT_REF, TREE_TYPE (field),
652 ctx->sender_decl, field, NULL);
655 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
657 static void
658 install_var_field (tree var, bool by_ref, omp_context *ctx)
660 tree field, type;
662 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
664 type = TREE_TYPE (var);
665 if (by_ref)
666 type = build_pointer_type (type);
668 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
670 /* Remember what variable this field was created for. This does have a
671 side effect of making dwarf2out ignore this member, so for helpful
672 debugging we clear it later in delete_omp_context. */
673 DECL_ABSTRACT_ORIGIN (field) = var;
675 insert_field_into_struct (ctx->record_type, field);
677 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
678 (splay_tree_value) field);
681 static tree
682 install_var_local (tree var, omp_context *ctx)
684 tree new_var = omp_copy_decl_1 (var, ctx);
685 insert_decl_map (&ctx->cb, var, new_var);
686 return new_var;
689 /* Adjust the replacement for DECL in CTX for the new context. This means
690 copying the DECL_VALUE_EXPR, and fixing up the type. */
692 static void
693 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
695 tree new_decl, size;
697 new_decl = lookup_decl (decl, ctx);
699 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
701 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
702 && DECL_HAS_VALUE_EXPR_P (decl))
704 tree ve = DECL_VALUE_EXPR (decl);
705 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
706 SET_DECL_VALUE_EXPR (new_decl, ve);
707 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
710 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
712 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
713 if (size == error_mark_node)
714 size = TYPE_SIZE (TREE_TYPE (new_decl));
715 DECL_SIZE (new_decl) = size;
717 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
718 if (size == error_mark_node)
719 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
720 DECL_SIZE_UNIT (new_decl) = size;
724 /* The callback for remap_decl. Search all containing contexts for a
725 mapping of the variable; this avoids having to duplicate the splay
726 tree ahead of time. We know a mapping doesn't already exist in the
727 given context. Create new mappings to implement default semantics. */
729 static tree
730 omp_copy_decl (tree var, copy_body_data *cb)
732 omp_context *ctx = (omp_context *) cb;
733 tree new_var;
735 if (TREE_CODE (var) == LABEL_DECL)
737 new_var = create_artificial_label ();
738 DECL_CONTEXT (new_var) = current_function_decl;
739 insert_decl_map (&ctx->cb, var, new_var);
740 return new_var;
743 while (!is_parallel_ctx (ctx))
745 ctx = ctx->outer;
746 if (ctx == NULL)
747 return var;
748 new_var = maybe_lookup_decl (var, ctx);
749 if (new_var)
750 return new_var;
753 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
754 return var;
756 return error_mark_node;
760 /* Return the parallel region associated with STMT. */
762 /* Debugging dumps for parallel regions. */
763 void dump_omp_region (FILE *, struct omp_region *, int);
764 void debug_omp_region (struct omp_region *);
765 void debug_all_omp_regions (void);
767 /* Dump the parallel region tree rooted at REGION. */
769 void
770 dump_omp_region (FILE *file, struct omp_region *region, int indent)
772 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
773 tree_code_name[region->type]);
775 if (region->inner)
776 dump_omp_region (file, region->inner, indent + 4);
778 if (region->cont)
780 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
781 region->cont->index);
784 if (region->exit)
785 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
786 region->exit->index);
787 else
788 fprintf (file, "%*s[no exit marker]\n", indent, "");
790 if (region->next)
791 dump_omp_region (file, region->next, indent);
794 void
795 debug_omp_region (struct omp_region *region)
797 dump_omp_region (stderr, region, 0);
800 void
801 debug_all_omp_regions (void)
803 dump_omp_region (stderr, root_omp_region, 0);
807 /* Create a new parallel region starting at STMT inside region PARENT. */
809 struct omp_region *
810 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
812 struct omp_region *region = xcalloc (1, sizeof (*region));
814 region->outer = parent;
815 region->entry = bb;
816 region->type = type;
818 if (parent)
820 /* This is a nested region. Add it to the list of inner
821 regions in PARENT. */
822 region->next = parent->inner;
823 parent->inner = region;
825 else
827 /* This is a toplevel region. Add it to the list of toplevel
828 regions in ROOT_OMP_REGION. */
829 region->next = root_omp_region;
830 root_omp_region = region;
833 return region;
836 /* Release the memory associated with the region tree rooted at REGION. */
838 static void
839 free_omp_region_1 (struct omp_region *region)
841 struct omp_region *i, *n;
843 for (i = region->inner; i ; i = n)
845 n = i->next;
846 free_omp_region_1 (i);
849 free (region);
852 /* Release the memory for the entire omp region tree. */
854 void
855 free_omp_regions (void)
857 struct omp_region *r, *n;
858 for (r = root_omp_region; r ; r = n)
860 n = r->next;
861 free_omp_region_1 (r);
863 root_omp_region = NULL;
867 /* Create a new context, with OUTER_CTX being the surrounding context. */
869 static omp_context *
870 new_omp_context (tree stmt, omp_context *outer_ctx)
872 omp_context *ctx = XCNEW (omp_context);
874 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
875 (splay_tree_value) ctx);
876 ctx->stmt = stmt;
878 if (outer_ctx)
880 ctx->outer = outer_ctx;
881 ctx->cb = outer_ctx->cb;
882 ctx->cb.block = NULL;
883 ctx->depth = outer_ctx->depth + 1;
885 else
887 ctx->cb.src_fn = current_function_decl;
888 ctx->cb.dst_fn = current_function_decl;
889 ctx->cb.src_node = cgraph_node (current_function_decl);
890 ctx->cb.dst_node = ctx->cb.src_node;
891 ctx->cb.src_cfun = cfun;
892 ctx->cb.copy_decl = omp_copy_decl;
893 ctx->cb.eh_region = -1;
894 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
895 ctx->depth = 1;
898 ctx->cb.decl_map = pointer_map_create ();
900 return ctx;
903 /* Destroy a omp_context data structures. Called through the splay tree
904 value delete callback. */
906 static void
907 delete_omp_context (splay_tree_value value)
909 omp_context *ctx = (omp_context *) value;
911 pointer_map_destroy (ctx->cb.decl_map);
913 if (ctx->field_map)
914 splay_tree_delete (ctx->field_map);
916 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
917 it produces corrupt debug information. */
918 if (ctx->record_type)
920 tree t;
921 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
922 DECL_ABSTRACT_ORIGIN (t) = NULL;
925 XDELETE (ctx);
928 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
929 context. */
931 static void
932 fixup_child_record_type (omp_context *ctx)
934 tree f, type = ctx->record_type;
936 /* ??? It isn't sufficient to just call remap_type here, because
937 variably_modified_type_p doesn't work the way we expect for
938 record types. Testing each field for whether it needs remapping
939 and creating a new record by hand works, however. */
940 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
941 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
942 break;
943 if (f)
945 tree name, new_fields = NULL;
947 type = lang_hooks.types.make_type (RECORD_TYPE);
948 name = DECL_NAME (TYPE_NAME (ctx->record_type));
949 name = build_decl (TYPE_DECL, name, type);
950 TYPE_NAME (type) = name;
952 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
954 tree new_f = copy_node (f);
955 DECL_CONTEXT (new_f) = type;
956 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
957 TREE_CHAIN (new_f) = new_fields;
958 new_fields = new_f;
960 /* Arrange to be able to look up the receiver field
961 given the sender field. */
962 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
963 (splay_tree_value) new_f);
965 TYPE_FIELDS (type) = nreverse (new_fields);
966 layout_type (type);
969 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
972 /* Instantiate decls as necessary in CTX to satisfy the data sharing
973 specified by CLAUSES. */
975 static void
976 scan_sharing_clauses (tree clauses, omp_context *ctx)
978 tree c, decl;
979 bool scan_array_reductions = false;
981 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
983 bool by_ref;
985 switch (OMP_CLAUSE_CODE (c))
987 case OMP_CLAUSE_PRIVATE:
988 decl = OMP_CLAUSE_DECL (c);
989 if (!is_variable_sized (decl))
990 install_var_local (decl, ctx);
991 break;
993 case OMP_CLAUSE_SHARED:
994 gcc_assert (is_parallel_ctx (ctx));
995 decl = OMP_CLAUSE_DECL (c);
996 gcc_assert (!is_variable_sized (decl));
997 by_ref = use_pointer_for_field (decl, ctx);
998 /* Global variables don't need to be copied,
999 the receiver side will use them directly. */
1000 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1001 break;
1002 if (! TREE_READONLY (decl)
1003 || TREE_ADDRESSABLE (decl)
1004 || by_ref
1005 || is_reference (decl))
1007 install_var_field (decl, by_ref, ctx);
1008 install_var_local (decl, ctx);
1009 break;
1011 /* We don't need to copy const scalar vars back. */
1012 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1013 goto do_private;
1015 case OMP_CLAUSE_LASTPRIVATE:
1016 /* Let the corresponding firstprivate clause create
1017 the variable. */
1018 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1019 break;
1020 /* FALLTHRU */
1022 case OMP_CLAUSE_FIRSTPRIVATE:
1023 case OMP_CLAUSE_REDUCTION:
1024 decl = OMP_CLAUSE_DECL (c);
1025 do_private:
1026 if (is_variable_sized (decl))
1027 break;
1028 else if (is_parallel_ctx (ctx)
1029 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
1030 ctx)))
1032 by_ref = use_pointer_for_field (decl, NULL);
1033 install_var_field (decl, by_ref, ctx);
1035 install_var_local (decl, ctx);
1036 break;
1038 case OMP_CLAUSE_COPYPRIVATE:
1039 if (ctx->outer)
1040 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
1041 /* FALLTHRU */
1043 case OMP_CLAUSE_COPYIN:
1044 decl = OMP_CLAUSE_DECL (c);
1045 by_ref = use_pointer_for_field (decl, NULL);
1046 install_var_field (decl, by_ref, ctx);
1047 break;
1049 case OMP_CLAUSE_DEFAULT:
1050 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1051 break;
1053 case OMP_CLAUSE_IF:
1054 case OMP_CLAUSE_NUM_THREADS:
1055 case OMP_CLAUSE_SCHEDULE:
1056 if (ctx->outer)
1057 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1058 break;
1060 case OMP_CLAUSE_NOWAIT:
1061 case OMP_CLAUSE_ORDERED:
1062 break;
1064 default:
1065 gcc_unreachable ();
1069 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1071 switch (OMP_CLAUSE_CODE (c))
1073 case OMP_CLAUSE_LASTPRIVATE:
1074 /* Let the corresponding firstprivate clause create
1075 the variable. */
1076 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1077 break;
1078 /* FALLTHRU */
1080 case OMP_CLAUSE_PRIVATE:
1081 case OMP_CLAUSE_FIRSTPRIVATE:
1082 case OMP_CLAUSE_REDUCTION:
1083 decl = OMP_CLAUSE_DECL (c);
1084 if (is_variable_sized (decl))
1085 install_var_local (decl, ctx);
1086 fixup_remapped_decl (decl, ctx,
1087 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1088 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1089 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1090 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1091 scan_array_reductions = true;
1092 break;
1094 case OMP_CLAUSE_SHARED:
1095 decl = OMP_CLAUSE_DECL (c);
1096 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1097 fixup_remapped_decl (decl, ctx, false);
1098 break;
1100 case OMP_CLAUSE_COPYPRIVATE:
1101 case OMP_CLAUSE_COPYIN:
1102 case OMP_CLAUSE_DEFAULT:
1103 case OMP_CLAUSE_IF:
1104 case OMP_CLAUSE_NUM_THREADS:
1105 case OMP_CLAUSE_SCHEDULE:
1106 case OMP_CLAUSE_NOWAIT:
1107 case OMP_CLAUSE_ORDERED:
1108 break;
1110 default:
1111 gcc_unreachable ();
1115 if (scan_array_reductions)
1116 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1117 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1118 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1120 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1121 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1125 /* Create a new name for omp child function. Returns an identifier. */
1127 static GTY(()) unsigned int tmp_ompfn_id_num;
1129 static tree
1130 create_omp_child_function_name (void)
1132 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1133 size_t len = IDENTIFIER_LENGTH (name);
1134 char *tmp_name, *prefix;
1136 prefix = alloca (len + sizeof ("_omp_fn"));
1137 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1138 strcpy (prefix + len, "_omp_fn");
1139 #ifndef NO_DOT_IN_LABEL
1140 prefix[len] = '.';
1141 #elif !defined NO_DOLLAR_IN_LABEL
1142 prefix[len] = '$';
1143 #endif
1144 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1145 return get_identifier (tmp_name);
1148 /* Build a decl for the omp child function. It'll not contain a body
1149 yet, just the bare decl. */
1151 static void
1152 create_omp_child_function (omp_context *ctx)
1154 tree decl, type, name, t;
1156 name = create_omp_child_function_name ();
1157 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1159 decl = build_decl (FUNCTION_DECL, name, type);
1160 decl = lang_hooks.decls.pushdecl (decl);
1162 ctx->cb.dst_fn = decl;
1164 TREE_STATIC (decl) = 1;
1165 TREE_USED (decl) = 1;
1166 DECL_ARTIFICIAL (decl) = 1;
1167 DECL_IGNORED_P (decl) = 0;
1168 TREE_PUBLIC (decl) = 0;
1169 DECL_UNINLINABLE (decl) = 1;
1170 DECL_EXTERNAL (decl) = 0;
1171 DECL_CONTEXT (decl) = NULL_TREE;
1172 DECL_INITIAL (decl) = make_node (BLOCK);
1174 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1175 DECL_ARTIFICIAL (t) = 1;
1176 DECL_IGNORED_P (t) = 1;
1177 DECL_RESULT (decl) = t;
1179 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1180 DECL_ARTIFICIAL (t) = 1;
1181 DECL_ARG_TYPE (t) = ptr_type_node;
1182 DECL_CONTEXT (t) = current_function_decl;
1183 TREE_USED (t) = 1;
1184 DECL_ARGUMENTS (decl) = t;
1185 ctx->receiver_decl = t;
1187 /* Allocate memory for the function structure. The call to
1188 allocate_struct_function clobbers CFUN, so we need to restore
1189 it afterward. */
1190 push_struct_function (decl);
1191 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1192 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1193 pop_cfun ();
1197 /* Scan an OpenMP parallel directive. */
1199 static void
1200 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1202 omp_context *ctx;
1203 tree name;
1205 /* Ignore parallel directives with empty bodies, unless there
1206 are copyin clauses. */
1207 if (optimize > 0
1208 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1209 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1211 *stmt_p = build_empty_stmt ();
1212 return;
1215 ctx = new_omp_context (*stmt_p, outer_ctx);
1216 if (parallel_nesting_level > 1)
1217 ctx->is_nested = true;
1218 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1219 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1220 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1221 name = create_tmp_var_name (".omp_data_s");
1222 name = build_decl (TYPE_DECL, name, ctx->record_type);
1223 TYPE_NAME (ctx->record_type) = name;
1224 create_omp_child_function (ctx);
1225 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1227 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1228 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1230 if (TYPE_FIELDS (ctx->record_type) == NULL)
1231 ctx->record_type = ctx->receiver_decl = NULL;
1232 else
1234 layout_type (ctx->record_type);
1235 fixup_child_record_type (ctx);
1240 /* Scan an OpenMP loop directive. */
1242 static void
1243 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1245 omp_context *ctx;
1246 tree stmt;
1248 stmt = *stmt_p;
1249 ctx = new_omp_context (stmt, outer_ctx);
1251 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1253 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1254 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1255 scan_omp (&OMP_FOR_COND (stmt), ctx);
1256 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1257 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1260 /* Scan an OpenMP sections directive. */
1262 static void
1263 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1265 tree stmt;
1266 omp_context *ctx;
1268 stmt = *stmt_p;
1269 ctx = new_omp_context (stmt, outer_ctx);
1270 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1271 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1274 /* Scan an OpenMP single directive. */
1276 static void
1277 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1279 tree stmt = *stmt_p;
1280 omp_context *ctx;
1281 tree name;
1283 ctx = new_omp_context (stmt, outer_ctx);
1284 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1285 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1286 name = create_tmp_var_name (".omp_copy_s");
1287 name = build_decl (TYPE_DECL, name, ctx->record_type);
1288 TYPE_NAME (ctx->record_type) = name;
1290 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1291 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1293 if (TYPE_FIELDS (ctx->record_type) == NULL)
1294 ctx->record_type = NULL;
1295 else
1296 layout_type (ctx->record_type);
1300 /* Check OpenMP nesting restrictions. */
1301 static void
1302 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1304 switch (TREE_CODE (t))
1306 case OMP_FOR:
1307 case OMP_SECTIONS:
1308 case OMP_SINGLE:
1309 for (; ctx != NULL; ctx = ctx->outer)
1310 switch (TREE_CODE (ctx->stmt))
1312 case OMP_FOR:
1313 case OMP_SECTIONS:
1314 case OMP_SINGLE:
1315 case OMP_ORDERED:
1316 case OMP_MASTER:
1317 warning (0, "work-sharing region may not be closely nested inside "
1318 "of work-sharing, critical, ordered or master region");
1319 return;
1320 case OMP_PARALLEL:
1321 return;
1322 default:
1323 break;
1325 break;
1326 case OMP_MASTER:
1327 for (; ctx != NULL; ctx = ctx->outer)
1328 switch (TREE_CODE (ctx->stmt))
1330 case OMP_FOR:
1331 case OMP_SECTIONS:
1332 case OMP_SINGLE:
1333 warning (0, "master region may not be closely nested inside "
1334 "of work-sharing region");
1335 return;
1336 case OMP_PARALLEL:
1337 return;
1338 default:
1339 break;
1341 break;
1342 case OMP_ORDERED:
1343 for (; ctx != NULL; ctx = ctx->outer)
1344 switch (TREE_CODE (ctx->stmt))
1346 case OMP_CRITICAL:
1347 warning (0, "ordered region may not be closely nested inside "
1348 "of critical region");
1349 return;
1350 case OMP_FOR:
1351 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1352 OMP_CLAUSE_ORDERED) == NULL)
1353 warning (0, "ordered region must be closely nested inside "
1354 "a loop region with an ordered clause");
1355 return;
1356 case OMP_PARALLEL:
1357 return;
1358 default:
1359 break;
1361 break;
1362 case OMP_CRITICAL:
1363 for (; ctx != NULL; ctx = ctx->outer)
1364 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1365 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1367 warning (0, "critical region may not be nested inside a critical "
1368 "region with the same name");
1369 return;
1371 break;
1372 default:
1373 break;
1378 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1380 static tree
1381 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1383 struct walk_stmt_info *wi = data;
1384 omp_context *ctx = wi->info;
1385 tree t = *tp;
1387 if (EXPR_HAS_LOCATION (t))
1388 input_location = EXPR_LOCATION (t);
1390 /* Check the OpenMP nesting restrictions. */
1391 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1392 check_omp_nesting_restrictions (t, ctx);
1394 *walk_subtrees = 0;
1395 switch (TREE_CODE (t))
1397 case OMP_PARALLEL:
1398 parallel_nesting_level++;
1399 scan_omp_parallel (tp, ctx);
1400 parallel_nesting_level--;
1401 break;
1403 case OMP_FOR:
1404 scan_omp_for (tp, ctx);
1405 break;
1407 case OMP_SECTIONS:
1408 scan_omp_sections (tp, ctx);
1409 break;
1411 case OMP_SINGLE:
1412 scan_omp_single (tp, ctx);
1413 break;
1415 case OMP_SECTION:
1416 case OMP_MASTER:
1417 case OMP_ORDERED:
1418 case OMP_CRITICAL:
1419 ctx = new_omp_context (*tp, ctx);
1420 scan_omp (&OMP_BODY (*tp), ctx);
1421 break;
1423 case BIND_EXPR:
1425 tree var;
1426 *walk_subtrees = 1;
1428 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1429 insert_decl_map (&ctx->cb, var, var);
1431 break;
1433 case VAR_DECL:
1434 case PARM_DECL:
1435 case LABEL_DECL:
1436 case RESULT_DECL:
1437 if (ctx)
1438 *tp = remap_decl (t, &ctx->cb);
1439 break;
1441 default:
1442 if (ctx && TYPE_P (t))
1443 *tp = remap_type (t, &ctx->cb);
1444 else if (!DECL_P (t))
1445 *walk_subtrees = 1;
1446 break;
1449 return NULL_TREE;
1453 /* Scan all the statements starting at STMT_P. CTX contains context
1454 information about the OpenMP directives and clauses found during
1455 the scan. */
1457 static void
1458 scan_omp (tree *stmt_p, omp_context *ctx)
1460 location_t saved_location;
1461 struct walk_stmt_info wi;
1463 memset (&wi, 0, sizeof (wi));
1464 wi.callback = scan_omp_1;
1465 wi.info = ctx;
1466 wi.want_bind_expr = (ctx != NULL);
1467 wi.want_locations = true;
1469 saved_location = input_location;
1470 walk_stmts (&wi, stmt_p);
1471 input_location = saved_location;
1474 /* Re-gimplification and code generation routines. */
1476 /* Build a call to GOMP_barrier. */
1478 static tree
1479 build_omp_barrier (void)
1481 return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1484 /* If a context was created for STMT when it was scanned, return it. */
1486 static omp_context *
1487 maybe_lookup_ctx (tree stmt)
1489 splay_tree_node n;
1490 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1491 return n ? (omp_context *) n->value : NULL;
1495 /* Find the mapping for DECL in CTX or the immediately enclosing
1496 context that has a mapping for DECL.
1498 If CTX is a nested parallel directive, we may have to use the decl
1499 mappings created in CTX's parent context. Suppose that we have the
1500 following parallel nesting (variable UIDs showed for clarity):
1502 iD.1562 = 0;
1503 #omp parallel shared(iD.1562) -> outer parallel
1504 iD.1562 = iD.1562 + 1;
1506 #omp parallel shared (iD.1562) -> inner parallel
1507 iD.1562 = iD.1562 - 1;
1509 Each parallel structure will create a distinct .omp_data_s structure
1510 for copying iD.1562 in/out of the directive:
1512 outer parallel .omp_data_s.1.i -> iD.1562
1513 inner parallel .omp_data_s.2.i -> iD.1562
1515 A shared variable mapping will produce a copy-out operation before
1516 the parallel directive and a copy-in operation after it. So, in
1517 this case we would have:
1519 iD.1562 = 0;
1520 .omp_data_o.1.i = iD.1562;
1521 #omp parallel shared(iD.1562) -> outer parallel
1522 .omp_data_i.1 = &.omp_data_o.1
1523 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1525 .omp_data_o.2.i = iD.1562; -> **
1526 #omp parallel shared(iD.1562) -> inner parallel
1527 .omp_data_i.2 = &.omp_data_o.2
1528 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1531 ** This is a problem. The symbol iD.1562 cannot be referenced
1532 inside the body of the outer parallel region. But since we are
1533 emitting this copy operation while expanding the inner parallel
1534 directive, we need to access the CTX structure of the outer
1535 parallel directive to get the correct mapping:
1537 .omp_data_o.2.i = .omp_data_i.1->i
1539 Since there may be other workshare or parallel directives enclosing
1540 the parallel directive, it may be necessary to walk up the context
1541 parent chain. This is not a problem in general because nested
1542 parallelism happens only rarely. */
1544 static tree
1545 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1547 tree t;
1548 omp_context *up;
1550 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1551 t = maybe_lookup_decl (decl, up);
1553 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
1555 return t ? t : decl;
1559 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1560 in outer contexts. */
1562 static tree
1563 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1565 tree t = NULL;
1566 omp_context *up;
1568 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1569 t = maybe_lookup_decl (decl, up);
1571 return t ? t : decl;
1575 /* Construct the initialization value for reduction CLAUSE. */
1577 tree
1578 omp_reduction_init (tree clause, tree type)
1580 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1582 case PLUS_EXPR:
1583 case MINUS_EXPR:
1584 case BIT_IOR_EXPR:
1585 case BIT_XOR_EXPR:
1586 case TRUTH_OR_EXPR:
1587 case TRUTH_ORIF_EXPR:
1588 case TRUTH_XOR_EXPR:
1589 case NE_EXPR:
1590 return fold_convert (type, integer_zero_node);
1592 case MULT_EXPR:
1593 case TRUTH_AND_EXPR:
1594 case TRUTH_ANDIF_EXPR:
1595 case EQ_EXPR:
1596 return fold_convert (type, integer_one_node);
1598 case BIT_AND_EXPR:
1599 return fold_convert (type, integer_minus_one_node);
1601 case MAX_EXPR:
1602 if (SCALAR_FLOAT_TYPE_P (type))
1604 REAL_VALUE_TYPE max, min;
1605 if (HONOR_INFINITIES (TYPE_MODE (type)))
1607 real_inf (&max);
1608 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1610 else
1611 real_maxval (&min, 1, TYPE_MODE (type));
1612 return build_real (type, min);
1614 else
1616 gcc_assert (INTEGRAL_TYPE_P (type));
1617 return TYPE_MIN_VALUE (type);
1620 case MIN_EXPR:
1621 if (SCALAR_FLOAT_TYPE_P (type))
1623 REAL_VALUE_TYPE max;
1624 if (HONOR_INFINITIES (TYPE_MODE (type)))
1625 real_inf (&max);
1626 else
1627 real_maxval (&max, 0, TYPE_MODE (type));
1628 return build_real (type, max);
1630 else
1632 gcc_assert (INTEGRAL_TYPE_P (type));
1633 return TYPE_MAX_VALUE (type);
1636 default:
1637 gcc_unreachable ();
1641 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1642 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1643 private variables. Initialization statements go in ILIST, while calls
1644 to destructors go in DLIST. */
1646 static void
1647 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1648 omp_context *ctx)
1650 tree_stmt_iterator diter;
1651 tree c, dtor, copyin_seq, x, ptr;
1652 bool copyin_by_ref = false;
1653 bool lastprivate_firstprivate = false;
1654 int pass;
1656 *dlist = alloc_stmt_list ();
1657 diter = tsi_start (*dlist);
1658 copyin_seq = NULL;
1660 /* Do all the fixed sized types in the first pass, and the variable sized
1661 types in the second pass. This makes sure that the scalar arguments to
1662 the variable sized types are processed before we use them in the
1663 variable sized operations. */
1664 for (pass = 0; pass < 2; ++pass)
1666 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1668 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1669 tree var, new_var;
1670 bool by_ref;
1672 switch (c_kind)
1674 case OMP_CLAUSE_PRIVATE:
1675 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1676 continue;
1677 break;
1678 case OMP_CLAUSE_SHARED:
1679 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1681 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1682 continue;
1684 case OMP_CLAUSE_FIRSTPRIVATE:
1685 case OMP_CLAUSE_COPYIN:
1686 case OMP_CLAUSE_REDUCTION:
1687 break;
1688 case OMP_CLAUSE_LASTPRIVATE:
1689 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1691 lastprivate_firstprivate = true;
1692 if (pass != 0)
1693 continue;
1695 break;
1696 default:
1697 continue;
1700 new_var = var = OMP_CLAUSE_DECL (c);
1701 if (c_kind != OMP_CLAUSE_COPYIN)
1702 new_var = lookup_decl (var, ctx);
1704 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1706 if (pass != 0)
1707 continue;
1709 else if (is_variable_sized (var))
1711 /* For variable sized types, we need to allocate the
1712 actual storage here. Call alloca and store the
1713 result in the pointer decl that we created elsewhere. */
1714 if (pass == 0)
1715 continue;
1717 ptr = DECL_VALUE_EXPR (new_var);
1718 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1719 ptr = TREE_OPERAND (ptr, 0);
1720 gcc_assert (DECL_P (ptr));
1722 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1723 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1724 x = fold_convert (TREE_TYPE (ptr), x);
1725 x = build_gimple_modify_stmt (ptr, x);
1726 gimplify_and_add (x, ilist);
1728 else if (is_reference (var))
1730 /* For references that are being privatized for Fortran,
1731 allocate new backing storage for the new pointer
1732 variable. This allows us to avoid changing all the
1733 code that expects a pointer to something that expects
1734 a direct variable. Note that this doesn't apply to
1735 C++, since reference types are disallowed in data
1736 sharing clauses there, except for NRV optimized
1737 return values. */
1738 if (pass == 0)
1739 continue;
1741 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1742 if (TREE_CONSTANT (x))
1744 const char *name = NULL;
1745 if (DECL_NAME (var))
1746 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1748 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1749 name);
1750 gimple_add_tmp_var (x);
1751 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1753 else
1755 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1756 x = fold_convert (TREE_TYPE (new_var), x);
1759 x = build_gimple_modify_stmt (new_var, x);
1760 gimplify_and_add (x, ilist);
1762 new_var = build_fold_indirect_ref (new_var);
1764 else if (c_kind == OMP_CLAUSE_REDUCTION
1765 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1767 if (pass == 0)
1768 continue;
1770 else if (pass != 0)
1771 continue;
1773 switch (OMP_CLAUSE_CODE (c))
1775 case OMP_CLAUSE_SHARED:
1776 /* Shared global vars are just accessed directly. */
1777 if (is_global_var (new_var))
1778 break;
1779 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1780 needs to be delayed until after fixup_child_record_type so
1781 that we get the correct type during the dereference. */
1782 by_ref = use_pointer_for_field (var, ctx);
1783 x = build_receiver_ref (var, by_ref, ctx);
1784 SET_DECL_VALUE_EXPR (new_var, x);
1785 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1787 /* ??? If VAR is not passed by reference, and the variable
1788 hasn't been initialized yet, then we'll get a warning for
1789 the store into the omp_data_s structure. Ideally, we'd be
1790 able to notice this and not store anything at all, but
1791 we're generating code too early. Suppress the warning. */
1792 if (!by_ref)
1793 TREE_NO_WARNING (var) = 1;
1794 break;
1796 case OMP_CLAUSE_LASTPRIVATE:
1797 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1798 break;
1799 /* FALLTHRU */
1801 case OMP_CLAUSE_PRIVATE:
1802 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1803 if (x)
1804 gimplify_and_add (x, ilist);
1805 /* FALLTHRU */
1807 do_dtor:
1808 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1809 if (x)
1811 dtor = x;
1812 gimplify_stmt (&dtor);
1813 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1815 break;
1817 case OMP_CLAUSE_FIRSTPRIVATE:
1818 x = build_outer_var_ref (var, ctx);
1819 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1820 gimplify_and_add (x, ilist);
1821 goto do_dtor;
1822 break;
1824 case OMP_CLAUSE_COPYIN:
1825 by_ref = use_pointer_for_field (var, NULL);
1826 x = build_receiver_ref (var, by_ref, ctx);
1827 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1828 append_to_statement_list (x, &copyin_seq);
1829 copyin_by_ref |= by_ref;
1830 break;
1832 case OMP_CLAUSE_REDUCTION:
1833 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1835 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1836 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1838 else
1840 x = omp_reduction_init (c, TREE_TYPE (new_var));
1841 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1842 x = build_gimple_modify_stmt (new_var, x);
1843 gimplify_and_add (x, ilist);
1845 break;
1847 default:
1848 gcc_unreachable ();
1853 /* The copyin sequence is not to be executed by the main thread, since
1854 that would result in self-copies. Perhaps not visible to scalars,
1855 but it certainly is to C++ operator=. */
1856 if (copyin_seq)
1858 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1859 x = build2 (NE_EXPR, boolean_type_node, x,
1860 build_int_cst (TREE_TYPE (x), 0));
1861 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1862 gimplify_and_add (x, ilist);
1865 /* If any copyin variable is passed by reference, we must ensure the
1866 master thread doesn't modify it before it is copied over in all
1867 threads. Similarly for variables in both firstprivate and
1868 lastprivate clauses we need to ensure the lastprivate copying
1869 happens after firstprivate copying in all threads. */
1870 if (copyin_by_ref || lastprivate_firstprivate)
1871 gimplify_and_add (build_omp_barrier (), ilist);
1875 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1876 both parallel and workshare constructs. PREDICATE may be NULL if it's
1877 always true. */
1879 static void
1880 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1881 omp_context *ctx)
1883 tree sub_list, x, c;
1885 /* Early exit if there are no lastprivate clauses. */
1886 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1887 if (clauses == NULL)
1889 /* If this was a workshare clause, see if it had been combined
1890 with its parallel. In that case, look for the clauses on the
1891 parallel statement itself. */
1892 if (is_parallel_ctx (ctx))
1893 return;
1895 ctx = ctx->outer;
1896 if (ctx == NULL || !is_parallel_ctx (ctx))
1897 return;
1899 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1900 OMP_CLAUSE_LASTPRIVATE);
1901 if (clauses == NULL)
1902 return;
1905 sub_list = alloc_stmt_list ();
1907 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1909 tree var, new_var;
1911 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1912 continue;
1914 var = OMP_CLAUSE_DECL (c);
1915 new_var = lookup_decl (var, ctx);
1917 x = build_outer_var_ref (var, ctx);
1918 if (is_reference (var))
1919 new_var = build_fold_indirect_ref (new_var);
1920 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1921 append_to_statement_list (x, &sub_list);
1924 if (predicate)
1925 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1926 else
1927 x = sub_list;
1929 gimplify_and_add (x, stmt_list);
1933 /* Generate code to implement the REDUCTION clauses. */
1935 static void
1936 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1938 tree sub_list = NULL, x, c;
1939 int count = 0;
1941 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1942 update in that case, otherwise use a lock. */
1943 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1944 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1946 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1948 /* Never use OMP_ATOMIC for array reductions. */
1949 count = -1;
1950 break;
1952 count++;
1955 if (count == 0)
1956 return;
1958 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1960 tree var, ref, new_var;
1961 enum tree_code code;
1963 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1964 continue;
1966 var = OMP_CLAUSE_DECL (c);
1967 new_var = lookup_decl (var, ctx);
1968 if (is_reference (var))
1969 new_var = build_fold_indirect_ref (new_var);
1970 ref = build_outer_var_ref (var, ctx);
1971 code = OMP_CLAUSE_REDUCTION_CODE (c);
1973 /* reduction(-:var) sums up the partial results, so it acts
1974 identically to reduction(+:var). */
1975 if (code == MINUS_EXPR)
1976 code = PLUS_EXPR;
1978 if (count == 1)
1980 tree addr = build_fold_addr_expr (ref);
1982 addr = save_expr (addr);
1983 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1984 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1985 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1986 gimplify_and_add (x, stmt_list);
1987 return;
1990 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1992 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1994 if (is_reference (var))
1995 ref = build_fold_addr_expr (ref);
1996 SET_DECL_VALUE_EXPR (placeholder, ref);
1997 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1998 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1999 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
2000 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2002 else
2004 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2005 ref = build_outer_var_ref (var, ctx);
2006 x = build_gimple_modify_stmt (ref, x);
2007 append_to_statement_list (x, &sub_list);
2011 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
2012 gimplify_and_add (x, stmt_list);
2014 gimplify_and_add (sub_list, stmt_list);
2016 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
2017 gimplify_and_add (x, stmt_list);
2021 /* Generate code to implement the COPYPRIVATE clauses. */
2023 static void
2024 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
2025 omp_context *ctx)
2027 tree c;
2029 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2031 tree var, ref, x;
2032 bool by_ref;
2034 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2035 continue;
2037 var = OMP_CLAUSE_DECL (c);
2038 by_ref = use_pointer_for_field (var, NULL);
2040 ref = build_sender_ref (var, ctx);
2041 x = lookup_decl_in_outer_ctx (var, ctx);
2042 x = by_ref ? build_fold_addr_expr (x) : x;
2043 x = build_gimple_modify_stmt (ref, x);
2044 gimplify_and_add (x, slist);
2046 ref = build_receiver_ref (var, by_ref, ctx);
2047 if (is_reference (var))
2049 ref = build_fold_indirect_ref (ref);
2050 var = build_fold_indirect_ref (var);
2052 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2053 gimplify_and_add (x, rlist);
2058 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2059 and REDUCTION from the sender (aka parent) side. */
2061 static void
2062 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2064 tree c;
2066 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2068 tree val, ref, x, var;
2069 bool by_ref, do_in = false, do_out = false;
2071 switch (OMP_CLAUSE_CODE (c))
2073 case OMP_CLAUSE_FIRSTPRIVATE:
2074 case OMP_CLAUSE_COPYIN:
2075 case OMP_CLAUSE_LASTPRIVATE:
2076 case OMP_CLAUSE_REDUCTION:
2077 break;
2078 default:
2079 continue;
2082 val = OMP_CLAUSE_DECL (c);
2083 var = lookup_decl_in_outer_ctx (val, ctx);
2085 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2086 && is_global_var (var))
2087 continue;
2088 if (is_variable_sized (val))
2089 continue;
2090 by_ref = use_pointer_for_field (val, NULL);
2092 switch (OMP_CLAUSE_CODE (c))
2094 case OMP_CLAUSE_FIRSTPRIVATE:
2095 case OMP_CLAUSE_COPYIN:
2096 do_in = true;
2097 break;
2099 case OMP_CLAUSE_LASTPRIVATE:
2100 if (by_ref || is_reference (val))
2102 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2103 continue;
2104 do_in = true;
2106 else
2107 do_out = true;
2108 break;
2110 case OMP_CLAUSE_REDUCTION:
2111 do_in = true;
2112 do_out = !(by_ref || is_reference (val));
2113 break;
2115 default:
2116 gcc_unreachable ();
2119 if (do_in)
2121 ref = build_sender_ref (val, ctx);
2122 x = by_ref ? build_fold_addr_expr (var) : var;
2123 x = build_gimple_modify_stmt (ref, x);
2124 gimplify_and_add (x, ilist);
2127 if (do_out)
2129 ref = build_sender_ref (val, ctx);
2130 x = build_gimple_modify_stmt (var, ref);
2131 gimplify_and_add (x, olist);
2136 /* Generate code to implement SHARED from the sender (aka parent) side.
2137 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2138 got automatically shared. */
2140 static void
2141 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2143 tree var, ovar, nvar, f, x;
2145 if (ctx->record_type == NULL)
2146 return;
2148 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2150 ovar = DECL_ABSTRACT_ORIGIN (f);
2151 nvar = maybe_lookup_decl (ovar, ctx);
2152 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2153 continue;
2155 /* If CTX is a nested parallel directive. Find the immediately
2156 enclosing parallel or workshare construct that contains a
2157 mapping for OVAR. */
2158 var = lookup_decl_in_outer_ctx (ovar, ctx);
2160 if (use_pointer_for_field (ovar, ctx))
2162 x = build_sender_ref (ovar, ctx);
2163 var = build_fold_addr_expr (var);
2164 x = build_gimple_modify_stmt (x, var);
2165 gimplify_and_add (x, ilist);
2167 else
2169 x = build_sender_ref (ovar, ctx);
2170 x = build_gimple_modify_stmt (x, var);
2171 gimplify_and_add (x, ilist);
2173 x = build_sender_ref (ovar, ctx);
2174 x = build_gimple_modify_stmt (var, x);
2175 gimplify_and_add (x, olist);
2180 /* Build the function calls to GOMP_parallel_start etc to actually
2181 generate the parallel operation. REGION is the parallel region
2182 being expanded. BB is the block where to insert the code. WS_ARGS
2183 will be set if this is a call to a combined parallel+workshare
2184 construct, it contains the list of additional arguments needed by
2185 the workshare construct. */
2187 static void
2188 expand_parallel_call (struct omp_region *region, basic_block bb,
2189 tree entry_stmt, tree ws_args)
2191 tree t, t1, t2, val, cond, c, clauses;
2192 block_stmt_iterator si;
2193 int start_ix;
2195 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2197 /* Determine what flavor of GOMP_parallel_start we will be
2198 emitting. */
2199 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2200 if (is_combined_parallel (region))
2202 switch (region->inner->type)
2204 case OMP_FOR:
2205 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2206 + region->inner->sched_kind;
2207 break;
2208 case OMP_SECTIONS:
2209 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2210 break;
2211 default:
2212 gcc_unreachable ();
2216 /* By default, the value of NUM_THREADS is zero (selected at run time)
2217 and there is no conditional. */
2218 cond = NULL_TREE;
2219 val = build_int_cst (unsigned_type_node, 0);
2221 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2222 if (c)
2223 cond = OMP_CLAUSE_IF_EXPR (c);
2225 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2226 if (c)
2227 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2229 /* Ensure 'val' is of the correct type. */
2230 val = fold_convert (unsigned_type_node, val);
2232 /* If we found the clause 'if (cond)', build either
2233 (cond != 0) or (cond ? val : 1u). */
2234 if (cond)
2236 block_stmt_iterator si;
2238 cond = gimple_boolify (cond);
2240 if (integer_zerop (val))
2241 val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
2242 build_int_cst (TREE_TYPE (cond), 0));
2243 else
2245 basic_block cond_bb, then_bb, else_bb;
2246 edge e, e_then, e_else;
2247 tree t, tmp_then, tmp_else, tmp_join, tmp_var;
2249 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
2250 if (gimple_in_ssa_p (cfun))
2252 tmp_then = make_ssa_name (tmp_var, NULL_TREE);
2253 tmp_else = make_ssa_name (tmp_var, NULL_TREE);
2254 tmp_join = make_ssa_name (tmp_var, NULL_TREE);
2256 else
2258 tmp_then = tmp_var;
2259 tmp_else = tmp_var;
2260 tmp_join = tmp_var;
2263 e = split_block (bb, NULL);
2264 cond_bb = e->src;
2265 bb = e->dest;
2266 remove_edge (e);
2268 then_bb = create_empty_bb (cond_bb);
2269 else_bb = create_empty_bb (then_bb);
2270 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
2271 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
2273 t = build3 (COND_EXPR, void_type_node,
2274 cond, NULL_TREE, NULL_TREE);
2276 si = bsi_start (cond_bb);
2277 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2279 si = bsi_start (then_bb);
2280 t = build_gimple_modify_stmt (tmp_then, val);
2281 if (gimple_in_ssa_p (cfun))
2282 SSA_NAME_DEF_STMT (tmp_then) = t;
2283 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2285 si = bsi_start (else_bb);
2286 t = build_gimple_modify_stmt (tmp_else,
2287 build_int_cst (unsigned_type_node, 1));
2288 if (gimple_in_ssa_p (cfun))
2289 SSA_NAME_DEF_STMT (tmp_else) = t;
2290 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2292 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2293 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2294 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
2295 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
2297 if (gimple_in_ssa_p (cfun))
2299 tree phi = create_phi_node (tmp_join, bb);
2300 SSA_NAME_DEF_STMT (tmp_join) = phi;
2301 add_phi_arg (phi, tmp_then, e_then);
2302 add_phi_arg (phi, tmp_else, e_else);
2305 val = tmp_join;
2308 si = bsi_start (bb);
2309 val = force_gimple_operand_bsi (&si, val, true, NULL_TREE,
2310 false, BSI_CONTINUE_LINKING);
2313 si = bsi_last (bb);
2314 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2315 if (t == NULL)
2316 t1 = null_pointer_node;
2317 else
2318 t1 = build_fold_addr_expr (t);
2319 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2321 if (ws_args)
2323 tree args = tree_cons (NULL, t2,
2324 tree_cons (NULL, t1,
2325 tree_cons (NULL, val, ws_args)));
2326 t = build_function_call_expr (built_in_decls[start_ix], args);
2328 else
2329 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2331 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2332 false, BSI_CONTINUE_LINKING);
2334 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2335 if (t == NULL)
2336 t = null_pointer_node;
2337 else
2338 t = build_fold_addr_expr (t);
2339 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2340 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2341 false, BSI_CONTINUE_LINKING);
2343 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2344 force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2345 false, BSI_CONTINUE_LINKING);
2349 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2350 handler. This prevents programs from violating the structured
2351 block semantics with throws. */
2353 static void
2354 maybe_catch_exception (tree *stmt_p)
2356 tree f, t;
2358 if (!flag_exceptions)
2359 return;
2361 if (lang_protect_cleanup_actions)
2362 t = lang_protect_cleanup_actions ();
2363 else
2364 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2365 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2366 EH_FILTER_MUST_NOT_THROW (f) = 1;
2367 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2369 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2370 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2372 *stmt_p = NULL;
2373 append_to_statement_list (t, stmt_p);
2376 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2378 static tree
2379 list2chain (tree list)
2381 tree t;
2383 for (t = list; t; t = TREE_CHAIN (t))
2385 tree var = TREE_VALUE (t);
2386 if (TREE_CHAIN (t))
2387 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2388 else
2389 TREE_CHAIN (var) = NULL_TREE;
2392 return list ? TREE_VALUE (list) : NULL_TREE;
2396 /* Remove barriers in REGION->EXIT's block. Note that this is only
2397 valid for OMP_PARALLEL regions. Since the end of a parallel region
2398 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2399 left a barrier at the end of the OMP_PARALLEL region can now be
2400 removed. */
2402 static void
2403 remove_exit_barrier (struct omp_region *region)
2405 block_stmt_iterator si;
2406 basic_block exit_bb;
2407 edge_iterator ei;
2408 edge e;
2409 tree t;
2411 exit_bb = region->exit;
2413 /* If the parallel region doesn't return, we don't have REGION->EXIT
2414 block at all. */
2415 if (! exit_bb)
2416 return;
2418 /* The last insn in the block will be the parallel's OMP_RETURN. The
2419 workshare's OMP_RETURN will be in a preceding block. The kinds of
2420 statements that can appear in between are extremely limited -- no
2421 memory operations at all. Here, we allow nothing at all, so the
2422 only thing we allow to precede this OMP_RETURN is a label. */
2423 si = bsi_last (exit_bb);
2424 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2425 bsi_prev (&si);
2426 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2427 return;
2429 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2431 si = bsi_last (e->src);
2432 if (bsi_end_p (si))
2433 continue;
2434 t = bsi_stmt (si);
2435 if (TREE_CODE (t) == OMP_RETURN)
2436 OMP_RETURN_NOWAIT (t) = 1;
2440 static void
2441 remove_exit_barriers (struct omp_region *region)
2443 if (region->type == OMP_PARALLEL)
2444 remove_exit_barrier (region);
2446 if (region->inner)
2448 region = region->inner;
2449 remove_exit_barriers (region);
2450 while (region->next)
2452 region = region->next;
2453 remove_exit_barriers (region);
2458 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
2459 calls. These can't be declared as const functions, but
2460 within one parallel body they are constant, so they can be
2461 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
2462 which are declared const. */
2464 static void
2465 optimize_omp_library_calls (void)
2467 basic_block bb;
2468 block_stmt_iterator bsi;
2469 tree thr_num_id
2470 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
2471 tree num_thr_id
2472 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
2474 FOR_EACH_BB (bb)
2475 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
2477 tree stmt = bsi_stmt (bsi);
2478 tree call = get_call_expr_in (stmt);
2479 tree decl;
2481 if (call
2482 && (decl = get_callee_fndecl (call))
2483 && DECL_EXTERNAL (decl)
2484 && TREE_PUBLIC (decl)
2485 && DECL_INITIAL (decl) == NULL)
2487 tree built_in;
2489 if (DECL_NAME (decl) == thr_num_id)
2490 built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
2491 else if (DECL_NAME (decl) == num_thr_id)
2492 built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
2493 else
2494 continue;
2496 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
2497 || call_expr_nargs (call) != 0)
2498 continue;
2500 if (flag_exceptions && !TREE_NOTHROW (decl))
2501 continue;
2503 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
2504 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
2505 != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
2506 continue;
2508 CALL_EXPR_FN (call) = build_fold_addr_expr (built_in);
2513 /* Expand the OpenMP parallel directive starting at REGION. */
2515 static void
2516 expand_omp_parallel (struct omp_region *region)
2518 basic_block entry_bb, exit_bb, new_bb;
2519 struct function *child_cfun;
2520 tree child_fn, block, t, ws_args;
2521 block_stmt_iterator si;
2522 tree entry_stmt;
2523 edge e;
2525 entry_stmt = last_stmt (region->entry);
2526 child_fn = OMP_PARALLEL_FN (entry_stmt);
2527 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2528 /* If this function has been already instrumented, make sure
2529 the child function isn't instrumented again. */
2530 child_cfun->after_tree_profile = cfun->after_tree_profile;
2532 entry_bb = region->entry;
2533 exit_bb = region->exit;
2535 if (is_combined_parallel (region))
2536 ws_args = region->ws_args;
2537 else
2538 ws_args = NULL_TREE;
2540 if (child_cfun->cfg)
2542 /* Due to inlining, it may happen that we have already outlined
2543 the region, in which case all we need to do is make the
2544 sub-graph unreachable and emit the parallel call. */
2545 edge entry_succ_e, exit_succ_e;
2546 block_stmt_iterator si;
2548 entry_succ_e = single_succ_edge (entry_bb);
2550 si = bsi_last (entry_bb);
2551 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2552 bsi_remove (&si, true);
2554 new_bb = entry_bb;
2555 if (exit_bb)
2557 exit_succ_e = single_succ_edge (exit_bb);
2558 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2560 remove_edge_and_dominated_blocks (entry_succ_e);
2562 else
2564 /* If the parallel region needs data sent from the parent
2565 function, then the very first statement (except possible
2566 tree profile counter updates) of the parallel body
2567 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2568 &.OMP_DATA_O is passed as an argument to the child function,
2569 we need to replace it with the argument as seen by the child
2570 function.
2572 In most cases, this will end up being the identity assignment
2573 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2574 a function call that has been inlined, the original PARM_DECL
2575 .OMP_DATA_I may have been converted into a different local
2576 variable. In which case, we need to keep the assignment. */
2577 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2579 basic_block entry_succ_bb = single_succ (entry_bb);
2580 block_stmt_iterator si;
2581 tree parcopy_stmt = NULL_TREE, arg, narg;
2583 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2585 tree stmt, arg;
2587 gcc_assert (!bsi_end_p (si));
2588 stmt = bsi_stmt (si);
2589 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2590 continue;
2592 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2593 STRIP_NOPS (arg);
2594 if (TREE_CODE (arg) == ADDR_EXPR
2595 && TREE_OPERAND (arg, 0)
2596 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2598 parcopy_stmt = stmt;
2599 break;
2603 gcc_assert (parcopy_stmt != NULL_TREE);
2604 arg = DECL_ARGUMENTS (child_fn);
2606 if (!gimple_in_ssa_p (cfun))
2608 if (GIMPLE_STMT_OPERAND (parcopy_stmt, 0) == arg)
2609 bsi_remove (&si, true);
2610 else
2611 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = arg;
2613 else
2615 /* If we are in ssa form, we must load the value from the default
2616 definition of the argument. That should not be defined now,
2617 since the argument is not used uninitialized. */
2618 gcc_assert (gimple_default_def (cfun, arg) == NULL);
2619 narg = make_ssa_name (arg, build_empty_stmt ());
2620 set_default_def (arg, narg);
2621 GIMPLE_STMT_OPERAND (parcopy_stmt, 1) = narg;
2622 update_stmt (parcopy_stmt);
2626 /* Declare local variables needed in CHILD_CFUN. */
2627 block = DECL_INITIAL (child_fn);
2628 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2629 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2631 /* Reset DECL_CONTEXT on function arguments. */
2632 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2633 DECL_CONTEXT (t) = child_fn;
2635 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2636 child function. */
2637 si = bsi_last (entry_bb);
2638 t = bsi_stmt (si);
2639 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2640 bsi_remove (&si, true);
2641 e = split_block (entry_bb, t);
2642 entry_bb = e->dest;
2643 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2645 /* Convert OMP_RETURN into a RETURN_EXPR. */
2646 if (exit_bb)
2648 si = bsi_last (exit_bb);
2649 gcc_assert (!bsi_end_p (si)
2650 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2651 t = build1 (RETURN_EXPR, void_type_node, NULL);
2652 bsi_insert_after (&si, t, BSI_SAME_STMT);
2653 bsi_remove (&si, true);
2656 /* Move the parallel region into CHILD_CFUN. */
2658 if (gimple_in_ssa_p (cfun))
2660 push_cfun (child_cfun);
2661 init_tree_ssa ();
2662 init_ssa_operands ();
2663 cfun->gimple_df->in_ssa_p = true;
2664 pop_cfun ();
2666 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2667 if (exit_bb)
2668 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2670 /* Inform the callgraph about the new function. */
2671 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2672 = cfun->curr_properties;
2673 cgraph_add_new_function (child_fn, true);
2675 /* Fix the callgraph edges for child_cfun. Those for cfun will be
2676 fixed in a following pass. */
2677 push_cfun (child_cfun);
2678 if (optimize)
2679 optimize_omp_library_calls ();
2680 rebuild_cgraph_edges ();
2682 /* Some EH regions might become dead, see PR34608. If
2683 pass_cleanup_cfg isn't the first pass to happen with the
2684 new child, these dead EH edges might cause problems.
2685 Clean them up now. */
2686 if (flag_exceptions)
2688 basic_block bb;
2689 tree save_current = current_function_decl;
2690 bool changed = false;
2692 current_function_decl = child_fn;
2693 FOR_EACH_BB (bb)
2694 changed |= tree_purge_dead_eh_edges (bb);
2695 if (changed)
2696 cleanup_tree_cfg ();
2697 current_function_decl = save_current;
2699 pop_cfun ();
2702 /* Emit a library call to launch the children threads. */
2703 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2704 update_ssa (TODO_update_ssa_only_virtuals);
2708 /* A subroutine of expand_omp_for. Generate code for a parallel
2709 loop with any schedule. Given parameters:
2711 for (V = N1; V cond N2; V += STEP) BODY;
2713 where COND is "<" or ">", we generate pseudocode
2715 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2716 if (more) goto L0; else goto L3;
2718 V = istart0;
2719 iend = iend0;
2721 BODY;
2722 V += STEP;
2723 if (V cond iend) goto L1; else goto L2;
2725 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2728 If this is a combined omp parallel loop, instead of the call to
2729 GOMP_loop_foo_start, we call GOMP_loop_foo_next. */
2731 static void
2732 expand_omp_for_generic (struct omp_region *region,
2733 struct omp_for_data *fd,
2734 enum built_in_function start_fn,
2735 enum built_in_function next_fn)
2737 tree type, istart0, iend0, iend, phi;
2738 tree t, vmain, vback;
2739 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2740 basic_block l2_bb = NULL, l3_bb = NULL;
2741 block_stmt_iterator si;
2742 bool in_combined_parallel = is_combined_parallel (region);
2743 bool broken_loop = region->cont == NULL;
2744 edge e, ne;
2746 gcc_assert (!broken_loop || !in_combined_parallel);
2748 type = TREE_TYPE (fd->v);
2750 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2751 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2752 TREE_ADDRESSABLE (istart0) = 1;
2753 TREE_ADDRESSABLE (iend0) = 1;
2754 if (gimple_in_ssa_p (cfun))
2756 add_referenced_var (istart0);
2757 add_referenced_var (iend0);
2760 entry_bb = region->entry;
2761 cont_bb = region->cont;
2762 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2763 gcc_assert (broken_loop
2764 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2765 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2766 l1_bb = single_succ (l0_bb);
2767 if (!broken_loop)
2769 l2_bb = create_empty_bb (cont_bb);
2770 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
2771 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2773 else
2774 l2_bb = NULL;
2775 l3_bb = BRANCH_EDGE (entry_bb)->dest;
2776 exit_bb = region->exit;
2778 si = bsi_last (entry_bb);
2779 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2780 if (in_combined_parallel)
2782 /* In a combined parallel loop, emit a call to
2783 GOMP_loop_foo_next. */
2784 t = build_call_expr (built_in_decls[next_fn], 2,
2785 build_fold_addr_expr (istart0),
2786 build_fold_addr_expr (iend0));
2788 else
2790 tree t0, t1, t2, t3, t4;
2791 /* If this is not a combined parallel loop, emit a call to
2792 GOMP_loop_foo_start in ENTRY_BB. */
2793 t4 = build_fold_addr_expr (iend0);
2794 t3 = build_fold_addr_expr (istart0);
2795 t2 = fold_convert (long_integer_type_node, fd->step);
2796 t1 = fold_convert (long_integer_type_node, fd->n2);
2797 t0 = fold_convert (long_integer_type_node, fd->n1);
2798 if (fd->chunk_size)
2800 t = fold_convert (long_integer_type_node, fd->chunk_size);
2801 t = build_call_expr (built_in_decls[start_fn], 6,
2802 t0, t1, t2, t, t3, t4);
2804 else
2805 t = build_call_expr (built_in_decls[start_fn], 5,
2806 t0, t1, t2, t3, t4);
2808 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2809 true, BSI_SAME_STMT);
2810 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2811 bsi_insert_after (&si, t, BSI_SAME_STMT);
2813 /* Remove the OMP_FOR statement. */
2814 bsi_remove (&si, true);
2816 /* Iteration setup for sequential loop goes in L0_BB. */
2817 si = bsi_start (l0_bb);
2818 t = fold_convert (type, istart0);
2819 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2820 false, BSI_CONTINUE_LINKING);
2821 t = build_gimple_modify_stmt (fd->v, t);
2822 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2823 if (gimple_in_ssa_p (cfun))
2824 SSA_NAME_DEF_STMT (fd->v) = t;
2826 t = fold_convert (type, iend0);
2827 iend = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2828 false, BSI_CONTINUE_LINKING);
2830 if (!broken_loop)
2832 /* Code to control the increment and predicate for the sequential
2833 loop goes in the CONT_BB. */
2834 si = bsi_last (cont_bb);
2835 t = bsi_stmt (si);
2836 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
2837 vmain = TREE_OPERAND (t, 1);
2838 vback = TREE_OPERAND (t, 0);
2840 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
2841 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
2842 true, BSI_SAME_STMT);
2843 t = build_gimple_modify_stmt (vback, t);
2844 bsi_insert_before (&si, t, BSI_SAME_STMT);
2845 if (gimple_in_ssa_p (cfun))
2846 SSA_NAME_DEF_STMT (vback) = t;
2848 t = build2 (fd->cond_code, boolean_type_node, vback, iend);
2849 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2850 bsi_insert_before (&si, t, BSI_SAME_STMT);
2852 /* Remove OMP_CONTINUE. */
2853 bsi_remove (&si, true);
2855 /* Emit code to get the next parallel iteration in L2_BB. */
2856 si = bsi_start (l2_bb);
2858 t = build_call_expr (built_in_decls[next_fn], 2,
2859 build_fold_addr_expr (istart0),
2860 build_fold_addr_expr (iend0));
2861 t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2862 false, BSI_CONTINUE_LINKING);
2863 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2864 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2867 /* Add the loop cleanup function. */
2868 si = bsi_last (exit_bb);
2869 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2870 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2871 else
2872 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2873 t = build_call_expr (t, 0);
2874 bsi_insert_after (&si, t, BSI_SAME_STMT);
2875 bsi_remove (&si, true);
2877 /* Connect the new blocks. */
2878 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
2879 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
2881 if (!broken_loop)
2883 e = find_edge (cont_bb, l3_bb);
2884 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2886 for (phi = phi_nodes (l3_bb); phi; phi = PHI_CHAIN (phi))
2887 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
2888 PHI_ARG_DEF_FROM_EDGE (phi, e));
2889 remove_edge (e);
2891 find_edge (cont_bb, l1_bb)->flags = EDGE_TRUE_VALUE;
2892 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2893 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2895 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
2896 recompute_dominator (CDI_DOMINATORS, l2_bb));
2897 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
2898 recompute_dominator (CDI_DOMINATORS, l3_bb));
2899 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
2900 recompute_dominator (CDI_DOMINATORS, l0_bb));
2901 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
2902 recompute_dominator (CDI_DOMINATORS, l1_bb));
2907 /* A subroutine of expand_omp_for. Generate code for a parallel
2908 loop with static schedule and no specified chunk size. Given
2909 parameters:
2911 for (V = N1; V cond N2; V += STEP) BODY;
2913 where COND is "<" or ">", we generate pseudocode
2915 if (cond is <)
2916 adj = STEP - 1;
2917 else
2918 adj = STEP + 1;
2919 n = (adj + N2 - N1) / STEP;
2920 q = n / nthreads;
2921 q += (q * nthreads != n);
2922 s0 = q * threadid;
2923 e0 = min(s0 + q, n);
2924 V = s0 * STEP + N1;
2925 if (s0 >= e0) goto L2; else goto L0;
2927 e = e0 * STEP + N1;
2929 BODY;
2930 V += STEP;
2931 if (V cond e) goto L1;
2935 static void
2936 expand_omp_for_static_nochunk (struct omp_region *region,
2937 struct omp_for_data *fd)
2939 tree n, q, s0, e0, e, t, nthreads, threadid;
2940 tree type, vmain, vback;
2941 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2942 basic_block fin_bb;
2943 block_stmt_iterator si;
2945 type = TREE_TYPE (fd->v);
2947 entry_bb = region->entry;
2948 cont_bb = region->cont;
2949 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2950 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2951 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2952 body_bb = single_succ (seq_start_bb);
2953 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
2954 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2955 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
2956 exit_bb = region->exit;
2958 /* Iteration space partitioning goes in ENTRY_BB. */
2959 si = bsi_last (entry_bb);
2960 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2962 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2963 t = fold_convert (type, t);
2964 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2965 true, BSI_SAME_STMT);
2967 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2968 t = fold_convert (type, t);
2969 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
2970 true, BSI_SAME_STMT);
2972 fd->n1 = force_gimple_operand_bsi (&si,
2973 fold_convert (type, fd->n1),
2974 true, NULL_TREE,
2975 true, BSI_SAME_STMT);
2977 fd->n2 = force_gimple_operand_bsi (&si,
2978 fold_convert (type, fd->n2),
2979 true, NULL_TREE,
2980 true, BSI_SAME_STMT);
2982 fd->step = force_gimple_operand_bsi (&si,
2983 fold_convert (type, fd->step),
2984 true, NULL_TREE,
2985 true, BSI_SAME_STMT);
2987 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2988 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2989 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2990 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2991 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2992 t = fold_convert (type, t);
2993 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2995 t = fold_build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2996 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
2998 t = fold_build2 (MULT_EXPR, type, q, nthreads);
2999 t = fold_build2 (NE_EXPR, type, t, n);
3000 t = fold_build2 (PLUS_EXPR, type, q, t);
3001 q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3003 t = build2 (MULT_EXPR, type, q, threadid);
3004 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3006 t = fold_build2 (PLUS_EXPR, type, s0, q);
3007 t = fold_build2 (MIN_EXPR, type, t, n);
3008 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
3010 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
3011 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3012 bsi_insert_before (&si, t, BSI_SAME_STMT);
3014 /* Remove the OMP_FOR statement. */
3015 bsi_remove (&si, true);
3017 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3018 si = bsi_start (seq_start_bb);
3020 t = fold_convert (type, s0);
3021 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3022 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3023 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3024 false, BSI_CONTINUE_LINKING);
3025 t = build_gimple_modify_stmt (fd->v, t);
3026 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3027 if (gimple_in_ssa_p (cfun))
3028 SSA_NAME_DEF_STMT (fd->v) = t;
3030 t = fold_convert (type, e0);
3031 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3032 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3033 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3034 false, BSI_CONTINUE_LINKING);
3036 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
3037 si = bsi_last (cont_bb);
3038 t = bsi_stmt (si);
3039 gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
3040 vmain = TREE_OPERAND (t, 1);
3041 vback = TREE_OPERAND (t, 0);
3043 t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
3044 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3045 true, BSI_SAME_STMT);
3046 t = build_gimple_modify_stmt (vback, t);
3047 bsi_insert_before (&si, t, BSI_SAME_STMT);
3048 if (gimple_in_ssa_p (cfun))
3049 SSA_NAME_DEF_STMT (vback) = t;
3051 t = build2 (fd->cond_code, boolean_type_node, vback, e);
3052 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3053 bsi_insert_before (&si, t, BSI_SAME_STMT);
3055 /* Remove the OMP_CONTINUE statement. */
3056 bsi_remove (&si, true);
3058 /* Replace the OMP_RETURN with a barrier, or nothing. */
3059 si = bsi_last (exit_bb);
3060 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3061 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3062 false, BSI_SAME_STMT);
3063 bsi_remove (&si, true);
3065 /* Connect all the blocks. */
3066 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
3067 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
3069 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3070 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
3072 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
3073 set_immediate_dominator (CDI_DOMINATORS, body_bb,
3074 recompute_dominator (CDI_DOMINATORS, body_bb));
3075 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
3076 recompute_dominator (CDI_DOMINATORS, fin_bb));
3080 /* A subroutine of expand_omp_for. Generate code for a parallel
3081 loop with static schedule and a specified chunk size. Given
3082 parameters:
3084 for (V = N1; V cond N2; V += STEP) BODY;
3086 where COND is "<" or ">", we generate pseudocode
3088 if (cond is <)
3089 adj = STEP - 1;
3090 else
3091 adj = STEP + 1;
3092 n = (adj + N2 - N1) / STEP;
3093 trip = 0;
3094 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
3095 here so that V is defined
3096 if the loop is not entered
3098 s0 = (trip * nthreads + threadid) * CHUNK;
3099 e0 = min(s0 + CHUNK, n);
3100 if (s0 < n) goto L1; else goto L4;
3102 V = s0 * STEP + N1;
3103 e = e0 * STEP + N1;
3105 BODY;
3106 V += STEP;
3107 if (V cond e) goto L2; else goto L3;
3109 trip += 1;
3110 goto L0;
3114 static void
3115 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
3117 tree n, s0, e0, e, t, phi, nphi, args;
3118 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
3119 tree type, cont, v_main, v_back, v_extra;
3120 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
3121 basic_block trip_update_bb, cont_bb, fin_bb;
3122 block_stmt_iterator si;
3123 edge se, re, ene;
3125 type = TREE_TYPE (fd->v);
3127 entry_bb = region->entry;
3128 se = split_block (entry_bb, last_stmt (entry_bb));
3129 entry_bb = se->src;
3130 iter_part_bb = se->dest;
3131 cont_bb = region->cont;
3132 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
3133 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
3134 == FALLTHRU_EDGE (cont_bb)->dest);
3135 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
3136 body_bb = single_succ (seq_start_bb);
3137 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
3138 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3139 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
3140 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
3141 exit_bb = region->exit;
3143 /* Trip and adjustment setup goes in ENTRY_BB. */
3144 si = bsi_last (entry_bb);
3145 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3147 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
3148 t = fold_convert (type, t);
3149 nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3150 true, BSI_SAME_STMT);
3152 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3153 t = fold_convert (type, t);
3154 threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3155 true, BSI_SAME_STMT);
3157 fd->n1 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n1),
3158 true, NULL_TREE,
3159 true, BSI_SAME_STMT);
3160 fd->n2 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n2),
3161 true, NULL_TREE,
3162 true, BSI_SAME_STMT);
3163 fd->step = force_gimple_operand_bsi (&si, fold_convert (type, fd->step),
3164 true, NULL_TREE,
3165 true, BSI_SAME_STMT);
3166 fd->chunk_size
3167 = force_gimple_operand_bsi (&si, fold_convert (type,
3168 fd->chunk_size),
3169 true, NULL_TREE,
3170 true, BSI_SAME_STMT);
3172 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
3173 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
3174 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
3175 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
3176 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
3177 t = fold_convert (type, t);
3178 n = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3179 true, BSI_SAME_STMT);
3181 trip_var = create_tmp_var (type, ".trip");
3182 if (gimple_in_ssa_p (cfun))
3184 add_referenced_var (trip_var);
3185 trip_init = make_ssa_name (trip_var, NULL_TREE);
3186 trip_main = make_ssa_name (trip_var, NULL_TREE);
3187 trip_back = make_ssa_name (trip_var, NULL_TREE);
3189 else
3191 trip_init = trip_var;
3192 trip_main = trip_var;
3193 trip_back = trip_var;
3196 t = build_gimple_modify_stmt (trip_init, build_int_cst (type, 0));
3197 bsi_insert_before (&si, t, BSI_SAME_STMT);
3198 if (gimple_in_ssa_p (cfun))
3199 SSA_NAME_DEF_STMT (trip_init) = t;
3201 t = fold_build2 (MULT_EXPR, type, threadid, fd->chunk_size);
3202 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3203 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3204 v_extra = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3205 true, BSI_SAME_STMT);
3207 /* Remove the OMP_FOR. */
3208 bsi_remove (&si, true);
3210 /* Iteration space partitioning goes in ITER_PART_BB. */
3211 si = bsi_last (iter_part_bb);
3213 t = fold_build2 (MULT_EXPR, type, trip_main, nthreads);
3214 t = fold_build2 (PLUS_EXPR, type, t, threadid);
3215 t = fold_build2 (MULT_EXPR, type, t, fd->chunk_size);
3216 s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3217 false, BSI_CONTINUE_LINKING);
3219 t = fold_build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3220 t = fold_build2 (MIN_EXPR, type, t, n);
3221 e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3222 false, BSI_CONTINUE_LINKING);
3224 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3225 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3226 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3228 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3229 si = bsi_start (seq_start_bb);
3231 t = fold_convert (type, s0);
3232 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3233 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3234 t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
3235 false, BSI_CONTINUE_LINKING);
3236 t = build_gimple_modify_stmt (fd->v, t);
3237 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3238 if (gimple_in_ssa_p (cfun))
3239 SSA_NAME_DEF_STMT (fd->v) = t;
3241 t = fold_convert (type, e0);
3242 t = fold_build2 (MULT_EXPR, type, t, fd->step);
3243 t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
3244 e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
3245 false, BSI_CONTINUE_LINKING);
3247 /* The code controlling the sequential loop goes in CONT_BB,
3248 replacing the OMP_CONTINUE. */
3249 si = bsi_last (cont_bb);
3250 cont = bsi_stmt (si);
3251 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3252 v_main = TREE_OPERAND (cont, 1);
3253 v_back = TREE_OPERAND (cont, 0);
3255 t = build2 (PLUS_EXPR, type, v_main, fd->step);
3256 t = build_gimple_modify_stmt (v_back, t);
3257 bsi_insert_before (&si, t, BSI_SAME_STMT);
3258 if (gimple_in_ssa_p (cfun))
3259 SSA_NAME_DEF_STMT (v_back) = t;
3261 t = build2 (fd->cond_code, boolean_type_node, v_back, e);
3262 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3263 bsi_insert_before (&si, t, BSI_SAME_STMT);
3265 /* Remove OMP_CONTINUE. */
3266 bsi_remove (&si, true);
3268 /* Trip update code goes into TRIP_UPDATE_BB. */
3269 si = bsi_start (trip_update_bb);
3271 t = build_int_cst (type, 1);
3272 t = build2 (PLUS_EXPR, type, trip_main, t);
3273 t = build_gimple_modify_stmt (trip_back, t);
3274 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3275 if (gimple_in_ssa_p (cfun))
3276 SSA_NAME_DEF_STMT (trip_back) = t;
3278 /* Replace the OMP_RETURN with a barrier, or nothing. */
3279 si = bsi_last (exit_bb);
3280 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3281 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3282 false, BSI_SAME_STMT);
3283 bsi_remove (&si, true);
3285 /* Connect the new blocks. */
3286 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
3287 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
3289 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3290 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
3292 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
3294 if (gimple_in_ssa_p (cfun))
3296 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
3297 remove arguments of the phi nodes in fin_bb. We need to create
3298 appropriate phi nodes in iter_part_bb instead. */
3299 se = single_pred_edge (fin_bb);
3300 re = single_succ_edge (trip_update_bb);
3301 ene = single_succ_edge (entry_bb);
3303 args = PENDING_STMT (re);
3304 PENDING_STMT (re) = NULL_TREE;
3305 for (phi = phi_nodes (fin_bb);
3306 phi && args;
3307 phi = PHI_CHAIN (phi), args = TREE_CHAIN (args))
3309 t = PHI_RESULT (phi);
3310 gcc_assert (t == TREE_PURPOSE (args));
3311 nphi = create_phi_node (t, iter_part_bb);
3312 SSA_NAME_DEF_STMT (t) = nphi;
3314 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
3315 /* A special case -- fd->v is not yet computed in iter_part_bb, we
3316 need to use v_extra instead. */
3317 if (t == fd->v)
3318 t = v_extra;
3319 add_phi_arg (nphi, t, ene);
3320 add_phi_arg (nphi, TREE_VALUE (args), re);
3322 gcc_assert (!phi && !args);
3323 while ((phi = phi_nodes (fin_bb)) != NULL_TREE)
3324 remove_phi_node (phi, NULL_TREE, false);
3326 /* Make phi node for trip. */
3327 phi = create_phi_node (trip_main, iter_part_bb);
3328 SSA_NAME_DEF_STMT (trip_main) = phi;
3329 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
3330 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
3333 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
3334 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
3335 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
3336 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
3337 recompute_dominator (CDI_DOMINATORS, fin_bb));
3338 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
3339 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
3340 set_immediate_dominator (CDI_DOMINATORS, body_bb,
3341 recompute_dominator (CDI_DOMINATORS, body_bb));
3345 /* Expand the OpenMP loop defined by REGION. */
3347 static void
3348 expand_omp_for (struct omp_region *region)
3350 struct omp_for_data fd;
3352 extract_omp_for_data (last_stmt (region->entry), &fd);
3353 region->sched_kind = fd.sched_kind;
3355 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
3356 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
3357 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
3358 if (region->cont)
3360 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
3361 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
3362 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
3365 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3366 && !fd.have_ordered
3367 && region->cont != NULL)
3369 if (fd.chunk_size == NULL)
3370 expand_omp_for_static_nochunk (region, &fd);
3371 else
3372 expand_omp_for_static_chunk (region, &fd);
3374 else
3376 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3377 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3378 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3379 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3382 update_ssa (TODO_update_ssa_only_virtuals);
3386 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3388 v = GOMP_sections_start (n);
3390 switch (v)
3392 case 0:
3393 goto L2;
3394 case 1:
3395 section 1;
3396 goto L1;
3397 case 2:
3399 case n:
3401 default:
3402 abort ();
3405 v = GOMP_sections_next ();
3406 goto L0;
3408 reduction;
3410 If this is a combined parallel sections, replace the call to
3411 GOMP_sections_start with call to GOMP_sections_next. */
3413 static void
3414 expand_omp_sections (struct omp_region *region)
3416 tree label_vec, l1, l2, t, u, sections_stmt, vin, vmain, vnext, cont;
3417 unsigned i, casei, len;
3418 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
3419 block_stmt_iterator si;
3420 struct omp_region *inner;
3421 bool exit_reachable = region->cont != NULL;
3423 gcc_assert (exit_reachable == (region->exit != NULL));
3424 entry_bb = region->entry;
3425 l0_bb = single_succ (entry_bb);
3426 l1_bb = region->cont;
3427 l2_bb = region->exit;
3428 if (exit_reachable)
3430 gcc_assert (single_pred (l2_bb) == l0_bb);
3431 default_bb = create_empty_bb (l1_bb->prev_bb);
3432 l1 = tree_block_label (l1_bb);
3433 l2 = tree_block_label (l2_bb);
3435 else
3437 default_bb = create_empty_bb (l0_bb);
3438 l1 = NULL_TREE;
3439 l2 = tree_block_label (default_bb);
3442 /* We will build a switch() with enough cases for all the
3443 OMP_SECTION regions, a '0' case to handle the end of more work
3444 and a default case to abort if something goes wrong. */
3445 len = EDGE_COUNT (l0_bb->succs);
3446 label_vec = make_tree_vec (len + 1);
3448 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3449 OMP_SECTIONS statement. */
3450 si = bsi_last (entry_bb);
3451 sections_stmt = bsi_stmt (si);
3452 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3453 vin = OMP_SECTIONS_CONTROL (sections_stmt);
3454 if (!is_combined_parallel (region))
3456 /* If we are not inside a combined parallel+sections region,
3457 call GOMP_sections_start. */
3458 t = build_int_cst (unsigned_type_node,
3459 exit_reachable ? len - 1 : len);
3460 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3461 t = build_call_expr (u, 1, t);
3463 else
3465 /* Otherwise, call GOMP_sections_next. */
3466 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3467 t = build_call_expr (u, 0);
3469 t = build_gimple_modify_stmt (vin, t);
3470 bsi_insert_after (&si, t, BSI_SAME_STMT);
3471 if (gimple_in_ssa_p (cfun))
3472 SSA_NAME_DEF_STMT (vin) = t;
3473 bsi_remove (&si, true);
3475 /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB. */
3476 si = bsi_last (l0_bb);
3477 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
3478 if (exit_reachable)
3480 cont = last_stmt (l1_bb);
3481 gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
3482 vmain = TREE_OPERAND (cont, 1);
3483 vnext = TREE_OPERAND (cont, 0);
3485 else
3487 vmain = vin;
3488 vnext = NULL_TREE;
3491 t = build3 (SWITCH_EXPR, void_type_node, vmain, NULL, label_vec);
3492 bsi_insert_after (&si, t, BSI_SAME_STMT);
3493 bsi_remove (&si, true);
3495 i = 0;
3496 if (exit_reachable)
3498 t = build3 (CASE_LABEL_EXPR, void_type_node,
3499 build_int_cst (unsigned_type_node, 0), NULL, l2);
3500 TREE_VEC_ELT (label_vec, 0) = t;
3501 i++;
3504 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3505 for (inner = region->inner, casei = 1;
3506 inner;
3507 inner = inner->next, i++, casei++)
3509 basic_block s_entry_bb, s_exit_bb;
3511 s_entry_bb = inner->entry;
3512 s_exit_bb = inner->exit;
3514 t = tree_block_label (s_entry_bb);
3515 u = build_int_cst (unsigned_type_node, casei);
3516 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3517 TREE_VEC_ELT (label_vec, i) = u;
3519 si = bsi_last (s_entry_bb);
3520 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3521 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3522 bsi_remove (&si, true);
3523 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3525 if (s_exit_bb == NULL)
3526 continue;
3528 si = bsi_last (s_exit_bb);
3529 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3530 bsi_remove (&si, true);
3532 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3535 /* Error handling code goes in DEFAULT_BB. */
3536 t = tree_block_label (default_bb);
3537 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3538 TREE_VEC_ELT (label_vec, len) = u;
3539 make_edge (l0_bb, default_bb, 0);
3541 si = bsi_start (default_bb);
3542 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3543 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3545 if (exit_reachable)
3547 /* Code to get the next section goes in L1_BB. */
3548 si = bsi_last (l1_bb);
3549 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3551 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3552 t = build_gimple_modify_stmt (vnext, t);
3553 bsi_insert_after (&si, t, BSI_SAME_STMT);
3554 if (gimple_in_ssa_p (cfun))
3555 SSA_NAME_DEF_STMT (vnext) = t;
3556 bsi_remove (&si, true);
3558 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
3560 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3561 si = bsi_last (l2_bb);
3562 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3563 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3564 else
3565 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3566 t = build_call_expr (t, 0);
3567 bsi_insert_after (&si, t, BSI_SAME_STMT);
3568 bsi_remove (&si, true);
3571 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
3575 /* Expand code for an OpenMP single directive. We've already expanded
3576 much of the code, here we simply place the GOMP_barrier call. */
3578 static void
3579 expand_omp_single (struct omp_region *region)
3581 basic_block entry_bb, exit_bb;
3582 block_stmt_iterator si;
3583 bool need_barrier = false;
3585 entry_bb = region->entry;
3586 exit_bb = region->exit;
3588 si = bsi_last (entry_bb);
3589 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3590 be removed. We need to ensure that the thread that entered the single
3591 does not exit before the data is copied out by the other threads. */
3592 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3593 OMP_CLAUSE_COPYPRIVATE))
3594 need_barrier = true;
3595 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3596 bsi_remove (&si, true);
3597 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3599 si = bsi_last (exit_bb);
3600 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3601 force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
3602 false, BSI_SAME_STMT);
3603 bsi_remove (&si, true);
3604 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3608 /* Generic expansion for OpenMP synchronization directives: master,
3609 ordered and critical. All we need to do here is remove the entry
3610 and exit markers for REGION. */
3612 static void
3613 expand_omp_synch (struct omp_region *region)
3615 basic_block entry_bb, exit_bb;
3616 block_stmt_iterator si;
3618 entry_bb = region->entry;
3619 exit_bb = region->exit;
3621 si = bsi_last (entry_bb);
3622 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3623 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3624 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3625 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3626 bsi_remove (&si, true);
3627 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3629 if (exit_bb)
3631 si = bsi_last (exit_bb);
3632 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3633 bsi_remove (&si, true);
3634 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3638 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
3639 operation as a __sync_fetch_and_op builtin. INDEX is log2 of the
3640 size of the data type, and thus usable to find the index of the builtin
3641 decl. Returns false if the expression is not of the proper form. */
3643 static bool
3644 expand_omp_atomic_fetch_op (basic_block load_bb,
3645 tree addr, tree loaded_val,
3646 tree stored_val, int index)
3648 enum built_in_function base;
3649 tree decl, itype, call;
3650 enum insn_code *optab;
3651 tree rhs;
3652 basic_block store_bb = single_succ (load_bb);
3653 block_stmt_iterator bsi;
3654 tree stmt;
3656 /* We expect to find the following sequences:
3658 load_bb:
3659 OMP_ATOMIC_LOAD (tmp, mem)
3661 store_bb:
3662 val = tmp OP something; (or: something OP tmp)
3663 OMP_STORE (val)
3665 ???FIXME: Allow a more flexible sequence.
3666 Perhaps use data flow to pick the statements.
3670 bsi = bsi_after_labels (store_bb);
3671 stmt = bsi_stmt (bsi);
3672 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
3673 return false;
3674 bsi_next (&bsi);
3675 if (TREE_CODE (bsi_stmt (bsi)) != OMP_ATOMIC_STORE)
3676 return false;
3678 if (!operand_equal_p (GIMPLE_STMT_OPERAND (stmt, 0), stored_val, 0))
3679 return false;
3681 rhs = GIMPLE_STMT_OPERAND (stmt, 1);
3683 /* Check for one of the supported fetch-op operations. */
3684 switch (TREE_CODE (rhs))
3686 case PLUS_EXPR:
3687 case POINTER_PLUS_EXPR:
3688 base = BUILT_IN_FETCH_AND_ADD_N;
3689 optab = sync_add_optab;
3690 break;
3691 case MINUS_EXPR:
3692 base = BUILT_IN_FETCH_AND_SUB_N;
3693 optab = sync_add_optab;
3694 break;
3695 case BIT_AND_EXPR:
3696 base = BUILT_IN_FETCH_AND_AND_N;
3697 optab = sync_and_optab;
3698 break;
3699 case BIT_IOR_EXPR:
3700 base = BUILT_IN_FETCH_AND_OR_N;
3701 optab = sync_ior_optab;
3702 break;
3703 case BIT_XOR_EXPR:
3704 base = BUILT_IN_FETCH_AND_XOR_N;
3705 optab = sync_xor_optab;
3706 break;
3707 default:
3708 return false;
3710 /* Make sure the expression is of the proper form. */
3711 if (operand_equal_p (TREE_OPERAND (rhs, 0), loaded_val, 0))
3712 rhs = TREE_OPERAND (rhs, 1);
3713 else if (commutative_tree_code (TREE_CODE (rhs))
3714 && operand_equal_p (TREE_OPERAND (rhs, 1), loaded_val, 0))
3715 rhs = TREE_OPERAND (rhs, 0);
3716 else
3717 return false;
3719 decl = built_in_decls[base + index + 1];
3720 itype = TREE_TYPE (TREE_TYPE (decl));
3722 if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing)
3723 return false;
3725 bsi = bsi_last (load_bb);
3726 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
3727 call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
3728 force_gimple_operand_bsi (&bsi, call, true, NULL_TREE, true, BSI_SAME_STMT);
3729 bsi_remove (&bsi, true);
3731 bsi = bsi_last (store_bb);
3732 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
3733 bsi_remove (&bsi, true);
3734 bsi = bsi_last (store_bb);
3735 bsi_remove (&bsi, true);
3737 if (gimple_in_ssa_p (cfun))
3738 update_ssa (TODO_update_ssa_no_phi);
3740 return true;
3743 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
3745 oldval = *addr;
3746 repeat:
3747 newval = rhs; // with oldval replacing *addr in rhs
3748 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
3749 if (oldval != newval)
3750 goto repeat;
3752 INDEX is log2 of the size of the data type, and thus usable to find the
3753 index of the builtin decl. */
3755 static bool
3756 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
3757 tree addr, tree loaded_val, tree stored_val,
3758 int index)
3760 tree loadedi, storedi, initial, new_stored, new_storedi, old_vali;
3761 tree type, itype, cmpxchg, iaddr;
3762 block_stmt_iterator bsi;
3763 basic_block loop_header = single_succ (load_bb);
3764 tree phi, x;
3765 edge e;
3767 cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1];
3768 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
3769 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
3771 if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing)
3772 return false;
3774 /* Load the initial value, replacing the OMP_ATOMIC_LOAD. */
3775 bsi = bsi_last (load_bb);
3776 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
3777 initial = force_gimple_operand_bsi (&bsi, build_fold_indirect_ref (addr),
3778 true, NULL_TREE, true, BSI_SAME_STMT);
3779 /* Move the value to the LOADED_VAL temporary. */
3780 if (gimple_in_ssa_p (cfun))
3782 gcc_assert (phi_nodes (loop_header) == NULL_TREE);
3783 phi = create_phi_node (loaded_val, loop_header);
3784 SSA_NAME_DEF_STMT (loaded_val) = phi;
3785 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
3786 initial);
3788 else
3789 bsi_insert_before (&bsi,
3790 build_gimple_modify_stmt (loaded_val, initial),
3791 BSI_SAME_STMT);
3792 bsi_remove (&bsi, true);
3794 bsi = bsi_last (store_bb);
3795 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
3797 /* For floating-point values, we'll need to view-convert them to integers
3798 so that we can perform the atomic compare and swap. Simplify the
3799 following code by always setting up the "i"ntegral variables. */
3800 if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3802 loadedi = loaded_val;
3803 storedi = stored_val;
3804 iaddr = addr;
3806 else
3808 loadedi = force_gimple_operand_bsi (&bsi,
3809 build1 (VIEW_CONVERT_EXPR, itype,
3810 loaded_val), true,
3811 NULL_TREE, true, BSI_SAME_STMT);
3812 storedi =
3813 force_gimple_operand_bsi (&bsi,
3814 build1 (VIEW_CONVERT_EXPR, itype,
3815 stored_val), true, NULL_TREE, true,
3816 BSI_SAME_STMT);
3817 iaddr = fold_convert (build_pointer_type (itype), addr);
3820 /* Build the compare&swap statement. */
3821 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
3822 new_storedi = force_gimple_operand_bsi (&bsi,
3823 fold_convert (itype, new_storedi),
3824 true, NULL_TREE,
3825 true, BSI_SAME_STMT);
3826 if (storedi == stored_val)
3827 new_stored = new_storedi;
3828 else
3829 new_stored = force_gimple_operand_bsi (&bsi,
3830 build1 (VIEW_CONVERT_EXPR, type,
3831 new_storedi), true,
3832 NULL_TREE, true, BSI_SAME_STMT);
3834 if (gimple_in_ssa_p (cfun))
3835 old_vali = loadedi;
3836 else
3838 old_vali = create_tmp_var (itype, NULL);
3839 x = build_gimple_modify_stmt (old_vali, loadedi);
3840 bsi_insert_before (&bsi, x, BSI_SAME_STMT);
3842 x = build_gimple_modify_stmt (loaded_val, new_stored);
3843 bsi_insert_before (&bsi, x, BSI_SAME_STMT);
3846 /* Note that we always perform the comparison as an integer, even for
3847 floating point. This allows the atomic operation to properly
3848 succeed even with NaNs and -0.0. */
3849 x = build3 (COND_EXPR, void_type_node,
3850 build2 (NE_EXPR, boolean_type_node,
3851 new_storedi, old_vali), NULL_TREE, NULL_TREE);
3852 bsi_insert_before (&bsi, x, BSI_SAME_STMT);
3854 /* Update cfg. */
3855 e = single_succ_edge (store_bb);
3856 e->flags &= ~EDGE_FALLTHRU;
3857 e->flags |= EDGE_FALSE_VALUE;
3859 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
3861 /* Copy the new value to loaded_val (we already did that before the condition
3862 if we are not in SSA). */
3863 if (gimple_in_ssa_p (cfun))
3865 phi = phi_nodes (loop_header);
3866 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_stored);
3869 /* Remove OMP_ATOMIC_STORE. */
3870 bsi_remove (&bsi, true);
3872 if (gimple_in_ssa_p (cfun))
3873 update_ssa (TODO_update_ssa_no_phi);
3875 return true;
3878 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
3880 GOMP_atomic_start ();
3881 *addr = rhs;
3882 GOMP_atomic_end ();
3884 The result is not globally atomic, but works so long as all parallel
3885 references are within #pragma omp atomic directives. According to
3886 responses received from omp@openmp.org, appears to be within spec.
3887 Which makes sense, since that's how several other compilers handle
3888 this situation as well.
3889 LOADED_VAL and ADDR are the operands of OMP_ATOMIC_LOAD we're expanding.
3890 STORED_VAL is the operand of the matching OMP_ATOMIC_STORE.
3892 We replace
3893 OMP_ATOMIC_LOAD (loaded_val, addr) with
3894 loaded_val = *addr;
3896 and replace
3897 OMP_ATOMIC_ATORE (stored_val) with
3898 *addr = stored_val;
3901 static bool
3902 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
3903 tree addr, tree loaded_val, tree stored_val)
3905 block_stmt_iterator bsi;
3906 tree t;
3908 bsi = bsi_last (load_bb);
3909 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_LOAD);
3911 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
3912 t = build_function_call_expr (t, 0);
3913 force_gimple_operand_bsi (&bsi, t, true, NULL_TREE, true, BSI_SAME_STMT);
3915 t = build_gimple_modify_stmt (loaded_val, build_fold_indirect_ref (addr));
3916 if (gimple_in_ssa_p (cfun))
3917 SSA_NAME_DEF_STMT (loaded_val) = t;
3918 bsi_insert_before (&bsi, t, BSI_SAME_STMT);
3919 bsi_remove (&bsi, true);
3921 bsi = bsi_last (store_bb);
3922 gcc_assert (TREE_CODE (bsi_stmt (bsi)) == OMP_ATOMIC_STORE);
3924 t = build_gimple_modify_stmt (build_fold_indirect_ref (unshare_expr (addr)),
3925 stored_val);
3926 bsi_insert_before (&bsi, t, BSI_SAME_STMT);
3928 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
3929 t = build_function_call_expr (t, 0);
3930 force_gimple_operand_bsi (&bsi, t, true, NULL_TREE, true, BSI_SAME_STMT);
3931 bsi_remove (&bsi, true);
3933 if (gimple_in_ssa_p (cfun))
3934 update_ssa (TODO_update_ssa_no_phi);
3935 return true;
3938 /* Expand an OMP_ATOMIC statement. We try to expand
3939 using expand_omp_atomic_fetch_op. If it failed, we try to
3940 call expand_omp_atomic_pipeline, and if it fails too, the
3941 ultimate fallback is wrapping the operation in a mutex
3942 (expand_omp_atomic_mutex). REGION is the atomic region built
3943 by build_omp_regions_1(). */
3945 static void
3946 expand_omp_atomic (struct omp_region *region)
3948 basic_block load_bb = region->entry, store_bb = region->exit;
3949 tree load = last_stmt (load_bb), store = last_stmt (store_bb);
3950 tree loaded_val = TREE_OPERAND (load, 0);
3951 tree addr = TREE_OPERAND (load, 1);
3952 tree stored_val = TREE_OPERAND (store, 0);
3953 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
3954 HOST_WIDE_INT index;
3956 /* Make sure the type is one of the supported sizes. */
3957 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
3958 index = exact_log2 (index);
3959 if (index >= 0 && index <= 4)
3961 unsigned int align = TYPE_ALIGN_UNIT (type);
3963 /* __sync builtins require strict data alignment. */
3964 if (exact_log2 (align) >= index)
3966 /* When possible, use specialized atomic update functions. */
3967 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3968 && store_bb == single_succ (load_bb))
3970 if (expand_omp_atomic_fetch_op (load_bb, addr,
3971 loaded_val, stored_val, index))
3972 return;
3975 /* If we don't have specialized __sync builtins, try and implement
3976 as a compare and swap loop. */
3977 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
3978 loaded_val, stored_val, index))
3979 return;
3983 /* The ultimate fallback is wrapping the operation in a mutex. */
3984 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
3988 /* Expand the parallel region tree rooted at REGION. Expansion
3989 proceeds in depth-first order. Innermost regions are expanded
3990 first. This way, parallel regions that require a new function to
3991 be created (e.g., OMP_PARALLEL) can be expanded without having any
3992 internal dependencies in their body. */
3994 static void
3995 expand_omp (struct omp_region *region)
3997 while (region)
3999 /* First, determine whether this is a combined parallel+workshare
4000 region. */
4001 if (region->type == OMP_PARALLEL)
4002 determine_parallel_type (region);
4004 if (region->inner)
4005 expand_omp (region->inner);
4007 switch (region->type)
4009 case OMP_PARALLEL:
4010 expand_omp_parallel (region);
4011 break;
4013 case OMP_FOR:
4014 expand_omp_for (region);
4015 break;
4017 case OMP_SECTIONS:
4018 expand_omp_sections (region);
4019 break;
4021 case OMP_SECTION:
4022 /* Individual omp sections are handled together with their
4023 parent OMP_SECTIONS region. */
4024 break;
4026 case OMP_SINGLE:
4027 expand_omp_single (region);
4028 break;
4030 case OMP_MASTER:
4031 case OMP_ORDERED:
4032 case OMP_CRITICAL:
4033 expand_omp_synch (region);
4034 break;
4036 case OMP_ATOMIC_LOAD:
4037 expand_omp_atomic (region);
4038 break;
4041 default:
4042 gcc_unreachable ();
4045 region = region->next;
4050 /* Helper for build_omp_regions. Scan the dominator tree starting at
4051 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
4052 true, the function ends once a single tree is built (otherwise, whole
4053 forest of OMP constructs may be built). */
4055 static void
4056 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
4057 bool single_tree)
4059 block_stmt_iterator si;
4060 tree stmt;
4061 basic_block son;
4063 si = bsi_last (bb);
4064 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
4066 struct omp_region *region;
4067 enum tree_code code;
4069 stmt = bsi_stmt (si);
4070 code = TREE_CODE (stmt);
4071 if (code == OMP_RETURN)
4073 /* STMT is the return point out of region PARENT. Mark it
4074 as the exit point and make PARENT the immediately
4075 enclosing region. */
4076 gcc_assert (parent);
4077 region = parent;
4078 region->exit = bb;
4079 parent = parent->outer;
4081 else if (code == OMP_ATOMIC_STORE)
4083 /* OMP_ATOMIC_STORE is analoguous to OMP_RETURN, but matches with
4084 OMP_ATOMIC_LOAD. */
4085 gcc_assert (parent);
4086 gcc_assert (parent->type == OMP_ATOMIC_LOAD);
4087 region = parent;
4088 region->exit = bb;
4089 parent = parent->outer;
4092 else if (code == OMP_CONTINUE)
4094 gcc_assert (parent);
4095 parent->cont = bb;
4097 else if (code == OMP_SECTIONS_SWITCH)
4099 /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
4100 it. */ ;
4102 else
4104 /* Otherwise, this directive becomes the parent for a new
4105 region. */
4106 region = new_omp_region (bb, code, parent);
4107 parent = region;
4111 if (single_tree && !parent)
4112 return;
4114 for (son = first_dom_son (CDI_DOMINATORS, bb);
4115 son;
4116 son = next_dom_son (CDI_DOMINATORS, son))
4117 build_omp_regions_1 (son, parent, single_tree);
4120 /* Builds the tree of OMP regions rooted at ROOT, storing it to
4121 root_omp_region. */
4123 static void
4124 build_omp_regions_root (basic_block root)
4126 gcc_assert (root_omp_region == NULL);
4127 build_omp_regions_1 (root, NULL, true);
4128 gcc_assert (root_omp_region != NULL);
4131 /* Expands omp construct (and its subconstructs) starting in HEAD. */
4133 void
4134 omp_expand_local (basic_block head)
4136 build_omp_regions_root (head);
4137 if (dump_file && (dump_flags & TDF_DETAILS))
4139 fprintf (dump_file, "\nOMP region tree\n\n");
4140 dump_omp_region (dump_file, root_omp_region, 0);
4141 fprintf (dump_file, "\n");
4144 remove_exit_barriers (root_omp_region);
4145 expand_omp (root_omp_region);
4147 free_omp_regions ();
4150 /* Scan the CFG and build a tree of OMP regions. Return the root of
4151 the OMP region tree. */
4153 static void
4154 build_omp_regions (void)
4156 gcc_assert (root_omp_region == NULL);
4157 calculate_dominance_info (CDI_DOMINATORS);
4158 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
4162 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
4164 static unsigned int
4165 execute_expand_omp (void)
4167 build_omp_regions ();
4169 if (!root_omp_region)
4170 return 0;
4172 if (dump_file)
4174 fprintf (dump_file, "\nOMP region tree\n\n");
4175 dump_omp_region (dump_file, root_omp_region, 0);
4176 fprintf (dump_file, "\n");
4179 remove_exit_barriers (root_omp_region);
4181 expand_omp (root_omp_region);
4183 cleanup_tree_cfg ();
4185 free_omp_regions ();
4187 return 0;
4190 /* OMP expansion in SSA form. For testing purposes only. */
4192 static bool
4193 gate_expand_omp_ssa (void)
4195 return flag_openmp_ssa && flag_openmp != 0 && errorcount == 0;
4198 struct gimple_opt_pass pass_expand_omp_ssa =
4201 GIMPLE_PASS,
4202 "ompexpssa", /* name */
4203 gate_expand_omp_ssa, /* gate */
4204 execute_expand_omp, /* execute */
4205 NULL, /* sub */
4206 NULL, /* next */
4207 0, /* static_pass_number */
4208 0, /* tv_id */
4209 PROP_gimple_any, /* properties_required */
4210 PROP_gimple_lomp, /* properties_provided */
4211 0, /* properties_destroyed */
4212 0, /* todo_flags_start */
4213 TODO_dump_func /* todo_flags_finish */
4217 /* OMP expansion -- the default pass, run before creation of SSA form. */
4219 static bool
4220 gate_expand_omp (void)
4222 return ((!flag_openmp_ssa || !optimize)
4223 && flag_openmp != 0 && errorcount == 0);
4226 struct gimple_opt_pass pass_expand_omp =
4229 GIMPLE_PASS,
4230 "ompexp", /* name */
4231 gate_expand_omp, /* gate */
4232 execute_expand_omp, /* execute */
4233 NULL, /* sub */
4234 NULL, /* next */
4235 0, /* static_pass_number */
4236 0, /* tv_id */
4237 PROP_gimple_any, /* properties_required */
4238 PROP_gimple_lomp, /* properties_provided */
4239 0, /* properties_destroyed */
4240 0, /* todo_flags_start */
4241 TODO_dump_func /* todo_flags_finish */
4245 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
4247 /* Lower the OpenMP sections directive in *STMT_P. */
4249 static void
4250 lower_omp_sections (tree *stmt_p, omp_context *ctx)
4252 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body, control;
4253 tree t, dlist;
4254 tree_stmt_iterator tsi;
4255 unsigned i, len;
4257 stmt = *stmt_p;
4259 push_gimplify_context ();
4261 dlist = NULL;
4262 ilist = NULL;
4263 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
4265 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
4266 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
4267 continue;
4269 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
4270 body = alloc_stmt_list ();
4271 for (i = 0; i < len; i++, tsi_next (&tsi))
4273 omp_context *sctx;
4274 tree sec_start, sec_end;
4276 sec_start = tsi_stmt (tsi);
4277 sctx = maybe_lookup_ctx (sec_start);
4278 gcc_assert (sctx);
4280 append_to_statement_list (sec_start, &body);
4282 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
4283 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
4284 OMP_SECTION_BODY (sec_start) = NULL;
4286 if (i == len - 1)
4288 tree l = alloc_stmt_list ();
4289 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
4290 &l, ctx);
4291 append_to_statement_list (l, &body);
4292 OMP_SECTION_LAST (sec_start) = 1;
4295 sec_end = make_node (OMP_RETURN);
4296 append_to_statement_list (sec_end, &body);
4299 block = make_node (BLOCK);
4300 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
4302 olist = NULL_TREE;
4303 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
4305 pop_gimplify_context (NULL_TREE);
4306 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4308 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4309 TREE_SIDE_EFFECTS (new_stmt) = 1;
4311 new_body = alloc_stmt_list ();
4312 append_to_statement_list (ilist, &new_body);
4313 append_to_statement_list (stmt, &new_body);
4314 append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
4315 append_to_statement_list (bind, &new_body);
4317 control = create_tmp_var (unsigned_type_node, ".section");
4318 t = build2 (OMP_CONTINUE, void_type_node, control, control);
4319 OMP_SECTIONS_CONTROL (stmt) = control;
4320 append_to_statement_list (t, &new_body);
4322 append_to_statement_list (olist, &new_body);
4323 append_to_statement_list (dlist, &new_body);
4325 maybe_catch_exception (&new_body);
4327 t = make_node (OMP_RETURN);
4328 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
4329 OMP_CLAUSE_NOWAIT);
4330 append_to_statement_list (t, &new_body);
4332 BIND_EXPR_BODY (new_stmt) = new_body;
4333 OMP_SECTIONS_BODY (stmt) = NULL;
4335 *stmt_p = new_stmt;
4339 /* A subroutine of lower_omp_single. Expand the simple form of
4340 an OMP_SINGLE, without a copyprivate clause:
4342 if (GOMP_single_start ())
4343 BODY;
4344 [ GOMP_barrier (); ] -> unless 'nowait' is present.
4346 FIXME. It may be better to delay expanding the logic of this until
4347 pass_expand_omp. The expanded logic may make the job more difficult
4348 to a synchronization analysis pass. */
4350 static void
4351 lower_omp_single_simple (tree single_stmt, tree *pre_p)
4353 tree t;
4355 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
4356 t = build3 (COND_EXPR, void_type_node, t,
4357 OMP_SINGLE_BODY (single_stmt), NULL);
4358 gimplify_and_add (t, pre_p);
4362 /* A subroutine of lower_omp_single. Expand the simple form of
4363 an OMP_SINGLE, with a copyprivate clause:
4365 #pragma omp single copyprivate (a, b, c)
4367 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
4370 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
4372 BODY;
4373 copyout.a = a;
4374 copyout.b = b;
4375 copyout.c = c;
4376 GOMP_single_copy_end (&copyout);
4378 else
4380 a = copyout_p->a;
4381 b = copyout_p->b;
4382 c = copyout_p->c;
4384 GOMP_barrier ();
4387 FIXME. It may be better to delay expanding the logic of this until
4388 pass_expand_omp. The expanded logic may make the job more difficult
4389 to a synchronization analysis pass. */
4391 static void
4392 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
4394 tree ptr_type, t, l0, l1, l2, copyin_seq;
4396 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
4398 ptr_type = build_pointer_type (ctx->record_type);
4399 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
4401 l0 = create_artificial_label ();
4402 l1 = create_artificial_label ();
4403 l2 = create_artificial_label ();
4405 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
4406 t = fold_convert (ptr_type, t);
4407 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4408 gimplify_and_add (t, pre_p);
4410 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
4411 build_int_cst (ptr_type, 0));
4412 t = build3 (COND_EXPR, void_type_node, t,
4413 build_and_jump (&l0), build_and_jump (&l1));
4414 gimplify_and_add (t, pre_p);
4416 t = build1 (LABEL_EXPR, void_type_node, l0);
4417 gimplify_and_add (t, pre_p);
4419 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
4421 copyin_seq = NULL;
4422 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
4423 &copyin_seq, ctx);
4425 t = build_fold_addr_expr (ctx->sender_decl);
4426 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
4427 gimplify_and_add (t, pre_p);
4429 t = build_and_jump (&l2);
4430 gimplify_and_add (t, pre_p);
4432 t = build1 (LABEL_EXPR, void_type_node, l1);
4433 gimplify_and_add (t, pre_p);
4435 append_to_statement_list (copyin_seq, pre_p);
4437 t = build1 (LABEL_EXPR, void_type_node, l2);
4438 gimplify_and_add (t, pre_p);
4442 /* Expand code for an OpenMP single directive. */
4444 static void
4445 lower_omp_single (tree *stmt_p, omp_context *ctx)
4447 tree t, bind, block, single_stmt = *stmt_p, dlist;
4449 push_gimplify_context ();
4451 block = make_node (BLOCK);
4452 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4453 TREE_SIDE_EFFECTS (bind) = 1;
4455 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
4456 &BIND_EXPR_BODY (bind), &dlist, ctx);
4457 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
4459 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
4461 if (ctx->record_type)
4462 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
4463 else
4464 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
4466 OMP_SINGLE_BODY (single_stmt) = NULL;
4468 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
4470 maybe_catch_exception (&BIND_EXPR_BODY (bind));
4472 t = make_node (OMP_RETURN);
4473 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
4474 OMP_CLAUSE_NOWAIT);
4475 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4477 pop_gimplify_context (bind);
4479 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4480 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4484 /* Expand code for an OpenMP master directive. */
4486 static void
4487 lower_omp_master (tree *stmt_p, omp_context *ctx)
4489 tree bind, block, stmt = *stmt_p, lab = NULL, x;
4491 push_gimplify_context ();
4493 block = make_node (BLOCK);
4494 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4495 TREE_SIDE_EFFECTS (bind) = 1;
4497 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4499 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
4500 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
4501 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
4502 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4504 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
4505 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
4506 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
4507 OMP_MASTER_BODY (stmt) = NULL;
4509 x = build1 (LABEL_EXPR, void_type_node, lab);
4510 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4512 x = make_node (OMP_RETURN);
4513 OMP_RETURN_NOWAIT (x) = 1;
4514 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4516 pop_gimplify_context (bind);
4518 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4519 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4523 /* Expand code for an OpenMP ordered directive. */
4525 static void
4526 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
4528 tree bind, block, stmt = *stmt_p, x;
4530 push_gimplify_context ();
4532 block = make_node (BLOCK);
4533 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4534 TREE_SIDE_EFFECTS (bind) = 1;
4536 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4538 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
4539 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4541 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
4542 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
4543 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
4544 OMP_ORDERED_BODY (stmt) = NULL;
4546 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
4547 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
4549 x = make_node (OMP_RETURN);
4550 OMP_RETURN_NOWAIT (x) = 1;
4551 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
4553 pop_gimplify_context (bind);
4555 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4556 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4560 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
4561 substitution of a couple of function calls. But in the NAMED case,
4562 requires that languages coordinate a symbol name. It is therefore
4563 best put here in common code. */
4565 static GTY((param1_is (tree), param2_is (tree)))
4566 splay_tree critical_name_mutexes;
4568 static void
4569 lower_omp_critical (tree *stmt_p, omp_context *ctx)
4571 tree bind, block, stmt = *stmt_p;
4572 tree t, lock, unlock, name;
4574 name = OMP_CRITICAL_NAME (stmt);
4575 if (name)
4577 tree decl;
4578 splay_tree_node n;
4580 if (!critical_name_mutexes)
4581 critical_name_mutexes
4582 = splay_tree_new_ggc (splay_tree_compare_pointers);
4584 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
4585 if (n == NULL)
4587 char *new_str;
4589 decl = create_tmp_var_raw (ptr_type_node, NULL);
4591 new_str = ACONCAT ((".gomp_critical_user_",
4592 IDENTIFIER_POINTER (name), NULL));
4593 DECL_NAME (decl) = get_identifier (new_str);
4594 TREE_PUBLIC (decl) = 1;
4595 TREE_STATIC (decl) = 1;
4596 DECL_COMMON (decl) = 1;
4597 DECL_ARTIFICIAL (decl) = 1;
4598 DECL_IGNORED_P (decl) = 1;
4599 varpool_finalize_decl (decl);
4601 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
4602 (splay_tree_value) decl);
4604 else
4605 decl = (tree) n->value;
4607 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
4608 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
4610 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
4611 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
4613 else
4615 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
4616 lock = build_call_expr (lock, 0);
4618 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
4619 unlock = build_call_expr (unlock, 0);
4622 push_gimplify_context ();
4624 block = make_node (BLOCK);
4625 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
4626 TREE_SIDE_EFFECTS (bind) = 1;
4628 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4630 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
4632 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
4633 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
4634 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
4635 OMP_CRITICAL_BODY (stmt) = NULL;
4637 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
4639 t = make_node (OMP_RETURN);
4640 OMP_RETURN_NOWAIT (t) = 1;
4641 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
4643 pop_gimplify_context (bind);
4644 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
4645 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
4649 /* A subroutine of lower_omp_for. Generate code to emit the predicate
4650 for a lastprivate clause. Given a loop control predicate of (V
4651 cond N2), we gate the clause on (!(V cond N2)). The lowered form
4652 is appended to *DLIST, iterator initialization is appended to
4653 *BODY_P. */
4655 static void
4656 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
4657 tree *dlist, struct omp_context *ctx)
4659 tree clauses, cond, stmts, vinit, t;
4660 enum tree_code cond_code;
4662 cond_code = fd->cond_code;
4663 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
4665 /* When possible, use a strict equality expression. This can let VRP
4666 type optimizations deduce the value and remove a copy. */
4667 if (host_integerp (fd->step, 0))
4669 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
4670 if (step == 1 || step == -1)
4671 cond_code = EQ_EXPR;
4674 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
4676 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
4677 stmts = NULL;
4678 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
4679 if (stmts != NULL)
4681 append_to_statement_list (stmts, dlist);
4683 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
4684 vinit = fd->n1;
4685 if (cond_code == EQ_EXPR
4686 && host_integerp (fd->n2, 0)
4687 && ! integer_zerop (fd->n2))
4688 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
4690 /* Initialize the iterator variable, so that threads that don't execute
4691 any iterations don't execute the lastprivate clauses by accident. */
4692 t = build_gimple_modify_stmt (fd->v, vinit);
4693 gimplify_and_add (t, body_p);
4698 /* Lower code for an OpenMP loop directive. */
4700 static void
4701 lower_omp_for (tree *stmt_p, omp_context *ctx)
4703 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
4704 struct omp_for_data fd;
4706 stmt = *stmt_p;
4708 push_gimplify_context ();
4710 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4711 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4713 /* Move declaration of temporaries in the loop body before we make
4714 it go away. */
4715 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4716 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4718 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4719 TREE_SIDE_EFFECTS (new_stmt) = 1;
4720 body_p = &BIND_EXPR_BODY (new_stmt);
4722 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4723 ilist = NULL;
4724 dlist = NULL;
4725 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4726 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4728 /* Lower the header expressions. At this point, we can assume that
4729 the header is of the form:
4731 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4733 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4734 using the .omp_data_s mapping, if needed. */
4735 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4736 if (!is_gimple_min_invariant (*rhs_p))
4737 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4739 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4740 if (!is_gimple_min_invariant (*rhs_p))
4741 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4743 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4744 if (!is_gimple_min_invariant (*rhs_p))
4745 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4747 /* Once lowered, extract the bounds and clauses. */
4748 extract_omp_for_data (stmt, &fd);
4750 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4752 append_to_statement_list (stmt, body_p);
4754 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4756 t = build2 (OMP_CONTINUE, void_type_node, fd.v, fd.v);
4757 append_to_statement_list (t, body_p);
4759 /* After the loop, add exit clauses. */
4760 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4761 append_to_statement_list (dlist, body_p);
4763 maybe_catch_exception (body_p);
4765 /* Region exit marker goes at the end of the loop body. */
4766 t = make_node (OMP_RETURN);
4767 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4768 append_to_statement_list (t, body_p);
4770 pop_gimplify_context (NULL_TREE);
4771 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4773 OMP_FOR_BODY (stmt) = NULL_TREE;
4774 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4775 *stmt_p = new_stmt;
4778 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
4779 or OMP_PARALLEL. */
4781 static tree
4782 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4784 struct walk_stmt_info *wi = data;
4785 int *info = wi->info;
4787 *walk_subtrees = 0;
4788 switch (TREE_CODE (*tp))
4790 case OMP_FOR:
4791 case OMP_SECTIONS:
4792 *info = *info == 0 ? 1 : -1;
4793 break;
4794 default:
4795 *info = -1;
4796 break;
4798 return NULL;
4801 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4802 information for the directive. */
4804 static void
4805 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4807 tree clauses, par_bind, par_body, new_body, bind;
4808 tree olist, ilist, par_olist, par_ilist;
4809 tree stmt, child_fn, t;
4811 stmt = *stmt_p;
4813 clauses = OMP_PARALLEL_CLAUSES (stmt);
4814 par_bind = OMP_PARALLEL_BODY (stmt);
4815 par_body = BIND_EXPR_BODY (par_bind);
4816 child_fn = ctx->cb.dst_fn;
4817 if (!OMP_PARALLEL_COMBINED (stmt))
4819 struct walk_stmt_info wi;
4820 int ws_num = 0;
4822 memset (&wi, 0, sizeof (wi));
4823 wi.callback = check_combined_parallel;
4824 wi.info = &ws_num;
4825 wi.val_only = true;
4826 walk_stmts (&wi, &par_bind);
4827 if (ws_num == 1)
4828 OMP_PARALLEL_COMBINED (stmt) = 1;
4831 push_gimplify_context ();
4833 par_olist = NULL_TREE;
4834 par_ilist = NULL_TREE;
4835 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4836 lower_omp (&par_body, ctx);
4837 lower_reduction_clauses (clauses, &par_olist, ctx);
4839 /* Declare all the variables created by mapping and the variables
4840 declared in the scope of the parallel body. */
4841 record_vars_into (ctx->block_vars, child_fn);
4842 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4844 if (ctx->record_type)
4846 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4847 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4850 olist = NULL_TREE;
4851 ilist = NULL_TREE;
4852 lower_send_clauses (clauses, &ilist, &olist, ctx);
4853 lower_send_shared_vars (&ilist, &olist, ctx);
4855 /* Once all the expansions are done, sequence all the different
4856 fragments inside OMP_PARALLEL_BODY. */
4857 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4858 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4860 new_body = alloc_stmt_list ();
4862 if (ctx->record_type)
4864 t = build_fold_addr_expr (ctx->sender_decl);
4865 /* fixup_child_record_type might have changed receiver_decl's type. */
4866 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4867 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4868 append_to_statement_list (t, &new_body);
4871 append_to_statement_list (par_ilist, &new_body);
4872 append_to_statement_list (par_body, &new_body);
4873 append_to_statement_list (par_olist, &new_body);
4874 maybe_catch_exception (&new_body);
4875 t = make_node (OMP_RETURN);
4876 append_to_statement_list (t, &new_body);
4877 OMP_PARALLEL_BODY (stmt) = new_body;
4879 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4880 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4882 *stmt_p = bind;
4884 pop_gimplify_context (NULL_TREE);
4887 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
4888 regimplified. */
4890 static tree
4891 lower_omp_2 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
4893 tree t = *tp;
4895 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4896 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4897 return t;
4899 /* If a global variable has been privatized, TREE_CONSTANT on
4900 ADDR_EXPR might be wrong. */
4901 if (TREE_CODE (t) == ADDR_EXPR)
4902 recompute_tree_invariant_for_addr_expr (t);
4904 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4905 return NULL_TREE;
4908 static void
4909 lower_omp_1 (tree *tp, omp_context *ctx, tree_stmt_iterator *tsi)
4911 tree t = *tp;
4913 if (!t)
4914 return;
4916 if (EXPR_HAS_LOCATION (t))
4917 input_location = EXPR_LOCATION (t);
4919 /* If we have issued syntax errors, avoid doing any heavy lifting.
4920 Just replace the OpenMP directives with a NOP to avoid
4921 confusing RTL expansion. */
4922 if (errorcount && OMP_DIRECTIVE_P (t))
4924 *tp = build_empty_stmt ();
4925 return;
4928 switch (TREE_CODE (t))
4930 case STATEMENT_LIST:
4932 tree_stmt_iterator i;
4933 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
4934 lower_omp_1 (tsi_stmt_ptr (i), ctx, &i);
4936 break;
4938 case COND_EXPR:
4939 lower_omp_1 (&COND_EXPR_THEN (t), ctx, NULL);
4940 lower_omp_1 (&COND_EXPR_ELSE (t), ctx, NULL);
4941 if (ctx
4942 && walk_tree (&COND_EXPR_COND (t), lower_omp_2, ctx, NULL))
4944 tree pre = NULL;
4945 gimplify_expr (&COND_EXPR_COND (t), &pre, NULL,
4946 is_gimple_condexpr, fb_rvalue);
4947 if (pre)
4949 if (tsi)
4950 tsi_link_before (tsi, pre, TSI_SAME_STMT);
4951 else
4953 append_to_statement_list (t, &pre);
4954 *tp = pre;
4958 break;
4959 case CATCH_EXPR:
4960 lower_omp_1 (&CATCH_BODY (t), ctx, NULL);
4961 break;
4962 case EH_FILTER_EXPR:
4963 lower_omp_1 (&EH_FILTER_FAILURE (t), ctx, NULL);
4964 break;
4965 case TRY_CATCH_EXPR:
4966 case TRY_FINALLY_EXPR:
4967 lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
4968 lower_omp_1 (&TREE_OPERAND (t, 1), ctx, NULL);
4969 break;
4970 case BIND_EXPR:
4971 lower_omp_1 (&BIND_EXPR_BODY (t), ctx, NULL);
4972 break;
4973 case RETURN_EXPR:
4974 lower_omp_1 (&TREE_OPERAND (t, 0), ctx, NULL);
4975 break;
4977 case OMP_PARALLEL:
4978 ctx = maybe_lookup_ctx (t);
4979 lower_omp_parallel (tp, ctx);
4980 break;
4981 case OMP_FOR:
4982 ctx = maybe_lookup_ctx (t);
4983 gcc_assert (ctx);
4984 lower_omp_for (tp, ctx);
4985 break;
4986 case OMP_SECTIONS:
4987 ctx = maybe_lookup_ctx (t);
4988 gcc_assert (ctx);
4989 lower_omp_sections (tp, ctx);
4990 break;
4991 case OMP_SINGLE:
4992 ctx = maybe_lookup_ctx (t);
4993 gcc_assert (ctx);
4994 lower_omp_single (tp, ctx);
4995 break;
4996 case OMP_MASTER:
4997 ctx = maybe_lookup_ctx (t);
4998 gcc_assert (ctx);
4999 lower_omp_master (tp, ctx);
5000 break;
5001 case OMP_ORDERED:
5002 ctx = maybe_lookup_ctx (t);
5003 gcc_assert (ctx);
5004 lower_omp_ordered (tp, ctx);
5005 break;
5006 case OMP_CRITICAL:
5007 ctx = maybe_lookup_ctx (t);
5008 gcc_assert (ctx);
5009 lower_omp_critical (tp, ctx);
5010 break;
5012 default:
5013 if (ctx && walk_tree (tp, lower_omp_2, ctx, NULL))
5015 /* The gimplifier doesn't gimplify CALL_EXPR_STATIC_CHAIN.
5016 Handle that here. */
5017 tree call = get_call_expr_in (t);
5018 if (call
5019 && CALL_EXPR_STATIC_CHAIN (call)
5020 && walk_tree (&CALL_EXPR_STATIC_CHAIN (call), lower_omp_2,
5021 ctx, NULL))
5023 tree pre = NULL;
5024 gimplify_expr (&CALL_EXPR_STATIC_CHAIN (call), &pre, NULL,
5025 is_gimple_val, fb_rvalue);
5026 if (pre)
5028 if (tsi)
5029 tsi_link_before (tsi, pre, TSI_SAME_STMT);
5030 else
5032 append_to_statement_list (t, &pre);
5033 lower_omp_1 (&pre, ctx, NULL);
5034 *tp = pre;
5035 return;
5040 if (tsi == NULL)
5041 gimplify_stmt (tp);
5042 else
5044 tree pre = NULL;
5045 gimplify_expr (tp, &pre, NULL, is_gimple_stmt, fb_none);
5046 if (pre)
5047 tsi_link_before (tsi, pre, TSI_SAME_STMT);
5050 break;
5054 static void
5055 lower_omp (tree *stmt_p, omp_context *ctx)
5057 lower_omp_1 (stmt_p, ctx, NULL);
5060 /* Main entry point. */
5062 static unsigned int
5063 execute_lower_omp (void)
5065 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
5066 delete_omp_context);
5068 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
5069 gcc_assert (parallel_nesting_level == 0);
5071 if (all_contexts->root)
5072 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
5074 if (all_contexts)
5076 splay_tree_delete (all_contexts);
5077 all_contexts = NULL;
5079 return 0;
5082 static bool
5083 gate_lower_omp (void)
5085 return flag_openmp != 0;
5088 struct gimple_opt_pass pass_lower_omp =
5091 GIMPLE_PASS,
5092 "omplower", /* name */
5093 gate_lower_omp, /* gate */
5094 execute_lower_omp, /* execute */
5095 NULL, /* sub */
5096 NULL, /* next */
5097 0, /* static_pass_number */
5098 0, /* tv_id */
5099 PROP_gimple_any, /* properties_required */
5100 PROP_gimple_lomp, /* properties_provided */
5101 0, /* properties_destroyed */
5102 0, /* todo_flags_start */
5103 TODO_dump_func /* todo_flags_finish */
5107 /* The following is a utility to diagnose OpenMP structured block violations.
5108 It is not part of the "omplower" pass, as that's invoked too late. It
5109 should be invoked by the respective front ends after gimplification. */
5111 static splay_tree all_labels;
5113 /* Check for mismatched contexts and generate an error if needed. Return
5114 true if an error is detected. */
5116 static bool
5117 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
5119 bool exit_p = true;
5121 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
5122 return false;
5124 /* Try to avoid confusing the user by producing and error message
5125 with correct "exit" or "enter" verbage. We prefer "exit"
5126 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
5127 if (branch_ctx == NULL)
5128 exit_p = false;
5129 else
5131 while (label_ctx)
5133 if (TREE_VALUE (label_ctx) == branch_ctx)
5135 exit_p = false;
5136 break;
5138 label_ctx = TREE_CHAIN (label_ctx);
5142 if (exit_p)
5143 error ("invalid exit from OpenMP structured block");
5144 else
5145 error ("invalid entry to OpenMP structured block");
5147 *stmt_p = build_empty_stmt ();
5148 return true;
5151 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
5152 where in the tree each label is found. */
5154 static tree
5155 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
5157 struct walk_stmt_info *wi = data;
5158 tree context = (tree) wi->info;
5159 tree inner_context;
5160 tree t = *tp;
5162 *walk_subtrees = 0;
5163 switch (TREE_CODE (t))
5165 case OMP_PARALLEL:
5166 case OMP_SECTIONS:
5167 case OMP_SINGLE:
5168 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
5169 /* FALLTHRU */
5170 case OMP_SECTION:
5171 case OMP_MASTER:
5172 case OMP_ORDERED:
5173 case OMP_CRITICAL:
5174 /* The minimal context here is just a tree of statements. */
5175 inner_context = tree_cons (NULL, t, context);
5176 wi->info = inner_context;
5177 walk_stmts (wi, &OMP_BODY (t));
5178 wi->info = context;
5179 break;
5181 case OMP_FOR:
5182 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
5183 inner_context = tree_cons (NULL, t, context);
5184 wi->info = inner_context;
5185 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
5186 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
5187 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
5188 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
5189 walk_stmts (wi, &OMP_FOR_BODY (t));
5190 wi->info = context;
5191 break;
5193 case LABEL_EXPR:
5194 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
5195 (splay_tree_value) context);
5196 break;
5198 default:
5199 break;
5202 return NULL_TREE;
5205 /* Pass 2: Check each branch and see if its context differs from that of
5206 the destination label's context. */
5208 static tree
5209 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
5211 struct walk_stmt_info *wi = data;
5212 tree context = (tree) wi->info;
5213 splay_tree_node n;
5214 tree t = *tp;
5216 *walk_subtrees = 0;
5217 switch (TREE_CODE (t))
5219 case OMP_PARALLEL:
5220 case OMP_SECTIONS:
5221 case OMP_SINGLE:
5222 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
5223 /* FALLTHRU */
5224 case OMP_SECTION:
5225 case OMP_MASTER:
5226 case OMP_ORDERED:
5227 case OMP_CRITICAL:
5228 wi->info = t;
5229 walk_stmts (wi, &OMP_BODY (t));
5230 wi->info = context;
5231 break;
5233 case OMP_FOR:
5234 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
5235 wi->info = t;
5236 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
5237 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
5238 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
5239 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
5240 walk_stmts (wi, &OMP_FOR_BODY (t));
5241 wi->info = context;
5242 break;
5244 case GOTO_EXPR:
5246 tree lab = GOTO_DESTINATION (t);
5247 if (TREE_CODE (lab) != LABEL_DECL)
5248 break;
5250 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
5251 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
5253 break;
5255 case SWITCH_EXPR:
5257 tree vec = SWITCH_LABELS (t);
5258 int i, len = TREE_VEC_LENGTH (vec);
5259 for (i = 0; i < len; ++i)
5261 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
5262 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
5263 if (diagnose_sb_0 (tp, context, (tree) n->value))
5264 break;
5267 break;
5269 case RETURN_EXPR:
5270 diagnose_sb_0 (tp, context, NULL_TREE);
5271 break;
5273 default:
5274 break;
5277 return NULL_TREE;
5280 void
5281 diagnose_omp_structured_block_errors (tree fndecl)
5283 tree save_current = current_function_decl;
5284 struct walk_stmt_info wi;
5286 current_function_decl = fndecl;
5288 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
5290 memset (&wi, 0, sizeof (wi));
5291 wi.callback = diagnose_sb_1;
5292 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
5294 memset (&wi, 0, sizeof (wi));
5295 wi.callback = diagnose_sb_2;
5296 wi.want_locations = true;
5297 wi.want_return_expr = true;
5298 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
5300 splay_tree_delete (all_labels);
5301 all_labels = NULL;
5303 current_function_decl = save_current;
5306 #include "gt-omp-low.h"