EnumSet*.class: Regenerate
[official-gcc.git] / gcc / omp-low.c
blob5aaa7fe86823f2acb6dfe24bd1bf5cfdbbe91586
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "tree-gimple.h"
31 #include "tree-inline.h"
32 #include "langhooks.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
35 #include "timevar.h"
36 #include "flags.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "toplev.h"
40 #include "tree-pass.h"
41 #include "ggc.h"
42 #include "except.h"
43 #include "splay-tree.h"
46 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
47 phases. The first phase scans the function looking for OMP statements
48 and then for variables that must be replaced to satisfy data sharing
49 clauses. The second phase expands code for the constructs, as well as
50 re-gimplifying things when variables have been replaced with complex
51 expressions.
53 Final code generation is done by pass_expand_omp. The flowgraph is
54 scanned for parallel regions which are then moved to a new
55 function, to be invoked by the thread library. */
57 /* Context structure. Used to store information about each parallel
58 directive in the code. */
60 typedef struct omp_context
62 /* This field must be at the beginning, as we do "inheritance": Some
63 callback functions for tree-inline.c (e.g., omp_copy_decl)
64 receive a copy_body_data pointer that is up-casted to an
65 omp_context pointer. */
66 copy_body_data cb;
68 /* The tree of contexts corresponding to the encountered constructs. */
69 struct omp_context *outer;
70 tree stmt;
72 /* Map variables to fields in a structure that allows communication
73 between sending and receiving threads. */
74 splay_tree field_map;
75 tree record_type;
76 tree sender_decl;
77 tree receiver_decl;
79 /* A chain of variables to add to the top-level block surrounding the
80 construct. In the case of a parallel, this is in the child function. */
81 tree block_vars;
83 /* What to do with variables with implicitly determined sharing
84 attributes. */
85 enum omp_clause_default_kind default_kind;
87 /* Nesting depth of this context. Used to beautify error messages re
88 invalid gotos. The outermost ctx is depth 1, with depth 0 being
89 reserved for the main body of the function. */
90 int depth;
92 /* True if this parallel directive is nested within another. */
93 bool is_nested;
94 } omp_context;
97 /* A structure describing the main elements of a parallel loop. */
99 struct omp_for_data
101 tree v, n1, n2, step, chunk_size, for_stmt;
102 enum tree_code cond_code;
103 tree pre;
104 bool have_nowait, have_ordered;
105 enum omp_clause_schedule_kind sched_kind;
109 static splay_tree all_contexts;
110 static int parallel_nesting_level;
111 struct omp_region *root_omp_region;
113 static void scan_omp (tree *, omp_context *);
114 static void lower_omp (tree *, omp_context *);
115 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
116 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
118 /* Find an OpenMP clause of type KIND within CLAUSES. */
120 static tree
121 find_omp_clause (tree clauses, enum tree_code kind)
123 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
124 if (OMP_CLAUSE_CODE (clauses) == kind)
125 return clauses;
127 return NULL_TREE;
130 /* Return true if CTX is for an omp parallel. */
132 static inline bool
133 is_parallel_ctx (omp_context *ctx)
135 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
139 /* Return true if REGION is a combined parallel+workshare region. */
141 static inline bool
142 is_combined_parallel (struct omp_region *region)
144 return region->is_combined_parallel;
148 /* Extract the header elements of parallel loop FOR_STMT and store
149 them into *FD. */
151 static void
152 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
154 tree t;
156 fd->for_stmt = for_stmt;
157 fd->pre = NULL;
159 t = OMP_FOR_INIT (for_stmt);
160 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
161 fd->v = GIMPLE_STMT_OPERAND (t, 0);
162 gcc_assert (DECL_P (fd->v));
163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
164 fd->n1 = GIMPLE_STMT_OPERAND (t, 1);
166 t = OMP_FOR_COND (for_stmt);
167 fd->cond_code = TREE_CODE (t);
168 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
169 fd->n2 = TREE_OPERAND (t, 1);
170 switch (fd->cond_code)
172 case LT_EXPR:
173 case GT_EXPR:
174 break;
175 case LE_EXPR:
176 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
177 build_int_cst (TREE_TYPE (fd->n2), 1));
178 fd->cond_code = LT_EXPR;
179 break;
180 case GE_EXPR:
181 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
182 build_int_cst (TREE_TYPE (fd->n2), 1));
183 fd->cond_code = GT_EXPR;
184 break;
185 default:
186 gcc_unreachable ();
189 t = OMP_FOR_INCR (fd->for_stmt);
190 gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
191 gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == fd->v);
192 t = GIMPLE_STMT_OPERAND (t, 1);
193 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
194 switch (TREE_CODE (t))
196 case PLUS_EXPR:
197 fd->step = TREE_OPERAND (t, 1);
198 break;
199 case MINUS_EXPR:
200 fd->step = TREE_OPERAND (t, 1);
201 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
202 break;
203 default:
204 gcc_unreachable ();
207 fd->have_nowait = fd->have_ordered = false;
208 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
209 fd->chunk_size = NULL_TREE;
211 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
212 switch (OMP_CLAUSE_CODE (t))
214 case OMP_CLAUSE_NOWAIT:
215 fd->have_nowait = true;
216 break;
217 case OMP_CLAUSE_ORDERED:
218 fd->have_ordered = true;
219 break;
220 case OMP_CLAUSE_SCHEDULE:
221 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
222 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
223 break;
224 default:
225 break;
228 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
229 gcc_assert (fd->chunk_size == NULL);
230 else if (fd->chunk_size == NULL)
232 /* We only need to compute a default chunk size for ordered
233 static loops and dynamic loops. */
234 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
235 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
236 ? integer_zero_node : integer_one_node;
241 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
242 is the immediate dominator of PAR_ENTRY_BB, return true if there
243 are no data dependencies that would prevent expanding the parallel
244 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
246 When expanding a combined parallel+workshare region, the call to
247 the child function may need additional arguments in the case of
248 OMP_FOR regions. In some cases, these arguments are computed out
249 of variables passed in from the parent to the child via 'struct
250 .omp_data_s'. For instance:
252 #pragma omp parallel for schedule (guided, i * 4)
253 for (j ...)
255 Is lowered into:
257 # BLOCK 2 (PAR_ENTRY_BB)
258 .omp_data_o.i = i;
259 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
261 # BLOCK 3 (WS_ENTRY_BB)
262 .omp_data_i = &.omp_data_o;
263 D.1667 = .omp_data_i->i;
264 D.1598 = D.1667 * 4;
265 #pragma omp for schedule (guided, D.1598)
267 When we outline the parallel region, the call to the child function
268 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
269 that value is computed *after* the call site. So, in principle we
270 cannot do the transformation.
272 To see whether the code in WS_ENTRY_BB blocks the combined
273 parallel+workshare call, we collect all the variables used in the
274 OMP_FOR header check whether they appear on the LHS of any
275 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
276 call.
278 FIXME. If we had the SSA form built at this point, we could merely
279 hoist the code in block 3 into block 2 and be done with it. But at
280 this point we don't have dataflow information and though we could
281 hack something up here, it is really not worth the aggravation. */
283 static bool
284 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
286 struct omp_for_data fd;
287 tree par_stmt, ws_stmt;
289 par_stmt = last_stmt (par_entry_bb);
290 ws_stmt = last_stmt (ws_entry_bb);
292 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
293 return true;
295 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
297 extract_omp_for_data (ws_stmt, &fd);
299 /* FIXME. We give up too easily here. If any of these arguments
300 are not constants, they will likely involve variables that have
301 been mapped into fields of .omp_data_s for sharing with the child
302 function. With appropriate data flow, it would be possible to
303 see through this. */
304 if (!is_gimple_min_invariant (fd.n1)
305 || !is_gimple_min_invariant (fd.n2)
306 || !is_gimple_min_invariant (fd.step)
307 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
308 return false;
310 return true;
314 /* Collect additional arguments needed to emit a combined
315 parallel+workshare call. WS_STMT is the workshare directive being
316 expanded. */
318 static tree
319 get_ws_args_for (tree ws_stmt)
321 tree t;
323 if (TREE_CODE (ws_stmt) == OMP_FOR)
325 struct omp_for_data fd;
326 tree ws_args;
328 extract_omp_for_data (ws_stmt, &fd);
330 ws_args = NULL_TREE;
331 if (fd.chunk_size)
333 t = fold_convert (long_integer_type_node, fd.chunk_size);
334 ws_args = tree_cons (NULL, t, ws_args);
337 t = fold_convert (long_integer_type_node, fd.step);
338 ws_args = tree_cons (NULL, t, ws_args);
340 t = fold_convert (long_integer_type_node, fd.n2);
341 ws_args = tree_cons (NULL, t, ws_args);
343 t = fold_convert (long_integer_type_node, fd.n1);
344 ws_args = tree_cons (NULL, t, ws_args);
346 return ws_args;
348 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
350 /* Number of sections is equal to the number of edges from the
351 OMP_SECTIONS_SWITCH statement, except for the one to the exit
352 of the sections region. */
353 basic_block bb = single_succ (bb_for_stmt (ws_stmt));
354 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
355 t = tree_cons (NULL, t, NULL);
356 return t;
359 gcc_unreachable ();
363 /* Discover whether REGION is a combined parallel+workshare region. */
365 static void
366 determine_parallel_type (struct omp_region *region)
368 basic_block par_entry_bb, par_exit_bb;
369 basic_block ws_entry_bb, ws_exit_bb;
371 if (region == NULL || region->inner == NULL
372 || region->exit == NULL || region->inner->exit == NULL
373 || region->inner->cont == NULL)
374 return;
376 /* We only support parallel+for and parallel+sections. */
377 if (region->type != OMP_PARALLEL
378 || (region->inner->type != OMP_FOR
379 && region->inner->type != OMP_SECTIONS))
380 return;
382 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
383 WS_EXIT_BB -> PAR_EXIT_BB. */
384 par_entry_bb = region->entry;
385 par_exit_bb = region->exit;
386 ws_entry_bb = region->inner->entry;
387 ws_exit_bb = region->inner->exit;
389 if (single_succ (par_entry_bb) == ws_entry_bb
390 && single_succ (ws_exit_bb) == par_exit_bb
391 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
392 && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
393 || (last_and_only_stmt (ws_entry_bb)
394 && last_and_only_stmt (par_exit_bb))))
396 tree ws_stmt = last_stmt (ws_entry_bb);
398 if (region->inner->type == OMP_FOR)
400 /* If this is a combined parallel loop, we need to determine
401 whether or not to use the combined library calls. There
402 are two cases where we do not apply the transformation:
403 static loops and any kind of ordered loop. In the first
404 case, we already open code the loop so there is no need
405 to do anything else. In the latter case, the combined
406 parallel loop call would still need extra synchronization
407 to implement ordered semantics, so there would not be any
408 gain in using the combined call. */
409 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
410 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
411 if (c == NULL
412 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
413 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
415 region->is_combined_parallel = false;
416 region->inner->is_combined_parallel = false;
417 return;
421 region->is_combined_parallel = true;
422 region->inner->is_combined_parallel = true;
423 region->ws_args = get_ws_args_for (ws_stmt);
428 /* Return true if EXPR is variable sized. */
430 static inline bool
431 is_variable_sized (const_tree expr)
433 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
436 /* Return true if DECL is a reference type. */
438 static inline bool
439 is_reference (tree decl)
441 return lang_hooks.decls.omp_privatize_by_reference (decl);
444 /* Lookup variables in the decl or field splay trees. The "maybe" form
445 allows for the variable form to not have been entered, otherwise we
446 assert that the variable must have been entered. */
448 static inline tree
449 lookup_decl (tree var, omp_context *ctx)
451 tree *n;
452 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
453 return *n;
456 static inline tree
457 maybe_lookup_decl (tree var, omp_context *ctx)
459 tree *n;
460 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
461 return n ? *n : NULL_TREE;
464 static inline tree
465 lookup_field (tree var, omp_context *ctx)
467 splay_tree_node n;
468 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
469 return (tree) n->value;
472 static inline tree
473 maybe_lookup_field (tree var, omp_context *ctx)
475 splay_tree_node n;
476 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
477 return n ? (tree) n->value : NULL_TREE;
480 /* Return true if DECL should be copied by pointer. SHARED_P is true
481 if DECL is to be shared. */
483 static bool
484 use_pointer_for_field (const_tree decl, bool shared_p)
486 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
487 return true;
489 /* We can only use copy-in/copy-out semantics for shared variables
490 when we know the value is not accessible from an outer scope. */
491 if (shared_p)
493 /* ??? Trivially accessible from anywhere. But why would we even
494 be passing an address in this case? Should we simply assert
495 this to be false, or should we have a cleanup pass that removes
496 these from the list of mappings? */
497 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
498 return true;
500 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
501 without analyzing the expression whether or not its location
502 is accessible to anyone else. In the case of nested parallel
503 regions it certainly may be. */
504 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
505 return true;
507 /* Do not use copy-in/copy-out for variables that have their
508 address taken. */
509 if (TREE_ADDRESSABLE (decl))
510 return true;
513 return false;
516 /* Construct a new automatic decl similar to VAR. */
518 static tree
519 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
521 tree copy = build_decl (VAR_DECL, name, type);
523 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
524 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
525 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
526 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
527 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
528 TREE_USED (copy) = 1;
529 DECL_CONTEXT (copy) = current_function_decl;
530 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
532 TREE_CHAIN (copy) = ctx->block_vars;
533 ctx->block_vars = copy;
535 return copy;
538 static tree
539 omp_copy_decl_1 (tree var, omp_context *ctx)
541 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
544 /* Build tree nodes to access the field for VAR on the receiver side. */
546 static tree
547 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
549 tree x, field = lookup_field (var, ctx);
551 /* If the receiver record type was remapped in the child function,
552 remap the field into the new record type. */
553 x = maybe_lookup_field (field, ctx);
554 if (x != NULL)
555 field = x;
557 x = build_fold_indirect_ref (ctx->receiver_decl);
558 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
559 if (by_ref)
560 x = build_fold_indirect_ref (x);
562 return x;
565 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
566 of a parallel, this is a component reference; for workshare constructs
567 this is some variable. */
569 static tree
570 build_outer_var_ref (tree var, omp_context *ctx)
572 tree x;
574 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
575 x = var;
576 else if (is_variable_sized (var))
578 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
579 x = build_outer_var_ref (x, ctx);
580 x = build_fold_indirect_ref (x);
582 else if (is_parallel_ctx (ctx))
584 bool by_ref = use_pointer_for_field (var, false);
585 x = build_receiver_ref (var, by_ref, ctx);
587 else if (ctx->outer)
588 x = lookup_decl (var, ctx->outer);
589 else if (is_reference (var))
590 /* This can happen with orphaned constructs. If var is reference, it is
591 possible it is shared and as such valid. */
592 x = var;
593 else
594 gcc_unreachable ();
596 if (is_reference (var))
597 x = build_fold_indirect_ref (x);
599 return x;
602 /* Build tree nodes to access the field for VAR on the sender side. */
604 static tree
605 build_sender_ref (tree var, omp_context *ctx)
607 tree field = lookup_field (var, ctx);
608 return build3 (COMPONENT_REF, TREE_TYPE (field),
609 ctx->sender_decl, field, NULL);
612 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
614 static void
615 install_var_field (tree var, bool by_ref, omp_context *ctx)
617 tree field, type;
619 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
621 type = TREE_TYPE (var);
622 if (by_ref)
623 type = build_pointer_type (type);
625 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
627 /* Remember what variable this field was created for. This does have a
628 side effect of making dwarf2out ignore this member, so for helpful
629 debugging we clear it later in delete_omp_context. */
630 DECL_ABSTRACT_ORIGIN (field) = var;
632 insert_field_into_struct (ctx->record_type, field);
634 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
635 (splay_tree_value) field);
638 static tree
639 install_var_local (tree var, omp_context *ctx)
641 tree new_var = omp_copy_decl_1 (var, ctx);
642 insert_decl_map (&ctx->cb, var, new_var);
643 return new_var;
646 /* Adjust the replacement for DECL in CTX for the new context. This means
647 copying the DECL_VALUE_EXPR, and fixing up the type. */
649 static void
650 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
652 tree new_decl, size;
654 new_decl = lookup_decl (decl, ctx);
656 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
658 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
659 && DECL_HAS_VALUE_EXPR_P (decl))
661 tree ve = DECL_VALUE_EXPR (decl);
662 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
663 SET_DECL_VALUE_EXPR (new_decl, ve);
664 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
667 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
669 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
670 if (size == error_mark_node)
671 size = TYPE_SIZE (TREE_TYPE (new_decl));
672 DECL_SIZE (new_decl) = size;
674 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
675 if (size == error_mark_node)
676 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
677 DECL_SIZE_UNIT (new_decl) = size;
681 /* The callback for remap_decl. Search all containing contexts for a
682 mapping of the variable; this avoids having to duplicate the splay
683 tree ahead of time. We know a mapping doesn't already exist in the
684 given context. Create new mappings to implement default semantics. */
686 static tree
687 omp_copy_decl (tree var, copy_body_data *cb)
689 omp_context *ctx = (omp_context *) cb;
690 tree new_var;
692 if (TREE_CODE (var) == LABEL_DECL)
694 new_var = create_artificial_label ();
695 DECL_CONTEXT (new_var) = current_function_decl;
696 insert_decl_map (&ctx->cb, var, new_var);
697 return new_var;
700 while (!is_parallel_ctx (ctx))
702 ctx = ctx->outer;
703 if (ctx == NULL)
704 return var;
705 new_var = maybe_lookup_decl (var, ctx);
706 if (new_var)
707 return new_var;
710 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
711 return var;
713 return error_mark_node;
717 /* Return the parallel region associated with STMT. */
719 /* Debugging dumps for parallel regions. */
720 void dump_omp_region (FILE *, struct omp_region *, int);
721 void debug_omp_region (struct omp_region *);
722 void debug_all_omp_regions (void);
724 /* Dump the parallel region tree rooted at REGION. */
726 void
727 dump_omp_region (FILE *file, struct omp_region *region, int indent)
729 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
730 tree_code_name[region->type]);
732 if (region->inner)
733 dump_omp_region (file, region->inner, indent + 4);
735 if (region->cont)
737 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
738 region->cont->index);
741 if (region->exit)
742 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
743 region->exit->index);
744 else
745 fprintf (file, "%*s[no exit marker]\n", indent, "");
747 if (region->next)
748 dump_omp_region (file, region->next, indent);
751 void
752 debug_omp_region (struct omp_region *region)
754 dump_omp_region (stderr, region, 0);
757 void
758 debug_all_omp_regions (void)
760 dump_omp_region (stderr, root_omp_region, 0);
764 /* Create a new parallel region starting at STMT inside region PARENT. */
766 struct omp_region *
767 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
769 struct omp_region *region = xcalloc (1, sizeof (*region));
771 region->outer = parent;
772 region->entry = bb;
773 region->type = type;
775 if (parent)
777 /* This is a nested region. Add it to the list of inner
778 regions in PARENT. */
779 region->next = parent->inner;
780 parent->inner = region;
782 else
784 /* This is a toplevel region. Add it to the list of toplevel
785 regions in ROOT_OMP_REGION. */
786 region->next = root_omp_region;
787 root_omp_region = region;
790 return region;
793 /* Release the memory associated with the region tree rooted at REGION. */
795 static void
796 free_omp_region_1 (struct omp_region *region)
798 struct omp_region *i, *n;
800 for (i = region->inner; i ; i = n)
802 n = i->next;
803 free_omp_region_1 (i);
806 free (region);
809 /* Release the memory for the entire omp region tree. */
811 void
812 free_omp_regions (void)
814 struct omp_region *r, *n;
815 for (r = root_omp_region; r ; r = n)
817 n = r->next;
818 free_omp_region_1 (r);
820 root_omp_region = NULL;
824 /* Create a new context, with OUTER_CTX being the surrounding context. */
826 static omp_context *
827 new_omp_context (tree stmt, omp_context *outer_ctx)
829 omp_context *ctx = XCNEW (omp_context);
831 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
832 (splay_tree_value) ctx);
833 ctx->stmt = stmt;
835 if (outer_ctx)
837 ctx->outer = outer_ctx;
838 ctx->cb = outer_ctx->cb;
839 ctx->cb.block = NULL;
840 ctx->depth = outer_ctx->depth + 1;
842 else
844 ctx->cb.src_fn = current_function_decl;
845 ctx->cb.dst_fn = current_function_decl;
846 ctx->cb.src_node = cgraph_node (current_function_decl);
847 ctx->cb.dst_node = ctx->cb.src_node;
848 ctx->cb.src_cfun = cfun;
849 ctx->cb.copy_decl = omp_copy_decl;
850 ctx->cb.eh_region = -1;
851 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
852 ctx->depth = 1;
855 ctx->cb.decl_map = pointer_map_create ();
857 return ctx;
860 /* Destroy a omp_context data structures. Called through the splay tree
861 value delete callback. */
863 static void
864 delete_omp_context (splay_tree_value value)
866 omp_context *ctx = (omp_context *) value;
868 pointer_map_destroy (ctx->cb.decl_map);
870 if (ctx->field_map)
871 splay_tree_delete (ctx->field_map);
873 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
874 it produces corrupt debug information. */
875 if (ctx->record_type)
877 tree t;
878 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
879 DECL_ABSTRACT_ORIGIN (t) = NULL;
882 XDELETE (ctx);
885 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
886 context. */
888 static void
889 fixup_child_record_type (omp_context *ctx)
891 tree f, type = ctx->record_type;
893 /* ??? It isn't sufficient to just call remap_type here, because
894 variably_modified_type_p doesn't work the way we expect for
895 record types. Testing each field for whether it needs remapping
896 and creating a new record by hand works, however. */
897 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
898 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
899 break;
900 if (f)
902 tree name, new_fields = NULL;
904 type = lang_hooks.types.make_type (RECORD_TYPE);
905 name = DECL_NAME (TYPE_NAME (ctx->record_type));
906 name = build_decl (TYPE_DECL, name, type);
907 TYPE_NAME (type) = name;
909 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
911 tree new_f = copy_node (f);
912 DECL_CONTEXT (new_f) = type;
913 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
914 TREE_CHAIN (new_f) = new_fields;
915 new_fields = new_f;
917 /* Arrange to be able to look up the receiver field
918 given the sender field. */
919 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
920 (splay_tree_value) new_f);
922 TYPE_FIELDS (type) = nreverse (new_fields);
923 layout_type (type);
926 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
929 /* Instantiate decls as necessary in CTX to satisfy the data sharing
930 specified by CLAUSES. */
932 static void
933 scan_sharing_clauses (tree clauses, omp_context *ctx)
935 tree c, decl;
936 bool scan_array_reductions = false;
938 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
940 bool by_ref;
942 switch (OMP_CLAUSE_CODE (c))
944 case OMP_CLAUSE_PRIVATE:
945 decl = OMP_CLAUSE_DECL (c);
946 if (!is_variable_sized (decl))
947 install_var_local (decl, ctx);
948 break;
950 case OMP_CLAUSE_SHARED:
951 gcc_assert (is_parallel_ctx (ctx));
952 decl = OMP_CLAUSE_DECL (c);
953 gcc_assert (!is_variable_sized (decl));
954 by_ref = use_pointer_for_field (decl, true);
955 /* Global variables don't need to be copied,
956 the receiver side will use them directly. */
957 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
958 break;
959 if (! TREE_READONLY (decl)
960 || TREE_ADDRESSABLE (decl)
961 || by_ref
962 || is_reference (decl))
964 install_var_field (decl, by_ref, ctx);
965 install_var_local (decl, ctx);
966 break;
968 /* We don't need to copy const scalar vars back. */
969 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
970 goto do_private;
972 case OMP_CLAUSE_LASTPRIVATE:
973 /* Let the corresponding firstprivate clause create
974 the variable. */
975 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
976 break;
977 /* FALLTHRU */
979 case OMP_CLAUSE_FIRSTPRIVATE:
980 case OMP_CLAUSE_REDUCTION:
981 decl = OMP_CLAUSE_DECL (c);
982 do_private:
983 if (is_variable_sized (decl))
984 break;
985 else if (is_parallel_ctx (ctx)
986 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
987 ctx)))
989 by_ref = use_pointer_for_field (decl, false);
990 install_var_field (decl, by_ref, ctx);
992 install_var_local (decl, ctx);
993 break;
995 case OMP_CLAUSE_COPYPRIVATE:
996 if (ctx->outer)
997 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
998 /* FALLTHRU */
1000 case OMP_CLAUSE_COPYIN:
1001 decl = OMP_CLAUSE_DECL (c);
1002 by_ref = use_pointer_for_field (decl, false);
1003 install_var_field (decl, by_ref, ctx);
1004 break;
1006 case OMP_CLAUSE_DEFAULT:
1007 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1008 break;
1010 case OMP_CLAUSE_IF:
1011 case OMP_CLAUSE_NUM_THREADS:
1012 case OMP_CLAUSE_SCHEDULE:
1013 if (ctx->outer)
1014 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1015 break;
1017 case OMP_CLAUSE_NOWAIT:
1018 case OMP_CLAUSE_ORDERED:
1019 break;
1021 default:
1022 gcc_unreachable ();
1026 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1028 switch (OMP_CLAUSE_CODE (c))
1030 case OMP_CLAUSE_LASTPRIVATE:
1031 /* Let the corresponding firstprivate clause create
1032 the variable. */
1033 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1034 break;
1035 /* FALLTHRU */
1037 case OMP_CLAUSE_PRIVATE:
1038 case OMP_CLAUSE_FIRSTPRIVATE:
1039 case OMP_CLAUSE_REDUCTION:
1040 decl = OMP_CLAUSE_DECL (c);
1041 if (is_variable_sized (decl))
1042 install_var_local (decl, ctx);
1043 fixup_remapped_decl (decl, ctx,
1044 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1045 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1046 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1047 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1048 scan_array_reductions = true;
1049 break;
1051 case OMP_CLAUSE_SHARED:
1052 decl = OMP_CLAUSE_DECL (c);
1053 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1054 fixup_remapped_decl (decl, ctx, false);
1055 break;
1057 case OMP_CLAUSE_COPYPRIVATE:
1058 case OMP_CLAUSE_COPYIN:
1059 case OMP_CLAUSE_DEFAULT:
1060 case OMP_CLAUSE_IF:
1061 case OMP_CLAUSE_NUM_THREADS:
1062 case OMP_CLAUSE_SCHEDULE:
1063 case OMP_CLAUSE_NOWAIT:
1064 case OMP_CLAUSE_ORDERED:
1065 break;
1067 default:
1068 gcc_unreachable ();
1072 if (scan_array_reductions)
1073 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1074 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1075 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1077 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1078 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1082 /* Create a new name for omp child function. Returns an identifier. */
1084 static GTY(()) unsigned int tmp_ompfn_id_num;
1086 static tree
1087 create_omp_child_function_name (void)
1089 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1090 size_t len = IDENTIFIER_LENGTH (name);
1091 char *tmp_name, *prefix;
1093 prefix = alloca (len + sizeof ("_omp_fn"));
1094 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1095 strcpy (prefix + len, "_omp_fn");
1096 #ifndef NO_DOT_IN_LABEL
1097 prefix[len] = '.';
1098 #elif !defined NO_DOLLAR_IN_LABEL
1099 prefix[len] = '$';
1100 #endif
1101 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1102 return get_identifier (tmp_name);
1105 /* Build a decl for the omp child function. It'll not contain a body
1106 yet, just the bare decl. */
1108 static void
1109 create_omp_child_function (omp_context *ctx)
1111 tree decl, type, name, t;
1113 name = create_omp_child_function_name ();
1114 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1116 decl = build_decl (FUNCTION_DECL, name, type);
1117 decl = lang_hooks.decls.pushdecl (decl);
1119 ctx->cb.dst_fn = decl;
1121 TREE_STATIC (decl) = 1;
1122 TREE_USED (decl) = 1;
1123 DECL_ARTIFICIAL (decl) = 1;
1124 DECL_IGNORED_P (decl) = 0;
1125 TREE_PUBLIC (decl) = 0;
1126 DECL_UNINLINABLE (decl) = 1;
1127 DECL_EXTERNAL (decl) = 0;
1128 DECL_CONTEXT (decl) = NULL_TREE;
1129 DECL_INITIAL (decl) = make_node (BLOCK);
1131 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1132 DECL_ARTIFICIAL (t) = 1;
1133 DECL_IGNORED_P (t) = 1;
1134 DECL_RESULT (decl) = t;
1136 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1137 DECL_ARTIFICIAL (t) = 1;
1138 DECL_ARG_TYPE (t) = ptr_type_node;
1139 DECL_CONTEXT (t) = current_function_decl;
1140 TREE_USED (t) = 1;
1141 DECL_ARGUMENTS (decl) = t;
1142 ctx->receiver_decl = t;
1144 /* Allocate memory for the function structure. The call to
1145 allocate_struct_function clobbers CFUN, so we need to restore
1146 it afterward. */
1147 allocate_struct_function (decl);
1148 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1149 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1150 cfun = ctx->cb.src_cfun;
1154 /* Scan an OpenMP parallel directive. */
1156 static void
1157 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1159 omp_context *ctx;
1160 tree name;
1162 /* Ignore parallel directives with empty bodies, unless there
1163 are copyin clauses. */
1164 if (optimize > 0
1165 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1166 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1168 *stmt_p = build_empty_stmt ();
1169 return;
1172 ctx = new_omp_context (*stmt_p, outer_ctx);
1173 if (parallel_nesting_level > 1)
1174 ctx->is_nested = true;
1175 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1176 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1177 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1178 name = create_tmp_var_name (".omp_data_s");
1179 name = build_decl (TYPE_DECL, name, ctx->record_type);
1180 TYPE_NAME (ctx->record_type) = name;
1181 create_omp_child_function (ctx);
1182 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1184 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1185 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1187 if (TYPE_FIELDS (ctx->record_type) == NULL)
1188 ctx->record_type = ctx->receiver_decl = NULL;
1189 else
1191 layout_type (ctx->record_type);
1192 fixup_child_record_type (ctx);
1197 /* Scan an OpenMP loop directive. */
1199 static void
1200 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1202 omp_context *ctx;
1203 tree stmt;
1205 stmt = *stmt_p;
1206 ctx = new_omp_context (stmt, outer_ctx);
1208 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1210 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1211 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1212 scan_omp (&OMP_FOR_COND (stmt), ctx);
1213 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1214 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1217 /* Scan an OpenMP sections directive. */
1219 static void
1220 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1222 tree stmt;
1223 omp_context *ctx;
1225 stmt = *stmt_p;
1226 ctx = new_omp_context (stmt, outer_ctx);
1227 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1228 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1231 /* Scan an OpenMP single directive. */
1233 static void
1234 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1236 tree stmt = *stmt_p;
1237 omp_context *ctx;
1238 tree name;
1240 ctx = new_omp_context (stmt, outer_ctx);
1241 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1242 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1243 name = create_tmp_var_name (".omp_copy_s");
1244 name = build_decl (TYPE_DECL, name, ctx->record_type);
1245 TYPE_NAME (ctx->record_type) = name;
1247 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1248 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1250 if (TYPE_FIELDS (ctx->record_type) == NULL)
1251 ctx->record_type = NULL;
1252 else
1253 layout_type (ctx->record_type);
1257 /* Check OpenMP nesting restrictions. */
1258 static void
1259 check_omp_nesting_restrictions (tree t, omp_context *ctx)
1261 switch (TREE_CODE (t))
1263 case OMP_FOR:
1264 case OMP_SECTIONS:
1265 case OMP_SINGLE:
1266 for (; ctx != NULL; ctx = ctx->outer)
1267 switch (TREE_CODE (ctx->stmt))
1269 case OMP_FOR:
1270 case OMP_SECTIONS:
1271 case OMP_SINGLE:
1272 case OMP_ORDERED:
1273 case OMP_MASTER:
1274 warning (0, "work-sharing region may not be closely nested inside "
1275 "of work-sharing, critical, ordered or master region");
1276 return;
1277 case OMP_PARALLEL:
1278 return;
1279 default:
1280 break;
1282 break;
1283 case OMP_MASTER:
1284 for (; ctx != NULL; ctx = ctx->outer)
1285 switch (TREE_CODE (ctx->stmt))
1287 case OMP_FOR:
1288 case OMP_SECTIONS:
1289 case OMP_SINGLE:
1290 warning (0, "master region may not be closely nested inside "
1291 "of work-sharing region");
1292 return;
1293 case OMP_PARALLEL:
1294 return;
1295 default:
1296 break;
1298 break;
1299 case OMP_ORDERED:
1300 for (; ctx != NULL; ctx = ctx->outer)
1301 switch (TREE_CODE (ctx->stmt))
1303 case OMP_CRITICAL:
1304 warning (0, "ordered region may not be closely nested inside "
1305 "of critical region");
1306 return;
1307 case OMP_FOR:
1308 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1309 OMP_CLAUSE_ORDERED) == NULL)
1310 warning (0, "ordered region must be closely nested inside "
1311 "a loop region with an ordered clause");
1312 return;
1313 case OMP_PARALLEL:
1314 return;
1315 default:
1316 break;
1318 break;
1319 case OMP_CRITICAL:
1320 for (; ctx != NULL; ctx = ctx->outer)
1321 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1322 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1324 warning (0, "critical region may not be nested inside a critical "
1325 "region with the same name");
1326 return;
1328 break;
1329 default:
1330 break;
1335 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1337 static tree
1338 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1340 struct walk_stmt_info *wi = data;
1341 omp_context *ctx = wi->info;
1342 tree t = *tp;
1344 if (EXPR_HAS_LOCATION (t))
1345 input_location = EXPR_LOCATION (t);
1347 /* Check the OpenMP nesting restrictions. */
1348 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1349 check_omp_nesting_restrictions (t, ctx);
1351 *walk_subtrees = 0;
1352 switch (TREE_CODE (t))
1354 case OMP_PARALLEL:
1355 parallel_nesting_level++;
1356 scan_omp_parallel (tp, ctx);
1357 parallel_nesting_level--;
1358 break;
1360 case OMP_FOR:
1361 scan_omp_for (tp, ctx);
1362 break;
1364 case OMP_SECTIONS:
1365 scan_omp_sections (tp, ctx);
1366 break;
1368 case OMP_SINGLE:
1369 scan_omp_single (tp, ctx);
1370 break;
1372 case OMP_SECTION:
1373 case OMP_MASTER:
1374 case OMP_ORDERED:
1375 case OMP_CRITICAL:
1376 ctx = new_omp_context (*tp, ctx);
1377 scan_omp (&OMP_BODY (*tp), ctx);
1378 break;
1380 case BIND_EXPR:
1382 tree var;
1383 *walk_subtrees = 1;
1385 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1386 insert_decl_map (&ctx->cb, var, var);
1388 break;
1390 case VAR_DECL:
1391 case PARM_DECL:
1392 case LABEL_DECL:
1393 case RESULT_DECL:
1394 if (ctx)
1395 *tp = remap_decl (t, &ctx->cb);
1396 break;
1398 default:
1399 if (ctx && TYPE_P (t))
1400 *tp = remap_type (t, &ctx->cb);
1401 else if (!DECL_P (t))
1402 *walk_subtrees = 1;
1403 break;
1406 return NULL_TREE;
1410 /* Scan all the statements starting at STMT_P. CTX contains context
1411 information about the OpenMP directives and clauses found during
1412 the scan. */
1414 static void
1415 scan_omp (tree *stmt_p, omp_context *ctx)
1417 location_t saved_location;
1418 struct walk_stmt_info wi;
1420 memset (&wi, 0, sizeof (wi));
1421 wi.callback = scan_omp_1;
1422 wi.info = ctx;
1423 wi.want_bind_expr = (ctx != NULL);
1424 wi.want_locations = true;
1426 saved_location = input_location;
1427 walk_stmts (&wi, stmt_p);
1428 input_location = saved_location;
1431 /* Re-gimplification and code generation routines. */
1433 /* Build a call to GOMP_barrier. */
1435 static void
1436 build_omp_barrier (tree *stmt_list)
1438 tree t = build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
1439 gimplify_and_add (t, stmt_list);
1442 /* If a context was created for STMT when it was scanned, return it. */
1444 static omp_context *
1445 maybe_lookup_ctx (tree stmt)
1447 splay_tree_node n;
1448 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1449 return n ? (omp_context *) n->value : NULL;
1453 /* Find the mapping for DECL in CTX or the immediately enclosing
1454 context that has a mapping for DECL.
1456 If CTX is a nested parallel directive, we may have to use the decl
1457 mappings created in CTX's parent context. Suppose that we have the
1458 following parallel nesting (variable UIDs showed for clarity):
1460 iD.1562 = 0;
1461 #omp parallel shared(iD.1562) -> outer parallel
1462 iD.1562 = iD.1562 + 1;
1464 #omp parallel shared (iD.1562) -> inner parallel
1465 iD.1562 = iD.1562 - 1;
1467 Each parallel structure will create a distinct .omp_data_s structure
1468 for copying iD.1562 in/out of the directive:
1470 outer parallel .omp_data_s.1.i -> iD.1562
1471 inner parallel .omp_data_s.2.i -> iD.1562
1473 A shared variable mapping will produce a copy-out operation before
1474 the parallel directive and a copy-in operation after it. So, in
1475 this case we would have:
1477 iD.1562 = 0;
1478 .omp_data_o.1.i = iD.1562;
1479 #omp parallel shared(iD.1562) -> outer parallel
1480 .omp_data_i.1 = &.omp_data_o.1
1481 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1483 .omp_data_o.2.i = iD.1562; -> **
1484 #omp parallel shared(iD.1562) -> inner parallel
1485 .omp_data_i.2 = &.omp_data_o.2
1486 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1489 ** This is a problem. The symbol iD.1562 cannot be referenced
1490 inside the body of the outer parallel region. But since we are
1491 emitting this copy operation while expanding the inner parallel
1492 directive, we need to access the CTX structure of the outer
1493 parallel directive to get the correct mapping:
1495 .omp_data_o.2.i = .omp_data_i.1->i
1497 Since there may be other workshare or parallel directives enclosing
1498 the parallel directive, it may be necessary to walk up the context
1499 parent chain. This is not a problem in general because nested
1500 parallelism happens only rarely. */
1502 static tree
1503 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1505 tree t;
1506 omp_context *up;
1508 gcc_assert (ctx->is_nested);
1510 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1511 t = maybe_lookup_decl (decl, up);
1513 gcc_assert (t || is_global_var (decl));
1515 return t ? t : decl;
1519 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1520 in outer contexts. */
1522 static tree
1523 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1525 tree t = NULL;
1526 omp_context *up;
1528 if (ctx->is_nested)
1529 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1530 t = maybe_lookup_decl (decl, up);
1532 return t ? t : decl;
1536 /* Construct the initialization value for reduction CLAUSE. */
1538 tree
1539 omp_reduction_init (tree clause, tree type)
1541 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1543 case PLUS_EXPR:
1544 case MINUS_EXPR:
1545 case BIT_IOR_EXPR:
1546 case BIT_XOR_EXPR:
1547 case TRUTH_OR_EXPR:
1548 case TRUTH_ORIF_EXPR:
1549 case TRUTH_XOR_EXPR:
1550 case NE_EXPR:
1551 return fold_convert (type, integer_zero_node);
1553 case MULT_EXPR:
1554 case TRUTH_AND_EXPR:
1555 case TRUTH_ANDIF_EXPR:
1556 case EQ_EXPR:
1557 return fold_convert (type, integer_one_node);
1559 case BIT_AND_EXPR:
1560 return fold_convert (type, integer_minus_one_node);
1562 case MAX_EXPR:
1563 if (SCALAR_FLOAT_TYPE_P (type))
1565 REAL_VALUE_TYPE max, min;
1566 if (HONOR_INFINITIES (TYPE_MODE (type)))
1568 real_inf (&max);
1569 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1571 else
1572 real_maxval (&min, 1, TYPE_MODE (type));
1573 return build_real (type, min);
1575 else
1577 gcc_assert (INTEGRAL_TYPE_P (type));
1578 return TYPE_MIN_VALUE (type);
1581 case MIN_EXPR:
1582 if (SCALAR_FLOAT_TYPE_P (type))
1584 REAL_VALUE_TYPE max;
1585 if (HONOR_INFINITIES (TYPE_MODE (type)))
1586 real_inf (&max);
1587 else
1588 real_maxval (&max, 0, TYPE_MODE (type));
1589 return build_real (type, max);
1591 else
1593 gcc_assert (INTEGRAL_TYPE_P (type));
1594 return TYPE_MAX_VALUE (type);
1597 default:
1598 gcc_unreachable ();
1602 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1603 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1604 private variables. Initialization statements go in ILIST, while calls
1605 to destructors go in DLIST. */
1607 static void
1608 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1609 omp_context *ctx)
1611 tree_stmt_iterator diter;
1612 tree c, dtor, copyin_seq, x, ptr;
1613 bool copyin_by_ref = false;
1614 bool lastprivate_firstprivate = false;
1615 int pass;
1617 *dlist = alloc_stmt_list ();
1618 diter = tsi_start (*dlist);
1619 copyin_seq = NULL;
1621 /* Do all the fixed sized types in the first pass, and the variable sized
1622 types in the second pass. This makes sure that the scalar arguments to
1623 the variable sized types are processed before we use them in the
1624 variable sized operations. */
1625 for (pass = 0; pass < 2; ++pass)
1627 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1629 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1630 tree var, new_var;
1631 bool by_ref;
1633 switch (c_kind)
1635 case OMP_CLAUSE_PRIVATE:
1636 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1637 continue;
1638 break;
1639 case OMP_CLAUSE_SHARED:
1640 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1642 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1643 continue;
1645 case OMP_CLAUSE_FIRSTPRIVATE:
1646 case OMP_CLAUSE_COPYIN:
1647 case OMP_CLAUSE_REDUCTION:
1648 break;
1649 case OMP_CLAUSE_LASTPRIVATE:
1650 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1652 lastprivate_firstprivate = true;
1653 if (pass != 0)
1654 continue;
1656 break;
1657 default:
1658 continue;
1661 new_var = var = OMP_CLAUSE_DECL (c);
1662 if (c_kind != OMP_CLAUSE_COPYIN)
1663 new_var = lookup_decl (var, ctx);
1665 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1667 if (pass != 0)
1668 continue;
1670 else if (is_variable_sized (var))
1672 /* For variable sized types, we need to allocate the
1673 actual storage here. Call alloca and store the
1674 result in the pointer decl that we created elsewhere. */
1675 if (pass == 0)
1676 continue;
1678 ptr = DECL_VALUE_EXPR (new_var);
1679 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1680 ptr = TREE_OPERAND (ptr, 0);
1681 gcc_assert (DECL_P (ptr));
1683 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1684 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1685 x = fold_convert (TREE_TYPE (ptr), x);
1686 x = build_gimple_modify_stmt (ptr, x);
1687 gimplify_and_add (x, ilist);
1689 else if (is_reference (var))
1691 /* For references that are being privatized for Fortran,
1692 allocate new backing storage for the new pointer
1693 variable. This allows us to avoid changing all the
1694 code that expects a pointer to something that expects
1695 a direct variable. Note that this doesn't apply to
1696 C++, since reference types are disallowed in data
1697 sharing clauses there, except for NRV optimized
1698 return values. */
1699 if (pass == 0)
1700 continue;
1702 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1703 if (TREE_CONSTANT (x))
1705 const char *name = NULL;
1706 if (DECL_NAME (var))
1707 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1709 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1710 name);
1711 gimple_add_tmp_var (x);
1712 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1714 else
1716 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
1717 x = fold_convert (TREE_TYPE (new_var), x);
1720 x = build_gimple_modify_stmt (new_var, x);
1721 gimplify_and_add (x, ilist);
1723 new_var = build_fold_indirect_ref (new_var);
1725 else if (c_kind == OMP_CLAUSE_REDUCTION
1726 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1728 if (pass == 0)
1729 continue;
1731 else if (pass != 0)
1732 continue;
1734 switch (OMP_CLAUSE_CODE (c))
1736 case OMP_CLAUSE_SHARED:
1737 /* Shared global vars are just accessed directly. */
1738 if (is_global_var (new_var))
1739 break;
1740 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1741 needs to be delayed until after fixup_child_record_type so
1742 that we get the correct type during the dereference. */
1743 by_ref = use_pointer_for_field (var, true);
1744 x = build_receiver_ref (var, by_ref, ctx);
1745 SET_DECL_VALUE_EXPR (new_var, x);
1746 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1748 /* ??? If VAR is not passed by reference, and the variable
1749 hasn't been initialized yet, then we'll get a warning for
1750 the store into the omp_data_s structure. Ideally, we'd be
1751 able to notice this and not store anything at all, but
1752 we're generating code too early. Suppress the warning. */
1753 if (!by_ref)
1754 TREE_NO_WARNING (var) = 1;
1755 break;
1757 case OMP_CLAUSE_LASTPRIVATE:
1758 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1759 break;
1760 /* FALLTHRU */
1762 case OMP_CLAUSE_PRIVATE:
1763 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1764 if (x)
1765 gimplify_and_add (x, ilist);
1766 /* FALLTHRU */
1768 do_dtor:
1769 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1770 if (x)
1772 dtor = x;
1773 gimplify_stmt (&dtor);
1774 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1776 break;
1778 case OMP_CLAUSE_FIRSTPRIVATE:
1779 x = build_outer_var_ref (var, ctx);
1780 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1781 gimplify_and_add (x, ilist);
1782 goto do_dtor;
1783 break;
1785 case OMP_CLAUSE_COPYIN:
1786 by_ref = use_pointer_for_field (var, false);
1787 x = build_receiver_ref (var, by_ref, ctx);
1788 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1789 append_to_statement_list (x, &copyin_seq);
1790 copyin_by_ref |= by_ref;
1791 break;
1793 case OMP_CLAUSE_REDUCTION:
1794 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1796 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1797 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1799 else
1801 x = omp_reduction_init (c, TREE_TYPE (new_var));
1802 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1803 x = build_gimple_modify_stmt (new_var, x);
1804 gimplify_and_add (x, ilist);
1806 break;
1808 default:
1809 gcc_unreachable ();
1814 /* The copyin sequence is not to be executed by the main thread, since
1815 that would result in self-copies. Perhaps not visible to scalars,
1816 but it certainly is to C++ operator=. */
1817 if (copyin_seq)
1819 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
1820 x = build2 (NE_EXPR, boolean_type_node, x,
1821 build_int_cst (TREE_TYPE (x), 0));
1822 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1823 gimplify_and_add (x, ilist);
1826 /* If any copyin variable is passed by reference, we must ensure the
1827 master thread doesn't modify it before it is copied over in all
1828 threads. Similarly for variables in both firstprivate and
1829 lastprivate clauses we need to ensure the lastprivate copying
1830 happens after firstprivate copying in all threads. */
1831 if (copyin_by_ref || lastprivate_firstprivate)
1832 build_omp_barrier (ilist);
1836 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1837 both parallel and workshare constructs. PREDICATE may be NULL if it's
1838 always true. */
1840 static void
1841 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1842 omp_context *ctx)
1844 tree sub_list, x, c;
1846 /* Early exit if there are no lastprivate clauses. */
1847 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1848 if (clauses == NULL)
1850 /* If this was a workshare clause, see if it had been combined
1851 with its parallel. In that case, look for the clauses on the
1852 parallel statement itself. */
1853 if (is_parallel_ctx (ctx))
1854 return;
1856 ctx = ctx->outer;
1857 if (ctx == NULL || !is_parallel_ctx (ctx))
1858 return;
1860 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1861 OMP_CLAUSE_LASTPRIVATE);
1862 if (clauses == NULL)
1863 return;
1866 sub_list = alloc_stmt_list ();
1868 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1870 tree var, new_var;
1872 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1873 continue;
1875 var = OMP_CLAUSE_DECL (c);
1876 new_var = lookup_decl (var, ctx);
1878 x = build_outer_var_ref (var, ctx);
1879 if (is_reference (var))
1880 new_var = build_fold_indirect_ref (new_var);
1881 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1882 append_to_statement_list (x, &sub_list);
1885 if (predicate)
1886 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1887 else
1888 x = sub_list;
1890 gimplify_and_add (x, stmt_list);
1894 /* Generate code to implement the REDUCTION clauses. */
1896 static void
1897 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1899 tree sub_list = NULL, x, c;
1900 int count = 0;
1902 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1903 update in that case, otherwise use a lock. */
1904 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1907 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1909 /* Never use OMP_ATOMIC for array reductions. */
1910 count = -1;
1911 break;
1913 count++;
1916 if (count == 0)
1917 return;
1919 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1921 tree var, ref, new_var;
1922 enum tree_code code;
1924 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1925 continue;
1927 var = OMP_CLAUSE_DECL (c);
1928 new_var = lookup_decl (var, ctx);
1929 if (is_reference (var))
1930 new_var = build_fold_indirect_ref (new_var);
1931 ref = build_outer_var_ref (var, ctx);
1932 code = OMP_CLAUSE_REDUCTION_CODE (c);
1934 /* reduction(-:var) sums up the partial results, so it acts
1935 identically to reduction(+:var). */
1936 if (code == MINUS_EXPR)
1937 code = PLUS_EXPR;
1939 if (count == 1)
1941 tree addr = build_fold_addr_expr (ref);
1943 addr = save_expr (addr);
1944 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1945 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1946 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1947 gimplify_and_add (x, stmt_list);
1948 return;
1951 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1953 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1955 if (is_reference (var))
1956 ref = build_fold_addr_expr (ref);
1957 SET_DECL_VALUE_EXPR (placeholder, ref);
1958 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1959 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1960 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1961 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1963 else
1965 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1966 ref = build_outer_var_ref (var, ctx);
1967 x = build_gimple_modify_stmt (ref, x);
1968 append_to_statement_list (x, &sub_list);
1972 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
1973 gimplify_and_add (x, stmt_list);
1975 gimplify_and_add (sub_list, stmt_list);
1977 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
1978 gimplify_and_add (x, stmt_list);
1982 /* Generate code to implement the COPYPRIVATE clauses. */
1984 static void
1985 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1986 omp_context *ctx)
1988 tree c;
1990 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1992 tree var, ref, x;
1993 bool by_ref;
1995 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1996 continue;
1998 var = OMP_CLAUSE_DECL (c);
1999 by_ref = use_pointer_for_field (var, false);
2001 ref = build_sender_ref (var, ctx);
2002 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
2003 x = by_ref ? build_fold_addr_expr (x) : x;
2004 x = build_gimple_modify_stmt (ref, x);
2005 gimplify_and_add (x, slist);
2007 ref = build_receiver_ref (var, by_ref, ctx);
2008 if (is_reference (var))
2010 ref = build_fold_indirect_ref (ref);
2011 var = build_fold_indirect_ref (var);
2013 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2014 gimplify_and_add (x, rlist);
2019 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2020 and REDUCTION from the sender (aka parent) side. */
2022 static void
2023 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2025 tree c;
2027 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2029 tree val, ref, x, var;
2030 bool by_ref, do_in = false, do_out = false;
2032 switch (OMP_CLAUSE_CODE (c))
2034 case OMP_CLAUSE_FIRSTPRIVATE:
2035 case OMP_CLAUSE_COPYIN:
2036 case OMP_CLAUSE_LASTPRIVATE:
2037 case OMP_CLAUSE_REDUCTION:
2038 break;
2039 default:
2040 continue;
2043 var = val = OMP_CLAUSE_DECL (c);
2044 if (ctx->is_nested)
2045 var = lookup_decl_in_outer_ctx (val, ctx);
2047 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2048 && is_global_var (var))
2049 continue;
2050 if (is_variable_sized (val))
2051 continue;
2052 by_ref = use_pointer_for_field (val, false);
2054 switch (OMP_CLAUSE_CODE (c))
2056 case OMP_CLAUSE_FIRSTPRIVATE:
2057 case OMP_CLAUSE_COPYIN:
2058 do_in = true;
2059 break;
2061 case OMP_CLAUSE_LASTPRIVATE:
2062 if (by_ref || is_reference (val))
2064 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2065 continue;
2066 do_in = true;
2068 else
2069 do_out = true;
2070 break;
2072 case OMP_CLAUSE_REDUCTION:
2073 do_in = true;
2074 do_out = !(by_ref || is_reference (val));
2075 break;
2077 default:
2078 gcc_unreachable ();
2081 if (do_in)
2083 ref = build_sender_ref (val, ctx);
2084 x = by_ref ? build_fold_addr_expr (var) : var;
2085 x = build_gimple_modify_stmt (ref, x);
2086 gimplify_and_add (x, ilist);
2089 if (do_out)
2091 ref = build_sender_ref (val, ctx);
2092 x = build_gimple_modify_stmt (var, ref);
2093 gimplify_and_add (x, olist);
2098 /* Generate code to implement SHARED from the sender (aka parent) side.
2099 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2100 got automatically shared. */
2102 static void
2103 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2105 tree var, ovar, nvar, f, x;
2107 if (ctx->record_type == NULL)
2108 return;
2110 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2112 ovar = DECL_ABSTRACT_ORIGIN (f);
2113 nvar = maybe_lookup_decl (ovar, ctx);
2114 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2115 continue;
2117 var = ovar;
2119 /* If CTX is a nested parallel directive. Find the immediately
2120 enclosing parallel or workshare construct that contains a
2121 mapping for OVAR. */
2122 if (ctx->is_nested)
2123 var = lookup_decl_in_outer_ctx (ovar, ctx);
2125 if (use_pointer_for_field (ovar, true))
2127 x = build_sender_ref (ovar, ctx);
2128 var = build_fold_addr_expr (var);
2129 x = build_gimple_modify_stmt (x, var);
2130 gimplify_and_add (x, ilist);
2132 else
2134 x = build_sender_ref (ovar, ctx);
2135 x = build_gimple_modify_stmt (x, var);
2136 gimplify_and_add (x, ilist);
2138 x = build_sender_ref (ovar, ctx);
2139 x = build_gimple_modify_stmt (var, x);
2140 gimplify_and_add (x, olist);
2145 /* Build the function calls to GOMP_parallel_start etc to actually
2146 generate the parallel operation. REGION is the parallel region
2147 being expanded. BB is the block where to insert the code. WS_ARGS
2148 will be set if this is a call to a combined parallel+workshare
2149 construct, it contains the list of additional arguments needed by
2150 the workshare construct. */
2152 static void
2153 expand_parallel_call (struct omp_region *region, basic_block bb,
2154 tree entry_stmt, tree ws_args)
2156 tree t, t1, t2, val, cond, c, list, clauses;
2157 block_stmt_iterator si;
2158 int start_ix;
2160 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2161 push_gimplify_context ();
2163 /* Determine what flavor of GOMP_parallel_start we will be
2164 emitting. */
2165 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2166 if (is_combined_parallel (region))
2168 switch (region->inner->type)
2170 case OMP_FOR:
2171 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2172 + region->inner->sched_kind;
2173 break;
2174 case OMP_SECTIONS:
2175 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2176 break;
2177 default:
2178 gcc_unreachable ();
2182 /* By default, the value of NUM_THREADS is zero (selected at run time)
2183 and there is no conditional. */
2184 cond = NULL_TREE;
2185 val = build_int_cst (unsigned_type_node, 0);
2187 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2188 if (c)
2189 cond = OMP_CLAUSE_IF_EXPR (c);
2191 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2192 if (c)
2193 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2195 /* Ensure 'val' is of the correct type. */
2196 val = fold_convert (unsigned_type_node, val);
2198 /* If we found the clause 'if (cond)', build either
2199 (cond != 0) or (cond ? val : 1u). */
2200 if (cond)
2202 block_stmt_iterator si;
2204 cond = gimple_boolify (cond);
2206 if (integer_zerop (val))
2207 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2208 build_int_cst (TREE_TYPE (cond), 0));
2209 else
2211 basic_block cond_bb, then_bb, else_bb;
2212 edge e;
2213 tree t, tmp;
2215 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2216 e = split_block (bb, NULL);
2217 cond_bb = e->src;
2218 bb = e->dest;
2219 remove_edge (e);
2221 then_bb = create_empty_bb (cond_bb);
2222 else_bb = create_empty_bb (then_bb);
2224 t = build3 (COND_EXPR, void_type_node,
2225 cond, NULL_TREE, NULL_TREE);
2227 si = bsi_start (cond_bb);
2228 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2230 si = bsi_start (then_bb);
2231 t = build_gimple_modify_stmt (tmp, val);
2232 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2234 si = bsi_start (else_bb);
2235 t = build_gimple_modify_stmt (tmp,
2236 build_int_cst (unsigned_type_node, 1));
2237 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2239 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2240 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2241 make_edge (then_bb, bb, EDGE_FALLTHRU);
2242 make_edge (else_bb, bb, EDGE_FALLTHRU);
2244 val = tmp;
2247 list = NULL_TREE;
2248 val = get_formal_tmp_var (val, &list);
2249 si = bsi_start (bb);
2250 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2253 list = NULL_TREE;
2254 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2255 if (t == NULL)
2256 t1 = null_pointer_node;
2257 else
2258 t1 = build_fold_addr_expr (t);
2259 t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2261 if (ws_args)
2263 tree args = tree_cons (NULL, t2,
2264 tree_cons (NULL, t1,
2265 tree_cons (NULL, val, ws_args)));
2266 t = build_function_call_expr (built_in_decls[start_ix], args);
2268 else
2269 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2271 gimplify_and_add (t, &list);
2273 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2274 if (t == NULL)
2275 t = null_pointer_node;
2276 else
2277 t = build_fold_addr_expr (t);
2278 t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2279 gimplify_and_add (t, &list);
2281 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2282 gimplify_and_add (t, &list);
2284 si = bsi_last (bb);
2285 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2287 pop_gimplify_context (NULL_TREE);
2291 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2292 handler. This prevents programs from violating the structured
2293 block semantics with throws. */
2295 static void
2296 maybe_catch_exception (tree *stmt_p)
2298 tree f, t;
2300 if (!flag_exceptions)
2301 return;
2303 if (lang_protect_cleanup_actions)
2304 t = lang_protect_cleanup_actions ();
2305 else
2306 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2307 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2308 EH_FILTER_MUST_NOT_THROW (f) = 1;
2309 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2311 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2312 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2314 *stmt_p = NULL;
2315 append_to_statement_list (t, stmt_p);
2318 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2320 static tree
2321 list2chain (tree list)
2323 tree t;
2325 for (t = list; t; t = TREE_CHAIN (t))
2327 tree var = TREE_VALUE (t);
2328 if (TREE_CHAIN (t))
2329 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2330 else
2331 TREE_CHAIN (var) = NULL_TREE;
2334 return list ? TREE_VALUE (list) : NULL_TREE;
2338 /* Remove barriers in REGION->EXIT's block. Note that this is only
2339 valid for OMP_PARALLEL regions. Since the end of a parallel region
2340 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2341 left a barrier at the end of the OMP_PARALLEL region can now be
2342 removed. */
2344 static void
2345 remove_exit_barrier (struct omp_region *region)
2347 block_stmt_iterator si;
2348 basic_block exit_bb;
2349 edge_iterator ei;
2350 edge e;
2351 tree t;
2353 exit_bb = region->exit;
2355 /* If the parallel region doesn't return, we don't have REGION->EXIT
2356 block at all. */
2357 if (! exit_bb)
2358 return;
2360 /* The last insn in the block will be the parallel's OMP_RETURN. The
2361 workshare's OMP_RETURN will be in a preceding block. The kinds of
2362 statements that can appear in between are extremely limited -- no
2363 memory operations at all. Here, we allow nothing at all, so the
2364 only thing we allow to precede this OMP_RETURN is a label. */
2365 si = bsi_last (exit_bb);
2366 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2367 bsi_prev (&si);
2368 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2369 return;
2371 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2373 si = bsi_last (e->src);
2374 if (bsi_end_p (si))
2375 continue;
2376 t = bsi_stmt (si);
2377 if (TREE_CODE (t) == OMP_RETURN)
2378 OMP_RETURN_NOWAIT (t) = 1;
2382 static void
2383 remove_exit_barriers (struct omp_region *region)
2385 if (region->type == OMP_PARALLEL)
2386 remove_exit_barrier (region);
2388 if (region->inner)
2390 region = region->inner;
2391 remove_exit_barriers (region);
2392 while (region->next)
2394 region = region->next;
2395 remove_exit_barriers (region);
2400 /* Expand the OpenMP parallel directive starting at REGION. */
2402 static void
2403 expand_omp_parallel (struct omp_region *region)
2405 basic_block entry_bb, exit_bb, new_bb;
2406 struct function *child_cfun, *saved_cfun;
2407 tree child_fn, block, t, ws_args;
2408 block_stmt_iterator si;
2409 tree entry_stmt;
2410 edge e;
2411 bool do_cleanup_cfg = false;
2413 entry_stmt = last_stmt (region->entry);
2414 child_fn = OMP_PARALLEL_FN (entry_stmt);
2415 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2416 saved_cfun = cfun;
2418 entry_bb = region->entry;
2419 exit_bb = region->exit;
2421 if (is_combined_parallel (region))
2422 ws_args = region->ws_args;
2423 else
2424 ws_args = NULL_TREE;
2426 if (child_cfun->cfg)
2428 /* Due to inlining, it may happen that we have already outlined
2429 the region, in which case all we need to do is make the
2430 sub-graph unreachable and emit the parallel call. */
2431 edge entry_succ_e, exit_succ_e;
2432 block_stmt_iterator si;
2434 entry_succ_e = single_succ_edge (entry_bb);
2436 si = bsi_last (entry_bb);
2437 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2438 bsi_remove (&si, true);
2440 new_bb = entry_bb;
2441 remove_edge (entry_succ_e);
2442 if (exit_bb)
2444 exit_succ_e = single_succ_edge (exit_bb);
2445 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2447 do_cleanup_cfg = true;
2449 else
2451 /* If the parallel region needs data sent from the parent
2452 function, then the very first statement (except possible
2453 tree profile counter updates) of the parallel body
2454 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2455 &.OMP_DATA_O is passed as an argument to the child function,
2456 we need to replace it with the argument as seen by the child
2457 function.
2459 In most cases, this will end up being the identity assignment
2460 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2461 a function call that has been inlined, the original PARM_DECL
2462 .OMP_DATA_I may have been converted into a different local
2463 variable. In which case, we need to keep the assignment. */
2464 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2466 basic_block entry_succ_bb = single_succ (entry_bb);
2467 block_stmt_iterator si;
2469 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2471 tree stmt, arg;
2473 gcc_assert (!bsi_end_p (si));
2474 stmt = bsi_stmt (si);
2475 if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2476 continue;
2478 arg = GIMPLE_STMT_OPERAND (stmt, 1);
2479 STRIP_NOPS (arg);
2480 if (TREE_CODE (arg) == ADDR_EXPR
2481 && TREE_OPERAND (arg, 0)
2482 == OMP_PARALLEL_DATA_ARG (entry_stmt))
2484 if (GIMPLE_STMT_OPERAND (stmt, 0)
2485 == DECL_ARGUMENTS (child_fn))
2486 bsi_remove (&si, true);
2487 else
2488 GIMPLE_STMT_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2489 break;
2494 /* Declare local variables needed in CHILD_CFUN. */
2495 block = DECL_INITIAL (child_fn);
2496 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2497 DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2499 /* Reset DECL_CONTEXT on locals and function arguments. */
2500 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2501 DECL_CONTEXT (t) = child_fn;
2503 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2504 DECL_CONTEXT (t) = child_fn;
2506 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2507 child function. */
2508 si = bsi_last (entry_bb);
2509 t = bsi_stmt (si);
2510 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2511 bsi_remove (&si, true);
2512 e = split_block (entry_bb, t);
2513 entry_bb = e->dest;
2514 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2516 /* Move the parallel region into CHILD_CFUN. We need to reset
2517 dominance information because the expansion of the inner
2518 regions has invalidated it. */
2519 free_dominance_info (CDI_DOMINATORS);
2520 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2521 if (exit_bb)
2522 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2523 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2524 = cfun->curr_properties;
2525 cgraph_add_new_function (child_fn, true);
2527 /* Convert OMP_RETURN into a RETURN_EXPR. */
2528 if (exit_bb)
2530 si = bsi_last (exit_bb);
2531 gcc_assert (!bsi_end_p (si)
2532 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2533 t = build1 (RETURN_EXPR, void_type_node, NULL);
2534 bsi_insert_after (&si, t, BSI_SAME_STMT);
2535 bsi_remove (&si, true);
2539 /* Emit a library call to launch the children threads. */
2540 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2542 if (do_cleanup_cfg)
2544 /* Clean up the unreachable sub-graph we created above. */
2545 free_dominance_info (CDI_DOMINATORS);
2546 free_dominance_info (CDI_POST_DOMINATORS);
2547 cleanup_tree_cfg ();
2552 /* A subroutine of expand_omp_for. Generate code for a parallel
2553 loop with any schedule. Given parameters:
2555 for (V = N1; V cond N2; V += STEP) BODY;
2557 where COND is "<" or ">", we generate pseudocode
2559 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2560 if (more) goto L0; else goto L3;
2562 V = istart0;
2563 iend = iend0;
2565 BODY;
2566 V += STEP;
2567 if (V cond iend) goto L1; else goto L2;
2569 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2572 If this is a combined omp parallel loop, instead of the call to
2573 GOMP_loop_foo_start, we emit 'goto L2'. */
2575 static void
2576 expand_omp_for_generic (struct omp_region *region,
2577 struct omp_for_data *fd,
2578 enum built_in_function start_fn,
2579 enum built_in_function next_fn)
2581 tree type, istart0, iend0, iend;
2582 tree t, list;
2583 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2584 basic_block l2_bb = NULL, l3_bb = NULL;
2585 block_stmt_iterator si;
2586 bool in_combined_parallel = is_combined_parallel (region);
2587 bool broken_loop = region->cont == NULL;
2589 gcc_assert (!broken_loop || !in_combined_parallel);
2591 type = TREE_TYPE (fd->v);
2593 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2594 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2595 iend = create_tmp_var (type, NULL);
2596 TREE_ADDRESSABLE (istart0) = 1;
2597 TREE_ADDRESSABLE (iend0) = 1;
2599 entry_bb = region->entry;
2600 cont_bb = region->cont;
2601 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2602 gcc_assert (broken_loop
2603 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2604 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2605 l1_bb = single_succ (l0_bb);
2606 if (!broken_loop)
2608 l2_bb = create_empty_bb (cont_bb);
2609 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
2610 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2612 else
2613 l2_bb = NULL;
2614 l3_bb = BRANCH_EDGE (entry_bb)->dest;
2615 exit_bb = region->exit;
2617 si = bsi_last (entry_bb);
2618 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2619 if (!in_combined_parallel)
2621 tree t0, t1, t2, t3, t4;
2622 /* If this is not a combined parallel loop, emit a call to
2623 GOMP_loop_foo_start in ENTRY_BB. */
2624 list = alloc_stmt_list ();
2625 t4 = build_fold_addr_expr (iend0);
2626 t3 = build_fold_addr_expr (istart0);
2627 t2 = fold_convert (long_integer_type_node, fd->step);
2628 t1 = fold_convert (long_integer_type_node, fd->n2);
2629 t0 = fold_convert (long_integer_type_node, fd->n1);
2630 if (fd->chunk_size)
2632 t = fold_convert (long_integer_type_node, fd->chunk_size);
2633 t = build_call_expr (built_in_decls[start_fn], 6,
2634 t0, t1, t2, t, t3, t4);
2636 else
2637 t = build_call_expr (built_in_decls[start_fn], 5,
2638 t0, t1, t2, t3, t4);
2639 t = get_formal_tmp_var (t, &list);
2640 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2641 append_to_statement_list (t, &list);
2642 bsi_insert_after (&si, list, BSI_SAME_STMT);
2644 bsi_remove (&si, true);
2646 /* Iteration setup for sequential loop goes in L0_BB. */
2647 list = alloc_stmt_list ();
2648 t = fold_convert (type, istart0);
2649 t = build_gimple_modify_stmt (fd->v, t);
2650 gimplify_and_add (t, &list);
2652 t = fold_convert (type, iend0);
2653 t = build_gimple_modify_stmt (iend, t);
2654 gimplify_and_add (t, &list);
2656 si = bsi_start (l0_bb);
2657 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2659 if (!broken_loop)
2661 /* Code to control the increment and predicate for the sequential
2662 loop goes in the CONT_BB. */
2663 list = alloc_stmt_list ();
2665 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2666 t = build_gimple_modify_stmt (fd->v, t);
2667 gimplify_and_add (t, &list);
2669 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2670 t = get_formal_tmp_var (t, &list);
2671 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2672 append_to_statement_list (t, &list);
2674 si = bsi_last (cont_bb);
2675 bsi_insert_after (&si, list, BSI_SAME_STMT);
2676 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2677 bsi_remove (&si, true);
2679 /* Emit code to get the next parallel iteration in L2_BB. */
2680 list = alloc_stmt_list ();
2682 t = build_call_expr (built_in_decls[next_fn], 2,
2683 build_fold_addr_expr (istart0),
2684 build_fold_addr_expr (iend0));
2685 t = get_formal_tmp_var (t, &list);
2686 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2687 append_to_statement_list (t, &list);
2689 si = bsi_start (l2_bb);
2690 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2693 /* Add the loop cleanup function. */
2694 si = bsi_last (exit_bb);
2695 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2696 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2697 else
2698 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2699 t = build_call_expr (t, 0);
2700 bsi_insert_after (&si, t, BSI_SAME_STMT);
2701 bsi_remove (&si, true);
2703 /* Connect the new blocks. */
2704 if (in_combined_parallel)
2706 remove_edge (BRANCH_EDGE (entry_bb));
2707 redirect_edge_and_branch (single_succ_edge (entry_bb), l2_bb);
2709 else
2711 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
2712 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
2715 if (!broken_loop)
2717 find_edge (cont_bb, l1_bb)->flags = EDGE_TRUE_VALUE;
2718 remove_edge (find_edge (cont_bb, l3_bb));
2719 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2721 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2722 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2727 /* A subroutine of expand_omp_for. Generate code for a parallel
2728 loop with static schedule and no specified chunk size. Given
2729 parameters:
2731 for (V = N1; V cond N2; V += STEP) BODY;
2733 where COND is "<" or ">", we generate pseudocode
2735 if (cond is <)
2736 adj = STEP - 1;
2737 else
2738 adj = STEP + 1;
2739 n = (adj + N2 - N1) / STEP;
2740 q = n / nthreads;
2741 q += (q * nthreads != n);
2742 s0 = q * threadid;
2743 e0 = min(s0 + q, n);
2744 if (s0 >= e0) goto L2; else goto L0;
2746 V = s0 * STEP + N1;
2747 e = e0 * STEP + N1;
2749 BODY;
2750 V += STEP;
2751 if (V cond e) goto L1;
2755 static void
2756 expand_omp_for_static_nochunk (struct omp_region *region,
2757 struct omp_for_data *fd)
2759 tree n, q, s0, e0, e, t, nthreads, threadid;
2760 tree type, list;
2761 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2762 basic_block fin_bb;
2763 block_stmt_iterator si;
2765 type = TREE_TYPE (fd->v);
2767 entry_bb = region->entry;
2768 cont_bb = region->cont;
2769 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
2770 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
2771 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
2772 body_bb = single_succ (seq_start_bb);
2773 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
2774 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2775 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
2776 exit_bb = region->exit;
2778 /* Iteration space partitioning goes in ENTRY_BB. */
2779 list = alloc_stmt_list ();
2781 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2782 t = fold_convert (type, t);
2783 nthreads = get_formal_tmp_var (t, &list);
2785 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2786 t = fold_convert (type, t);
2787 threadid = get_formal_tmp_var (t, &list);
2789 fd->n1 = fold_convert (type, fd->n1);
2790 if (!is_gimple_val (fd->n1))
2791 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2793 fd->n2 = fold_convert (type, fd->n2);
2794 if (!is_gimple_val (fd->n2))
2795 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2797 fd->step = fold_convert (type, fd->step);
2798 if (!is_gimple_val (fd->step))
2799 fd->step = get_formal_tmp_var (fd->step, &list);
2801 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2802 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2803 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2804 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2805 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2806 t = fold_convert (type, t);
2807 if (is_gimple_val (t))
2808 n = t;
2809 else
2810 n = get_formal_tmp_var (t, &list);
2812 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2813 q = get_formal_tmp_var (t, &list);
2815 t = build2 (MULT_EXPR, type, q, nthreads);
2816 t = build2 (NE_EXPR, type, t, n);
2817 t = build2 (PLUS_EXPR, type, q, t);
2818 q = get_formal_tmp_var (t, &list);
2820 t = build2 (MULT_EXPR, type, q, threadid);
2821 s0 = get_formal_tmp_var (t, &list);
2823 t = build2 (PLUS_EXPR, type, s0, q);
2824 t = build2 (MIN_EXPR, type, t, n);
2825 e0 = get_formal_tmp_var (t, &list);
2827 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2828 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2829 append_to_statement_list (t, &list);
2831 si = bsi_last (entry_bb);
2832 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2833 bsi_insert_after (&si, list, BSI_SAME_STMT);
2834 bsi_remove (&si, true);
2836 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2837 list = alloc_stmt_list ();
2839 t = fold_convert (type, s0);
2840 t = build2 (MULT_EXPR, type, t, fd->step);
2841 t = build2 (PLUS_EXPR, type, t, fd->n1);
2842 t = build_gimple_modify_stmt (fd->v, t);
2843 gimplify_and_add (t, &list);
2845 t = fold_convert (type, e0);
2846 t = build2 (MULT_EXPR, type, t, fd->step);
2847 t = build2 (PLUS_EXPR, type, t, fd->n1);
2848 e = get_formal_tmp_var (t, &list);
2850 si = bsi_start (seq_start_bb);
2851 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2853 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2854 list = alloc_stmt_list ();
2856 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2857 t = build_gimple_modify_stmt (fd->v, t);
2858 gimplify_and_add (t, &list);
2860 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2861 t = get_formal_tmp_var (t, &list);
2862 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2863 append_to_statement_list (t, &list);
2865 si = bsi_last (cont_bb);
2866 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2867 bsi_insert_after (&si, list, BSI_SAME_STMT);
2868 bsi_remove (&si, true);
2870 /* Replace the OMP_RETURN with a barrier, or nothing. */
2871 si = bsi_last (exit_bb);
2872 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2874 list = alloc_stmt_list ();
2875 build_omp_barrier (&list);
2876 bsi_insert_after (&si, list, BSI_SAME_STMT);
2878 bsi_remove (&si, true);
2880 /* Connect all the blocks. */
2881 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
2882 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
2884 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
2885 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2889 /* A subroutine of expand_omp_for. Generate code for a parallel
2890 loop with static schedule and a specified chunk size. Given
2891 parameters:
2893 for (V = N1; V cond N2; V += STEP) BODY;
2895 where COND is "<" or ">", we generate pseudocode
2897 if (cond is <)
2898 adj = STEP - 1;
2899 else
2900 adj = STEP + 1;
2901 n = (adj + N2 - N1) / STEP;
2902 trip = 0;
2904 s0 = (trip * nthreads + threadid) * CHUNK;
2905 e0 = min(s0 + CHUNK, n);
2906 if (s0 < n) goto L1; else goto L4;
2908 V = s0 * STEP + N1;
2909 e = e0 * STEP + N1;
2911 BODY;
2912 V += STEP;
2913 if (V cond e) goto L2; else goto L3;
2915 trip += 1;
2916 goto L0;
2920 static void
2921 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2923 tree n, s0, e0, e, t;
2924 tree trip, nthreads, threadid;
2925 tree type;
2926 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2927 basic_block trip_update_bb, cont_bb, fin_bb;
2928 tree list;
2929 block_stmt_iterator si;
2930 edge se;
2932 type = TREE_TYPE (fd->v);
2934 entry_bb = region->entry;
2935 se = split_block (entry_bb, last_stmt (entry_bb));
2936 entry_bb = se->src;
2937 iter_part_bb = se->dest;
2938 cont_bb = region->cont;
2939 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
2940 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
2941 == FALLTHRU_EDGE (cont_bb)->dest);
2942 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
2943 body_bb = single_succ (seq_start_bb);
2944 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
2945 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
2946 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
2947 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
2948 exit_bb = region->exit;
2950 /* Trip and adjustment setup goes in ENTRY_BB. */
2951 list = alloc_stmt_list ();
2953 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2954 t = fold_convert (type, t);
2955 nthreads = get_formal_tmp_var (t, &list);
2957 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2958 t = fold_convert (type, t);
2959 threadid = get_formal_tmp_var (t, &list);
2961 fd->n1 = fold_convert (type, fd->n1);
2962 if (!is_gimple_val (fd->n1))
2963 fd->n1 = get_formal_tmp_var (fd->n1, &list);
2965 fd->n2 = fold_convert (type, fd->n2);
2966 if (!is_gimple_val (fd->n2))
2967 fd->n2 = get_formal_tmp_var (fd->n2, &list);
2969 fd->step = fold_convert (type, fd->step);
2970 if (!is_gimple_val (fd->step))
2971 fd->step = get_formal_tmp_var (fd->step, &list);
2973 fd->chunk_size = fold_convert (type, fd->chunk_size);
2974 if (!is_gimple_val (fd->chunk_size))
2975 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2977 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2978 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2979 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2980 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2981 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2982 t = fold_convert (type, t);
2983 if (is_gimple_val (t))
2984 n = t;
2985 else
2986 n = get_formal_tmp_var (t, &list);
2988 t = build_int_cst (type, 0);
2989 trip = get_initialized_tmp_var (t, &list, NULL);
2991 si = bsi_last (entry_bb);
2992 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2993 bsi_insert_after (&si, list, BSI_SAME_STMT);
2994 bsi_remove (&si, true);
2996 /* Iteration space partitioning goes in ITER_PART_BB. */
2997 list = alloc_stmt_list ();
2999 t = build2 (MULT_EXPR, type, trip, nthreads);
3000 t = build2 (PLUS_EXPR, type, t, threadid);
3001 t = build2 (MULT_EXPR, type, t, fd->chunk_size);
3002 s0 = get_formal_tmp_var (t, &list);
3004 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3005 t = build2 (MIN_EXPR, type, t, n);
3006 e0 = get_formal_tmp_var (t, &list);
3008 t = build2 (LT_EXPR, boolean_type_node, s0, n);
3009 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3010 append_to_statement_list (t, &list);
3012 si = bsi_start (iter_part_bb);
3013 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3015 /* Setup code for sequential iteration goes in SEQ_START_BB. */
3016 list = alloc_stmt_list ();
3018 t = fold_convert (type, s0);
3019 t = build2 (MULT_EXPR, type, t, fd->step);
3020 t = build2 (PLUS_EXPR, type, t, fd->n1);
3021 t = build_gimple_modify_stmt (fd->v, t);
3022 gimplify_and_add (t, &list);
3024 t = fold_convert (type, e0);
3025 t = build2 (MULT_EXPR, type, t, fd->step);
3026 t = build2 (PLUS_EXPR, type, t, fd->n1);
3027 e = get_formal_tmp_var (t, &list);
3029 si = bsi_start (seq_start_bb);
3030 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3032 /* The code controlling the sequential loop goes in CONT_BB,
3033 replacing the OMP_CONTINUE. */
3034 list = alloc_stmt_list ();
3036 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3037 t = build_gimple_modify_stmt (fd->v, t);
3038 gimplify_and_add (t, &list);
3040 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3041 t = get_formal_tmp_var (t, &list);
3042 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3043 append_to_statement_list (t, &list);
3045 si = bsi_last (cont_bb);
3046 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3047 bsi_insert_after (&si, list, BSI_SAME_STMT);
3048 bsi_remove (&si, true);
3050 /* Trip update code goes into TRIP_UPDATE_BB. */
3051 list = alloc_stmt_list ();
3053 t = build_int_cst (type, 1);
3054 t = build2 (PLUS_EXPR, type, trip, t);
3055 t = build_gimple_modify_stmt (trip, t);
3056 gimplify_and_add (t, &list);
3058 si = bsi_start (trip_update_bb);
3059 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3061 /* Replace the OMP_RETURN with a barrier, or nothing. */
3062 si = bsi_last (exit_bb);
3063 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3065 list = alloc_stmt_list ();
3066 build_omp_barrier (&list);
3067 bsi_insert_after (&si, list, BSI_SAME_STMT);
3069 bsi_remove (&si, true);
3071 /* Connect the new blocks. */
3072 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
3073 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
3075 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
3076 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
3078 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
3082 /* Expand the OpenMP loop defined by REGION. */
3084 static void
3085 expand_omp_for (struct omp_region *region)
3087 struct omp_for_data fd;
3089 push_gimplify_context ();
3091 extract_omp_for_data (last_stmt (region->entry), &fd);
3092 region->sched_kind = fd.sched_kind;
3094 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3095 && !fd.have_ordered
3096 && region->cont != NULL)
3098 if (fd.chunk_size == NULL)
3099 expand_omp_for_static_nochunk (region, &fd);
3100 else
3101 expand_omp_for_static_chunk (region, &fd);
3103 else
3105 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3106 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3107 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3108 expand_omp_for_generic (region, &fd, start_ix, next_ix);
3111 pop_gimplify_context (NULL);
3115 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
3117 v = GOMP_sections_start (n);
3119 switch (v)
3121 case 0:
3122 goto L2;
3123 case 1:
3124 section 1;
3125 goto L1;
3126 case 2:
3128 case n:
3130 default:
3131 abort ();
3134 v = GOMP_sections_next ();
3135 goto L0;
3137 reduction;
3139 If this is a combined parallel sections, replace the call to
3140 GOMP_sections_start with 'goto L1'. */
3142 static void
3143 expand_omp_sections (struct omp_region *region)
3145 tree label_vec, l1, l2, t, u, v, sections_stmt;
3146 unsigned i, casei, len;
3147 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
3148 block_stmt_iterator si;
3149 struct omp_region *inner;
3150 bool exit_reachable = region->cont != NULL;
3152 gcc_assert (exit_reachable == (region->exit != NULL));
3153 entry_bb = region->entry;
3154 l0_bb = single_succ (entry_bb);
3155 l1_bb = region->cont;
3156 l2_bb = region->exit;
3157 if (exit_reachable)
3159 gcc_assert (single_pred (l2_bb) == l0_bb);
3160 default_bb = create_empty_bb (l1_bb->prev_bb);
3161 l1 = tree_block_label (l1_bb);
3162 l2 = tree_block_label (l2_bb);
3164 else
3166 default_bb = create_empty_bb (l0_bb);
3167 l1 = NULL_TREE;
3168 l2 = tree_block_label (default_bb);
3171 /* We will build a switch() with enough cases for all the
3172 OMP_SECTION regions, a '0' case to handle the end of more work
3173 and a default case to abort if something goes wrong. */
3174 len = EDGE_COUNT (l0_bb->succs);
3175 label_vec = make_tree_vec (len + 1);
3177 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3178 OMP_SECTIONS statement. */
3179 si = bsi_last (entry_bb);
3180 sections_stmt = bsi_stmt (si);
3181 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3182 v = OMP_SECTIONS_CONTROL (sections_stmt);
3183 if (!is_combined_parallel (region))
3185 /* If we are not inside a combined parallel+sections region,
3186 call GOMP_sections_start. */
3187 t = build_int_cst (unsigned_type_node,
3188 exit_reachable ? len - 1 : len);
3189 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3190 t = build_call_expr (u, 1, t);
3191 t = build_gimple_modify_stmt (v, t);
3192 bsi_insert_after (&si, t, BSI_SAME_STMT);
3194 bsi_remove (&si, true);
3196 /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB. */
3197 si = bsi_last (l0_bb);
3198 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
3200 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3201 bsi_insert_after (&si, t, BSI_SAME_STMT);
3202 bsi_remove (&si, true);
3204 i = 0;
3205 if (exit_reachable)
3207 t = build3 (CASE_LABEL_EXPR, void_type_node,
3208 build_int_cst (unsigned_type_node, 0), NULL, l2);
3209 TREE_VEC_ELT (label_vec, 0) = t;
3210 i++;
3213 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3214 for (inner = region->inner, casei = 1;
3215 inner;
3216 inner = inner->next, i++, casei++)
3218 basic_block s_entry_bb, s_exit_bb;
3220 s_entry_bb = inner->entry;
3221 s_exit_bb = inner->exit;
3223 t = tree_block_label (s_entry_bb);
3224 u = build_int_cst (unsigned_type_node, casei);
3225 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3226 TREE_VEC_ELT (label_vec, i) = u;
3228 si = bsi_last (s_entry_bb);
3229 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3230 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3231 bsi_remove (&si, true);
3232 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3234 if (s_exit_bb == NULL)
3235 continue;
3237 si = bsi_last (s_exit_bb);
3238 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3239 bsi_remove (&si, true);
3241 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3244 /* Error handling code goes in DEFAULT_BB. */
3245 t = tree_block_label (default_bb);
3246 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3247 TREE_VEC_ELT (label_vec, len) = u;
3248 make_edge (l0_bb, default_bb, 0);
3250 si = bsi_start (default_bb);
3251 t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3252 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3254 if (exit_reachable)
3256 /* Code to get the next section goes in L1_BB. */
3257 si = bsi_last (l1_bb);
3258 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3260 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3261 t = build_gimple_modify_stmt (v, t);
3262 bsi_insert_after (&si, t, BSI_SAME_STMT);
3263 bsi_remove (&si, true);
3265 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
3267 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3268 si = bsi_last (l2_bb);
3269 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3270 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3271 else
3272 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3273 t = build_call_expr (t, 0);
3274 bsi_insert_after (&si, t, BSI_SAME_STMT);
3275 bsi_remove (&si, true);
3278 /* Connect the new blocks. */
3279 if (is_combined_parallel (region))
3281 /* If this was a combined parallel+sections region, we did not
3282 emit a GOMP_sections_start in the entry block, so we just
3283 need to jump to L1_BB to get the next section. */
3284 gcc_assert (exit_reachable);
3285 redirect_edge_and_branch (single_succ_edge (entry_bb), l1_bb);
3290 /* Expand code for an OpenMP single directive. We've already expanded
3291 much of the code, here we simply place the GOMP_barrier call. */
3293 static void
3294 expand_omp_single (struct omp_region *region)
3296 basic_block entry_bb, exit_bb;
3297 block_stmt_iterator si;
3298 bool need_barrier = false;
3300 entry_bb = region->entry;
3301 exit_bb = region->exit;
3303 si = bsi_last (entry_bb);
3304 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3305 be removed. We need to ensure that the thread that entered the single
3306 does not exit before the data is copied out by the other threads. */
3307 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3308 OMP_CLAUSE_COPYPRIVATE))
3309 need_barrier = true;
3310 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3311 bsi_remove (&si, true);
3312 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3314 si = bsi_last (exit_bb);
3315 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3317 tree t = alloc_stmt_list ();
3318 build_omp_barrier (&t);
3319 bsi_insert_after (&si, t, BSI_SAME_STMT);
3321 bsi_remove (&si, true);
3322 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3326 /* Generic expansion for OpenMP synchronization directives: master,
3327 ordered and critical. All we need to do here is remove the entry
3328 and exit markers for REGION. */
3330 static void
3331 expand_omp_synch (struct omp_region *region)
3333 basic_block entry_bb, exit_bb;
3334 block_stmt_iterator si;
3336 entry_bb = region->entry;
3337 exit_bb = region->exit;
3339 si = bsi_last (entry_bb);
3340 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3341 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3342 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3343 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3344 bsi_remove (&si, true);
3345 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3347 if (exit_bb)
3349 si = bsi_last (exit_bb);
3350 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3351 bsi_remove (&si, true);
3352 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3357 /* Expand the parallel region tree rooted at REGION. Expansion
3358 proceeds in depth-first order. Innermost regions are expanded
3359 first. This way, parallel regions that require a new function to
3360 be created (e.g., OMP_PARALLEL) can be expanded without having any
3361 internal dependencies in their body. */
3363 static void
3364 expand_omp (struct omp_region *region)
3366 while (region)
3368 if (region->inner)
3369 expand_omp (region->inner);
3371 switch (region->type)
3373 case OMP_PARALLEL:
3374 expand_omp_parallel (region);
3375 break;
3377 case OMP_FOR:
3378 expand_omp_for (region);
3379 break;
3381 case OMP_SECTIONS:
3382 expand_omp_sections (region);
3383 break;
3385 case OMP_SECTION:
3386 /* Individual omp sections are handled together with their
3387 parent OMP_SECTIONS region. */
3388 break;
3390 case OMP_SINGLE:
3391 expand_omp_single (region);
3392 break;
3394 case OMP_MASTER:
3395 case OMP_ORDERED:
3396 case OMP_CRITICAL:
3397 expand_omp_synch (region);
3398 break;
3400 default:
3401 gcc_unreachable ();
3404 region = region->next;
3409 /* Helper for build_omp_regions. Scan the dominator tree starting at
3410 block BB. PARENT is the region that contains BB. */
3412 static void
3413 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3415 block_stmt_iterator si;
3416 tree stmt;
3417 basic_block son;
3419 si = bsi_last (bb);
3420 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3422 struct omp_region *region;
3423 enum tree_code code;
3425 stmt = bsi_stmt (si);
3426 code = TREE_CODE (stmt);
3428 if (code == OMP_RETURN)
3430 /* STMT is the return point out of region PARENT. Mark it
3431 as the exit point and make PARENT the immediately
3432 enclosing region. */
3433 gcc_assert (parent);
3434 region = parent;
3435 region->exit = bb;
3436 parent = parent->outer;
3438 /* If REGION is a parallel region, determine whether it is
3439 a combined parallel+workshare region. */
3440 if (region->type == OMP_PARALLEL)
3441 determine_parallel_type (region);
3443 else if (code == OMP_CONTINUE)
3445 gcc_assert (parent);
3446 parent->cont = bb;
3448 else if (code == OMP_SECTIONS_SWITCH)
3450 /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
3451 it. */
3453 else
3455 /* Otherwise, this directive becomes the parent for a new
3456 region. */
3457 region = new_omp_region (bb, code, parent);
3458 parent = region;
3462 for (son = first_dom_son (CDI_DOMINATORS, bb);
3463 son;
3464 son = next_dom_son (CDI_DOMINATORS, son))
3465 build_omp_regions_1 (son, parent);
3469 /* Scan the CFG and build a tree of OMP regions. Return the root of
3470 the OMP region tree. */
3472 static void
3473 build_omp_regions (void)
3475 gcc_assert (root_omp_region == NULL);
3476 calculate_dominance_info (CDI_DOMINATORS);
3477 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3481 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3483 static unsigned int
3484 execute_expand_omp (void)
3486 build_omp_regions ();
3488 if (!root_omp_region)
3489 return 0;
3491 if (dump_file)
3493 fprintf (dump_file, "\nOMP region tree\n\n");
3494 dump_omp_region (dump_file, root_omp_region, 0);
3495 fprintf (dump_file, "\n");
3498 remove_exit_barriers (root_omp_region);
3500 expand_omp (root_omp_region);
3502 free_dominance_info (CDI_DOMINATORS);
3503 free_dominance_info (CDI_POST_DOMINATORS);
3504 cleanup_tree_cfg ();
3506 free_omp_regions ();
3508 return 0;
3511 static bool
3512 gate_expand_omp (void)
3514 return flag_openmp != 0 && errorcount == 0;
3517 struct tree_opt_pass pass_expand_omp =
3519 "ompexp", /* name */
3520 gate_expand_omp, /* gate */
3521 execute_expand_omp, /* execute */
3522 NULL, /* sub */
3523 NULL, /* next */
3524 0, /* static_pass_number */
3525 0, /* tv_id */
3526 PROP_gimple_any, /* properties_required */
3527 PROP_gimple_lomp, /* properties_provided */
3528 0, /* properties_destroyed */
3529 0, /* todo_flags_start */
3530 TODO_dump_func, /* todo_flags_finish */
3531 0 /* letter */
3534 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3536 /* Lower the OpenMP sections directive in *STMT_P. */
3538 static void
3539 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3541 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body, control;
3542 tree t, dlist;
3543 tree_stmt_iterator tsi;
3544 unsigned i, len;
3546 stmt = *stmt_p;
3548 push_gimplify_context ();
3550 dlist = NULL;
3551 ilist = NULL;
3552 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3554 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3555 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3556 continue;
3558 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3559 body = alloc_stmt_list ();
3560 for (i = 0; i < len; i++, tsi_next (&tsi))
3562 omp_context *sctx;
3563 tree sec_start, sec_end;
3565 sec_start = tsi_stmt (tsi);
3566 sctx = maybe_lookup_ctx (sec_start);
3567 gcc_assert (sctx);
3569 append_to_statement_list (sec_start, &body);
3571 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3572 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3573 OMP_SECTION_BODY (sec_start) = NULL;
3575 if (i == len - 1)
3577 tree l = alloc_stmt_list ();
3578 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3579 &l, ctx);
3580 append_to_statement_list (l, &body);
3581 OMP_SECTION_LAST (sec_start) = 1;
3584 sec_end = make_node (OMP_RETURN);
3585 append_to_statement_list (sec_end, &body);
3588 block = make_node (BLOCK);
3589 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3591 olist = NULL_TREE;
3592 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3594 pop_gimplify_context (NULL_TREE);
3595 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3597 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3598 TREE_SIDE_EFFECTS (new_stmt) = 1;
3600 new_body = alloc_stmt_list ();
3601 append_to_statement_list (ilist, &new_body);
3602 append_to_statement_list (stmt, &new_body);
3603 append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
3604 append_to_statement_list (bind, &new_body);
3606 control = create_tmp_var (unsigned_type_node, ".section");
3607 t = build2 (OMP_CONTINUE, void_type_node, control, control);
3608 OMP_SECTIONS_CONTROL (stmt) = control;
3609 append_to_statement_list (t, &new_body);
3611 append_to_statement_list (olist, &new_body);
3612 append_to_statement_list (dlist, &new_body);
3614 maybe_catch_exception (&new_body);
3616 t = make_node (OMP_RETURN);
3617 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3618 OMP_CLAUSE_NOWAIT);
3619 append_to_statement_list (t, &new_body);
3621 BIND_EXPR_BODY (new_stmt) = new_body;
3622 OMP_SECTIONS_BODY (stmt) = NULL;
3624 *stmt_p = new_stmt;
3628 /* A subroutine of lower_omp_single. Expand the simple form of
3629 an OMP_SINGLE, without a copyprivate clause:
3631 if (GOMP_single_start ())
3632 BODY;
3633 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3635 FIXME. It may be better to delay expanding the logic of this until
3636 pass_expand_omp. The expanded logic may make the job more difficult
3637 to a synchronization analysis pass. */
3639 static void
3640 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3642 tree t;
3644 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3645 t = build3 (COND_EXPR, void_type_node, t,
3646 OMP_SINGLE_BODY (single_stmt), NULL);
3647 gimplify_and_add (t, pre_p);
3651 /* A subroutine of lower_omp_single. Expand the simple form of
3652 an OMP_SINGLE, with a copyprivate clause:
3654 #pragma omp single copyprivate (a, b, c)
3656 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3659 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3661 BODY;
3662 copyout.a = a;
3663 copyout.b = b;
3664 copyout.c = c;
3665 GOMP_single_copy_end (&copyout);
3667 else
3669 a = copyout_p->a;
3670 b = copyout_p->b;
3671 c = copyout_p->c;
3673 GOMP_barrier ();
3676 FIXME. It may be better to delay expanding the logic of this until
3677 pass_expand_omp. The expanded logic may make the job more difficult
3678 to a synchronization analysis pass. */
3680 static void
3681 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3683 tree ptr_type, t, l0, l1, l2, copyin_seq;
3685 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3687 ptr_type = build_pointer_type (ctx->record_type);
3688 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3690 l0 = create_artificial_label ();
3691 l1 = create_artificial_label ();
3692 l2 = create_artificial_label ();
3694 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3695 t = fold_convert (ptr_type, t);
3696 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3697 gimplify_and_add (t, pre_p);
3699 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3700 build_int_cst (ptr_type, 0));
3701 t = build3 (COND_EXPR, void_type_node, t,
3702 build_and_jump (&l0), build_and_jump (&l1));
3703 gimplify_and_add (t, pre_p);
3705 t = build1 (LABEL_EXPR, void_type_node, l0);
3706 gimplify_and_add (t, pre_p);
3708 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3710 copyin_seq = NULL;
3711 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3712 &copyin_seq, ctx);
3714 t = build_fold_addr_expr (ctx->sender_decl);
3715 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3716 gimplify_and_add (t, pre_p);
3718 t = build_and_jump (&l2);
3719 gimplify_and_add (t, pre_p);
3721 t = build1 (LABEL_EXPR, void_type_node, l1);
3722 gimplify_and_add (t, pre_p);
3724 append_to_statement_list (copyin_seq, pre_p);
3726 t = build1 (LABEL_EXPR, void_type_node, l2);
3727 gimplify_and_add (t, pre_p);
3731 /* Expand code for an OpenMP single directive. */
3733 static void
3734 lower_omp_single (tree *stmt_p, omp_context *ctx)
3736 tree t, bind, block, single_stmt = *stmt_p, dlist;
3738 push_gimplify_context ();
3740 block = make_node (BLOCK);
3741 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3742 TREE_SIDE_EFFECTS (bind) = 1;
3744 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3745 &BIND_EXPR_BODY (bind), &dlist, ctx);
3746 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3748 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3750 if (ctx->record_type)
3751 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3752 else
3753 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3755 OMP_SINGLE_BODY (single_stmt) = NULL;
3757 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3759 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3761 t = make_node (OMP_RETURN);
3762 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3763 OMP_CLAUSE_NOWAIT);
3764 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3766 pop_gimplify_context (bind);
3768 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3769 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3773 /* Expand code for an OpenMP master directive. */
3775 static void
3776 lower_omp_master (tree *stmt_p, omp_context *ctx)
3778 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3780 push_gimplify_context ();
3782 block = make_node (BLOCK);
3783 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3784 TREE_SIDE_EFFECTS (bind) = 1;
3786 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3788 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3789 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3790 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3791 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3793 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3794 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3795 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3796 OMP_MASTER_BODY (stmt) = NULL;
3798 x = build1 (LABEL_EXPR, void_type_node, lab);
3799 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3801 x = make_node (OMP_RETURN);
3802 OMP_RETURN_NOWAIT (x) = 1;
3803 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3805 pop_gimplify_context (bind);
3807 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3808 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3812 /* Expand code for an OpenMP ordered directive. */
3814 static void
3815 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3817 tree bind, block, stmt = *stmt_p, x;
3819 push_gimplify_context ();
3821 block = make_node (BLOCK);
3822 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3823 TREE_SIDE_EFFECTS (bind) = 1;
3825 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3827 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
3828 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3830 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3831 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3832 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3833 OMP_ORDERED_BODY (stmt) = NULL;
3835 x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
3836 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3838 x = make_node (OMP_RETURN);
3839 OMP_RETURN_NOWAIT (x) = 1;
3840 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3842 pop_gimplify_context (bind);
3844 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3845 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3849 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3850 substitution of a couple of function calls. But in the NAMED case,
3851 requires that languages coordinate a symbol name. It is therefore
3852 best put here in common code. */
3854 static GTY((param1_is (tree), param2_is (tree)))
3855 splay_tree critical_name_mutexes;
3857 static void
3858 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3860 tree bind, block, stmt = *stmt_p;
3861 tree t, lock, unlock, name;
3863 name = OMP_CRITICAL_NAME (stmt);
3864 if (name)
3866 tree decl;
3867 splay_tree_node n;
3869 if (!critical_name_mutexes)
3870 critical_name_mutexes
3871 = splay_tree_new_ggc (splay_tree_compare_pointers);
3873 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3874 if (n == NULL)
3876 char *new_str;
3878 decl = create_tmp_var_raw (ptr_type_node, NULL);
3880 new_str = ACONCAT ((".gomp_critical_user_",
3881 IDENTIFIER_POINTER (name), NULL));
3882 DECL_NAME (decl) = get_identifier (new_str);
3883 TREE_PUBLIC (decl) = 1;
3884 TREE_STATIC (decl) = 1;
3885 DECL_COMMON (decl) = 1;
3886 DECL_ARTIFICIAL (decl) = 1;
3887 DECL_IGNORED_P (decl) = 1;
3888 varpool_finalize_decl (decl);
3890 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3891 (splay_tree_value) decl);
3893 else
3894 decl = (tree) n->value;
3896 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3897 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
3899 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3900 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
3902 else
3904 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3905 lock = build_call_expr (lock, 0);
3907 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3908 unlock = build_call_expr (unlock, 0);
3911 push_gimplify_context ();
3913 block = make_node (BLOCK);
3914 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3915 TREE_SIDE_EFFECTS (bind) = 1;
3917 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3919 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3921 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3922 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3923 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3924 OMP_CRITICAL_BODY (stmt) = NULL;
3926 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3928 t = make_node (OMP_RETURN);
3929 OMP_RETURN_NOWAIT (t) = 1;
3930 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3932 pop_gimplify_context (bind);
3933 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3934 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3938 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3939 for a lastprivate clause. Given a loop control predicate of (V
3940 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3941 is appended to *DLIST, iterator initialization is appended to
3942 *BODY_P. */
3944 static void
3945 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3946 tree *dlist, struct omp_context *ctx)
3948 tree clauses, cond, stmts, vinit, t;
3949 enum tree_code cond_code;
3951 cond_code = fd->cond_code;
3952 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3954 /* When possible, use a strict equality expression. This can let VRP
3955 type optimizations deduce the value and remove a copy. */
3956 if (host_integerp (fd->step, 0))
3958 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3959 if (step == 1 || step == -1)
3960 cond_code = EQ_EXPR;
3963 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3965 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3966 stmts = NULL;
3967 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
3968 if (stmts != NULL)
3970 append_to_statement_list (stmts, dlist);
3972 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
3973 vinit = fd->n1;
3974 if (cond_code == EQ_EXPR
3975 && host_integerp (fd->n2, 0)
3976 && ! integer_zerop (fd->n2))
3977 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
3979 /* Initialize the iterator variable, so that threads that don't execute
3980 any iterations don't execute the lastprivate clauses by accident. */
3981 t = build_gimple_modify_stmt (fd->v, vinit);
3982 gimplify_and_add (t, body_p);
3987 /* Lower code for an OpenMP loop directive. */
3989 static void
3990 lower_omp_for (tree *stmt_p, omp_context *ctx)
3992 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3993 struct omp_for_data fd;
3995 stmt = *stmt_p;
3997 push_gimplify_context ();
3999 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4000 lower_omp (&OMP_FOR_BODY (stmt), ctx);
4002 /* Move declaration of temporaries in the loop body before we make
4003 it go away. */
4004 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4005 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4007 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4008 TREE_SIDE_EFFECTS (new_stmt) = 1;
4009 body_p = &BIND_EXPR_BODY (new_stmt);
4011 /* The pre-body and input clauses go before the lowered OMP_FOR. */
4012 ilist = NULL;
4013 dlist = NULL;
4014 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4015 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4017 /* Lower the header expressions. At this point, we can assume that
4018 the header is of the form:
4020 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4022 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4023 using the .omp_data_s mapping, if needed. */
4024 rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4025 if (!is_gimple_min_invariant (*rhs_p))
4026 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4028 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4029 if (!is_gimple_min_invariant (*rhs_p))
4030 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4032 rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4033 if (!is_gimple_min_invariant (*rhs_p))
4034 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4036 /* Once lowered, extract the bounds and clauses. */
4037 extract_omp_for_data (stmt, &fd);
4039 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4041 append_to_statement_list (stmt, body_p);
4043 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4045 t = build2 (OMP_CONTINUE, void_type_node, fd.v, fd.v);
4046 append_to_statement_list (t, body_p);
4048 /* After the loop, add exit clauses. */
4049 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4050 append_to_statement_list (dlist, body_p);
4052 maybe_catch_exception (body_p);
4054 /* Region exit marker goes at the end of the loop body. */
4055 t = make_node (OMP_RETURN);
4056 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4057 append_to_statement_list (t, body_p);
4059 pop_gimplify_context (NULL_TREE);
4060 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4062 OMP_FOR_BODY (stmt) = NULL_TREE;
4063 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4064 *stmt_p = new_stmt;
4067 /* Callback for walk_stmts. Check if *TP only contains OMP_FOR
4068 or OMP_PARALLEL. */
4070 static tree
4071 check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4073 struct walk_stmt_info *wi = data;
4074 int *info = wi->info;
4076 *walk_subtrees = 0;
4077 switch (TREE_CODE (*tp))
4079 case OMP_FOR:
4080 case OMP_SECTIONS:
4081 *info = *info == 0 ? 1 : -1;
4082 break;
4083 default:
4084 *info = -1;
4085 break;
4087 return NULL;
4090 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
4091 information for the directive. */
4093 static void
4094 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4096 tree clauses, par_bind, par_body, new_body, bind;
4097 tree olist, ilist, par_olist, par_ilist;
4098 tree stmt, child_fn, t;
4100 stmt = *stmt_p;
4102 clauses = OMP_PARALLEL_CLAUSES (stmt);
4103 par_bind = OMP_PARALLEL_BODY (stmt);
4104 par_body = BIND_EXPR_BODY (par_bind);
4105 child_fn = ctx->cb.dst_fn;
4106 if (!OMP_PARALLEL_COMBINED (stmt))
4108 struct walk_stmt_info wi;
4109 int ws_num = 0;
4111 memset (&wi, 0, sizeof (wi));
4112 wi.callback = check_combined_parallel;
4113 wi.info = &ws_num;
4114 wi.val_only = true;
4115 walk_stmts (&wi, &par_bind);
4116 if (ws_num == 1)
4117 OMP_PARALLEL_COMBINED (stmt) = 1;
4120 push_gimplify_context ();
4122 par_olist = NULL_TREE;
4123 par_ilist = NULL_TREE;
4124 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4125 lower_omp (&par_body, ctx);
4126 lower_reduction_clauses (clauses, &par_olist, ctx);
4128 /* Declare all the variables created by mapping and the variables
4129 declared in the scope of the parallel body. */
4130 record_vars_into (ctx->block_vars, child_fn);
4131 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4133 if (ctx->record_type)
4135 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4136 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4139 olist = NULL_TREE;
4140 ilist = NULL_TREE;
4141 lower_send_clauses (clauses, &ilist, &olist, ctx);
4142 lower_send_shared_vars (&ilist, &olist, ctx);
4144 /* Once all the expansions are done, sequence all the different
4145 fragments inside OMP_PARALLEL_BODY. */
4146 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4147 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4149 new_body = alloc_stmt_list ();
4151 if (ctx->record_type)
4153 t = build_fold_addr_expr (ctx->sender_decl);
4154 /* fixup_child_record_type might have changed receiver_decl's type. */
4155 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4156 t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4157 append_to_statement_list (t, &new_body);
4160 append_to_statement_list (par_ilist, &new_body);
4161 append_to_statement_list (par_body, &new_body);
4162 append_to_statement_list (par_olist, &new_body);
4163 maybe_catch_exception (&new_body);
4164 t = make_node (OMP_RETURN);
4165 append_to_statement_list (t, &new_body);
4166 OMP_PARALLEL_BODY (stmt) = new_body;
4168 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4169 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4171 *stmt_p = bind;
4173 pop_gimplify_context (NULL_TREE);
4177 /* Pass *TP back through the gimplifier within the context determined by WI.
4178 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4179 flags on ADDR_EXPR. */
4181 static void
4182 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4184 enum gimplify_status gs;
4185 tree pre = NULL;
4187 if (wi->is_lhs)
4188 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4189 else if (wi->val_only)
4190 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4191 else
4192 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4193 gcc_assert (gs == GS_ALL_DONE);
4195 if (pre)
4196 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4199 /* Copy EXP into a temporary. Insert the initialization statement before TSI. */
4201 static tree
4202 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4204 tree t, stmt;
4206 t = create_tmp_var (TREE_TYPE (exp), NULL);
4207 DECL_GIMPLE_REG_P (t) = 1;
4208 stmt = build_gimple_modify_stmt (t, exp);
4209 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4210 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4212 return t;
4215 /* Similarly, but copy from the temporary and insert the statement
4216 after the iterator. */
4218 static tree
4219 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4221 tree t, stmt;
4223 t = create_tmp_var (TREE_TYPE (exp), NULL);
4224 DECL_GIMPLE_REG_P (t) = 1;
4225 stmt = build_gimple_modify_stmt (exp, t);
4226 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4227 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4229 return t;
4232 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4234 static tree
4235 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4237 struct walk_stmt_info *wi = data;
4238 omp_context *ctx = wi->info;
4239 tree t = *tp;
4241 /* If we have issued syntax errors, avoid doing any heavy lifting.
4242 Just replace the OpenMP directives with a NOP to avoid
4243 confusing RTL expansion. */
4244 if (errorcount && OMP_DIRECTIVE_P (*tp))
4246 *tp = build_empty_stmt ();
4247 return NULL_TREE;
4250 *walk_subtrees = 0;
4251 switch (TREE_CODE (*tp))
4253 case OMP_PARALLEL:
4254 ctx = maybe_lookup_ctx (t);
4255 lower_omp_parallel (tp, ctx);
4256 break;
4258 case OMP_FOR:
4259 ctx = maybe_lookup_ctx (t);
4260 gcc_assert (ctx);
4261 lower_omp_for (tp, ctx);
4262 break;
4264 case OMP_SECTIONS:
4265 ctx = maybe_lookup_ctx (t);
4266 gcc_assert (ctx);
4267 lower_omp_sections (tp, ctx);
4268 break;
4270 case OMP_SINGLE:
4271 ctx = maybe_lookup_ctx (t);
4272 gcc_assert (ctx);
4273 lower_omp_single (tp, ctx);
4274 break;
4276 case OMP_MASTER:
4277 ctx = maybe_lookup_ctx (t);
4278 gcc_assert (ctx);
4279 lower_omp_master (tp, ctx);
4280 break;
4282 case OMP_ORDERED:
4283 ctx = maybe_lookup_ctx (t);
4284 gcc_assert (ctx);
4285 lower_omp_ordered (tp, ctx);
4286 break;
4288 case OMP_CRITICAL:
4289 ctx = maybe_lookup_ctx (t);
4290 gcc_assert (ctx);
4291 lower_omp_critical (tp, ctx);
4292 break;
4294 case VAR_DECL:
4295 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4297 lower_regimplify (&t, wi);
4298 if (wi->val_only)
4300 if (wi->is_lhs)
4301 t = save_tmp_var (t, &wi->tsi);
4302 else
4303 t = init_tmp_var (t, &wi->tsi);
4305 *tp = t;
4307 break;
4309 case ADDR_EXPR:
4310 if (ctx)
4311 lower_regimplify (tp, wi);
4312 break;
4314 case ARRAY_REF:
4315 case ARRAY_RANGE_REF:
4316 case REALPART_EXPR:
4317 case IMAGPART_EXPR:
4318 case COMPONENT_REF:
4319 case VIEW_CONVERT_EXPR:
4320 if (ctx)
4321 lower_regimplify (tp, wi);
4322 break;
4324 case INDIRECT_REF:
4325 if (ctx)
4327 wi->is_lhs = false;
4328 wi->val_only = true;
4329 lower_regimplify (&TREE_OPERAND (t, 0), wi);
4331 break;
4333 default:
4334 if (!TYPE_P (t) && !DECL_P (t))
4335 *walk_subtrees = 1;
4336 break;
4339 return NULL_TREE;
4342 static void
4343 lower_omp (tree *stmt_p, omp_context *ctx)
4345 struct walk_stmt_info wi;
4347 memset (&wi, 0, sizeof (wi));
4348 wi.callback = lower_omp_1;
4349 wi.info = ctx;
4350 wi.val_only = true;
4351 wi.want_locations = true;
4353 walk_stmts (&wi, stmt_p);
4356 /* Main entry point. */
4358 static unsigned int
4359 execute_lower_omp (void)
4361 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4362 delete_omp_context);
4364 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4365 gcc_assert (parallel_nesting_level == 0);
4367 if (all_contexts->root)
4368 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4370 if (all_contexts)
4372 splay_tree_delete (all_contexts);
4373 all_contexts = NULL;
4375 return 0;
4378 static bool
4379 gate_lower_omp (void)
4381 return flag_openmp != 0;
4384 struct tree_opt_pass pass_lower_omp =
4386 "omplower", /* name */
4387 gate_lower_omp, /* gate */
4388 execute_lower_omp, /* execute */
4389 NULL, /* sub */
4390 NULL, /* next */
4391 0, /* static_pass_number */
4392 0, /* tv_id */
4393 PROP_gimple_any, /* properties_required */
4394 PROP_gimple_lomp, /* properties_provided */
4395 0, /* properties_destroyed */
4396 0, /* todo_flags_start */
4397 TODO_dump_func, /* todo_flags_finish */
4398 0 /* letter */
4401 /* The following is a utility to diagnose OpenMP structured block violations.
4402 It is not part of the "omplower" pass, as that's invoked too late. It
4403 should be invoked by the respective front ends after gimplification. */
4405 static splay_tree all_labels;
4407 /* Check for mismatched contexts and generate an error if needed. Return
4408 true if an error is detected. */
4410 static bool
4411 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4413 bool exit_p = true;
4415 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4416 return false;
4418 /* Try to avoid confusing the user by producing and error message
4419 with correct "exit" or "enter" verbage. We prefer "exit"
4420 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4421 if (branch_ctx == NULL)
4422 exit_p = false;
4423 else
4425 while (label_ctx)
4427 if (TREE_VALUE (label_ctx) == branch_ctx)
4429 exit_p = false;
4430 break;
4432 label_ctx = TREE_CHAIN (label_ctx);
4436 if (exit_p)
4437 error ("invalid exit from OpenMP structured block");
4438 else
4439 error ("invalid entry to OpenMP structured block");
4441 *stmt_p = build_empty_stmt ();
4442 return true;
4445 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4446 where in the tree each label is found. */
4448 static tree
4449 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4451 struct walk_stmt_info *wi = data;
4452 tree context = (tree) wi->info;
4453 tree inner_context;
4454 tree t = *tp;
4456 *walk_subtrees = 0;
4457 switch (TREE_CODE (t))
4459 case OMP_PARALLEL:
4460 case OMP_SECTIONS:
4461 case OMP_SINGLE:
4462 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4463 /* FALLTHRU */
4464 case OMP_SECTION:
4465 case OMP_MASTER:
4466 case OMP_ORDERED:
4467 case OMP_CRITICAL:
4468 /* The minimal context here is just a tree of statements. */
4469 inner_context = tree_cons (NULL, t, context);
4470 wi->info = inner_context;
4471 walk_stmts (wi, &OMP_BODY (t));
4472 wi->info = context;
4473 break;
4475 case OMP_FOR:
4476 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4477 inner_context = tree_cons (NULL, t, context);
4478 wi->info = inner_context;
4479 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4480 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4481 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4482 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4483 walk_stmts (wi, &OMP_FOR_BODY (t));
4484 wi->info = context;
4485 break;
4487 case LABEL_EXPR:
4488 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4489 (splay_tree_value) context);
4490 break;
4492 default:
4493 break;
4496 return NULL_TREE;
4499 /* Pass 2: Check each branch and see if its context differs from that of
4500 the destination label's context. */
4502 static tree
4503 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4505 struct walk_stmt_info *wi = data;
4506 tree context = (tree) wi->info;
4507 splay_tree_node n;
4508 tree t = *tp;
4510 *walk_subtrees = 0;
4511 switch (TREE_CODE (t))
4513 case OMP_PARALLEL:
4514 case OMP_SECTIONS:
4515 case OMP_SINGLE:
4516 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4517 /* FALLTHRU */
4518 case OMP_SECTION:
4519 case OMP_MASTER:
4520 case OMP_ORDERED:
4521 case OMP_CRITICAL:
4522 wi->info = t;
4523 walk_stmts (wi, &OMP_BODY (t));
4524 wi->info = context;
4525 break;
4527 case OMP_FOR:
4528 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4529 wi->info = t;
4530 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4531 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4532 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4533 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4534 walk_stmts (wi, &OMP_FOR_BODY (t));
4535 wi->info = context;
4536 break;
4538 case GOTO_EXPR:
4540 tree lab = GOTO_DESTINATION (t);
4541 if (TREE_CODE (lab) != LABEL_DECL)
4542 break;
4544 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4545 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4547 break;
4549 case SWITCH_EXPR:
4551 tree vec = SWITCH_LABELS (t);
4552 int i, len = TREE_VEC_LENGTH (vec);
4553 for (i = 0; i < len; ++i)
4555 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4556 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4557 if (diagnose_sb_0 (tp, context, (tree) n->value))
4558 break;
4561 break;
4563 case RETURN_EXPR:
4564 diagnose_sb_0 (tp, context, NULL_TREE);
4565 break;
4567 default:
4568 break;
4571 return NULL_TREE;
4574 void
4575 diagnose_omp_structured_block_errors (tree fndecl)
4577 tree save_current = current_function_decl;
4578 struct walk_stmt_info wi;
4580 current_function_decl = fndecl;
4582 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4584 memset (&wi, 0, sizeof (wi));
4585 wi.callback = diagnose_sb_1;
4586 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4588 memset (&wi, 0, sizeof (wi));
4589 wi.callback = diagnose_sb_2;
4590 wi.want_locations = true;
4591 wi.want_return_expr = true;
4592 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4594 splay_tree_delete (all_labels);
4595 all_labels = NULL;
4597 current_function_decl = save_current;
4600 #include "gt-omp-low.h"