* cfgcleanup.c, config/dfp-bit.c, expr.c, fold-const.c,
[official-gcc.git] / gcc / omp-low.c
blobbcc3650c26a1d2247e4f565f6304bfa2947ac98f
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to the Free
22 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "rtl.h"
31 #include "tree-gimple.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
36 #include "timevar.h"
37 #include "flags.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "toplev.h"
41 #include "tree-pass.h"
42 #include "ggc.h"
43 #include "except.h"
46 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
47 phases. The first phase scans the function looking for OMP statements
48 and then for variables that must be replaced to satisfy data sharing
49 clauses. The second phase expands code for the constructs, as well as
50 re-gimplifying things when variables have been replaced with complex
51 expressions.
53 Final code generation is done by pass_expand_omp. The flowgraph is
54 scanned for parallel regions which are then moved to a new
55 function, to be invoked by the thread library. */
57 /* Context structure. Used to store information about each parallel
58 directive in the code. */
60 typedef struct omp_context
62 /* This field must be at the beginning, as we do "inheritance": Some
63 callback functions for tree-inline.c (e.g., omp_copy_decl)
64 receive a copy_body_data pointer that is up-casted to an
65 omp_context pointer. */
66 copy_body_data cb;
68 /* The tree of contexts corresponding to the encountered constructs. */
69 struct omp_context *outer;
70 tree stmt;
72 /* Map variables to fields in a structure that allows communication
73 between sending and receiving threads. */
74 splay_tree field_map;
75 tree record_type;
76 tree sender_decl;
77 tree receiver_decl;
79 /* A chain of variables to add to the top-level block surrounding the
80 construct. In the case of a parallel, this is in the child function. */
81 tree block_vars;
83 /* What to do with variables with implicitly determined sharing
84 attributes. */
85 enum omp_clause_default_kind default_kind;
87 /* Nesting depth of this context. Used to beautify error messages re
88 invalid gotos. The outermost ctx is depth 1, with depth 0 being
89 reserved for the main body of the function. */
90 int depth;
92 /* True if this parallel directive is nested within another. */
93 bool is_nested;
94 } omp_context;
97 /* A structure describing the main elements of a parallel loop. */
99 struct omp_for_data
101 tree v, n1, n2, step, chunk_size, for_stmt;
102 enum tree_code cond_code;
103 tree pre;
104 bool have_nowait, have_ordered;
105 enum omp_clause_schedule_kind sched_kind;
109 static splay_tree all_contexts;
110 static int parallel_nesting_level;
111 struct omp_region *root_omp_region;
113 static void scan_omp (tree *, omp_context *);
114 static void lower_omp (tree *, omp_context *);
116 /* Find an OpenMP clause of type KIND within CLAUSES. */
118 static tree
119 find_omp_clause (tree clauses, enum tree_code kind)
121 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
122 if (OMP_CLAUSE_CODE (clauses) == kind)
123 return clauses;
125 return NULL_TREE;
128 /* Return true if CTX is for an omp parallel. */
130 static inline bool
131 is_parallel_ctx (omp_context *ctx)
133 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
137 /* Return true if REGION is a combined parallel+workshare region. */
139 static inline bool
140 is_combined_parallel (struct omp_region *region)
142 return region->is_combined_parallel;
146 /* Extract the header elements of parallel loop FOR_STMT and store
147 them into *FD. */
149 static void
150 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
152 tree t;
154 fd->for_stmt = for_stmt;
155 fd->pre = NULL;
157 t = OMP_FOR_INIT (for_stmt);
158 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
159 fd->v = TREE_OPERAND (t, 0);
160 gcc_assert (DECL_P (fd->v));
161 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
162 fd->n1 = TREE_OPERAND (t, 1);
164 t = OMP_FOR_COND (for_stmt);
165 fd->cond_code = TREE_CODE (t);
166 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
167 fd->n2 = TREE_OPERAND (t, 1);
168 switch (fd->cond_code)
170 case LT_EXPR:
171 case GT_EXPR:
172 break;
173 case LE_EXPR:
174 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
175 build_int_cst (TREE_TYPE (fd->n2), 1));
176 fd->cond_code = LT_EXPR;
177 break;
178 case GE_EXPR:
179 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
180 build_int_cst (TREE_TYPE (fd->n2), 1));
181 fd->cond_code = GT_EXPR;
182 break;
183 default:
184 gcc_unreachable ();
187 t = OMP_FOR_INCR (fd->for_stmt);
188 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
189 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
190 t = TREE_OPERAND (t, 1);
191 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
192 switch (TREE_CODE (t))
194 case PLUS_EXPR:
195 fd->step = TREE_OPERAND (t, 1);
196 break;
197 case MINUS_EXPR:
198 fd->step = TREE_OPERAND (t, 1);
199 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
200 break;
201 default:
202 gcc_unreachable ();
205 fd->have_nowait = fd->have_ordered = false;
206 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
207 fd->chunk_size = NULL_TREE;
209 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
210 switch (OMP_CLAUSE_CODE (t))
212 case OMP_CLAUSE_NOWAIT:
213 fd->have_nowait = true;
214 break;
215 case OMP_CLAUSE_ORDERED:
216 fd->have_ordered = true;
217 break;
218 case OMP_CLAUSE_SCHEDULE:
219 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
220 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
221 break;
222 default:
223 break;
226 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
227 gcc_assert (fd->chunk_size == NULL);
228 else if (fd->chunk_size == NULL)
230 /* We only need to compute a default chunk size for ordered
231 static loops and dynamic loops. */
232 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
233 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
234 ? integer_zero_node : integer_one_node;
239 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
240 is the immediate dominator of PAR_ENTRY_BB, return true if there
241 are no data dependencies that would prevent expanding the parallel
242 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
244 When expanding a combined parallel+workshare region, the call to
245 the child function may need additional arguments in the case of
246 OMP_FOR regions. In some cases, these arguments are computed out
247 of variables passed in from the parent to the child via 'struct
248 .omp_data_s'. For instance:
250 #pragma omp parallel for schedule (guided, i * 4)
251 for (j ...)
253 Is lowered into:
255 # BLOCK 2 (PAR_ENTRY_BB)
256 .omp_data_o.i = i;
257 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
259 # BLOCK 3 (WS_ENTRY_BB)
260 .omp_data_i = &.omp_data_o;
261 D.1667 = .omp_data_i->i;
262 D.1598 = D.1667 * 4;
263 #pragma omp for schedule (guided, D.1598)
265 When we outline the parallel region, the call to the child function
266 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
267 that value is computed *after* the call site. So, in principle we
268 cannot do the transformation.
270 To see whether the code in WS_ENTRY_BB blocks the combined
271 parallel+workshare call, we collect all the variables used in the
272 OMP_FOR header check whether they appear on the LHS of any
273 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
274 call.
276 FIXME. If we had the SSA form built at this point, we could merely
277 hoist the code in block 3 into block 2 and be done with it. But at
278 this point we don't have dataflow information and though we could
279 hack something up here, it is really not worth the aggravation. */
281 static bool
282 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
284 struct omp_for_data fd;
285 tree par_stmt, ws_stmt;
287 par_stmt = last_stmt (par_entry_bb);
288 ws_stmt = last_stmt (ws_entry_bb);
290 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
291 return true;
293 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
295 extract_omp_for_data (ws_stmt, &fd);
297 /* FIXME. We give up too easily here. If any of these arguments
298 are not constants, they will likely involve variables that have
299 been mapped into fields of .omp_data_s for sharing with the child
300 function. With appropriate data flow, it would be possible to
301 see through this. */
302 if (!is_gimple_min_invariant (fd.n1)
303 || !is_gimple_min_invariant (fd.n2)
304 || !is_gimple_min_invariant (fd.step)
305 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
306 return false;
308 return true;
312 /* Collect additional arguments needed to emit a combined
313 parallel+workshare call. WS_STMT is the workshare directive being
314 expanded. */
316 static tree
317 get_ws_args_for (tree ws_stmt)
319 tree t;
321 if (TREE_CODE (ws_stmt) == OMP_FOR)
323 struct omp_for_data fd;
324 tree ws_args;
326 extract_omp_for_data (ws_stmt, &fd);
328 ws_args = NULL_TREE;
329 if (fd.chunk_size)
331 t = fold_convert (long_integer_type_node, fd.chunk_size);
332 ws_args = tree_cons (NULL, t, ws_args);
335 t = fold_convert (long_integer_type_node, fd.step);
336 ws_args = tree_cons (NULL, t, ws_args);
338 t = fold_convert (long_integer_type_node, fd.n2);
339 ws_args = tree_cons (NULL, t, ws_args);
341 t = fold_convert (long_integer_type_node, fd.n1);
342 ws_args = tree_cons (NULL, t, ws_args);
344 return ws_args;
346 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
348 basic_block bb = bb_for_stmt (ws_stmt);
349 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
350 t = tree_cons (NULL, t, NULL);
351 return t;
354 gcc_unreachable ();
358 /* Discover whether REGION is a combined parallel+workshare region. */
360 static void
361 determine_parallel_type (struct omp_region *region)
363 basic_block par_entry_bb, par_exit_bb;
364 basic_block ws_entry_bb, ws_exit_bb;
366 if (region == NULL || region->inner == NULL)
367 return;
369 /* We only support parallel+for and parallel+sections. */
370 if (region->type != OMP_PARALLEL
371 || (region->inner->type != OMP_FOR
372 && region->inner->type != OMP_SECTIONS))
373 return;
375 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
376 WS_EXIT_BB -> PAR_EXIT_BB. */
377 par_entry_bb = region->entry;
378 par_exit_bb = region->exit;
379 ws_entry_bb = region->inner->entry;
380 ws_exit_bb = region->inner->exit;
382 if (single_succ (par_entry_bb) == ws_entry_bb
383 && single_succ (ws_exit_bb) == par_exit_bb
384 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
386 tree ws_stmt = last_stmt (region->inner->entry);
388 if (region->inner->type == OMP_FOR)
390 /* If this is a combined parallel loop, we need to determine
391 whether or not to use the combined library calls. There
392 are two cases where we do not apply the transformation:
393 static loops and any kind of ordered loop. In the first
394 case, we already open code the loop so there is no need
395 to do anything else. In the latter case, the combined
396 parallel loop call would still need extra synchronization
397 to implement ordered semantics, so there would not be any
398 gain in using the combined call. */
399 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
400 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
401 if (c == NULL
402 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
403 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
405 region->is_combined_parallel = false;
406 region->inner->is_combined_parallel = false;
407 return;
411 region->is_combined_parallel = true;
412 region->inner->is_combined_parallel = true;
413 region->ws_args = get_ws_args_for (ws_stmt);
418 /* Return true if EXPR is variable sized. */
420 static inline bool
421 is_variable_sized (tree expr)
423 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
426 /* Return true if DECL is a reference type. */
428 static inline bool
429 is_reference (tree decl)
431 return lang_hooks.decls.omp_privatize_by_reference (decl);
434 /* Lookup variables in the decl or field splay trees. The "maybe" form
435 allows for the variable form to not have been entered, otherwise we
436 assert that the variable must have been entered. */
438 static inline tree
439 lookup_decl (tree var, omp_context *ctx)
441 splay_tree_node n;
442 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
443 return (tree) n->value;
446 static inline tree
447 maybe_lookup_decl (tree var, omp_context *ctx)
449 splay_tree_node n;
450 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
451 return n ? (tree) n->value : NULL_TREE;
454 static inline tree
455 lookup_field (tree var, omp_context *ctx)
457 splay_tree_node n;
458 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
459 return (tree) n->value;
462 static inline tree
463 maybe_lookup_field (tree var, omp_context *ctx)
465 splay_tree_node n;
466 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
467 return n ? (tree) n->value : NULL_TREE;
470 /* Return true if DECL should be copied by pointer. SHARED_P is true
471 if DECL is to be shared. */
473 static bool
474 use_pointer_for_field (tree decl, bool shared_p)
476 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
477 return true;
479 /* We can only use copy-in/copy-out semantics for shared varibles
480 when we know the value is not accessible from an outer scope. */
481 if (shared_p)
483 /* ??? Trivially accessible from anywhere. But why would we even
484 be passing an address in this case? Should we simply assert
485 this to be false, or should we have a cleanup pass that removes
486 these from the list of mappings? */
487 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
488 return true;
490 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
491 without analyzing the expression whether or not its location
492 is accessible to anyone else. In the case of nested parallel
493 regions it certainly may be. */
494 if (DECL_HAS_VALUE_EXPR_P (decl))
495 return true;
497 /* Do not use copy-in/copy-out for variables that have their
498 address taken. */
499 if (TREE_ADDRESSABLE (decl))
500 return true;
503 return false;
506 /* Construct a new automatic decl similar to VAR. */
508 static tree
509 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
511 tree copy = build_decl (VAR_DECL, name, type);
513 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
514 DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
515 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
516 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
517 TREE_USED (copy) = 1;
518 DECL_CONTEXT (copy) = current_function_decl;
519 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
521 TREE_CHAIN (copy) = ctx->block_vars;
522 ctx->block_vars = copy;
524 return copy;
527 static tree
528 omp_copy_decl_1 (tree var, omp_context *ctx)
530 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
533 /* Build tree nodes to access the field for VAR on the receiver side. */
535 static tree
536 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
538 tree x, field = lookup_field (var, ctx);
540 /* If the receiver record type was remapped in the child function,
541 remap the field into the new record type. */
542 x = maybe_lookup_field (field, ctx);
543 if (x != NULL)
544 field = x;
546 x = build_fold_indirect_ref (ctx->receiver_decl);
547 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
548 if (by_ref)
549 x = build_fold_indirect_ref (x);
551 return x;
554 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
555 of a parallel, this is a component reference; for workshare constructs
556 this is some variable. */
558 static tree
559 build_outer_var_ref (tree var, omp_context *ctx)
561 tree x;
563 if (is_global_var (var))
564 x = var;
565 else if (is_variable_sized (var))
567 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
568 x = build_outer_var_ref (x, ctx);
569 x = build_fold_indirect_ref (x);
571 else if (is_parallel_ctx (ctx))
573 bool by_ref = use_pointer_for_field (var, false);
574 x = build_receiver_ref (var, by_ref, ctx);
576 else if (ctx->outer)
577 x = lookup_decl (var, ctx->outer);
578 else
579 gcc_unreachable ();
581 if (is_reference (var))
582 x = build_fold_indirect_ref (x);
584 return x;
587 /* Build tree nodes to access the field for VAR on the sender side. */
589 static tree
590 build_sender_ref (tree var, omp_context *ctx)
592 tree field = lookup_field (var, ctx);
593 return build3 (COMPONENT_REF, TREE_TYPE (field),
594 ctx->sender_decl, field, NULL);
597 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
599 static void
600 install_var_field (tree var, bool by_ref, omp_context *ctx)
602 tree field, type;
604 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
606 type = TREE_TYPE (var);
607 if (by_ref)
608 type = build_pointer_type (type);
610 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
612 /* Remember what variable this field was created for. This does have a
613 side effect of making dwarf2out ignore this member, so for helpful
614 debugging we clear it later in delete_omp_context. */
615 DECL_ABSTRACT_ORIGIN (field) = var;
617 insert_field_into_struct (ctx->record_type, field);
619 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
620 (splay_tree_value) field);
623 static tree
624 install_var_local (tree var, omp_context *ctx)
626 tree new_var = omp_copy_decl_1 (var, ctx);
627 insert_decl_map (&ctx->cb, var, new_var);
628 return new_var;
631 /* Adjust the replacement for DECL in CTX for the new context. This means
632 copying the DECL_VALUE_EXPR, and fixing up the type. */
634 static void
635 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
637 tree new_decl, size;
639 new_decl = lookup_decl (decl, ctx);
641 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
643 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
644 && DECL_HAS_VALUE_EXPR_P (decl))
646 tree ve = DECL_VALUE_EXPR (decl);
647 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
648 SET_DECL_VALUE_EXPR (new_decl, ve);
649 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
652 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
654 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
655 if (size == error_mark_node)
656 size = TYPE_SIZE (TREE_TYPE (new_decl));
657 DECL_SIZE (new_decl) = size;
659 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
660 if (size == error_mark_node)
661 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
662 DECL_SIZE_UNIT (new_decl) = size;
666 /* The callback for remap_decl. Search all containing contexts for a
667 mapping of the variable; this avoids having to duplicate the splay
668 tree ahead of time. We know a mapping doesn't already exist in the
669 given context. Create new mappings to implement default semantics. */
671 static tree
672 omp_copy_decl (tree var, copy_body_data *cb)
674 omp_context *ctx = (omp_context *) cb;
675 tree new_var;
677 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
678 return var;
680 if (TREE_CODE (var) == LABEL_DECL)
682 new_var = create_artificial_label ();
683 DECL_CONTEXT (new_var) = current_function_decl;
684 insert_decl_map (&ctx->cb, var, new_var);
685 return new_var;
688 while (!is_parallel_ctx (ctx))
690 ctx = ctx->outer;
691 if (ctx == NULL)
692 return var;
693 new_var = maybe_lookup_decl (var, ctx);
694 if (new_var)
695 return new_var;
698 return error_mark_node;
702 /* Return the parallel region associated with STMT. */
704 /* Debugging dumps for parallel regions. */
705 void dump_omp_region (FILE *, struct omp_region *, int);
706 void debug_omp_region (struct omp_region *);
707 void debug_all_omp_regions (void);
709 /* Dump the parallel region tree rooted at REGION. */
711 void
712 dump_omp_region (FILE *file, struct omp_region *region, int indent)
714 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
715 tree_code_name[region->type]);
717 if (region->inner)
718 dump_omp_region (file, region->inner, indent + 4);
720 if (region->cont)
722 fprintf (file, "%*sbb %d: OMP_CONTINUE", indent, "",
723 region->cont->index);
726 if (region->exit)
727 fprintf (file, "%*sbb: %d: OMP_RETURN", indent, "",
728 region->exit->index);
729 else
730 fprintf (file, "%*s[no exit marker]\n", indent, "");
732 if (region->next)
733 dump_omp_region (file, region->next, indent);
736 void
737 debug_omp_region (struct omp_region *region)
739 dump_omp_region (stderr, region, 0);
742 void
743 debug_all_omp_regions (void)
745 dump_omp_region (stderr, root_omp_region, 0);
749 /* Create a new parallel region starting at STMT inside region PARENT. */
751 struct omp_region *
752 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
754 struct omp_region *region = xcalloc (1, sizeof (*region));
756 region->outer = parent;
757 region->entry = bb;
758 region->type = type;
760 if (parent)
762 /* This is a nested region. Add it to the list of inner
763 regions in PARENT. */
764 region->next = parent->inner;
765 parent->inner = region;
767 else
769 /* This is a toplevel region. Add it to the list of toplevel
770 regions in ROOT_OMP_REGION. */
771 region->next = root_omp_region;
772 root_omp_region = region;
775 return region;
778 /* Release the memory associated with the region tree rooted at REGION. */
780 static void
781 free_omp_region_1 (struct omp_region *region)
783 struct omp_region *i, *n;
785 for (i = region->inner; i ; i = n)
787 n = i->next;
788 free_omp_region_1 (i);
791 free (region);
794 /* Release the memory for the entire omp region tree. */
796 void
797 free_omp_regions (void)
799 struct omp_region *r, *n;
800 for (r = root_omp_region; r ; r = n)
802 n = r->next;
803 free_omp_region_1 (r);
805 root_omp_region = NULL;
809 /* Create a new context, with OUTER_CTX being the surrounding context. */
811 static omp_context *
812 new_omp_context (tree stmt, omp_context *outer_ctx)
814 omp_context *ctx = XCNEW (omp_context);
816 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
817 (splay_tree_value) ctx);
818 ctx->stmt = stmt;
820 if (outer_ctx)
822 ctx->outer = outer_ctx;
823 ctx->cb = outer_ctx->cb;
824 ctx->cb.block = NULL;
825 ctx->depth = outer_ctx->depth + 1;
827 else
829 ctx->cb.src_fn = current_function_decl;
830 ctx->cb.dst_fn = current_function_decl;
831 ctx->cb.src_node = cgraph_node (current_function_decl);
832 ctx->cb.dst_node = ctx->cb.src_node;
833 ctx->cb.src_cfun = cfun;
834 ctx->cb.copy_decl = omp_copy_decl;
835 ctx->cb.eh_region = -1;
836 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
837 ctx->depth = 1;
840 ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
842 return ctx;
845 /* Destroy a omp_context data structures. Called through the splay tree
846 value delete callback. */
848 static void
849 delete_omp_context (splay_tree_value value)
851 omp_context *ctx = (omp_context *) value;
853 splay_tree_delete (ctx->cb.decl_map);
855 if (ctx->field_map)
856 splay_tree_delete (ctx->field_map);
858 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
859 it produces corrupt debug information. */
860 if (ctx->record_type)
862 tree t;
863 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
864 DECL_ABSTRACT_ORIGIN (t) = NULL;
867 XDELETE (ctx);
870 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
871 context. */
873 static void
874 fixup_child_record_type (omp_context *ctx)
876 tree f, type = ctx->record_type;
878 /* ??? It isn't sufficient to just call remap_type here, because
879 variably_modified_type_p doesn't work the way we expect for
880 record types. Testing each field for whether it needs remapping
881 and creating a new record by hand works, however. */
882 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
883 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
884 break;
885 if (f)
887 tree name, new_fields = NULL;
889 type = lang_hooks.types.make_type (RECORD_TYPE);
890 name = DECL_NAME (TYPE_NAME (ctx->record_type));
891 name = build_decl (TYPE_DECL, name, type);
892 TYPE_NAME (type) = name;
894 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
896 tree new_f = copy_node (f);
897 DECL_CONTEXT (new_f) = type;
898 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
899 TREE_CHAIN (new_f) = new_fields;
900 new_fields = new_f;
902 /* Arrange to be able to look up the receiver field
903 given the sender field. */
904 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
905 (splay_tree_value) new_f);
907 TYPE_FIELDS (type) = nreverse (new_fields);
908 layout_type (type);
911 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
914 /* Instantiate decls as necessary in CTX to satisfy the data sharing
915 specified by CLAUSES. */
917 static void
918 scan_sharing_clauses (tree clauses, omp_context *ctx)
920 tree c, decl;
921 bool scan_array_reductions = false;
923 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
925 bool by_ref;
927 switch (OMP_CLAUSE_CODE (c))
929 case OMP_CLAUSE_PRIVATE:
930 decl = OMP_CLAUSE_DECL (c);
931 if (!is_variable_sized (decl))
932 install_var_local (decl, ctx);
933 break;
935 case OMP_CLAUSE_SHARED:
936 gcc_assert (is_parallel_ctx (ctx));
937 decl = OMP_CLAUSE_DECL (c);
938 gcc_assert (!is_variable_sized (decl));
939 by_ref = use_pointer_for_field (decl, true);
940 if (! TREE_READONLY (decl)
941 || TREE_ADDRESSABLE (decl)
942 || by_ref
943 || is_reference (decl))
945 install_var_field (decl, by_ref, ctx);
946 install_var_local (decl, ctx);
947 break;
949 /* We don't need to copy const scalar vars back. */
950 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
951 goto do_private;
953 case OMP_CLAUSE_LASTPRIVATE:
954 /* Let the corresponding firstprivate clause create
955 the variable. */
956 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
957 break;
958 /* FALLTHRU */
960 case OMP_CLAUSE_FIRSTPRIVATE:
961 case OMP_CLAUSE_REDUCTION:
962 decl = OMP_CLAUSE_DECL (c);
963 do_private:
964 if (is_variable_sized (decl))
965 break;
966 else if (is_parallel_ctx (ctx))
968 by_ref = use_pointer_for_field (decl, false);
969 install_var_field (decl, by_ref, ctx);
971 install_var_local (decl, ctx);
972 break;
974 case OMP_CLAUSE_COPYPRIVATE:
975 if (ctx->outer)
976 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
977 /* FALLTHRU */
979 case OMP_CLAUSE_COPYIN:
980 decl = OMP_CLAUSE_DECL (c);
981 by_ref = use_pointer_for_field (decl, false);
982 install_var_field (decl, by_ref, ctx);
983 break;
985 case OMP_CLAUSE_DEFAULT:
986 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
987 break;
989 case OMP_CLAUSE_IF:
990 case OMP_CLAUSE_NUM_THREADS:
991 case OMP_CLAUSE_SCHEDULE:
992 if (ctx->outer)
993 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
994 break;
996 case OMP_CLAUSE_NOWAIT:
997 case OMP_CLAUSE_ORDERED:
998 break;
1000 default:
1001 gcc_unreachable ();
1005 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1007 switch (OMP_CLAUSE_CODE (c))
1009 case OMP_CLAUSE_LASTPRIVATE:
1010 /* Let the corresponding firstprivate clause create
1011 the variable. */
1012 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1013 break;
1014 /* FALLTHRU */
1016 case OMP_CLAUSE_PRIVATE:
1017 case OMP_CLAUSE_FIRSTPRIVATE:
1018 case OMP_CLAUSE_REDUCTION:
1019 decl = OMP_CLAUSE_DECL (c);
1020 if (is_variable_sized (decl))
1021 install_var_local (decl, ctx);
1022 fixup_remapped_decl (decl, ctx,
1023 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1024 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1025 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1026 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1027 scan_array_reductions = true;
1028 break;
1030 case OMP_CLAUSE_SHARED:
1031 decl = OMP_CLAUSE_DECL (c);
1032 fixup_remapped_decl (decl, ctx, false);
1033 break;
1035 case OMP_CLAUSE_COPYPRIVATE:
1036 case OMP_CLAUSE_COPYIN:
1037 case OMP_CLAUSE_DEFAULT:
1038 case OMP_CLAUSE_IF:
1039 case OMP_CLAUSE_NUM_THREADS:
1040 case OMP_CLAUSE_SCHEDULE:
1041 case OMP_CLAUSE_NOWAIT:
1042 case OMP_CLAUSE_ORDERED:
1043 break;
1045 default:
1046 gcc_unreachable ();
1050 if (scan_array_reductions)
1051 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1052 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1053 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1055 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1056 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1060 /* Create a new name for omp child function. Returns an identifier. */
1062 static GTY(()) unsigned int tmp_ompfn_id_num;
1064 static tree
1065 create_omp_child_function_name (void)
1067 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1068 size_t len = IDENTIFIER_LENGTH (name);
1069 char *tmp_name, *prefix;
1071 prefix = alloca (len + sizeof ("_omp_fn"));
1072 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1073 strcpy (prefix + len, "_omp_fn");
1074 #ifndef NO_DOT_IN_LABEL
1075 prefix[len] = '.';
1076 #elif !defined NO_DOLLAR_IN_LABEL
1077 prefix[len] = '$';
1078 #endif
1079 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1080 return get_identifier (tmp_name);
1083 /* Build a decl for the omp child function. It'll not contain a body
1084 yet, just the bare decl. */
1086 static void
1087 create_omp_child_function (omp_context *ctx)
1089 tree decl, type, name, t;
1091 name = create_omp_child_function_name ();
1092 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1094 decl = build_decl (FUNCTION_DECL, name, type);
1095 decl = lang_hooks.decls.pushdecl (decl);
1097 ctx->cb.dst_fn = decl;
1099 TREE_STATIC (decl) = 1;
1100 TREE_USED (decl) = 1;
1101 DECL_ARTIFICIAL (decl) = 1;
1102 DECL_IGNORED_P (decl) = 0;
1103 TREE_PUBLIC (decl) = 0;
1104 DECL_UNINLINABLE (decl) = 1;
1105 DECL_EXTERNAL (decl) = 0;
1106 DECL_CONTEXT (decl) = NULL_TREE;
1107 DECL_INITIAL (decl) = make_node (BLOCK);
1109 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1110 DECL_ARTIFICIAL (t) = 1;
1111 DECL_IGNORED_P (t) = 1;
1112 DECL_RESULT (decl) = t;
1114 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1115 DECL_ARTIFICIAL (t) = 1;
1116 DECL_ARG_TYPE (t) = ptr_type_node;
1117 DECL_CONTEXT (t) = current_function_decl;
1118 TREE_USED (t) = 1;
1119 DECL_ARGUMENTS (decl) = t;
1120 ctx->receiver_decl = t;
1122 /* Allocate memory for the function structure. The call to
1123 allocate_struct_function clobbers CFUN, so we need to restore
1124 it afterward. */
1125 allocate_struct_function (decl);
1126 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1127 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1128 cfun = ctx->cb.src_cfun;
1132 /* Scan an OpenMP parallel directive. */
1134 static void
1135 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1137 omp_context *ctx;
1138 tree name;
1140 /* Ignore parallel directives with empty bodies, unless there
1141 are copyin clauses. */
1142 if (optimize > 0
1143 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1144 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1146 *stmt_p = build_empty_stmt ();
1147 return;
1150 ctx = new_omp_context (*stmt_p, outer_ctx);
1151 if (parallel_nesting_level > 1)
1152 ctx->is_nested = true;
1153 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1154 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1155 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1156 name = create_tmp_var_name (".omp_data_s");
1157 name = build_decl (TYPE_DECL, name, ctx->record_type);
1158 TYPE_NAME (ctx->record_type) = name;
1159 create_omp_child_function (ctx);
1160 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1162 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1163 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1165 if (TYPE_FIELDS (ctx->record_type) == NULL)
1166 ctx->record_type = ctx->receiver_decl = NULL;
1167 else
1169 layout_type (ctx->record_type);
1170 fixup_child_record_type (ctx);
1175 /* Scan an OpenMP loop directive. */
1177 static void
1178 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1180 omp_context *ctx;
1181 tree stmt;
1183 stmt = *stmt_p;
1184 ctx = new_omp_context (stmt, outer_ctx);
1186 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1188 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1189 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1190 scan_omp (&OMP_FOR_COND (stmt), ctx);
1191 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1192 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1195 /* Scan an OpenMP sections directive. */
1197 static void
1198 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1200 tree stmt;
1201 omp_context *ctx;
1203 stmt = *stmt_p;
1204 ctx = new_omp_context (stmt, outer_ctx);
1205 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1206 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1209 /* Scan an OpenMP single directive. */
1211 static void
1212 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1214 tree stmt = *stmt_p;
1215 omp_context *ctx;
1216 tree name;
1218 ctx = new_omp_context (stmt, outer_ctx);
1219 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1220 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1221 name = create_tmp_var_name (".omp_copy_s");
1222 name = build_decl (TYPE_DECL, name, ctx->record_type);
1223 TYPE_NAME (ctx->record_type) = name;
1225 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1226 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1228 if (TYPE_FIELDS (ctx->record_type) == NULL)
1229 ctx->record_type = NULL;
1230 else
1231 layout_type (ctx->record_type);
1235 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1237 static tree
1238 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1240 struct walk_stmt_info *wi = data;
1241 omp_context *ctx = wi->info;
1242 tree t = *tp;
1244 if (EXPR_HAS_LOCATION (t))
1245 input_location = EXPR_LOCATION (t);
1247 *walk_subtrees = 0;
1248 switch (TREE_CODE (t))
1250 case OMP_PARALLEL:
1251 parallel_nesting_level++;
1252 scan_omp_parallel (tp, ctx);
1253 parallel_nesting_level--;
1254 break;
1256 case OMP_FOR:
1257 scan_omp_for (tp, ctx);
1258 break;
1260 case OMP_SECTIONS:
1261 scan_omp_sections (tp, ctx);
1262 break;
1264 case OMP_SINGLE:
1265 scan_omp_single (tp, ctx);
1266 break;
1268 case OMP_SECTION:
1269 case OMP_MASTER:
1270 case OMP_ORDERED:
1271 case OMP_CRITICAL:
1272 ctx = new_omp_context (*tp, ctx);
1273 scan_omp (&OMP_BODY (*tp), ctx);
1274 break;
1276 case BIND_EXPR:
1278 tree var;
1279 *walk_subtrees = 1;
1281 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1282 insert_decl_map (&ctx->cb, var, var);
1284 break;
1286 case VAR_DECL:
1287 case PARM_DECL:
1288 case LABEL_DECL:
1289 if (ctx)
1290 *tp = remap_decl (t, &ctx->cb);
1291 break;
1293 default:
1294 if (ctx && TYPE_P (t))
1295 *tp = remap_type (t, &ctx->cb);
1296 else if (!DECL_P (t))
1297 *walk_subtrees = 1;
1298 break;
1301 return NULL_TREE;
1305 /* Scan all the statements starting at STMT_P. CTX contains context
1306 information about the OpenMP directives and clauses found during
1307 the scan. */
1309 static void
1310 scan_omp (tree *stmt_p, omp_context *ctx)
1312 location_t saved_location;
1313 struct walk_stmt_info wi;
1315 memset (&wi, 0, sizeof (wi));
1316 wi.callback = scan_omp_1;
1317 wi.info = ctx;
1318 wi.want_bind_expr = (ctx != NULL);
1319 wi.want_locations = true;
1321 saved_location = input_location;
1322 walk_stmts (&wi, stmt_p);
1323 input_location = saved_location;
1326 /* Re-gimplification and code generation routines. */
1328 /* Build a call to GOMP_barrier. */
1330 static void
1331 build_omp_barrier (tree *stmt_list)
1333 tree t;
1335 t = built_in_decls[BUILT_IN_GOMP_BARRIER];
1336 t = build_function_call_expr (t, NULL);
1337 gimplify_and_add (t, stmt_list);
1340 /* If a context was created for STMT when it was scanned, return it. */
1342 static omp_context *
1343 maybe_lookup_ctx (tree stmt)
1345 splay_tree_node n;
1346 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1347 return n ? (omp_context *) n->value : NULL;
1351 /* Find the mapping for DECL in CTX or the immediately enclosing
1352 context that has a mapping for DECL.
1354 If CTX is a nested parallel directive, we may have to use the decl
1355 mappings created in CTX's parent context. Suppose that we have the
1356 following parallel nesting (variable UIDs showed for clarity):
1358 iD.1562 = 0;
1359 #omp parallel shared(iD.1562) -> outer parallel
1360 iD.1562 = iD.1562 + 1;
1362 #omp parallel shared (iD.1562) -> inner parallel
1363 iD.1562 = iD.1562 - 1;
1365 Each parallel structure will create a distinct .omp_data_s structure
1366 for copying iD.1562 in/out of the directive:
1368 outer parallel .omp_data_s.1.i -> iD.1562
1369 inner parallel .omp_data_s.2.i -> iD.1562
1371 A shared variable mapping will produce a copy-out operation before
1372 the parallel directive and a copy-in operation after it. So, in
1373 this case we would have:
1375 iD.1562 = 0;
1376 .omp_data_o.1.i = iD.1562;
1377 #omp parallel shared(iD.1562) -> outer parallel
1378 .omp_data_i.1 = &.omp_data_o.1
1379 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1381 .omp_data_o.2.i = iD.1562; -> **
1382 #omp parallel shared(iD.1562) -> inner parallel
1383 .omp_data_i.2 = &.omp_data_o.2
1384 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1387 ** This is a problem. The symbol iD.1562 cannot be referenced
1388 inside the body of the outer parallel region. But since we are
1389 emitting this copy operation while expanding the inner parallel
1390 directive, we need to access the CTX structure of the outer
1391 parallel directive to get the correct mapping:
1393 .omp_data_o.2.i = .omp_data_i.1->i
1395 Since there may be other workshare or parallel directives enclosing
1396 the parallel directive, it may be necessary to walk up the context
1397 parent chain. This is not a problem in general because nested
1398 parallelism happens only rarely. */
1400 static tree
1401 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1403 tree t;
1404 omp_context *up;
1406 gcc_assert (ctx->is_nested);
1408 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1409 t = maybe_lookup_decl (decl, up);
1411 gcc_assert (t);
1413 return t;
1417 /* Construct the initialization value for reduction CLAUSE. */
1419 tree
1420 omp_reduction_init (tree clause, tree type)
1422 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1424 case PLUS_EXPR:
1425 case MINUS_EXPR:
1426 case BIT_IOR_EXPR:
1427 case BIT_XOR_EXPR:
1428 case TRUTH_OR_EXPR:
1429 case TRUTH_ORIF_EXPR:
1430 case TRUTH_XOR_EXPR:
1431 case NE_EXPR:
1432 return fold_convert (type, integer_zero_node);
1434 case MULT_EXPR:
1435 case TRUTH_AND_EXPR:
1436 case TRUTH_ANDIF_EXPR:
1437 case EQ_EXPR:
1438 return fold_convert (type, integer_one_node);
1440 case BIT_AND_EXPR:
1441 return fold_convert (type, integer_minus_one_node);
1443 case MAX_EXPR:
1444 if (SCALAR_FLOAT_TYPE_P (type))
1446 REAL_VALUE_TYPE max, min;
1447 if (HONOR_INFINITIES (TYPE_MODE (type)))
1449 real_inf (&max);
1450 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1452 else
1453 real_maxval (&min, 1, TYPE_MODE (type));
1454 return build_real (type, min);
1456 else
1458 gcc_assert (INTEGRAL_TYPE_P (type));
1459 return TYPE_MIN_VALUE (type);
1462 case MIN_EXPR:
1463 if (SCALAR_FLOAT_TYPE_P (type))
1465 REAL_VALUE_TYPE max;
1466 if (HONOR_INFINITIES (TYPE_MODE (type)))
1467 real_inf (&max);
1468 else
1469 real_maxval (&max, 0, TYPE_MODE (type));
1470 return build_real (type, max);
1472 else
1474 gcc_assert (INTEGRAL_TYPE_P (type));
1475 return TYPE_MAX_VALUE (type);
1478 default:
1479 gcc_unreachable ();
1483 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1484 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1485 private variables. Initialization statements go in ILIST, while calls
1486 to destructors go in DLIST. */
1488 static void
1489 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1490 omp_context *ctx)
1492 tree_stmt_iterator diter;
1493 tree c, dtor, copyin_seq, x, args, ptr;
1494 bool copyin_by_ref = false;
1495 int pass;
1497 *dlist = alloc_stmt_list ();
1498 diter = tsi_start (*dlist);
1499 copyin_seq = NULL;
1501 /* Do all the fixed sized types in the first pass, and the variable sized
1502 types in the second pass. This makes sure that the scalar arguments to
1503 the variable sized types are processed before we use them in the
1504 variable sized operations. */
1505 for (pass = 0; pass < 2; ++pass)
1507 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1509 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1510 tree var, new_var;
1511 bool by_ref;
1513 switch (c_kind)
1515 case OMP_CLAUSE_PRIVATE:
1516 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1517 continue;
1518 break;
1519 case OMP_CLAUSE_SHARED:
1520 case OMP_CLAUSE_FIRSTPRIVATE:
1521 case OMP_CLAUSE_LASTPRIVATE:
1522 case OMP_CLAUSE_COPYIN:
1523 case OMP_CLAUSE_REDUCTION:
1524 break;
1525 default:
1526 continue;
1529 new_var = var = OMP_CLAUSE_DECL (c);
1530 if (c_kind != OMP_CLAUSE_COPYIN)
1531 new_var = lookup_decl (var, ctx);
1533 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1535 if (pass != 0)
1536 continue;
1538 else if (is_variable_sized (var))
1540 /* For variable sized types, we need to allocate the
1541 actual storage here. Call alloca and store the
1542 result in the pointer decl that we created elsewhere. */
1543 if (pass == 0)
1544 continue;
1546 ptr = DECL_VALUE_EXPR (new_var);
1547 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1548 ptr = TREE_OPERAND (ptr, 0);
1549 gcc_assert (DECL_P (ptr));
1551 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1552 args = tree_cons (NULL, x, NULL);
1553 x = built_in_decls[BUILT_IN_ALLOCA];
1554 x = build_function_call_expr (x, args);
1555 x = fold_convert (TREE_TYPE (ptr), x);
1556 x = build2 (MODIFY_EXPR, void_type_node, ptr, x);
1557 gimplify_and_add (x, ilist);
1559 else if (is_reference (var))
1561 /* For references that are being privatized for Fortran,
1562 allocate new backing storage for the new pointer
1563 variable. This allows us to avoid changing all the
1564 code that expects a pointer to something that expects
1565 a direct variable. Note that this doesn't apply to
1566 C++, since reference types are disallowed in data
1567 sharing clauses there. */
1568 if (pass == 0)
1569 continue;
1571 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1572 if (TREE_CONSTANT (x))
1574 const char *name = NULL;
1575 if (DECL_NAME (var))
1576 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1578 x = create_tmp_var (TREE_TYPE (TREE_TYPE (new_var)), name);
1579 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1581 else
1583 args = tree_cons (NULL, x, NULL);
1584 x = built_in_decls[BUILT_IN_ALLOCA];
1585 x = build_function_call_expr (x, args);
1586 x = fold_convert (TREE_TYPE (new_var), x);
1589 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1590 gimplify_and_add (x, ilist);
1592 new_var = build_fold_indirect_ref (new_var);
1594 else if (c_kind == OMP_CLAUSE_REDUCTION
1595 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1597 if (pass == 0)
1598 continue;
1600 else if (pass != 0)
1601 continue;
1603 switch (OMP_CLAUSE_CODE (c))
1605 case OMP_CLAUSE_SHARED:
1606 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1607 needs to be delayed until after fixup_child_record_type so
1608 that we get the correct type during the dereference. */
1609 by_ref = use_pointer_for_field (var, true);
1610 x = build_receiver_ref (var, by_ref, ctx);
1611 SET_DECL_VALUE_EXPR (new_var, x);
1612 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1614 /* ??? If VAR is not passed by reference, and the variable
1615 hasn't been initialized yet, then we'll get a warning for
1616 the store into the omp_data_s structure. Ideally, we'd be
1617 able to notice this and not store anything at all, but
1618 we're generating code too early. Suppress the warning. */
1619 if (!by_ref)
1620 TREE_NO_WARNING (var) = 1;
1621 break;
1623 case OMP_CLAUSE_LASTPRIVATE:
1624 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1625 break;
1626 /* FALLTHRU */
1628 case OMP_CLAUSE_PRIVATE:
1629 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1630 if (x)
1631 gimplify_and_add (x, ilist);
1632 /* FALLTHRU */
1634 do_dtor:
1635 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1636 if (x)
1638 dtor = x;
1639 gimplify_stmt (&dtor);
1640 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1642 break;
1644 case OMP_CLAUSE_FIRSTPRIVATE:
1645 x = build_outer_var_ref (var, ctx);
1646 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1647 gimplify_and_add (x, ilist);
1648 goto do_dtor;
1649 break;
1651 case OMP_CLAUSE_COPYIN:
1652 by_ref = use_pointer_for_field (var, false);
1653 x = build_receiver_ref (var, by_ref, ctx);
1654 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1655 append_to_statement_list (x, &copyin_seq);
1656 copyin_by_ref |= by_ref;
1657 break;
1659 case OMP_CLAUSE_REDUCTION:
1660 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1662 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1663 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1665 else
1667 x = omp_reduction_init (c, TREE_TYPE (new_var));
1668 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1669 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1670 gimplify_and_add (x, ilist);
1672 break;
1674 default:
1675 gcc_unreachable ();
1680 /* The copyin sequence is not to be executed by the main thread, since
1681 that would result in self-copies. Perhaps not visible to scalars,
1682 but it certainly is to C++ operator=. */
1683 if (copyin_seq)
1685 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
1686 x = build_function_call_expr (x, NULL);
1687 x = build2 (NE_EXPR, boolean_type_node, x,
1688 build_int_cst (TREE_TYPE (x), 0));
1689 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1690 gimplify_and_add (x, ilist);
1693 /* If any copyin variable is passed by reference, we must ensure the
1694 master thread doesn't modify it before it is copied over in all
1695 threads. */
1696 if (copyin_by_ref)
1697 build_omp_barrier (ilist);
1701 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1702 both parallel and workshare constructs. PREDICATE may be NULL if it's
1703 always true. */
1705 static void
1706 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1707 omp_context *ctx)
1709 tree sub_list, x, c;
1711 /* Early exit if there are no lastprivate clauses. */
1712 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1713 if (clauses == NULL)
1715 /* If this was a workshare clause, see if it had been combined
1716 with its parallel. In that case, look for the clauses on the
1717 parallel statement itself. */
1718 if (is_parallel_ctx (ctx))
1719 return;
1721 ctx = ctx->outer;
1722 if (ctx == NULL || !is_parallel_ctx (ctx))
1723 return;
1725 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1726 OMP_CLAUSE_LASTPRIVATE);
1727 if (clauses == NULL)
1728 return;
1731 sub_list = alloc_stmt_list ();
1733 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1735 tree var, new_var;
1737 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1738 continue;
1740 var = OMP_CLAUSE_DECL (c);
1741 new_var = lookup_decl (var, ctx);
1743 x = build_outer_var_ref (var, ctx);
1744 if (is_reference (var))
1745 new_var = build_fold_indirect_ref (new_var);
1746 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1747 append_to_statement_list (x, &sub_list);
1750 if (predicate)
1751 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1752 else
1753 x = sub_list;
1755 gimplify_and_add (x, stmt_list);
1759 /* Generate code to implement the REDUCTION clauses. */
1761 static void
1762 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1764 tree sub_list = NULL, x, c;
1765 int count = 0;
1767 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1768 update in that case, otherwise use a lock. */
1769 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1770 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1772 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1774 /* Never use OMP_ATOMIC for array reductions. */
1775 count = -1;
1776 break;
1778 count++;
1781 if (count == 0)
1782 return;
1784 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1786 tree var, ref, new_var;
1787 enum tree_code code;
1789 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1790 continue;
1792 var = OMP_CLAUSE_DECL (c);
1793 new_var = lookup_decl (var, ctx);
1794 if (is_reference (var))
1795 new_var = build_fold_indirect_ref (new_var);
1796 ref = build_outer_var_ref (var, ctx);
1797 code = OMP_CLAUSE_REDUCTION_CODE (c);
1799 /* reduction(-:var) sums up the partial results, so it acts
1800 identically to reduction(+:var). */
1801 if (code == MINUS_EXPR)
1802 code = PLUS_EXPR;
1804 if (count == 1)
1806 tree addr = build_fold_addr_expr (ref);
1808 addr = save_expr (addr);
1809 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1810 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1811 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1812 gimplify_and_add (x, stmt_list);
1813 return;
1816 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1818 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1820 if (is_reference (var))
1821 ref = build_fold_addr_expr (ref);
1822 SET_DECL_VALUE_EXPR (placeholder, ref);
1823 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1824 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1825 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1826 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1828 else
1830 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1831 ref = build_outer_var_ref (var, ctx);
1832 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1833 append_to_statement_list (x, &sub_list);
1837 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
1838 x = build_function_call_expr (x, NULL);
1839 gimplify_and_add (x, stmt_list);
1841 gimplify_and_add (sub_list, stmt_list);
1843 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
1844 x = build_function_call_expr (x, NULL);
1845 gimplify_and_add (x, stmt_list);
1849 /* Generate code to implement the COPYPRIVATE clauses. */
1851 static void
1852 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1853 omp_context *ctx)
1855 tree c;
1857 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1859 tree var, ref, x;
1860 bool by_ref;
1862 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1863 continue;
1865 var = OMP_CLAUSE_DECL (c);
1866 by_ref = use_pointer_for_field (var, false);
1868 ref = build_sender_ref (var, ctx);
1869 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
1870 x = by_ref ? build_fold_addr_expr (x) : x;
1871 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1872 gimplify_and_add (x, slist);
1874 ref = build_receiver_ref (var, by_ref, ctx);
1875 if (is_reference (var))
1877 ref = build_fold_indirect_ref (ref);
1878 var = build_fold_indirect_ref (var);
1880 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
1881 gimplify_and_add (x, rlist);
1886 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
1887 and REDUCTION from the sender (aka parent) side. */
1889 static void
1890 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
1892 tree c;
1894 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1896 tree val, ref, x, var;
1897 bool by_ref, do_in = false, do_out = false;
1899 switch (OMP_CLAUSE_CODE (c))
1901 case OMP_CLAUSE_FIRSTPRIVATE:
1902 case OMP_CLAUSE_COPYIN:
1903 case OMP_CLAUSE_LASTPRIVATE:
1904 case OMP_CLAUSE_REDUCTION:
1905 break;
1906 default:
1907 continue;
1910 var = val = OMP_CLAUSE_DECL (c);
1911 if (ctx->is_nested)
1912 var = lookup_decl_in_outer_ctx (val, ctx);
1914 if (is_variable_sized (val))
1915 continue;
1916 by_ref = use_pointer_for_field (val, false);
1918 switch (OMP_CLAUSE_CODE (c))
1920 case OMP_CLAUSE_FIRSTPRIVATE:
1921 case OMP_CLAUSE_COPYIN:
1922 do_in = true;
1923 break;
1925 case OMP_CLAUSE_LASTPRIVATE:
1926 if (by_ref || is_reference (val))
1928 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1929 continue;
1930 do_in = true;
1932 else
1933 do_out = true;
1934 break;
1936 case OMP_CLAUSE_REDUCTION:
1937 do_in = true;
1938 do_out = !(by_ref || is_reference (val));
1939 break;
1941 default:
1942 gcc_unreachable ();
1945 if (do_in)
1947 ref = build_sender_ref (val, ctx);
1948 x = by_ref ? build_fold_addr_expr (var) : var;
1949 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1950 gimplify_and_add (x, ilist);
1953 if (do_out)
1955 ref = build_sender_ref (val, ctx);
1956 x = build2 (MODIFY_EXPR, void_type_node, var, ref);
1957 gimplify_and_add (x, olist);
1962 /* Generate code to implement SHARED from the sender (aka parent) side.
1963 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
1964 got automatically shared. */
1966 static void
1967 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
1969 tree var, ovar, nvar, f, x;
1971 if (ctx->record_type == NULL)
1972 return;
1974 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
1976 ovar = DECL_ABSTRACT_ORIGIN (f);
1977 nvar = maybe_lookup_decl (ovar, ctx);
1978 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
1979 continue;
1981 var = ovar;
1983 /* If CTX is a nested parallel directive. Find the immediately
1984 enclosing parallel or workshare construct that contains a
1985 mapping for OVAR. */
1986 if (ctx->is_nested)
1987 var = lookup_decl_in_outer_ctx (ovar, ctx);
1989 if (use_pointer_for_field (ovar, true))
1991 x = build_sender_ref (ovar, ctx);
1992 var = build_fold_addr_expr (var);
1993 x = build2 (MODIFY_EXPR, void_type_node, x, var);
1994 gimplify_and_add (x, ilist);
1996 else
1998 x = build_sender_ref (ovar, ctx);
1999 x = build2 (MODIFY_EXPR, void_type_node, x, var);
2000 gimplify_and_add (x, ilist);
2002 x = build_sender_ref (ovar, ctx);
2003 x = build2 (MODIFY_EXPR, void_type_node, var, x);
2004 gimplify_and_add (x, olist);
2009 /* Build the function calls to GOMP_parallel_start etc to actually
2010 generate the parallel operation. REGION is the parallel region
2011 being expanded. BB is the block where to insert the code. WS_ARGS
2012 will be set if this is a call to a combined parallel+workshare
2013 construct, it contains the list of additional arguments needed by
2014 the workshare construct. */
2016 static void
2017 expand_parallel_call (struct omp_region *region, basic_block bb,
2018 tree entry_stmt, tree ws_args)
2020 tree t, args, val, cond, c, list, clauses;
2021 block_stmt_iterator si;
2022 int start_ix;
2024 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2025 push_gimplify_context ();
2027 /* Determine what flavor of GOMP_parallel_start we will be
2028 emitting. */
2029 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2030 if (is_combined_parallel (region))
2032 switch (region->inner->type)
2034 case OMP_FOR:
2036 tree stmt = last_stmt (region->inner->entry);
2037 struct omp_for_data fd;
2038 extract_omp_for_data (stmt, &fd);
2039 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2040 + fd.sched_kind;
2042 break;
2043 case OMP_SECTIONS:
2044 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2045 break;
2046 default:
2047 gcc_unreachable ();
2051 /* By default, the value of NUM_THREADS is zero (selected at run time)
2052 and there is no conditional. */
2053 cond = NULL_TREE;
2054 val = build_int_cst (unsigned_type_node, 0);
2056 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2057 if (c)
2058 cond = OMP_CLAUSE_IF_EXPR (c);
2060 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2061 if (c)
2062 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2064 /* Ensure 'val' is of the correct type. */
2065 val = fold_convert (unsigned_type_node, val);
2067 /* If we found the clause 'if (cond)', build either
2068 (cond != 0) or (cond ? val : 1u). */
2069 if (cond)
2071 block_stmt_iterator si;
2073 cond = gimple_boolify (cond);
2075 if (integer_zerop (val))
2076 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2077 build_int_cst (TREE_TYPE (cond), 0));
2078 else
2080 basic_block cond_bb, then_bb, else_bb;
2081 edge e;
2082 tree t, then_lab, else_lab, tmp;
2084 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2085 e = split_block (bb, NULL);
2086 cond_bb = e->src;
2087 bb = e->dest;
2088 remove_edge (e);
2090 then_bb = create_empty_bb (cond_bb);
2091 else_bb = create_empty_bb (then_bb);
2092 then_lab = create_artificial_label ();
2093 else_lab = create_artificial_label ();
2095 t = build3 (COND_EXPR, void_type_node,
2096 cond,
2097 build_and_jump (&then_lab),
2098 build_and_jump (&else_lab));
2100 si = bsi_start (cond_bb);
2101 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2103 si = bsi_start (then_bb);
2104 t = build1 (LABEL_EXPR, void_type_node, then_lab);
2105 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2106 t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
2107 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2109 si = bsi_start (else_bb);
2110 t = build1 (LABEL_EXPR, void_type_node, else_lab);
2111 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2112 t = build2 (MODIFY_EXPR, void_type_node, tmp,
2113 build_int_cst (unsigned_type_node, 1));
2114 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2116 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2117 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2118 make_edge (then_bb, bb, EDGE_FALLTHRU);
2119 make_edge (else_bb, bb, EDGE_FALLTHRU);
2121 val = tmp;
2124 list = NULL_TREE;
2125 val = get_formal_tmp_var (val, &list);
2126 si = bsi_start (bb);
2127 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2130 list = NULL_TREE;
2131 args = tree_cons (NULL, val, NULL);
2132 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2133 if (t == NULL)
2134 t = null_pointer_node;
2135 else
2136 t = build_fold_addr_expr (t);
2137 args = tree_cons (NULL, t, args);
2138 t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2139 args = tree_cons (NULL, t, args);
2141 if (ws_args)
2142 args = chainon (args, ws_args);
2144 t = built_in_decls[start_ix];
2145 t = build_function_call_expr (t, args);
2146 gimplify_and_add (t, &list);
2148 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2149 if (t == NULL)
2150 t = null_pointer_node;
2151 else
2152 t = build_fold_addr_expr (t);
2153 args = tree_cons (NULL, t, NULL);
2154 t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
2155 gimplify_and_add (t, &list);
2157 t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
2158 t = build_function_call_expr (t, NULL);
2159 gimplify_and_add (t, &list);
2161 si = bsi_last (bb);
2162 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2164 pop_gimplify_context (NULL_TREE);
2168 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2169 handler. This prevents programs from violating the structured
2170 block semantics with throws. */
2172 static void
2173 maybe_catch_exception (tree *stmt_p)
2175 tree f, t;
2177 if (!flag_exceptions)
2178 return;
2180 if (lang_protect_cleanup_actions)
2181 t = lang_protect_cleanup_actions ();
2182 else
2184 t = built_in_decls[BUILT_IN_TRAP];
2185 t = build_function_call_expr (t, NULL);
2187 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2188 EH_FILTER_MUST_NOT_THROW (f) = 1;
2189 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2191 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2192 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2194 *stmt_p = NULL;
2195 append_to_statement_list (t, stmt_p);
2198 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2200 static tree
2201 list2chain (tree list)
2203 tree t;
2205 for (t = list; t; t = TREE_CHAIN (t))
2207 tree var = TREE_VALUE (t);
2208 if (TREE_CHAIN (t))
2209 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2210 else
2211 TREE_CHAIN (var) = NULL_TREE;
2214 return list ? TREE_VALUE (list) : NULL_TREE;
2218 /* Remove barriers in REGION->EXIT's block. Note that this is only
2219 valid for OMP_PARALLEL regions. Since the end of a parallel region
2220 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2221 left a barrier at the end of the OMP_PARALLEL region can now be
2222 removed. */
2224 static void
2225 remove_exit_barrier (struct omp_region *region)
2227 block_stmt_iterator si;
2228 basic_block exit_bb;
2229 edge_iterator ei;
2230 edge e;
2231 tree t;
2233 exit_bb = region->exit;
2235 /* The last insn in the block will be the parallel's OMP_RETURN. The
2236 workshare's OMP_RETURN will be in a preceding block. The kinds of
2237 statements that can appear in between are extremely limited -- no
2238 memory operations at all. Here, we allow nothing at all, so the
2239 only thing we allow to precede this OMP_RETURN is a label. */
2240 si = bsi_last (exit_bb);
2241 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2242 bsi_prev (&si);
2243 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2244 return;
2246 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2248 si = bsi_last (e->src);
2249 if (bsi_end_p (si))
2250 continue;
2251 t = bsi_stmt (si);
2252 if (TREE_CODE (t) == OMP_RETURN)
2253 OMP_RETURN_NOWAIT (t) = 1;
2257 static void
2258 remove_exit_barriers (struct omp_region *region)
2260 if (region->type == OMP_PARALLEL)
2261 remove_exit_barrier (region);
2263 if (region->inner)
2265 region = region->inner;
2266 remove_exit_barriers (region);
2267 while (region->next)
2269 region = region->next;
2270 remove_exit_barriers (region);
2275 /* Expand the OpenMP parallel directive starting at REGION. */
2277 static void
2278 expand_omp_parallel (struct omp_region *region)
2280 basic_block entry_bb, exit_bb, new_bb;
2281 struct function *child_cfun, *saved_cfun;
2282 tree child_fn, block, t, ws_args;
2283 block_stmt_iterator si;
2284 tree entry_stmt;
2285 edge e;
2287 entry_stmt = last_stmt (region->entry);
2288 child_fn = OMP_PARALLEL_FN (entry_stmt);
2289 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2290 saved_cfun = cfun;
2292 entry_bb = region->entry;
2293 exit_bb = region->exit;
2295 if (is_combined_parallel (region))
2296 ws_args = region->ws_args;
2297 else
2298 ws_args = NULL_TREE;
2300 if (child_cfun->cfg)
2302 /* Due to inlining, it may happen that we have already outlined
2303 the region, in which case all we need to do is make the
2304 sub-graph unreachable and emit the parallel call. */
2305 edge entry_succ_e, exit_succ_e;
2306 block_stmt_iterator si;
2308 entry_succ_e = single_succ_edge (entry_bb);
2309 exit_succ_e = single_succ_edge (exit_bb);
2311 si = bsi_last (entry_bb);
2312 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2313 bsi_remove (&si, true);
2315 new_bb = entry_bb;
2316 remove_edge (entry_succ_e);
2317 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2319 else
2321 /* If the parallel region needs data sent from the parent
2322 function, then the very first statement of the parallel body
2323 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2324 &.OMP_DATA_O is passed as an argument to the child function,
2325 we need to replace it with the argument as seen by the child
2326 function.
2328 In most cases, this will end up being the identity assignment
2329 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2330 a function call that has been inlined, the original PARM_DECL
2331 .OMP_DATA_I may have been converted into a different local
2332 variable. In which case, we need to keep the assignment. */
2333 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2335 basic_block entry_succ_bb = single_succ (entry_bb);
2336 block_stmt_iterator si = bsi_start (entry_succ_bb);
2337 tree stmt;
2339 gcc_assert (!bsi_end_p (si));
2341 stmt = bsi_stmt (si);
2342 gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR
2343 && TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
2344 && TREE_OPERAND (TREE_OPERAND (stmt, 1), 0)
2345 == OMP_PARALLEL_DATA_ARG (entry_stmt));
2347 if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
2348 bsi_remove (&si, true);
2349 else
2350 TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2353 /* Declare local variables needed in CHILD_CFUN. */
2354 block = DECL_INITIAL (child_fn);
2355 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2356 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
2358 /* Reset DECL_CONTEXT on locals and function arguments. */
2359 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2360 DECL_CONTEXT (t) = child_fn;
2362 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2363 DECL_CONTEXT (t) = child_fn;
2365 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2366 child function. */
2367 si = bsi_last (entry_bb);
2368 t = bsi_stmt (si);
2369 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2370 bsi_remove (&si, true);
2371 e = split_block (entry_bb, t);
2372 entry_bb = e->dest;
2373 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2375 /* Move the parallel region into CHILD_CFUN. We need to reset
2376 dominance information because the expansion of the inner
2377 regions has invalidated it. */
2378 free_dominance_info (CDI_DOMINATORS);
2379 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2380 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2381 cgraph_add_new_function (child_fn);
2383 /* Convert OMP_RETURN into a RETURN_EXPR. */
2384 si = bsi_last (exit_bb);
2385 gcc_assert (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2386 t = build1 (RETURN_EXPR, void_type_node, NULL);
2387 bsi_insert_after (&si, t, TSI_SAME_STMT);
2388 bsi_remove (&si, true);
2391 /* Emit a library call to launch the children threads. */
2392 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2396 /* A subroutine of expand_omp_for. Generate code for a parallel
2397 loop with any schedule. Given parameters:
2399 for (V = N1; V cond N2; V += STEP) BODY;
2401 where COND is "<" or ">", we generate pseudocode
2403 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2404 if (more) goto L0; else goto L3;
2406 V = istart0;
2407 iend = iend0;
2409 BODY;
2410 V += STEP;
2411 if (V cond iend) goto L1; else goto L2;
2413 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2416 If this is a combined omp parallel loop, instead of the call to
2417 GOMP_loop_foo_start, we emit 'goto L3'. */
2419 static void
2420 expand_omp_for_generic (struct omp_region *region,
2421 struct omp_for_data *fd,
2422 enum built_in_function start_fn,
2423 enum built_in_function next_fn)
2425 tree l0, l1, l2, l3;
2426 tree type, istart0, iend0, iend;
2427 tree t, args, list;
2428 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l3_bb;
2429 block_stmt_iterator si;
2430 bool in_combined_parallel = is_combined_parallel (region);
2432 type = TREE_TYPE (fd->v);
2434 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2435 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2436 iend = create_tmp_var (type, NULL);
2437 TREE_ADDRESSABLE (istart0) = 1;
2438 TREE_ADDRESSABLE (iend0) = 1;
2440 entry_bb = region->entry;
2441 l0_bb = create_empty_bb (entry_bb);
2442 l1_bb = single_succ (entry_bb);
2443 cont_bb = region->cont;
2444 l2_bb = create_empty_bb (cont_bb);
2445 l3_bb = single_succ (cont_bb);
2446 exit_bb = region->exit;
2448 l0 = tree_block_label (l0_bb);
2449 l1 = tree_block_label (l1_bb);
2450 l2 = tree_block_label (l2_bb);
2451 l3 = tree_block_label (l3_bb);
2453 si = bsi_last (entry_bb);
2454 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2455 if (!in_combined_parallel)
2457 /* If this is not a combined parallel loop, emit a call to
2458 GOMP_loop_foo_start in ENTRY_BB. */
2459 list = alloc_stmt_list ();
2460 t = build_fold_addr_expr (iend0);
2461 args = tree_cons (NULL, t, NULL);
2462 t = build_fold_addr_expr (istart0);
2463 args = tree_cons (NULL, t, args);
2464 if (fd->chunk_size)
2466 t = fold_convert (long_integer_type_node, fd->chunk_size);
2467 args = tree_cons (NULL, t, args);
2469 t = fold_convert (long_integer_type_node, fd->step);
2470 args = tree_cons (NULL, t, args);
2471 t = fold_convert (long_integer_type_node, fd->n2);
2472 args = tree_cons (NULL, t, args);
2473 t = fold_convert (long_integer_type_node, fd->n1);
2474 args = tree_cons (NULL, t, args);
2475 t = build_function_call_expr (built_in_decls[start_fn], args);
2476 t = get_formal_tmp_var (t, &list);
2477 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2478 build_and_jump (&l3));
2479 append_to_statement_list (t, &list);
2480 bsi_insert_after (&si, list, BSI_SAME_STMT);
2482 bsi_remove (&si, true);
2484 /* Iteration setup for sequential loop goes in L0_BB. */
2485 list = alloc_stmt_list ();
2486 t = fold_convert (type, istart0);
2487 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2488 gimplify_and_add (t, &list);
2490 t = fold_convert (type, iend0);
2491 t = build2 (MODIFY_EXPR, void_type_node, iend, t);
2492 gimplify_and_add (t, &list);
2494 si = bsi_start (l0_bb);
2495 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2497 /* Code to control the increment and predicate for the sequential
2498 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2499 that we can inherit all the edges going out of the loop
2500 body). */
2501 list = alloc_stmt_list ();
2503 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2504 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2505 gimplify_and_add (t, &list);
2507 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2508 t = get_formal_tmp_var (t, &list);
2509 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2510 build_and_jump (&l2));
2511 append_to_statement_list (t, &list);
2513 si = bsi_last (cont_bb);
2514 bsi_insert_after (&si, list, BSI_SAME_STMT);
2515 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2516 bsi_remove (&si, true);
2518 /* Emit code to get the next parallel iteration in L2_BB. */
2519 list = alloc_stmt_list ();
2521 t = build_fold_addr_expr (iend0);
2522 args = tree_cons (NULL, t, NULL);
2523 t = build_fold_addr_expr (istart0);
2524 args = tree_cons (NULL, t, args);
2525 t = build_function_call_expr (built_in_decls[next_fn], args);
2526 t = get_formal_tmp_var (t, &list);
2527 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2528 build_and_jump (&l3));
2529 append_to_statement_list (t, &list);
2531 si = bsi_start (l2_bb);
2532 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2534 /* Add the loop cleanup function. */
2535 si = bsi_last (exit_bb);
2536 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2537 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2538 else
2539 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2540 t = build_function_call_expr (t, NULL);
2541 bsi_insert_after (&si, t, BSI_SAME_STMT);
2542 bsi_remove (&si, true);
2544 /* Connect the new blocks. */
2545 remove_edge (single_succ_edge (entry_bb));
2546 if (in_combined_parallel)
2547 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2548 else
2550 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2551 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2554 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2556 remove_edge (single_succ_edge (cont_bb));
2557 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2558 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2560 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2561 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2565 /* A subroutine of expand_omp_for. Generate code for a parallel
2566 loop with static schedule and no specified chunk size. Given
2567 parameters:
2569 for (V = N1; V cond N2; V += STEP) BODY;
2571 where COND is "<" or ">", we generate pseudocode
2573 if (cond is <)
2574 adj = STEP - 1;
2575 else
2576 adj = STEP + 1;
2577 n = (adj + N2 - N1) / STEP;
2578 q = n / nthreads;
2579 q += (q * nthreads != n);
2580 s0 = q * threadid;
2581 e0 = min(s0 + q, n);
2582 if (s0 >= e0) goto L2; else goto L0;
2584 V = s0 * STEP + N1;
2585 e = e0 * STEP + N1;
2587 BODY;
2588 V += STEP;
2589 if (V cond e) goto L1;
2593 static void
2594 expand_omp_for_static_nochunk (struct omp_region *region,
2595 struct omp_for_data *fd)
2597 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
2598 tree type, utype, list;
2599 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2600 basic_block fin_bb;
2601 block_stmt_iterator si;
2603 type = TREE_TYPE (fd->v);
2604 utype = lang_hooks.types.unsigned_type (type);
2606 entry_bb = region->entry;
2607 seq_start_bb = create_empty_bb (entry_bb);
2608 body_bb = single_succ (entry_bb);
2609 cont_bb = region->cont;
2610 fin_bb = single_succ (cont_bb);
2611 exit_bb = region->exit;
2613 l0 = tree_block_label (seq_start_bb);
2614 l1 = tree_block_label (body_bb);
2615 l2 = tree_block_label (fin_bb);
2617 /* Iteration space partitioning goes in ENTRY_BB. */
2618 list = alloc_stmt_list ();
2620 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2621 t = build_function_call_expr (t, NULL);
2622 t = fold_convert (utype, t);
2623 nthreads = get_formal_tmp_var (t, &list);
2625 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2626 t = build_function_call_expr (t, NULL);
2627 t = fold_convert (utype, t);
2628 threadid = get_formal_tmp_var (t, &list);
2630 fd->n1 = fold_convert (type, fd->n1);
2631 if (!is_gimple_val (fd->n1))
2632 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2634 fd->n2 = fold_convert (type, fd->n2);
2635 if (!is_gimple_val (fd->n2))
2636 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2638 fd->step = fold_convert (type, fd->step);
2639 if (!is_gimple_val (fd->step))
2640 fd->step = get_formal_tmp_var (fd->step, &list);
2642 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2643 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2644 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2645 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2646 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2647 t = fold_convert (utype, t);
2648 if (is_gimple_val (t))
2649 n = t;
2650 else
2651 n = get_formal_tmp_var (t, &list);
2653 t = build2 (TRUNC_DIV_EXPR, utype, n, nthreads);
2654 q = get_formal_tmp_var (t, &list);
2656 t = build2 (MULT_EXPR, utype, q, nthreads);
2657 t = build2 (NE_EXPR, utype, t, n);
2658 t = build2 (PLUS_EXPR, utype, q, t);
2659 q = get_formal_tmp_var (t, &list);
2661 t = build2 (MULT_EXPR, utype, q, threadid);
2662 s0 = get_formal_tmp_var (t, &list);
2664 t = build2 (PLUS_EXPR, utype, s0, q);
2665 t = build2 (MIN_EXPR, utype, t, n);
2666 e0 = get_formal_tmp_var (t, &list);
2668 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2669 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
2670 build_and_jump (&l0));
2671 append_to_statement_list (t, &list);
2673 si = bsi_last (entry_bb);
2674 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2675 bsi_insert_after (&si, list, BSI_SAME_STMT);
2676 bsi_remove (&si, true);
2678 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2679 list = alloc_stmt_list ();
2681 t = fold_convert (type, s0);
2682 t = build2 (MULT_EXPR, type, t, fd->step);
2683 t = build2 (PLUS_EXPR, type, t, fd->n1);
2684 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2685 gimplify_and_add (t, &list);
2687 t = fold_convert (type, e0);
2688 t = build2 (MULT_EXPR, type, t, fd->step);
2689 t = build2 (PLUS_EXPR, type, t, fd->n1);
2690 e = get_formal_tmp_var (t, &list);
2692 si = bsi_start (seq_start_bb);
2693 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2695 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2696 list = alloc_stmt_list ();
2698 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2699 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2700 gimplify_and_add (t, &list);
2702 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2703 t = get_formal_tmp_var (t, &list);
2704 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2705 build_and_jump (&l2));
2706 append_to_statement_list (t, &list);
2708 si = bsi_last (cont_bb);
2709 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2710 bsi_insert_after (&si, list, BSI_SAME_STMT);
2711 bsi_remove (&si, true);
2713 /* Replace the OMP_RETURN with a barrier, or nothing. */
2714 si = bsi_last (exit_bb);
2715 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2717 list = alloc_stmt_list ();
2718 build_omp_barrier (&list);
2719 bsi_insert_after (&si, list, BSI_SAME_STMT);
2721 bsi_remove (&si, true);
2723 /* Connect all the blocks. */
2724 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2726 remove_edge (single_succ_edge (entry_bb));
2727 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2728 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2730 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2731 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2735 /* A subroutine of expand_omp_for. Generate code for a parallel
2736 loop with static schedule and a specified chunk size. Given
2737 parameters:
2739 for (V = N1; V cond N2; V += STEP) BODY;
2741 where COND is "<" or ">", we generate pseudocode
2743 if (cond is <)
2744 adj = STEP - 1;
2745 else
2746 adj = STEP + 1;
2747 n = (adj + N2 - N1) / STEP;
2748 trip = 0;
2750 s0 = (trip * nthreads + threadid) * CHUNK;
2751 e0 = min(s0 + CHUNK, n);
2752 if (s0 < n) goto L1; else goto L4;
2754 V = s0 * STEP + N1;
2755 e = e0 * STEP + N1;
2757 BODY;
2758 V += STEP;
2759 if (V cond e) goto L2; else goto L3;
2761 trip += 1;
2762 goto L0;
2766 static void
2767 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2769 tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
2770 tree trip, nthreads, threadid;
2771 tree type, utype;
2772 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2773 basic_block trip_update_bb, cont_bb, fin_bb;
2774 tree list;
2775 block_stmt_iterator si;
2777 type = TREE_TYPE (fd->v);
2778 utype = lang_hooks.types.unsigned_type (type);
2780 entry_bb = region->entry;
2781 iter_part_bb = create_empty_bb (entry_bb);
2782 seq_start_bb = create_empty_bb (iter_part_bb);
2783 body_bb = single_succ (entry_bb);
2784 cont_bb = region->cont;
2785 trip_update_bb = create_empty_bb (cont_bb);
2786 fin_bb = single_succ (cont_bb);
2787 exit_bb = region->exit;
2789 l0 = tree_block_label (iter_part_bb);
2790 l1 = tree_block_label (seq_start_bb);
2791 l2 = tree_block_label (body_bb);
2792 l3 = tree_block_label (trip_update_bb);
2793 l4 = tree_block_label (fin_bb);
2795 /* Trip and adjustment setup goes in ENTRY_BB. */
2796 list = alloc_stmt_list ();
2798 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2799 t = build_function_call_expr (t, NULL);
2800 t = fold_convert (utype, t);
2801 nthreads = get_formal_tmp_var (t, &list);
2803 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2804 t = build_function_call_expr (t, NULL);
2805 t = fold_convert (utype, t);
2806 threadid = get_formal_tmp_var (t, &list);
2808 fd->n1 = fold_convert (type, fd->n1);
2809 if (!is_gimple_val (fd->n1))
2810 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2812 fd->n2 = fold_convert (type, fd->n2);
2813 if (!is_gimple_val (fd->n2))
2814 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2816 fd->step = fold_convert (type, fd->step);
2817 if (!is_gimple_val (fd->step))
2818 fd->step = get_formal_tmp_var (fd->step, &list);
2820 fd->chunk_size = fold_convert (utype, fd->chunk_size);
2821 if (!is_gimple_val (fd->chunk_size))
2822 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2824 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2825 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2826 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2827 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2828 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2829 t = fold_convert (utype, t);
2830 if (is_gimple_val (t))
2831 n = t;
2832 else
2833 n = get_formal_tmp_var (t, &list);
2835 t = build_int_cst (utype, 0);
2836 trip = get_initialized_tmp_var (t, &list, NULL);
2838 si = bsi_last (entry_bb);
2839 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2840 bsi_insert_after (&si, list, BSI_SAME_STMT);
2841 bsi_remove (&si, true);
2843 /* Iteration space partitioning goes in ITER_PART_BB. */
2844 list = alloc_stmt_list ();
2846 t = build2 (MULT_EXPR, utype, trip, nthreads);
2847 t = build2 (PLUS_EXPR, utype, t, threadid);
2848 t = build2 (MULT_EXPR, utype, t, fd->chunk_size);
2849 s0 = get_formal_tmp_var (t, &list);
2851 t = build2 (PLUS_EXPR, utype, s0, fd->chunk_size);
2852 t = build2 (MIN_EXPR, utype, t, n);
2853 e0 = get_formal_tmp_var (t, &list);
2855 t = build2 (LT_EXPR, boolean_type_node, s0, n);
2856 t = build3 (COND_EXPR, void_type_node, t,
2857 build_and_jump (&l1), build_and_jump (&l4));
2858 append_to_statement_list (t, &list);
2860 si = bsi_start (iter_part_bb);
2861 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2863 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2864 list = alloc_stmt_list ();
2866 t = fold_convert (type, s0);
2867 t = build2 (MULT_EXPR, type, t, fd->step);
2868 t = build2 (PLUS_EXPR, type, t, fd->n1);
2869 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2870 gimplify_and_add (t, &list);
2872 t = fold_convert (type, e0);
2873 t = build2 (MULT_EXPR, type, t, fd->step);
2874 t = build2 (PLUS_EXPR, type, t, fd->n1);
2875 e = get_formal_tmp_var (t, &list);
2877 si = bsi_start (seq_start_bb);
2878 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2880 /* The code controlling the sequential loop goes in CONT_BB,
2881 replacing the OMP_CONTINUE. */
2882 list = alloc_stmt_list ();
2884 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2885 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2886 gimplify_and_add (t, &list);
2888 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2889 t = get_formal_tmp_var (t, &list);
2890 t = build3 (COND_EXPR, void_type_node, t,
2891 build_and_jump (&l2), build_and_jump (&l3));
2892 append_to_statement_list (t, &list);
2894 si = bsi_last (cont_bb);
2895 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2896 bsi_insert_after (&si, list, BSI_SAME_STMT);
2897 bsi_remove (&si, true);
2899 /* Trip update code goes into TRIP_UPDATE_BB. */
2900 list = alloc_stmt_list ();
2902 t = build_int_cst (utype, 1);
2903 t = build2 (PLUS_EXPR, utype, trip, t);
2904 t = build2 (MODIFY_EXPR, void_type_node, trip, t);
2905 gimplify_and_add (t, &list);
2907 si = bsi_start (trip_update_bb);
2908 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2910 /* Replace the OMP_RETURN with a barrier, or nothing. */
2911 si = bsi_last (exit_bb);
2912 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2914 list = alloc_stmt_list ();
2915 build_omp_barrier (&list);
2916 bsi_insert_after (&si, list, BSI_SAME_STMT);
2918 bsi_remove (&si, true);
2920 /* Connect the new blocks. */
2921 remove_edge (single_succ_edge (entry_bb));
2922 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
2924 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
2925 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
2927 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2929 remove_edge (single_succ_edge (cont_bb));
2930 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2931 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
2933 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
2937 /* Expand the OpenMP loop defined by REGION. */
2939 static void
2940 expand_omp_for (struct omp_region *region)
2942 struct omp_for_data fd;
2944 push_gimplify_context ();
2946 extract_omp_for_data (last_stmt (region->entry), &fd);
2948 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered)
2950 if (fd.chunk_size == NULL)
2951 expand_omp_for_static_nochunk (region, &fd);
2952 else
2953 expand_omp_for_static_chunk (region, &fd);
2955 else
2957 int fn_index = fd.sched_kind + fd.have_ordered * 4;
2958 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
2959 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
2960 expand_omp_for_generic (region, &fd, start_ix, next_ix);
2963 pop_gimplify_context (NULL);
2967 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
2969 v = GOMP_sections_start (n);
2971 switch (v)
2973 case 0:
2974 goto L2;
2975 case 1:
2976 section 1;
2977 goto L1;
2978 case 2:
2980 case n:
2982 default:
2983 abort ();
2986 v = GOMP_sections_next ();
2987 goto L0;
2989 reduction;
2991 If this is a combined parallel sections, replace the call to
2992 GOMP_sections_start with 'goto L1'. */
2994 static void
2995 expand_omp_sections (struct omp_region *region)
2997 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
2998 unsigned i, len;
2999 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3000 block_stmt_iterator si;
3001 struct omp_region *inner;
3002 edge e;
3004 entry_bb = region->entry;
3005 l0_bb = create_empty_bb (entry_bb);
3006 l1_bb = region->cont;
3007 l2_bb = single_succ (l1_bb);
3008 default_bb = create_empty_bb (l1_bb->prev_bb);
3009 exit_bb = region->exit;
3011 l0 = tree_block_label (l0_bb);
3012 l1 = tree_block_label (l1_bb);
3013 l2 = tree_block_label (l2_bb);
3015 v = create_tmp_var (unsigned_type_node, ".section");
3017 /* We will build a switch() with enough cases for all the
3018 OMP_SECTION regions, a '0' case to handle the end of more work
3019 and a default case to abort if something goes wrong. */
3020 len = EDGE_COUNT (entry_bb->succs);
3021 label_vec = make_tree_vec (len + 2);
3023 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3024 OMP_SECTIONS statement. */
3025 si = bsi_last (entry_bb);
3026 sections_stmt = bsi_stmt (si);
3027 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3028 if (!is_combined_parallel (region))
3030 /* If we are not inside a combined parallel+sections region,
3031 call GOMP_sections_start. */
3032 t = build_int_cst (unsigned_type_node, len);
3033 t = tree_cons (NULL, t, NULL);
3034 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3035 t = build_function_call_expr (u, t);
3036 t = build2 (MODIFY_EXPR, void_type_node, v, t);
3037 bsi_insert_after (&si, t, BSI_SAME_STMT);
3039 bsi_remove (&si, true);
3041 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
3042 si = bsi_start (l0_bb);
3044 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3045 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3047 t = build3 (CASE_LABEL_EXPR, void_type_node,
3048 build_int_cst (unsigned_type_node, 0), NULL, l2);
3049 TREE_VEC_ELT (label_vec, 0) = t;
3050 make_edge (l0_bb, l2_bb, 0);
3052 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3053 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3055 basic_block s_entry_bb, s_exit_bb;
3057 s_entry_bb = inner->entry;
3058 s_exit_bb = inner->exit;
3060 t = tree_block_label (s_entry_bb);
3061 u = build_int_cst (unsigned_type_node, i);
3062 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3063 TREE_VEC_ELT (label_vec, i) = u;
3065 si = bsi_last (s_entry_bb);
3066 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3067 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3068 bsi_remove (&si, true);
3070 si = bsi_last (s_exit_bb);
3071 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3072 bsi_remove (&si, true);
3074 e = single_pred_edge (s_entry_bb);
3075 e->flags = 0;
3076 redirect_edge_pred (e, l0_bb);
3078 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3079 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3082 /* Error handling code goes in DEFAULT_BB. */
3083 t = tree_block_label (default_bb);
3084 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3085 TREE_VEC_ELT (label_vec, len + 1) = u;
3086 make_edge (l0_bb, default_bb, 0);
3088 si = bsi_start (default_bb);
3089 t = built_in_decls[BUILT_IN_TRAP];
3090 t = build_function_call_expr (t, NULL);
3091 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3093 /* Code to get the next section goes in L1_BB. */
3094 si = bsi_last (l1_bb);
3095 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3097 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3098 t = build_function_call_expr (t, NULL);
3099 t = build2 (MODIFY_EXPR, void_type_node, v, t);
3100 bsi_insert_after (&si, t, BSI_SAME_STMT);
3101 bsi_remove (&si, true);
3103 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3104 si = bsi_last (exit_bb);
3105 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3106 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3107 else
3108 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3109 t = build_function_call_expr (t, NULL);
3110 bsi_insert_after (&si, t, BSI_SAME_STMT);
3111 bsi_remove (&si, true);
3113 /* Connect the new blocks. */
3114 if (is_combined_parallel (region))
3116 /* If this was a combined parallel+sections region, we did not
3117 emit a GOMP_sections_start in the entry block, so we just
3118 need to jump to L1_BB to get the next section. */
3119 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3121 else
3122 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3124 e = single_succ_edge (l1_bb);
3125 redirect_edge_succ (e, l0_bb);
3126 e->flags = EDGE_FALLTHRU;
3130 /* Expand code for an OpenMP single directive. We've already expanded
3131 much of the code, here we simply place the GOMP_barrier call. */
3133 static void
3134 expand_omp_single (struct omp_region *region)
3136 basic_block entry_bb, exit_bb;
3137 block_stmt_iterator si;
3138 bool need_barrier = false;
3140 entry_bb = region->entry;
3141 exit_bb = region->exit;
3143 si = bsi_last (entry_bb);
3144 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3145 be removed. We need to ensure that the thread that entered the single
3146 does not exit before the data is copied out by the other threads. */
3147 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3148 OMP_CLAUSE_COPYPRIVATE))
3149 need_barrier = true;
3150 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3151 bsi_remove (&si, true);
3152 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3154 si = bsi_last (exit_bb);
3155 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3157 tree t = alloc_stmt_list ();
3158 build_omp_barrier (&t);
3159 bsi_insert_after (&si, t, BSI_SAME_STMT);
3161 bsi_remove (&si, true);
3162 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3166 /* Generic expansion for OpenMP synchronization directives: master,
3167 ordered and critical. All we need to do here is remove the entry
3168 and exit markers for REGION. */
3170 static void
3171 expand_omp_synch (struct omp_region *region)
3173 basic_block entry_bb, exit_bb;
3174 block_stmt_iterator si;
3176 entry_bb = region->entry;
3177 exit_bb = region->exit;
3179 si = bsi_last (entry_bb);
3180 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3181 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3182 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3183 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3184 bsi_remove (&si, true);
3185 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3187 si = bsi_last (exit_bb);
3188 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3189 bsi_remove (&si, true);
3190 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3194 /* Expand the parallel region tree rooted at REGION. Expansion
3195 proceeds in depth-first order. Innermost regions are expanded
3196 first. This way, parallel regions that require a new function to
3197 be created (e.g., OMP_PARALLEL) can be expanded without having any
3198 internal dependencies in their body. */
3200 static void
3201 expand_omp (struct omp_region *region)
3203 while (region)
3205 if (region->inner)
3206 expand_omp (region->inner);
3208 switch (region->type)
3210 case OMP_PARALLEL:
3211 expand_omp_parallel (region);
3212 break;
3214 case OMP_FOR:
3215 expand_omp_for (region);
3216 break;
3218 case OMP_SECTIONS:
3219 expand_omp_sections (region);
3220 break;
3222 case OMP_SECTION:
3223 /* Individual omp sections are handled together with their
3224 parent OMP_SECTIONS region. */
3225 break;
3227 case OMP_SINGLE:
3228 expand_omp_single (region);
3229 break;
3231 case OMP_MASTER:
3232 case OMP_ORDERED:
3233 case OMP_CRITICAL:
3234 expand_omp_synch (region);
3235 break;
3237 default:
3238 gcc_unreachable ();
3241 region = region->next;
3246 /* Helper for build_omp_regions. Scan the dominator tree starting at
3247 block BB. PARENT is the region that contains BB. */
3249 static void
3250 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3252 block_stmt_iterator si;
3253 tree stmt;
3254 basic_block son;
3256 si = bsi_last (bb);
3257 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3259 struct omp_region *region;
3260 enum tree_code code;
3262 stmt = bsi_stmt (si);
3263 code = TREE_CODE (stmt);
3265 if (code == OMP_RETURN)
3267 /* STMT is the return point out of region PARENT. Mark it
3268 as the exit point and make PARENT the immediately
3269 enclosing region. */
3270 gcc_assert (parent);
3271 region = parent;
3272 region->exit = bb;
3273 parent = parent->outer;
3275 /* If REGION is a parallel region, determine whether it is
3276 a combined parallel+workshare region. */
3277 if (region->type == OMP_PARALLEL)
3278 determine_parallel_type (region);
3280 else if (code == OMP_CONTINUE)
3282 gcc_assert (parent);
3283 parent->cont = bb;
3285 else
3287 /* Otherwise, this directive becomes the parent for a new
3288 region. */
3289 region = new_omp_region (bb, code, parent);
3290 parent = region;
3294 for (son = first_dom_son (CDI_DOMINATORS, bb);
3295 son;
3296 son = next_dom_son (CDI_DOMINATORS, son))
3297 build_omp_regions_1 (son, parent);
3301 /* Scan the CFG and build a tree of OMP regions. Return the root of
3302 the OMP region tree. */
3304 static void
3305 build_omp_regions (void)
3307 gcc_assert (root_omp_region == NULL);
3308 calculate_dominance_info (CDI_DOMINATORS);
3309 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3313 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3315 static unsigned int
3316 execute_expand_omp (void)
3318 build_omp_regions ();
3320 if (!root_omp_region)
3321 return 0;
3323 if (dump_file)
3325 fprintf (dump_file, "\nOMP region tree\n\n");
3326 dump_omp_region (dump_file, root_omp_region, 0);
3327 fprintf (dump_file, "\n");
3330 remove_exit_barriers (root_omp_region);
3332 expand_omp (root_omp_region);
3334 free_dominance_info (CDI_DOMINATORS);
3335 free_dominance_info (CDI_POST_DOMINATORS);
3336 cleanup_tree_cfg ();
3338 free_omp_regions ();
3340 return 0;
3343 static bool
3344 gate_expand_omp (void)
3346 return flag_openmp != 0 && errorcount == 0;
3349 struct tree_opt_pass pass_expand_omp =
3351 "ompexp", /* name */
3352 gate_expand_omp, /* gate */
3353 execute_expand_omp, /* execute */
3354 NULL, /* sub */
3355 NULL, /* next */
3356 0, /* static_pass_number */
3357 0, /* tv_id */
3358 PROP_gimple_any, /* properties_required */
3359 PROP_gimple_lomp, /* properties_provided */
3360 0, /* properties_destroyed */
3361 0, /* todo_flags_start */
3362 TODO_dump_func, /* todo_flags_finish */
3363 0 /* letter */
3366 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3368 /* Lower the OpenMP sections directive in *STMT_P. */
3370 static void
3371 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3373 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3374 tree t, dlist;
3375 tree_stmt_iterator tsi;
3376 unsigned i, len;
3378 stmt = *stmt_p;
3380 push_gimplify_context ();
3382 dlist = NULL;
3383 ilist = NULL;
3384 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3386 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3387 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3388 continue;
3390 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3391 body = alloc_stmt_list ();
3392 for (i = 0; i < len; i++, tsi_next (&tsi))
3394 omp_context *sctx;
3395 tree sec_start, sec_end;
3397 sec_start = tsi_stmt (tsi);
3398 sctx = maybe_lookup_ctx (sec_start);
3399 gcc_assert (sctx);
3401 append_to_statement_list (sec_start, &body);
3403 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3404 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3405 OMP_SECTION_BODY (sec_start) = NULL;
3407 if (i == len - 1)
3409 tree l = alloc_stmt_list ();
3410 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3411 &l, ctx);
3412 append_to_statement_list (l, &body);
3413 OMP_SECTION_LAST (sec_start) = 1;
3416 sec_end = make_node (OMP_RETURN);
3417 append_to_statement_list (sec_end, &body);
3420 block = make_node (BLOCK);
3421 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3422 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3424 olist = NULL_TREE;
3425 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3427 pop_gimplify_context (NULL_TREE);
3428 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3430 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3431 TREE_SIDE_EFFECTS (new_stmt) = 1;
3433 new_body = alloc_stmt_list ();
3434 append_to_statement_list (ilist, &new_body);
3435 append_to_statement_list (stmt, &new_body);
3436 append_to_statement_list (bind, &new_body);
3438 t = make_node (OMP_CONTINUE);
3439 append_to_statement_list (t, &new_body);
3441 append_to_statement_list (olist, &new_body);
3442 append_to_statement_list (dlist, &new_body);
3444 t = make_node (OMP_RETURN);
3445 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3446 OMP_CLAUSE_NOWAIT);
3447 append_to_statement_list (t, &new_body);
3449 BIND_EXPR_BODY (new_stmt) = new_body;
3450 OMP_SECTIONS_BODY (stmt) = NULL;
3452 *stmt_p = new_stmt;
3456 /* A subroutine of lower_omp_single. Expand the simple form of
3457 an OMP_SINGLE, without a copyprivate clause:
3459 if (GOMP_single_start ())
3460 BODY;
3461 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3463 FIXME. It may be better to delay expanding the logic of this until
3464 pass_expand_omp. The expanded logic may make the job more difficult
3465 to a synchronization analysis pass. */
3467 static void
3468 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3470 tree t;
3472 t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
3473 t = build_function_call_expr (t, NULL);
3474 t = build3 (COND_EXPR, void_type_node, t,
3475 OMP_SINGLE_BODY (single_stmt), NULL);
3476 gimplify_and_add (t, pre_p);
3480 /* A subroutine of lower_omp_single. Expand the simple form of
3481 an OMP_SINGLE, with a copyprivate clause:
3483 #pragma omp single copyprivate (a, b, c)
3485 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3488 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3490 BODY;
3491 copyout.a = a;
3492 copyout.b = b;
3493 copyout.c = c;
3494 GOMP_single_copy_end (&copyout);
3496 else
3498 a = copyout_p->a;
3499 b = copyout_p->b;
3500 c = copyout_p->c;
3502 GOMP_barrier ();
3505 FIXME. It may be better to delay expanding the logic of this until
3506 pass_expand_omp. The expanded logic may make the job more difficult
3507 to a synchronization analysis pass. */
3509 static void
3510 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3512 tree ptr_type, t, args, l0, l1, l2, copyin_seq;
3514 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3516 ptr_type = build_pointer_type (ctx->record_type);
3517 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3519 l0 = create_artificial_label ();
3520 l1 = create_artificial_label ();
3521 l2 = create_artificial_label ();
3523 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
3524 t = build_function_call_expr (t, NULL);
3525 t = fold_convert (ptr_type, t);
3526 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
3527 gimplify_and_add (t, pre_p);
3529 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3530 build_int_cst (ptr_type, 0));
3531 t = build3 (COND_EXPR, void_type_node, t,
3532 build_and_jump (&l0), build_and_jump (&l1));
3533 gimplify_and_add (t, pre_p);
3535 t = build1 (LABEL_EXPR, void_type_node, l0);
3536 gimplify_and_add (t, pre_p);
3538 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3540 copyin_seq = NULL;
3541 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3542 &copyin_seq, ctx);
3544 t = build_fold_addr_expr (ctx->sender_decl);
3545 args = tree_cons (NULL, t, NULL);
3546 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
3547 t = build_function_call_expr (t, args);
3548 gimplify_and_add (t, pre_p);
3550 t = build_and_jump (&l2);
3551 gimplify_and_add (t, pre_p);
3553 t = build1 (LABEL_EXPR, void_type_node, l1);
3554 gimplify_and_add (t, pre_p);
3556 append_to_statement_list (copyin_seq, pre_p);
3558 t = build1 (LABEL_EXPR, void_type_node, l2);
3559 gimplify_and_add (t, pre_p);
3563 /* Expand code for an OpenMP single directive. */
3565 static void
3566 lower_omp_single (tree *stmt_p, omp_context *ctx)
3568 tree t, bind, block, single_stmt = *stmt_p, dlist;
3570 push_gimplify_context ();
3572 block = make_node (BLOCK);
3573 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3574 TREE_SIDE_EFFECTS (bind) = 1;
3576 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3577 &BIND_EXPR_BODY (bind), &dlist, ctx);
3578 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3579 maybe_catch_exception (&OMP_SINGLE_BODY (single_stmt));
3581 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3583 if (ctx->record_type)
3584 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3585 else
3586 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3588 OMP_SINGLE_BODY (single_stmt) = NULL;
3590 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3592 t = make_node (OMP_RETURN);
3593 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3594 OMP_CLAUSE_NOWAIT);
3595 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3597 pop_gimplify_context (bind);
3599 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3600 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3604 /* Expand code for an OpenMP master directive. */
3606 static void
3607 lower_omp_master (tree *stmt_p, omp_context *ctx)
3609 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3611 push_gimplify_context ();
3613 block = make_node (BLOCK);
3614 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3615 TREE_SIDE_EFFECTS (bind) = 1;
3617 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3619 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
3620 x = build_function_call_expr (x, NULL);
3621 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3622 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3623 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3625 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3626 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3627 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3628 OMP_MASTER_BODY (stmt) = NULL;
3630 x = build1 (LABEL_EXPR, void_type_node, lab);
3631 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3633 x = make_node (OMP_RETURN);
3634 OMP_RETURN_NOWAIT (x) = 1;
3635 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3637 pop_gimplify_context (bind);
3639 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3640 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3644 /* Expand code for an OpenMP ordered directive. */
3646 static void
3647 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3649 tree bind, block, stmt = *stmt_p, x;
3651 push_gimplify_context ();
3653 block = make_node (BLOCK);
3654 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3655 TREE_SIDE_EFFECTS (bind) = 1;
3657 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3659 x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
3660 x = build_function_call_expr (x, NULL);
3661 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3663 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3664 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3665 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3666 OMP_ORDERED_BODY (stmt) = NULL;
3668 x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
3669 x = build_function_call_expr (x, NULL);
3670 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3672 x = make_node (OMP_RETURN);
3673 OMP_RETURN_NOWAIT (x) = 1;
3674 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3676 pop_gimplify_context (bind);
3678 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3679 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3683 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3684 substitution of a couple of function calls. But in the NAMED case,
3685 requires that languages coordinate a symbol name. It is therefore
3686 best put here in common code. */
3688 static GTY((param1_is (tree), param2_is (tree)))
3689 splay_tree critical_name_mutexes;
3691 static void
3692 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3694 tree bind, block, stmt = *stmt_p;
3695 tree t, lock, unlock, name;
3697 name = OMP_CRITICAL_NAME (stmt);
3698 if (name)
3700 tree decl, args;
3701 splay_tree_node n;
3703 if (!critical_name_mutexes)
3704 critical_name_mutexes
3705 = splay_tree_new_ggc (splay_tree_compare_pointers);
3707 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3708 if (n == NULL)
3710 char *new_str;
3712 decl = create_tmp_var_raw (ptr_type_node, NULL);
3714 new_str = ACONCAT ((".gomp_critical_user_",
3715 IDENTIFIER_POINTER (name), NULL));
3716 DECL_NAME (decl) = get_identifier (new_str);
3717 TREE_PUBLIC (decl) = 1;
3718 TREE_STATIC (decl) = 1;
3719 DECL_COMMON (decl) = 1;
3720 DECL_ARTIFICIAL (decl) = 1;
3721 DECL_IGNORED_P (decl) = 1;
3722 cgraph_varpool_finalize_decl (decl);
3724 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3725 (splay_tree_value) decl);
3727 else
3728 decl = (tree) n->value;
3730 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3731 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3732 lock = build_function_call_expr (lock, args);
3734 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3735 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3736 unlock = build_function_call_expr (unlock, args);
3738 else
3740 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3741 lock = build_function_call_expr (lock, NULL);
3743 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3744 unlock = build_function_call_expr (unlock, NULL);
3747 push_gimplify_context ();
3749 block = make_node (BLOCK);
3750 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3751 TREE_SIDE_EFFECTS (bind) = 1;
3753 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3755 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3757 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3758 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3759 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3760 OMP_CRITICAL_BODY (stmt) = NULL;
3762 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3764 t = make_node (OMP_RETURN);
3765 OMP_RETURN_NOWAIT (t) = 1;
3766 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3768 pop_gimplify_context (bind);
3769 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3770 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3774 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3775 for a lastprivate clause. Given a loop control predicate of (V
3776 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3777 is appended to *BODY_P. */
3779 static void
3780 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3781 struct omp_context *ctx)
3783 tree clauses, cond;
3784 enum tree_code cond_code;
3786 cond_code = fd->cond_code;
3787 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3789 /* When possible, use a strict equality expression. This can let VRP
3790 type optimizations deduce the value and remove a copy. */
3791 if (host_integerp (fd->step, 0))
3793 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3794 if (step == 1 || step == -1)
3795 cond_code = EQ_EXPR;
3798 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3800 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3801 lower_lastprivate_clauses (clauses, cond, body_p, ctx);
3805 /* Lower code for an OpenMP loop directive. */
3807 static void
3808 lower_omp_for (tree *stmt_p, omp_context *ctx)
3810 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3811 struct omp_for_data fd;
3813 stmt = *stmt_p;
3815 push_gimplify_context ();
3817 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3818 lower_omp (&OMP_FOR_BODY (stmt), ctx);
3820 /* Move declaration of temporaries in the loop body before we make
3821 it go away. */
3822 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
3823 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
3825 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3826 TREE_SIDE_EFFECTS (new_stmt) = 1;
3827 body_p = &BIND_EXPR_BODY (new_stmt);
3829 /* The pre-body and input clauses go before the lowered OMP_FOR. */
3830 ilist = NULL;
3831 dlist = NULL;
3832 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
3833 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
3835 /* Lower the header expressions. At this point, we can assume that
3836 the header is of the form:
3838 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
3840 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
3841 using the .omp_data_s mapping, if needed. */
3842 rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1);
3843 if (!is_gimple_min_invariant (*rhs_p))
3844 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3846 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
3847 if (!is_gimple_min_invariant (*rhs_p))
3848 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3850 rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
3851 if (!is_gimple_min_invariant (*rhs_p))
3852 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3854 /* Once lowered, extract the bounds and clauses. */
3855 extract_omp_for_data (stmt, &fd);
3857 append_to_statement_list (stmt, body_p);
3859 maybe_catch_exception (&OMP_FOR_BODY (stmt));
3860 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
3862 t = make_node (OMP_CONTINUE);
3863 append_to_statement_list (t, body_p);
3865 /* After the loop, add exit clauses. */
3866 lower_omp_for_lastprivate (&fd, &dlist, ctx);
3867 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
3868 append_to_statement_list (dlist, body_p);
3870 /* Region exit marker goes at the end of the loop body. */
3871 t = make_node (OMP_RETURN);
3872 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
3873 append_to_statement_list (t, body_p);
3875 pop_gimplify_context (NULL_TREE);
3876 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3878 OMP_FOR_BODY (stmt) = NULL_TREE;
3879 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
3880 *stmt_p = new_stmt;
3884 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
3885 information for the directive. */
3887 static void
3888 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
3890 tree clauses, par_bind, par_body, new_body, bind;
3891 tree olist, ilist, par_olist, par_ilist;
3892 tree stmt, child_fn, t;
3894 stmt = *stmt_p;
3896 clauses = OMP_PARALLEL_CLAUSES (stmt);
3897 par_bind = OMP_PARALLEL_BODY (stmt);
3898 par_body = BIND_EXPR_BODY (par_bind);
3899 child_fn = ctx->cb.dst_fn;
3901 push_gimplify_context ();
3903 par_olist = NULL_TREE;
3904 par_ilist = NULL_TREE;
3905 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
3906 lower_omp (&par_body, ctx);
3907 maybe_catch_exception (&par_body);
3908 lower_reduction_clauses (clauses, &par_olist, ctx);
3910 /* Declare all the variables created by mapping and the variables
3911 declared in the scope of the parallel body. */
3912 record_vars_into (ctx->block_vars, child_fn);
3913 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
3915 if (ctx->record_type)
3917 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
3918 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
3921 olist = NULL_TREE;
3922 ilist = NULL_TREE;
3923 lower_send_clauses (clauses, &ilist, &olist, ctx);
3924 lower_send_shared_vars (&ilist, &olist, ctx);
3926 /* Once all the expansions are done, sequence all the different
3927 fragments inside OMP_PARALLEL_BODY. */
3928 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3929 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
3931 new_body = alloc_stmt_list ();
3933 if (ctx->record_type)
3935 t = build_fold_addr_expr (ctx->sender_decl);
3936 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
3937 append_to_statement_list (t, &new_body);
3940 append_to_statement_list (par_ilist, &new_body);
3941 append_to_statement_list (par_body, &new_body);
3942 append_to_statement_list (par_olist, &new_body);
3943 t = make_node (OMP_RETURN);
3944 append_to_statement_list (t, &new_body);
3945 OMP_PARALLEL_BODY (stmt) = new_body;
3947 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3948 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
3950 *stmt_p = bind;
3952 pop_gimplify_context (NULL_TREE);
3956 /* Pass *TP back through the gimplifier within the context determined by WI.
3957 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
3958 flags on ADDR_EXPR. */
3960 static void
3961 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
3963 enum gimplify_status gs;
3964 tree pre = NULL;
3966 if (wi->is_lhs)
3967 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
3968 else if (wi->val_only)
3969 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
3970 else
3971 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
3972 gcc_assert (gs == GS_ALL_DONE);
3974 if (pre)
3975 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
3979 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
3981 static tree
3982 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
3984 struct walk_stmt_info *wi = data;
3985 omp_context *ctx = wi->info;
3986 tree t = *tp;
3988 /* If we have issued syntax errors, avoid doing any heavy lifting.
3989 Just replace the OpenMP directives with a NOP to avoid
3990 confusing RTL expansion. */
3991 if (errorcount && OMP_DIRECTIVE_P (*tp))
3993 *tp = build_empty_stmt ();
3994 return NULL_TREE;
3997 *walk_subtrees = 0;
3998 switch (TREE_CODE (*tp))
4000 case OMP_PARALLEL:
4001 ctx = maybe_lookup_ctx (t);
4002 lower_omp_parallel (tp, ctx);
4003 break;
4005 case OMP_FOR:
4006 ctx = maybe_lookup_ctx (t);
4007 gcc_assert (ctx);
4008 lower_omp_for (tp, ctx);
4009 break;
4011 case OMP_SECTIONS:
4012 ctx = maybe_lookup_ctx (t);
4013 gcc_assert (ctx);
4014 lower_omp_sections (tp, ctx);
4015 break;
4017 case OMP_SINGLE:
4018 ctx = maybe_lookup_ctx (t);
4019 gcc_assert (ctx);
4020 lower_omp_single (tp, ctx);
4021 break;
4023 case OMP_MASTER:
4024 ctx = maybe_lookup_ctx (t);
4025 gcc_assert (ctx);
4026 lower_omp_master (tp, ctx);
4027 break;
4029 case OMP_ORDERED:
4030 ctx = maybe_lookup_ctx (t);
4031 gcc_assert (ctx);
4032 lower_omp_ordered (tp, ctx);
4033 break;
4035 case OMP_CRITICAL:
4036 ctx = maybe_lookup_ctx (t);
4037 gcc_assert (ctx);
4038 lower_omp_critical (tp, ctx);
4039 break;
4041 case VAR_DECL:
4042 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4043 lower_regimplify (tp, wi);
4044 break;
4046 case ADDR_EXPR:
4047 if (ctx)
4048 lower_regimplify (tp, wi);
4049 break;
4051 case ARRAY_REF:
4052 case ARRAY_RANGE_REF:
4053 case REALPART_EXPR:
4054 case IMAGPART_EXPR:
4055 case COMPONENT_REF:
4056 case VIEW_CONVERT_EXPR:
4057 if (ctx)
4058 lower_regimplify (tp, wi);
4059 break;
4061 case INDIRECT_REF:
4062 if (ctx)
4064 wi->is_lhs = false;
4065 wi->val_only = true;
4066 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4068 break;
4070 default:
4071 if (!TYPE_P (t) && !DECL_P (t))
4072 *walk_subtrees = 1;
4073 break;
4076 return NULL_TREE;
4079 static void
4080 lower_omp (tree *stmt_p, omp_context *ctx)
4082 struct walk_stmt_info wi;
4084 memset (&wi, 0, sizeof (wi));
4085 wi.callback = lower_omp_1;
4086 wi.info = ctx;
4087 wi.val_only = true;
4088 wi.want_locations = true;
4090 walk_stmts (&wi, stmt_p);
4093 /* Main entry point. */
4095 static unsigned int
4096 execute_lower_omp (void)
4098 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4099 delete_omp_context);
4101 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4102 gcc_assert (parallel_nesting_level == 0);
4104 if (all_contexts->root)
4105 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4107 if (all_contexts)
4109 splay_tree_delete (all_contexts);
4110 all_contexts = NULL;
4112 return 0;
4115 static bool
4116 gate_lower_omp (void)
4118 return flag_openmp != 0;
4121 struct tree_opt_pass pass_lower_omp =
4123 "omplower", /* name */
4124 gate_lower_omp, /* gate */
4125 execute_lower_omp, /* execute */
4126 NULL, /* sub */
4127 NULL, /* next */
4128 0, /* static_pass_number */
4129 0, /* tv_id */
4130 PROP_gimple_any, /* properties_required */
4131 PROP_gimple_lomp, /* properties_provided */
4132 0, /* properties_destroyed */
4133 0, /* todo_flags_start */
4134 TODO_dump_func, /* todo_flags_finish */
4135 0 /* letter */
4138 /* The following is a utility to diagnose OpenMP structured block violations.
4139 It is not part of the "omplower" pass, as that's invoked too late. It
4140 should be invoked by the respective front ends after gimplification. */
4142 static splay_tree all_labels;
4144 /* Check for mismatched contexts and generate an error if needed. Return
4145 true if an error is detected. */
4147 static bool
4148 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4150 bool exit_p = true;
4152 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4153 return false;
4155 /* Try to avoid confusing the user by producing and error message
4156 with correct "exit" or "enter" verbage. We prefer "exit"
4157 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4158 if (branch_ctx == NULL)
4159 exit_p = false;
4160 else
4162 while (label_ctx)
4164 if (TREE_VALUE (label_ctx) == branch_ctx)
4166 exit_p = false;
4167 break;
4169 label_ctx = TREE_CHAIN (label_ctx);
4173 if (exit_p)
4174 error ("invalid exit from OpenMP structured block");
4175 else
4176 error ("invalid entry to OpenMP structured block");
4178 *stmt_p = build_empty_stmt ();
4179 return true;
4182 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4183 where in the tree each label is found. */
4185 static tree
4186 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4188 struct walk_stmt_info *wi = data;
4189 tree context = (tree) wi->info;
4190 tree inner_context;
4191 tree t = *tp;
4193 *walk_subtrees = 0;
4194 switch (TREE_CODE (t))
4196 case OMP_PARALLEL:
4197 case OMP_SECTIONS:
4198 case OMP_SINGLE:
4199 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4200 /* FALLTHRU */
4201 case OMP_SECTION:
4202 case OMP_MASTER:
4203 case OMP_ORDERED:
4204 case OMP_CRITICAL:
4205 /* The minimal context here is just a tree of statements. */
4206 inner_context = tree_cons (NULL, t, context);
4207 wi->info = inner_context;
4208 walk_stmts (wi, &OMP_BODY (t));
4209 wi->info = context;
4210 break;
4212 case OMP_FOR:
4213 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4214 inner_context = tree_cons (NULL, t, context);
4215 wi->info = inner_context;
4216 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4217 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4218 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4219 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4220 walk_stmts (wi, &OMP_FOR_BODY (t));
4221 wi->info = context;
4222 break;
4224 case LABEL_EXPR:
4225 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4226 (splay_tree_value) context);
4227 break;
4229 default:
4230 break;
4233 return NULL_TREE;
4236 /* Pass 2: Check each branch and see if its context differs from that of
4237 the destination label's context. */
4239 static tree
4240 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4242 struct walk_stmt_info *wi = data;
4243 tree context = (tree) wi->info;
4244 splay_tree_node n;
4245 tree t = *tp;
4247 *walk_subtrees = 0;
4248 switch (TREE_CODE (t))
4250 case OMP_PARALLEL:
4251 case OMP_SECTIONS:
4252 case OMP_SINGLE:
4253 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4254 /* FALLTHRU */
4255 case OMP_SECTION:
4256 case OMP_MASTER:
4257 case OMP_ORDERED:
4258 case OMP_CRITICAL:
4259 wi->info = t;
4260 walk_stmts (wi, &OMP_BODY (t));
4261 wi->info = context;
4262 break;
4264 case OMP_FOR:
4265 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4266 wi->info = t;
4267 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4268 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4269 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4270 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4271 walk_stmts (wi, &OMP_FOR_BODY (t));
4272 wi->info = context;
4273 break;
4275 case GOTO_EXPR:
4277 tree lab = GOTO_DESTINATION (t);
4278 if (TREE_CODE (lab) != LABEL_DECL)
4279 break;
4281 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4282 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4284 break;
4286 case SWITCH_EXPR:
4288 tree vec = SWITCH_LABELS (t);
4289 int i, len = TREE_VEC_LENGTH (vec);
4290 for (i = 0; i < len; ++i)
4292 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4293 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4294 if (diagnose_sb_0 (tp, context, (tree) n->value))
4295 break;
4298 break;
4300 case RETURN_EXPR:
4301 diagnose_sb_0 (tp, context, NULL_TREE);
4302 break;
4304 default:
4305 break;
4308 return NULL_TREE;
4311 void
4312 diagnose_omp_structured_block_errors (tree fndecl)
4314 tree save_current = current_function_decl;
4315 struct walk_stmt_info wi;
4317 current_function_decl = fndecl;
4319 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4321 memset (&wi, 0, sizeof (wi));
4322 wi.callback = diagnose_sb_1;
4323 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4325 memset (&wi, 0, sizeof (wi));
4326 wi.callback = diagnose_sb_2;
4327 wi.want_locations = true;
4328 wi.want_return_expr = true;
4329 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4331 splay_tree_delete (all_labels);
4332 all_labels = NULL;
4334 current_function_decl = save_current;
4337 #include "gt-omp-low.h"