gcc/:
[official-gcc.git] / gcc / omp-low.c
blob5a25e95c33aa00d9999cdc3be06db4ac889b5ae3
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005, 2006, 2007, 2008, 2009 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 "gimple.h"
31 #include "tree-iterator.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
36 #include "timevar.h"
37 #include "flags.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "toplev.h"
41 #include "tree-pass.h"
42 #include "ggc.h"
43 #include "except.h"
44 #include "splay-tree.h"
45 #include "optabs.h"
46 #include "cfgloop.h"
49 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
50 phases. The first phase scans the function looking for OMP statements
51 and then for variables that must be replaced to satisfy data sharing
52 clauses. The second phase expands code for the constructs, as well as
53 re-gimplifying things when variables have been replaced with complex
54 expressions.
56 Final code generation is done by pass_expand_omp. The flowgraph is
57 scanned for parallel regions which are then moved to a new
58 function, to be invoked by the thread library. */
60 /* Context structure. Used to store information about each parallel
61 directive in the code. */
63 typedef struct omp_context
65 /* This field must be at the beginning, as we do "inheritance": Some
66 callback functions for tree-inline.c (e.g., omp_copy_decl)
67 receive a copy_body_data pointer that is up-casted to an
68 omp_context pointer. */
69 copy_body_data cb;
71 /* The tree of contexts corresponding to the encountered constructs. */
72 struct omp_context *outer;
73 gimple stmt;
75 /* Map variables to fields in a structure that allows communication
76 between sending and receiving threads. */
77 splay_tree field_map;
78 tree record_type;
79 tree sender_decl;
80 tree receiver_decl;
82 /* These are used just by task contexts, if task firstprivate fn is
83 needed. srecord_type is used to communicate from the thread
84 that encountered the task construct to task firstprivate fn,
85 record_type is allocated by GOMP_task, initialized by task firstprivate
86 fn and passed to the task body fn. */
87 splay_tree sfield_map;
88 tree srecord_type;
90 /* A chain of variables to add to the top-level block surrounding the
91 construct. In the case of a parallel, this is in the child function. */
92 tree block_vars;
94 /* What to do with variables with implicitly determined sharing
95 attributes. */
96 enum omp_clause_default_kind default_kind;
98 /* Nesting depth of this context. Used to beautify error messages re
99 invalid gotos. The outermost ctx is depth 1, with depth 0 being
100 reserved for the main body of the function. */
101 int depth;
103 /* True if this parallel directive is nested within another. */
104 bool is_nested;
105 } omp_context;
108 struct omp_for_data_loop
110 tree v, n1, n2, step;
111 enum tree_code cond_code;
114 /* A structure describing the main elements of a parallel loop. */
116 struct omp_for_data
118 struct omp_for_data_loop loop;
119 tree chunk_size;
120 gimple for_stmt;
121 tree pre, iter_type;
122 int collapse;
123 bool have_nowait, have_ordered;
124 enum omp_clause_schedule_kind sched_kind;
125 struct omp_for_data_loop *loops;
129 static splay_tree all_contexts;
130 static int taskreg_nesting_level;
131 struct omp_region *root_omp_region;
132 static bitmap task_shared_vars;
134 static void scan_omp (gimple_seq, omp_context *);
135 static tree scan_omp_1_op (tree *, int *, void *);
137 #define WALK_SUBSTMTS \
138 case GIMPLE_BIND: \
139 case GIMPLE_TRY: \
140 case GIMPLE_CATCH: \
141 case GIMPLE_EH_FILTER: \
142 /* The sub-statements for these should be walked. */ \
143 *handled_ops_p = false; \
144 break;
146 /* Convenience function for calling scan_omp_1_op on tree operands. */
148 static inline tree
149 scan_omp_op (tree *tp, omp_context *ctx)
151 struct walk_stmt_info wi;
153 memset (&wi, 0, sizeof (wi));
154 wi.info = ctx;
155 wi.want_locations = true;
157 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
160 static void lower_omp (gimple_seq, omp_context *);
161 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
162 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
164 /* Find an OpenMP clause of type KIND within CLAUSES. */
166 tree
167 find_omp_clause (tree clauses, enum omp_clause_code kind)
169 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
170 if (OMP_CLAUSE_CODE (clauses) == kind)
171 return clauses;
173 return NULL_TREE;
176 /* Return true if CTX is for an omp parallel. */
178 static inline bool
179 is_parallel_ctx (omp_context *ctx)
181 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
185 /* Return true if CTX is for an omp task. */
187 static inline bool
188 is_task_ctx (omp_context *ctx)
190 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
194 /* Return true if CTX is for an omp parallel or omp task. */
196 static inline bool
197 is_taskreg_ctx (omp_context *ctx)
199 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
200 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
204 /* Return true if REGION is a combined parallel+workshare region. */
206 static inline bool
207 is_combined_parallel (struct omp_region *region)
209 return region->is_combined_parallel;
213 /* Extract the header elements of parallel loop FOR_STMT and store
214 them into *FD. */
216 static void
217 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
218 struct omp_for_data_loop *loops)
220 tree t, var, *collapse_iter, *collapse_count;
221 tree count = NULL_TREE, iter_type = long_integer_type_node;
222 struct omp_for_data_loop *loop;
223 int i;
224 struct omp_for_data_loop dummy_loop;
226 fd->for_stmt = for_stmt;
227 fd->pre = NULL;
228 fd->collapse = gimple_omp_for_collapse (for_stmt);
229 if (fd->collapse > 1)
230 fd->loops = loops;
231 else
232 fd->loops = &fd->loop;
234 fd->have_nowait = fd->have_ordered = false;
235 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
236 fd->chunk_size = NULL_TREE;
237 collapse_iter = NULL;
238 collapse_count = NULL;
240 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
241 switch (OMP_CLAUSE_CODE (t))
243 case OMP_CLAUSE_NOWAIT:
244 fd->have_nowait = true;
245 break;
246 case OMP_CLAUSE_ORDERED:
247 fd->have_ordered = true;
248 break;
249 case OMP_CLAUSE_SCHEDULE:
250 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
251 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
252 break;
253 case OMP_CLAUSE_COLLAPSE:
254 if (fd->collapse > 1)
256 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
257 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
259 default:
260 break;
263 /* FIXME: for now map schedule(auto) to schedule(static).
264 There should be analysis to determine whether all iterations
265 are approximately the same amount of work (then schedule(static)
266 is best) or if it varies (then schedule(dynamic,N) is better). */
267 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
269 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
270 gcc_assert (fd->chunk_size == NULL);
272 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
273 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
274 gcc_assert (fd->chunk_size == NULL);
275 else if (fd->chunk_size == NULL)
277 /* We only need to compute a default chunk size for ordered
278 static loops and dynamic loops. */
279 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
280 || fd->have_ordered
281 || fd->collapse > 1)
282 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
283 ? integer_zero_node : integer_one_node;
286 for (i = 0; i < fd->collapse; i++)
288 if (fd->collapse == 1)
289 loop = &fd->loop;
290 else if (loops != NULL)
291 loop = loops + i;
292 else
293 loop = &dummy_loop;
296 loop->v = gimple_omp_for_index (for_stmt, i);
297 gcc_assert (SSA_VAR_P (loop->v));
298 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
299 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
300 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
301 loop->n1 = gimple_omp_for_initial (for_stmt, i);
303 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
304 loop->n2 = gimple_omp_for_final (for_stmt, i);
305 switch (loop->cond_code)
307 case LT_EXPR:
308 case GT_EXPR:
309 break;
310 case LE_EXPR:
311 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
312 loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
313 loop->n2, size_one_node);
314 else
315 loop->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
316 build_int_cst (TREE_TYPE (loop->n2), 1));
317 loop->cond_code = LT_EXPR;
318 break;
319 case GE_EXPR:
320 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
321 loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
322 loop->n2, size_int (-1));
323 else
324 loop->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
325 build_int_cst (TREE_TYPE (loop->n2), 1));
326 loop->cond_code = GT_EXPR;
327 break;
328 default:
329 gcc_unreachable ();
332 t = gimple_omp_for_incr (for_stmt, i);
333 gcc_assert (TREE_OPERAND (t, 0) == var);
334 switch (TREE_CODE (t))
336 case PLUS_EXPR:
337 case POINTER_PLUS_EXPR:
338 loop->step = TREE_OPERAND (t, 1);
339 break;
340 case MINUS_EXPR:
341 loop->step = TREE_OPERAND (t, 1);
342 loop->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (loop->step),
343 loop->step);
344 break;
345 default:
346 gcc_unreachable ();
349 if (iter_type != long_long_unsigned_type_node)
351 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
352 iter_type = long_long_unsigned_type_node;
353 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
354 && TYPE_PRECISION (TREE_TYPE (loop->v))
355 >= TYPE_PRECISION (iter_type))
357 tree n;
359 if (loop->cond_code == LT_EXPR)
360 n = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
361 loop->n2, loop->step);
362 else
363 n = loop->n1;
364 if (TREE_CODE (n) != INTEGER_CST
365 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
366 iter_type = long_long_unsigned_type_node;
368 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
369 > TYPE_PRECISION (iter_type))
371 tree n1, n2;
373 if (loop->cond_code == LT_EXPR)
375 n1 = loop->n1;
376 n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
377 loop->n2, loop->step);
379 else
381 n1 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->v),
382 loop->n2, loop->step);
383 n2 = loop->n1;
385 if (TREE_CODE (n1) != INTEGER_CST
386 || TREE_CODE (n2) != INTEGER_CST
387 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
388 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
389 iter_type = long_long_unsigned_type_node;
393 if (collapse_count && *collapse_count == NULL)
395 if ((i == 0 || count != NULL_TREE)
396 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
397 && TREE_CONSTANT (loop->n1)
398 && TREE_CONSTANT (loop->n2)
399 && TREE_CODE (loop->step) == INTEGER_CST)
401 tree itype = TREE_TYPE (loop->v);
403 if (POINTER_TYPE_P (itype))
404 itype
405 = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
406 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
407 t = fold_build2 (PLUS_EXPR, itype,
408 fold_convert (itype, loop->step), t);
409 t = fold_build2 (PLUS_EXPR, itype, t,
410 fold_convert (itype, loop->n2));
411 t = fold_build2 (MINUS_EXPR, itype, t,
412 fold_convert (itype, loop->n1));
413 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
414 t = fold_build2 (TRUNC_DIV_EXPR, itype,
415 fold_build1 (NEGATE_EXPR, itype, t),
416 fold_build1 (NEGATE_EXPR, itype,
417 fold_convert (itype,
418 loop->step)));
419 else
420 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
421 fold_convert (itype, loop->step));
422 t = fold_convert (long_long_unsigned_type_node, t);
423 if (count != NULL_TREE)
424 count = fold_build2 (MULT_EXPR, long_long_unsigned_type_node,
425 count, t);
426 else
427 count = t;
428 if (TREE_CODE (count) != INTEGER_CST)
429 count = NULL_TREE;
431 else
432 count = NULL_TREE;
436 if (count)
438 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
439 iter_type = long_long_unsigned_type_node;
440 else
441 iter_type = long_integer_type_node;
443 else if (collapse_iter && *collapse_iter != NULL)
444 iter_type = TREE_TYPE (*collapse_iter);
445 fd->iter_type = iter_type;
446 if (collapse_iter && *collapse_iter == NULL)
447 *collapse_iter = create_tmp_var (iter_type, ".iter");
448 if (collapse_count && *collapse_count == NULL)
450 if (count)
451 *collapse_count = fold_convert (iter_type, count);
452 else
453 *collapse_count = create_tmp_var (iter_type, ".count");
456 if (fd->collapse > 1)
458 fd->loop.v = *collapse_iter;
459 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
460 fd->loop.n2 = *collapse_count;
461 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
462 fd->loop.cond_code = LT_EXPR;
467 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
468 is the immediate dominator of PAR_ENTRY_BB, return true if there
469 are no data dependencies that would prevent expanding the parallel
470 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
472 When expanding a combined parallel+workshare region, the call to
473 the child function may need additional arguments in the case of
474 GIMPLE_OMP_FOR regions. In some cases, these arguments are
475 computed out of variables passed in from the parent to the child
476 via 'struct .omp_data_s'. For instance:
478 #pragma omp parallel for schedule (guided, i * 4)
479 for (j ...)
481 Is lowered into:
483 # BLOCK 2 (PAR_ENTRY_BB)
484 .omp_data_o.i = i;
485 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
487 # BLOCK 3 (WS_ENTRY_BB)
488 .omp_data_i = &.omp_data_o;
489 D.1667 = .omp_data_i->i;
490 D.1598 = D.1667 * 4;
491 #pragma omp for schedule (guided, D.1598)
493 When we outline the parallel region, the call to the child function
494 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
495 that value is computed *after* the call site. So, in principle we
496 cannot do the transformation.
498 To see whether the code in WS_ENTRY_BB blocks the combined
499 parallel+workshare call, we collect all the variables used in the
500 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
501 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
502 call.
504 FIXME. If we had the SSA form built at this point, we could merely
505 hoist the code in block 3 into block 2 and be done with it. But at
506 this point we don't have dataflow information and though we could
507 hack something up here, it is really not worth the aggravation. */
509 static bool
510 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
512 struct omp_for_data fd;
513 gimple par_stmt, ws_stmt;
515 par_stmt = last_stmt (par_entry_bb);
516 ws_stmt = last_stmt (ws_entry_bb);
518 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
519 return true;
521 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
523 extract_omp_for_data (ws_stmt, &fd, NULL);
525 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
526 return false;
527 if (fd.iter_type != long_integer_type_node)
528 return false;
530 /* FIXME. We give up too easily here. If any of these arguments
531 are not constants, they will likely involve variables that have
532 been mapped into fields of .omp_data_s for sharing with the child
533 function. With appropriate data flow, it would be possible to
534 see through this. */
535 if (!is_gimple_min_invariant (fd.loop.n1)
536 || !is_gimple_min_invariant (fd.loop.n2)
537 || !is_gimple_min_invariant (fd.loop.step)
538 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
539 return false;
541 return true;
545 /* Collect additional arguments needed to emit a combined
546 parallel+workshare call. WS_STMT is the workshare directive being
547 expanded. */
549 static tree
550 get_ws_args_for (gimple ws_stmt)
552 tree t;
554 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
556 struct omp_for_data fd;
557 tree ws_args;
559 extract_omp_for_data (ws_stmt, &fd, NULL);
561 ws_args = NULL_TREE;
562 if (fd.chunk_size)
564 t = fold_convert (long_integer_type_node, fd.chunk_size);
565 ws_args = tree_cons (NULL, t, ws_args);
568 t = fold_convert (long_integer_type_node, fd.loop.step);
569 ws_args = tree_cons (NULL, t, ws_args);
571 t = fold_convert (long_integer_type_node, fd.loop.n2);
572 ws_args = tree_cons (NULL, t, ws_args);
574 t = fold_convert (long_integer_type_node, fd.loop.n1);
575 ws_args = tree_cons (NULL, t, ws_args);
577 return ws_args;
579 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
581 /* Number of sections is equal to the number of edges from the
582 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
583 the exit of the sections region. */
584 basic_block bb = single_succ (gimple_bb (ws_stmt));
585 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
586 t = tree_cons (NULL, t, NULL);
587 return t;
590 gcc_unreachable ();
594 /* Discover whether REGION is a combined parallel+workshare region. */
596 static void
597 determine_parallel_type (struct omp_region *region)
599 basic_block par_entry_bb, par_exit_bb;
600 basic_block ws_entry_bb, ws_exit_bb;
602 if (region == NULL || region->inner == NULL
603 || region->exit == NULL || region->inner->exit == NULL
604 || region->inner->cont == NULL)
605 return;
607 /* We only support parallel+for and parallel+sections. */
608 if (region->type != GIMPLE_OMP_PARALLEL
609 || (region->inner->type != GIMPLE_OMP_FOR
610 && region->inner->type != GIMPLE_OMP_SECTIONS))
611 return;
613 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
614 WS_EXIT_BB -> PAR_EXIT_BB. */
615 par_entry_bb = region->entry;
616 par_exit_bb = region->exit;
617 ws_entry_bb = region->inner->entry;
618 ws_exit_bb = region->inner->exit;
620 if (single_succ (par_entry_bb) == ws_entry_bb
621 && single_succ (ws_exit_bb) == par_exit_bb
622 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
623 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
624 || (last_and_only_stmt (ws_entry_bb)
625 && last_and_only_stmt (par_exit_bb))))
627 gimple ws_stmt = last_stmt (ws_entry_bb);
629 if (region->inner->type == GIMPLE_OMP_FOR)
631 /* If this is a combined parallel loop, we need to determine
632 whether or not to use the combined library calls. There
633 are two cases where we do not apply the transformation:
634 static loops and any kind of ordered loop. In the first
635 case, we already open code the loop so there is no need
636 to do anything else. In the latter case, the combined
637 parallel loop call would still need extra synchronization
638 to implement ordered semantics, so there would not be any
639 gain in using the combined call. */
640 tree clauses = gimple_omp_for_clauses (ws_stmt);
641 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
642 if (c == NULL
643 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
644 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
646 region->is_combined_parallel = false;
647 region->inner->is_combined_parallel = false;
648 return;
652 region->is_combined_parallel = true;
653 region->inner->is_combined_parallel = true;
654 region->ws_args = get_ws_args_for (ws_stmt);
659 /* Return true if EXPR is variable sized. */
661 static inline bool
662 is_variable_sized (const_tree expr)
664 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
667 /* Return true if DECL is a reference type. */
669 static inline bool
670 is_reference (tree decl)
672 return lang_hooks.decls.omp_privatize_by_reference (decl);
675 /* Lookup variables in the decl or field splay trees. The "maybe" form
676 allows for the variable form to not have been entered, otherwise we
677 assert that the variable must have been entered. */
679 static inline tree
680 lookup_decl (tree var, omp_context *ctx)
682 tree *n;
683 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
684 return *n;
687 static inline tree
688 maybe_lookup_decl (const_tree var, omp_context *ctx)
690 tree *n;
691 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
692 return n ? *n : NULL_TREE;
695 static inline tree
696 lookup_field (tree var, omp_context *ctx)
698 splay_tree_node n;
699 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
700 return (tree) n->value;
703 static inline tree
704 lookup_sfield (tree var, omp_context *ctx)
706 splay_tree_node n;
707 n = splay_tree_lookup (ctx->sfield_map
708 ? ctx->sfield_map : ctx->field_map,
709 (splay_tree_key) var);
710 return (tree) n->value;
713 static inline tree
714 maybe_lookup_field (tree var, omp_context *ctx)
716 splay_tree_node n;
717 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
718 return n ? (tree) n->value : NULL_TREE;
721 /* Return true if DECL should be copied by pointer. SHARED_CTX is
722 the parallel context if DECL is to be shared. */
724 static bool
725 use_pointer_for_field (tree decl, omp_context *shared_ctx)
727 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
728 return true;
730 /* We can only use copy-in/copy-out semantics for shared variables
731 when we know the value is not accessible from an outer scope. */
732 if (shared_ctx)
734 /* ??? Trivially accessible from anywhere. But why would we even
735 be passing an address in this case? Should we simply assert
736 this to be false, or should we have a cleanup pass that removes
737 these from the list of mappings? */
738 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
739 return true;
741 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
742 without analyzing the expression whether or not its location
743 is accessible to anyone else. In the case of nested parallel
744 regions it certainly may be. */
745 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
746 return true;
748 /* Do not use copy-in/copy-out for variables that have their
749 address taken. */
750 if (TREE_ADDRESSABLE (decl))
751 return true;
753 /* Disallow copy-in/out in nested parallel if
754 decl is shared in outer parallel, otherwise
755 each thread could store the shared variable
756 in its own copy-in location, making the
757 variable no longer really shared. */
758 if (!TREE_READONLY (decl) && shared_ctx->is_nested)
760 omp_context *up;
762 for (up = shared_ctx->outer; up; up = up->outer)
763 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
764 break;
766 if (up)
768 tree c;
770 for (c = gimple_omp_taskreg_clauses (up->stmt);
771 c; c = OMP_CLAUSE_CHAIN (c))
772 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
773 && OMP_CLAUSE_DECL (c) == decl)
774 break;
776 if (c)
777 return true;
781 /* For tasks avoid using copy-in/out, unless they are readonly
782 (in which case just copy-in is used). As tasks can be
783 deferred or executed in different thread, when GOMP_task
784 returns, the task hasn't necessarily terminated. */
785 if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
787 tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
788 if (is_gimple_reg (outer))
790 /* Taking address of OUTER in lower_send_shared_vars
791 might need regimplification of everything that uses the
792 variable. */
793 if (!task_shared_vars)
794 task_shared_vars = BITMAP_ALLOC (NULL);
795 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
796 TREE_ADDRESSABLE (outer) = 1;
798 return true;
802 return false;
805 /* Create a new VAR_DECL and copy information from VAR to it. */
807 tree
808 copy_var_decl (tree var, tree name, tree type)
810 tree copy = build_decl (VAR_DECL, name, type);
812 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
813 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
814 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
815 DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
816 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
817 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
818 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
819 DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (var);
820 TREE_USED (copy) = 1;
821 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
823 return copy;
826 /* Construct a new automatic decl similar to VAR. */
828 static tree
829 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
831 tree copy = copy_var_decl (var, name, type);
833 DECL_CONTEXT (copy) = current_function_decl;
834 TREE_CHAIN (copy) = ctx->block_vars;
835 ctx->block_vars = copy;
837 return copy;
840 static tree
841 omp_copy_decl_1 (tree var, omp_context *ctx)
843 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
846 /* Build tree nodes to access the field for VAR on the receiver side. */
848 static tree
849 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
851 tree x, field = lookup_field (var, ctx);
853 /* If the receiver record type was remapped in the child function,
854 remap the field into the new record type. */
855 x = maybe_lookup_field (field, ctx);
856 if (x != NULL)
857 field = x;
859 x = build_fold_indirect_ref (ctx->receiver_decl);
860 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
861 if (by_ref)
862 x = build_fold_indirect_ref (x);
864 return x;
867 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
868 of a parallel, this is a component reference; for workshare constructs
869 this is some variable. */
871 static tree
872 build_outer_var_ref (tree var, omp_context *ctx)
874 tree x;
876 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
877 x = var;
878 else if (is_variable_sized (var))
880 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
881 x = build_outer_var_ref (x, ctx);
882 x = build_fold_indirect_ref (x);
884 else if (is_taskreg_ctx (ctx))
886 bool by_ref = use_pointer_for_field (var, NULL);
887 x = build_receiver_ref (var, by_ref, ctx);
889 else if (ctx->outer)
890 x = lookup_decl (var, ctx->outer);
891 else if (is_reference (var))
892 /* This can happen with orphaned constructs. If var is reference, it is
893 possible it is shared and as such valid. */
894 x = var;
895 else
896 gcc_unreachable ();
898 if (is_reference (var))
899 x = build_fold_indirect_ref (x);
901 return x;
904 /* Build tree nodes to access the field for VAR on the sender side. */
906 static tree
907 build_sender_ref (tree var, omp_context *ctx)
909 tree field = lookup_sfield (var, ctx);
910 return build3 (COMPONENT_REF, TREE_TYPE (field),
911 ctx->sender_decl, field, NULL);
914 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
916 static void
917 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
919 tree field, type, sfield = NULL_TREE;
921 gcc_assert ((mask & 1) == 0
922 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
923 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
924 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
926 type = TREE_TYPE (var);
927 if (by_ref)
928 type = build_pointer_type (type);
929 else if ((mask & 3) == 1 && is_reference (var))
930 type = TREE_TYPE (type);
932 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
934 /* Remember what variable this field was created for. This does have a
935 side effect of making dwarf2out ignore this member, so for helpful
936 debugging we clear it later in delete_omp_context. */
937 DECL_ABSTRACT_ORIGIN (field) = var;
938 if (type == TREE_TYPE (var))
940 DECL_ALIGN (field) = DECL_ALIGN (var);
941 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
942 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
944 else
945 DECL_ALIGN (field) = TYPE_ALIGN (type);
947 if ((mask & 3) == 3)
949 insert_field_into_struct (ctx->record_type, field);
950 if (ctx->srecord_type)
952 sfield = build_decl (FIELD_DECL, DECL_NAME (var), type);
953 DECL_ABSTRACT_ORIGIN (sfield) = var;
954 DECL_ALIGN (sfield) = DECL_ALIGN (field);
955 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
956 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
957 insert_field_into_struct (ctx->srecord_type, sfield);
960 else
962 if (ctx->srecord_type == NULL_TREE)
964 tree t;
966 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
967 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
968 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
970 sfield = build_decl (FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
971 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
972 insert_field_into_struct (ctx->srecord_type, sfield);
973 splay_tree_insert (ctx->sfield_map,
974 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
975 (splay_tree_value) sfield);
978 sfield = field;
979 insert_field_into_struct ((mask & 1) ? ctx->record_type
980 : ctx->srecord_type, field);
983 if (mask & 1)
984 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
985 (splay_tree_value) field);
986 if ((mask & 2) && ctx->sfield_map)
987 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
988 (splay_tree_value) sfield);
991 static tree
992 install_var_local (tree var, omp_context *ctx)
994 tree new_var = omp_copy_decl_1 (var, ctx);
995 insert_decl_map (&ctx->cb, var, new_var);
996 return new_var;
999 /* Adjust the replacement for DECL in CTX for the new context. This means
1000 copying the DECL_VALUE_EXPR, and fixing up the type. */
1002 static void
1003 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1005 tree new_decl, size;
1007 new_decl = lookup_decl (decl, ctx);
1009 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1011 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1012 && DECL_HAS_VALUE_EXPR_P (decl))
1014 tree ve = DECL_VALUE_EXPR (decl);
1015 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1016 SET_DECL_VALUE_EXPR (new_decl, ve);
1017 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1020 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1022 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1023 if (size == error_mark_node)
1024 size = TYPE_SIZE (TREE_TYPE (new_decl));
1025 DECL_SIZE (new_decl) = size;
1027 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1028 if (size == error_mark_node)
1029 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1030 DECL_SIZE_UNIT (new_decl) = size;
1034 /* The callback for remap_decl. Search all containing contexts for a
1035 mapping of the variable; this avoids having to duplicate the splay
1036 tree ahead of time. We know a mapping doesn't already exist in the
1037 given context. Create new mappings to implement default semantics. */
1039 static tree
1040 omp_copy_decl (tree var, copy_body_data *cb)
1042 omp_context *ctx = (omp_context *) cb;
1043 tree new_var;
1045 if (TREE_CODE (var) == LABEL_DECL)
1047 new_var = create_artificial_label ();
1048 DECL_CONTEXT (new_var) = current_function_decl;
1049 insert_decl_map (&ctx->cb, var, new_var);
1050 return new_var;
1053 while (!is_taskreg_ctx (ctx))
1055 ctx = ctx->outer;
1056 if (ctx == NULL)
1057 return var;
1058 new_var = maybe_lookup_decl (var, ctx);
1059 if (new_var)
1060 return new_var;
1063 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1064 return var;
1066 return error_mark_node;
1070 /* Return the parallel region associated with STMT. */
1072 /* Debugging dumps for parallel regions. */
1073 void dump_omp_region (FILE *, struct omp_region *, int);
1074 void debug_omp_region (struct omp_region *);
1075 void debug_all_omp_regions (void);
1077 /* Dump the parallel region tree rooted at REGION. */
1079 void
1080 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1082 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1083 gimple_code_name[region->type]);
1085 if (region->inner)
1086 dump_omp_region (file, region->inner, indent + 4);
1088 if (region->cont)
1090 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1091 region->cont->index);
1094 if (region->exit)
1095 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1096 region->exit->index);
1097 else
1098 fprintf (file, "%*s[no exit marker]\n", indent, "");
1100 if (region->next)
1101 dump_omp_region (file, region->next, indent);
1104 void
1105 debug_omp_region (struct omp_region *region)
1107 dump_omp_region (stderr, region, 0);
1110 void
1111 debug_all_omp_regions (void)
1113 dump_omp_region (stderr, root_omp_region, 0);
1117 /* Create a new parallel region starting at STMT inside region PARENT. */
1119 struct omp_region *
1120 new_omp_region (basic_block bb, enum gimple_code type,
1121 struct omp_region *parent)
1123 struct omp_region *region = XCNEW (struct omp_region);
1125 region->outer = parent;
1126 region->entry = bb;
1127 region->type = type;
1129 if (parent)
1131 /* This is a nested region. Add it to the list of inner
1132 regions in PARENT. */
1133 region->next = parent->inner;
1134 parent->inner = region;
1136 else
1138 /* This is a toplevel region. Add it to the list of toplevel
1139 regions in ROOT_OMP_REGION. */
1140 region->next = root_omp_region;
1141 root_omp_region = region;
1144 return region;
1147 /* Release the memory associated with the region tree rooted at REGION. */
1149 static void
1150 free_omp_region_1 (struct omp_region *region)
1152 struct omp_region *i, *n;
1154 for (i = region->inner; i ; i = n)
1156 n = i->next;
1157 free_omp_region_1 (i);
1160 free (region);
1163 /* Release the memory for the entire omp region tree. */
1165 void
1166 free_omp_regions (void)
1168 struct omp_region *r, *n;
1169 for (r = root_omp_region; r ; r = n)
1171 n = r->next;
1172 free_omp_region_1 (r);
1174 root_omp_region = NULL;
1178 /* Create a new context, with OUTER_CTX being the surrounding context. */
1180 static omp_context *
1181 new_omp_context (gimple stmt, omp_context *outer_ctx)
1183 omp_context *ctx = XCNEW (omp_context);
1185 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1186 (splay_tree_value) ctx);
1187 ctx->stmt = stmt;
1189 if (outer_ctx)
1191 ctx->outer = outer_ctx;
1192 ctx->cb = outer_ctx->cb;
1193 ctx->cb.block = NULL;
1194 ctx->depth = outer_ctx->depth + 1;
1196 else
1198 ctx->cb.src_fn = current_function_decl;
1199 ctx->cb.dst_fn = current_function_decl;
1200 ctx->cb.src_node = cgraph_node (current_function_decl);
1201 ctx->cb.dst_node = ctx->cb.src_node;
1202 ctx->cb.src_cfun = cfun;
1203 ctx->cb.copy_decl = omp_copy_decl;
1204 ctx->cb.eh_region = -1;
1205 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1206 ctx->depth = 1;
1209 ctx->cb.decl_map = pointer_map_create ();
1211 return ctx;
1214 static gimple_seq maybe_catch_exception (gimple_seq);
1216 /* Finalize task copyfn. */
1218 static void
1219 finalize_task_copyfn (gimple task_stmt)
1221 struct function *child_cfun;
1222 tree child_fn, old_fn;
1223 gimple_seq seq, new_seq;
1224 gimple bind;
1226 child_fn = gimple_omp_task_copy_fn (task_stmt);
1227 if (child_fn == NULL_TREE)
1228 return;
1230 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1232 /* Inform the callgraph about the new function. */
1233 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
1234 = cfun->curr_properties;
1236 old_fn = current_function_decl;
1237 push_cfun (child_cfun);
1238 current_function_decl = child_fn;
1239 bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
1240 seq = gimple_seq_alloc ();
1241 gimple_seq_add_stmt (&seq, bind);
1242 new_seq = maybe_catch_exception (seq);
1243 if (new_seq != seq)
1245 bind = gimple_build_bind (NULL, new_seq, NULL);
1246 seq = gimple_seq_alloc ();
1247 gimple_seq_add_stmt (&seq, bind);
1249 gimple_set_body (child_fn, seq);
1250 pop_cfun ();
1251 current_function_decl = old_fn;
1253 cgraph_add_new_function (child_fn, false);
1256 /* Destroy a omp_context data structures. Called through the splay tree
1257 value delete callback. */
1259 static void
1260 delete_omp_context (splay_tree_value value)
1262 omp_context *ctx = (omp_context *) value;
1264 pointer_map_destroy (ctx->cb.decl_map);
1266 if (ctx->field_map)
1267 splay_tree_delete (ctx->field_map);
1268 if (ctx->sfield_map)
1269 splay_tree_delete (ctx->sfield_map);
1271 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1272 it produces corrupt debug information. */
1273 if (ctx->record_type)
1275 tree t;
1276 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1277 DECL_ABSTRACT_ORIGIN (t) = NULL;
1279 if (ctx->srecord_type)
1281 tree t;
1282 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = TREE_CHAIN (t))
1283 DECL_ABSTRACT_ORIGIN (t) = NULL;
1286 if (is_task_ctx (ctx))
1287 finalize_task_copyfn (ctx->stmt);
1289 XDELETE (ctx);
1292 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1293 context. */
1295 static void
1296 fixup_child_record_type (omp_context *ctx)
1298 tree f, type = ctx->record_type;
1300 /* ??? It isn't sufficient to just call remap_type here, because
1301 variably_modified_type_p doesn't work the way we expect for
1302 record types. Testing each field for whether it needs remapping
1303 and creating a new record by hand works, however. */
1304 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
1305 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1306 break;
1307 if (f)
1309 tree name, new_fields = NULL;
1311 type = lang_hooks.types.make_type (RECORD_TYPE);
1312 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1313 name = build_decl (TYPE_DECL, name, type);
1314 TYPE_NAME (type) = name;
1316 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
1318 tree new_f = copy_node (f);
1319 DECL_CONTEXT (new_f) = type;
1320 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1321 TREE_CHAIN (new_f) = new_fields;
1322 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1323 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1324 &ctx->cb, NULL);
1325 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1326 &ctx->cb, NULL);
1327 new_fields = new_f;
1329 /* Arrange to be able to look up the receiver field
1330 given the sender field. */
1331 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1332 (splay_tree_value) new_f);
1334 TYPE_FIELDS (type) = nreverse (new_fields);
1335 layout_type (type);
1338 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1341 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1342 specified by CLAUSES. */
1344 static void
1345 scan_sharing_clauses (tree clauses, omp_context *ctx)
1347 tree c, decl;
1348 bool scan_array_reductions = false;
1350 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1352 bool by_ref;
1354 switch (OMP_CLAUSE_CODE (c))
1356 case OMP_CLAUSE_PRIVATE:
1357 decl = OMP_CLAUSE_DECL (c);
1358 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1359 goto do_private;
1360 else if (!is_variable_sized (decl))
1361 install_var_local (decl, ctx);
1362 break;
1364 case OMP_CLAUSE_SHARED:
1365 gcc_assert (is_taskreg_ctx (ctx));
1366 decl = OMP_CLAUSE_DECL (c);
1367 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1368 || !is_variable_sized (decl));
1369 /* Global variables don't need to be copied,
1370 the receiver side will use them directly. */
1371 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1372 break;
1373 by_ref = use_pointer_for_field (decl, ctx);
1374 if (! TREE_READONLY (decl)
1375 || TREE_ADDRESSABLE (decl)
1376 || by_ref
1377 || is_reference (decl))
1379 install_var_field (decl, by_ref, 3, ctx);
1380 install_var_local (decl, ctx);
1381 break;
1383 /* We don't need to copy const scalar vars back. */
1384 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1385 goto do_private;
1387 case OMP_CLAUSE_LASTPRIVATE:
1388 /* Let the corresponding firstprivate clause create
1389 the variable. */
1390 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1391 break;
1392 /* FALLTHRU */
1394 case OMP_CLAUSE_FIRSTPRIVATE:
1395 case OMP_CLAUSE_REDUCTION:
1396 decl = OMP_CLAUSE_DECL (c);
1397 do_private:
1398 if (is_variable_sized (decl))
1400 if (is_task_ctx (ctx))
1401 install_var_field (decl, false, 1, ctx);
1402 break;
1404 else if (is_taskreg_ctx (ctx))
1406 bool global
1407 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1408 by_ref = use_pointer_for_field (decl, NULL);
1410 if (is_task_ctx (ctx)
1411 && (global || by_ref || is_reference (decl)))
1413 install_var_field (decl, false, 1, ctx);
1414 if (!global)
1415 install_var_field (decl, by_ref, 2, ctx);
1417 else if (!global)
1418 install_var_field (decl, by_ref, 3, ctx);
1420 install_var_local (decl, ctx);
1421 break;
1423 case OMP_CLAUSE_COPYPRIVATE:
1424 if (ctx->outer)
1425 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1426 /* FALLTHRU */
1428 case OMP_CLAUSE_COPYIN:
1429 decl = OMP_CLAUSE_DECL (c);
1430 by_ref = use_pointer_for_field (decl, NULL);
1431 install_var_field (decl, by_ref, 3, ctx);
1432 break;
1434 case OMP_CLAUSE_DEFAULT:
1435 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1436 break;
1438 case OMP_CLAUSE_IF:
1439 case OMP_CLAUSE_NUM_THREADS:
1440 case OMP_CLAUSE_SCHEDULE:
1441 if (ctx->outer)
1442 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1443 break;
1445 case OMP_CLAUSE_NOWAIT:
1446 case OMP_CLAUSE_ORDERED:
1447 case OMP_CLAUSE_COLLAPSE:
1448 case OMP_CLAUSE_UNTIED:
1449 break;
1451 default:
1452 gcc_unreachable ();
1456 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1458 switch (OMP_CLAUSE_CODE (c))
1460 case OMP_CLAUSE_LASTPRIVATE:
1461 /* Let the corresponding firstprivate clause create
1462 the variable. */
1463 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1464 scan_array_reductions = true;
1465 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1466 break;
1467 /* FALLTHRU */
1469 case OMP_CLAUSE_PRIVATE:
1470 case OMP_CLAUSE_FIRSTPRIVATE:
1471 case OMP_CLAUSE_REDUCTION:
1472 decl = OMP_CLAUSE_DECL (c);
1473 if (is_variable_sized (decl))
1474 install_var_local (decl, ctx);
1475 fixup_remapped_decl (decl, ctx,
1476 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1477 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1478 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1479 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1480 scan_array_reductions = true;
1481 break;
1483 case OMP_CLAUSE_SHARED:
1484 decl = OMP_CLAUSE_DECL (c);
1485 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1486 fixup_remapped_decl (decl, ctx, false);
1487 break;
1489 case OMP_CLAUSE_COPYPRIVATE:
1490 case OMP_CLAUSE_COPYIN:
1491 case OMP_CLAUSE_DEFAULT:
1492 case OMP_CLAUSE_IF:
1493 case OMP_CLAUSE_NUM_THREADS:
1494 case OMP_CLAUSE_SCHEDULE:
1495 case OMP_CLAUSE_NOWAIT:
1496 case OMP_CLAUSE_ORDERED:
1497 case OMP_CLAUSE_COLLAPSE:
1498 case OMP_CLAUSE_UNTIED:
1499 break;
1501 default:
1502 gcc_unreachable ();
1506 if (scan_array_reductions)
1507 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1508 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1509 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1511 scan_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1512 scan_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1514 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1515 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1516 scan_omp (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1519 /* Create a new name for omp child function. Returns an identifier. */
1521 static GTY(()) unsigned int tmp_ompfn_id_num;
1523 static tree
1524 create_omp_child_function_name (bool task_copy)
1526 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1527 size_t len = IDENTIFIER_LENGTH (name);
1528 char *tmp_name, *prefix;
1529 const char *suffix;
1531 suffix = task_copy ? "_omp_cpyfn" : "_omp_fn";
1532 prefix = XALLOCAVEC (char, len + strlen (suffix) + 1);
1533 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1534 strcpy (prefix + len, suffix);
1535 #ifndef NO_DOT_IN_LABEL
1536 prefix[len] = '.';
1537 #elif !defined NO_DOLLAR_IN_LABEL
1538 prefix[len] = '$';
1539 #endif
1540 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1541 return get_identifier (tmp_name);
1544 /* Build a decl for the omp child function. It'll not contain a body
1545 yet, just the bare decl. */
1547 static void
1548 create_omp_child_function (omp_context *ctx, bool task_copy)
1550 tree decl, type, name, t;
1552 name = create_omp_child_function_name (task_copy);
1553 if (task_copy)
1554 type = build_function_type_list (void_type_node, ptr_type_node,
1555 ptr_type_node, NULL_TREE);
1556 else
1557 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1559 decl = build_decl (FUNCTION_DECL, name, type);
1560 decl = lang_hooks.decls.pushdecl (decl);
1562 if (!task_copy)
1563 ctx->cb.dst_fn = decl;
1564 else
1565 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1567 TREE_STATIC (decl) = 1;
1568 TREE_USED (decl) = 1;
1569 DECL_ARTIFICIAL (decl) = 1;
1570 DECL_IGNORED_P (decl) = 0;
1571 TREE_PUBLIC (decl) = 0;
1572 DECL_UNINLINABLE (decl) = 1;
1573 DECL_EXTERNAL (decl) = 0;
1574 DECL_CONTEXT (decl) = NULL_TREE;
1575 DECL_INITIAL (decl) = make_node (BLOCK);
1577 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1578 DECL_ARTIFICIAL (t) = 1;
1579 DECL_IGNORED_P (t) = 1;
1580 DECL_CONTEXT (t) = decl;
1581 DECL_RESULT (decl) = t;
1583 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1584 DECL_ARTIFICIAL (t) = 1;
1585 DECL_ARG_TYPE (t) = ptr_type_node;
1586 DECL_CONTEXT (t) = current_function_decl;
1587 TREE_USED (t) = 1;
1588 DECL_ARGUMENTS (decl) = t;
1589 if (!task_copy)
1590 ctx->receiver_decl = t;
1591 else
1593 t = build_decl (PARM_DECL, get_identifier (".omp_data_o"),
1594 ptr_type_node);
1595 DECL_ARTIFICIAL (t) = 1;
1596 DECL_ARG_TYPE (t) = ptr_type_node;
1597 DECL_CONTEXT (t) = current_function_decl;
1598 TREE_USED (t) = 1;
1599 TREE_ADDRESSABLE (t) = 1;
1600 TREE_CHAIN (t) = DECL_ARGUMENTS (decl);
1601 DECL_ARGUMENTS (decl) = t;
1604 /* Allocate memory for the function structure. The call to
1605 allocate_struct_function clobbers CFUN, so we need to restore
1606 it afterward. */
1607 push_struct_function (decl);
1608 DECL_SOURCE_LOCATION (decl) = gimple_location (ctx->stmt);
1609 cfun->function_end_locus = gimple_location (ctx->stmt);
1610 pop_cfun ();
1614 /* Scan an OpenMP parallel directive. */
1616 static void
1617 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1619 omp_context *ctx;
1620 tree name;
1621 gimple stmt = gsi_stmt (*gsi);
1623 /* Ignore parallel directives with empty bodies, unless there
1624 are copyin clauses. */
1625 if (optimize > 0
1626 && empty_body_p (gimple_omp_body (stmt))
1627 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1628 OMP_CLAUSE_COPYIN) == NULL)
1630 gsi_replace (gsi, gimple_build_nop (), false);
1631 return;
1634 ctx = new_omp_context (stmt, outer_ctx);
1635 if (taskreg_nesting_level > 1)
1636 ctx->is_nested = true;
1637 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1638 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1639 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1640 name = create_tmp_var_name (".omp_data_s");
1641 name = build_decl (TYPE_DECL, name, ctx->record_type);
1642 TYPE_NAME (ctx->record_type) = name;
1643 create_omp_child_function (ctx, false);
1644 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1646 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1647 scan_omp (gimple_omp_body (stmt), ctx);
1649 if (TYPE_FIELDS (ctx->record_type) == NULL)
1650 ctx->record_type = ctx->receiver_decl = NULL;
1651 else
1653 layout_type (ctx->record_type);
1654 fixup_child_record_type (ctx);
1658 /* Scan an OpenMP task directive. */
1660 static void
1661 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1663 omp_context *ctx;
1664 tree name, t;
1665 gimple stmt = gsi_stmt (*gsi);
1667 /* Ignore task directives with empty bodies. */
1668 if (optimize > 0
1669 && empty_body_p (gimple_omp_body (stmt)))
1671 gsi_replace (gsi, gimple_build_nop (), false);
1672 return;
1675 ctx = new_omp_context (stmt, outer_ctx);
1676 if (taskreg_nesting_level > 1)
1677 ctx->is_nested = true;
1678 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1679 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1680 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1681 name = create_tmp_var_name (".omp_data_s");
1682 name = build_decl (TYPE_DECL, name, ctx->record_type);
1683 TYPE_NAME (ctx->record_type) = name;
1684 create_omp_child_function (ctx, false);
1685 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
1687 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
1689 if (ctx->srecord_type)
1691 name = create_tmp_var_name (".omp_data_a");
1692 name = build_decl (TYPE_DECL, name, ctx->srecord_type);
1693 TYPE_NAME (ctx->srecord_type) = name;
1694 create_omp_child_function (ctx, true);
1697 scan_omp (gimple_omp_body (stmt), ctx);
1699 if (TYPE_FIELDS (ctx->record_type) == NULL)
1701 ctx->record_type = ctx->receiver_decl = NULL;
1702 t = build_int_cst (long_integer_type_node, 0);
1703 gimple_omp_task_set_arg_size (stmt, t);
1704 t = build_int_cst (long_integer_type_node, 1);
1705 gimple_omp_task_set_arg_align (stmt, t);
1707 else
1709 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1710 /* Move VLA fields to the end. */
1711 p = &TYPE_FIELDS (ctx->record_type);
1712 while (*p)
1713 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1714 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1716 *q = *p;
1717 *p = TREE_CHAIN (*p);
1718 TREE_CHAIN (*q) = NULL_TREE;
1719 q = &TREE_CHAIN (*q);
1721 else
1722 p = &TREE_CHAIN (*p);
1723 *p = vla_fields;
1724 layout_type (ctx->record_type);
1725 fixup_child_record_type (ctx);
1726 if (ctx->srecord_type)
1727 layout_type (ctx->srecord_type);
1728 t = fold_convert (long_integer_type_node,
1729 TYPE_SIZE_UNIT (ctx->record_type));
1730 gimple_omp_task_set_arg_size (stmt, t);
1731 t = build_int_cst (long_integer_type_node,
1732 TYPE_ALIGN_UNIT (ctx->record_type));
1733 gimple_omp_task_set_arg_align (stmt, t);
1738 /* Scan an OpenMP loop directive. */
1740 static void
1741 scan_omp_for (gimple stmt, omp_context *outer_ctx)
1743 omp_context *ctx;
1744 size_t i;
1746 ctx = new_omp_context (stmt, outer_ctx);
1748 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1750 scan_omp (gimple_omp_for_pre_body (stmt), ctx);
1751 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
1753 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1754 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1755 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1756 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
1758 scan_omp (gimple_omp_body (stmt), ctx);
1761 /* Scan an OpenMP sections directive. */
1763 static void
1764 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1766 omp_context *ctx;
1768 ctx = new_omp_context (stmt, outer_ctx);
1769 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
1770 scan_omp (gimple_omp_body (stmt), ctx);
1773 /* Scan an OpenMP single directive. */
1775 static void
1776 scan_omp_single (gimple stmt, omp_context *outer_ctx)
1778 omp_context *ctx;
1779 tree name;
1781 ctx = new_omp_context (stmt, outer_ctx);
1782 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1783 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1784 name = create_tmp_var_name (".omp_copy_s");
1785 name = build_decl (TYPE_DECL, name, ctx->record_type);
1786 TYPE_NAME (ctx->record_type) = name;
1788 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
1789 scan_omp (gimple_omp_body (stmt), ctx);
1791 if (TYPE_FIELDS (ctx->record_type) == NULL)
1792 ctx->record_type = NULL;
1793 else
1794 layout_type (ctx->record_type);
1798 /* Check OpenMP nesting restrictions. */
1799 static void
1800 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
1802 switch (gimple_code (stmt))
1804 case GIMPLE_OMP_FOR:
1805 case GIMPLE_OMP_SECTIONS:
1806 case GIMPLE_OMP_SINGLE:
1807 case GIMPLE_CALL:
1808 for (; ctx != NULL; ctx = ctx->outer)
1809 switch (gimple_code (ctx->stmt))
1811 case GIMPLE_OMP_FOR:
1812 case GIMPLE_OMP_SECTIONS:
1813 case GIMPLE_OMP_SINGLE:
1814 case GIMPLE_OMP_ORDERED:
1815 case GIMPLE_OMP_MASTER:
1816 case GIMPLE_OMP_TASK:
1817 if (is_gimple_call (stmt))
1819 warning (0, "barrier region may not be closely nested inside "
1820 "of work-sharing, critical, ordered, master or "
1821 "explicit task region");
1822 return;
1824 warning (0, "work-sharing region may not be closely nested inside "
1825 "of work-sharing, critical, ordered, master or explicit "
1826 "task region");
1827 return;
1828 case GIMPLE_OMP_PARALLEL:
1829 return;
1830 default:
1831 break;
1833 break;
1834 case GIMPLE_OMP_MASTER:
1835 for (; ctx != NULL; ctx = ctx->outer)
1836 switch (gimple_code (ctx->stmt))
1838 case GIMPLE_OMP_FOR:
1839 case GIMPLE_OMP_SECTIONS:
1840 case GIMPLE_OMP_SINGLE:
1841 case GIMPLE_OMP_TASK:
1842 warning (0, "master region may not be closely nested inside "
1843 "of work-sharing or explicit task region");
1844 return;
1845 case GIMPLE_OMP_PARALLEL:
1846 return;
1847 default:
1848 break;
1850 break;
1851 case GIMPLE_OMP_ORDERED:
1852 for (; ctx != NULL; ctx = ctx->outer)
1853 switch (gimple_code (ctx->stmt))
1855 case GIMPLE_OMP_CRITICAL:
1856 case GIMPLE_OMP_TASK:
1857 warning (0, "ordered region may not be closely nested inside "
1858 "of critical or explicit task region");
1859 return;
1860 case GIMPLE_OMP_FOR:
1861 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
1862 OMP_CLAUSE_ORDERED) == NULL)
1863 warning (0, "ordered region must be closely nested inside "
1864 "a loop region with an ordered clause");
1865 return;
1866 case GIMPLE_OMP_PARALLEL:
1867 return;
1868 default:
1869 break;
1871 break;
1872 case GIMPLE_OMP_CRITICAL:
1873 for (; ctx != NULL; ctx = ctx->outer)
1874 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1875 && (gimple_omp_critical_name (stmt)
1876 == gimple_omp_critical_name (ctx->stmt)))
1878 warning (0, "critical region may not be nested inside a critical "
1879 "region with the same name");
1880 return;
1882 break;
1883 default:
1884 break;
1889 /* Helper function scan_omp.
1891 Callback for walk_tree or operators in walk_gimple_stmt used to
1892 scan for OpenMP directives in TP. */
1894 static tree
1895 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1897 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1898 omp_context *ctx = (omp_context *) wi->info;
1899 tree t = *tp;
1901 switch (TREE_CODE (t))
1903 case VAR_DECL:
1904 case PARM_DECL:
1905 case LABEL_DECL:
1906 case RESULT_DECL:
1907 if (ctx)
1908 *tp = remap_decl (t, &ctx->cb);
1909 break;
1911 default:
1912 if (ctx && TYPE_P (t))
1913 *tp = remap_type (t, &ctx->cb);
1914 else if (!DECL_P (t))
1915 *walk_subtrees = 1;
1916 break;
1919 return NULL_TREE;
1923 /* Helper function for scan_omp.
1925 Callback for walk_gimple_stmt used to scan for OpenMP directives in
1926 the current statement in GSI. */
1928 static tree
1929 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1930 struct walk_stmt_info *wi)
1932 gimple stmt = gsi_stmt (*gsi);
1933 omp_context *ctx = (omp_context *) wi->info;
1935 if (gimple_has_location (stmt))
1936 input_location = gimple_location (stmt);
1938 /* Check the OpenMP nesting restrictions. */
1939 if (ctx != NULL)
1941 if (is_gimple_omp (stmt))
1942 check_omp_nesting_restrictions (stmt, ctx);
1943 else if (is_gimple_call (stmt))
1945 tree fndecl = gimple_call_fndecl (stmt);
1946 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
1947 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
1948 check_omp_nesting_restrictions (stmt, ctx);
1952 *handled_ops_p = true;
1954 switch (gimple_code (stmt))
1956 case GIMPLE_OMP_PARALLEL:
1957 taskreg_nesting_level++;
1958 scan_omp_parallel (gsi, ctx);
1959 taskreg_nesting_level--;
1960 break;
1962 case GIMPLE_OMP_TASK:
1963 taskreg_nesting_level++;
1964 scan_omp_task (gsi, ctx);
1965 taskreg_nesting_level--;
1966 break;
1968 case GIMPLE_OMP_FOR:
1969 scan_omp_for (stmt, ctx);
1970 break;
1972 case GIMPLE_OMP_SECTIONS:
1973 scan_omp_sections (stmt, ctx);
1974 break;
1976 case GIMPLE_OMP_SINGLE:
1977 scan_omp_single (stmt, ctx);
1978 break;
1980 case GIMPLE_OMP_SECTION:
1981 case GIMPLE_OMP_MASTER:
1982 case GIMPLE_OMP_ORDERED:
1983 case GIMPLE_OMP_CRITICAL:
1984 ctx = new_omp_context (stmt, ctx);
1985 scan_omp (gimple_omp_body (stmt), ctx);
1986 break;
1988 case GIMPLE_BIND:
1990 tree var;
1992 *handled_ops_p = false;
1993 if (ctx)
1994 for (var = gimple_bind_vars (stmt); var ; var = TREE_CHAIN (var))
1995 insert_decl_map (&ctx->cb, var, var);
1997 break;
1998 default:
1999 *handled_ops_p = false;
2000 break;
2003 return NULL_TREE;
2007 /* Scan all the statements starting at the current statement. CTX
2008 contains context information about the OpenMP directives and
2009 clauses found during the scan. */
2011 static void
2012 scan_omp (gimple_seq body, omp_context *ctx)
2014 location_t saved_location;
2015 struct walk_stmt_info wi;
2017 memset (&wi, 0, sizeof (wi));
2018 wi.info = ctx;
2019 wi.want_locations = true;
2021 saved_location = input_location;
2022 walk_gimple_seq (body, scan_omp_1_stmt, scan_omp_1_op, &wi);
2023 input_location = saved_location;
2026 /* Re-gimplification and code generation routines. */
2028 /* Build a call to GOMP_barrier. */
2030 static tree
2031 build_omp_barrier (void)
2033 return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
2036 /* If a context was created for STMT when it was scanned, return it. */
2038 static omp_context *
2039 maybe_lookup_ctx (gimple stmt)
2041 splay_tree_node n;
2042 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2043 return n ? (omp_context *) n->value : NULL;
2047 /* Find the mapping for DECL in CTX or the immediately enclosing
2048 context that has a mapping for DECL.
2050 If CTX is a nested parallel directive, we may have to use the decl
2051 mappings created in CTX's parent context. Suppose that we have the
2052 following parallel nesting (variable UIDs showed for clarity):
2054 iD.1562 = 0;
2055 #omp parallel shared(iD.1562) -> outer parallel
2056 iD.1562 = iD.1562 + 1;
2058 #omp parallel shared (iD.1562) -> inner parallel
2059 iD.1562 = iD.1562 - 1;
2061 Each parallel structure will create a distinct .omp_data_s structure
2062 for copying iD.1562 in/out of the directive:
2064 outer parallel .omp_data_s.1.i -> iD.1562
2065 inner parallel .omp_data_s.2.i -> iD.1562
2067 A shared variable mapping will produce a copy-out operation before
2068 the parallel directive and a copy-in operation after it. So, in
2069 this case we would have:
2071 iD.1562 = 0;
2072 .omp_data_o.1.i = iD.1562;
2073 #omp parallel shared(iD.1562) -> outer parallel
2074 .omp_data_i.1 = &.omp_data_o.1
2075 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2077 .omp_data_o.2.i = iD.1562; -> **
2078 #omp parallel shared(iD.1562) -> inner parallel
2079 .omp_data_i.2 = &.omp_data_o.2
2080 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2083 ** This is a problem. The symbol iD.1562 cannot be referenced
2084 inside the body of the outer parallel region. But since we are
2085 emitting this copy operation while expanding the inner parallel
2086 directive, we need to access the CTX structure of the outer
2087 parallel directive to get the correct mapping:
2089 .omp_data_o.2.i = .omp_data_i.1->i
2091 Since there may be other workshare or parallel directives enclosing
2092 the parallel directive, it may be necessary to walk up the context
2093 parent chain. This is not a problem in general because nested
2094 parallelism happens only rarely. */
2096 static tree
2097 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2099 tree t;
2100 omp_context *up;
2102 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2103 t = maybe_lookup_decl (decl, up);
2105 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2107 return t ? t : decl;
2111 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2112 in outer contexts. */
2114 static tree
2115 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2117 tree t = NULL;
2118 omp_context *up;
2120 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2121 t = maybe_lookup_decl (decl, up);
2123 return t ? t : decl;
2127 /* Construct the initialization value for reduction CLAUSE. */
2129 tree
2130 omp_reduction_init (tree clause, tree type)
2132 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2134 case PLUS_EXPR:
2135 case MINUS_EXPR:
2136 case BIT_IOR_EXPR:
2137 case BIT_XOR_EXPR:
2138 case TRUTH_OR_EXPR:
2139 case TRUTH_ORIF_EXPR:
2140 case TRUTH_XOR_EXPR:
2141 case NE_EXPR:
2142 return fold_convert (type, integer_zero_node);
2144 case MULT_EXPR:
2145 case TRUTH_AND_EXPR:
2146 case TRUTH_ANDIF_EXPR:
2147 case EQ_EXPR:
2148 return fold_convert (type, integer_one_node);
2150 case BIT_AND_EXPR:
2151 return fold_convert (type, integer_minus_one_node);
2153 case MAX_EXPR:
2154 if (SCALAR_FLOAT_TYPE_P (type))
2156 REAL_VALUE_TYPE max, min;
2157 if (HONOR_INFINITIES (TYPE_MODE (type)))
2159 real_inf (&max);
2160 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2162 else
2163 real_maxval (&min, 1, TYPE_MODE (type));
2164 return build_real (type, min);
2166 else
2168 gcc_assert (INTEGRAL_TYPE_P (type));
2169 return TYPE_MIN_VALUE (type);
2172 case MIN_EXPR:
2173 if (SCALAR_FLOAT_TYPE_P (type))
2175 REAL_VALUE_TYPE max;
2176 if (HONOR_INFINITIES (TYPE_MODE (type)))
2177 real_inf (&max);
2178 else
2179 real_maxval (&max, 0, TYPE_MODE (type));
2180 return build_real (type, max);
2182 else
2184 gcc_assert (INTEGRAL_TYPE_P (type));
2185 return TYPE_MAX_VALUE (type);
2188 default:
2189 gcc_unreachable ();
2193 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2194 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2195 private variables. Initialization statements go in ILIST, while calls
2196 to destructors go in DLIST. */
2198 static void
2199 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2200 omp_context *ctx)
2202 gimple_stmt_iterator diter;
2203 tree c, dtor, copyin_seq, x, ptr;
2204 bool copyin_by_ref = false;
2205 bool lastprivate_firstprivate = false;
2206 int pass;
2208 *dlist = gimple_seq_alloc ();
2209 diter = gsi_start (*dlist);
2210 copyin_seq = NULL;
2212 /* Do all the fixed sized types in the first pass, and the variable sized
2213 types in the second pass. This makes sure that the scalar arguments to
2214 the variable sized types are processed before we use them in the
2215 variable sized operations. */
2216 for (pass = 0; pass < 2; ++pass)
2218 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2220 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2221 tree var, new_var;
2222 bool by_ref;
2224 switch (c_kind)
2226 case OMP_CLAUSE_PRIVATE:
2227 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2228 continue;
2229 break;
2230 case OMP_CLAUSE_SHARED:
2231 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2233 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2234 continue;
2236 case OMP_CLAUSE_FIRSTPRIVATE:
2237 case OMP_CLAUSE_COPYIN:
2238 case OMP_CLAUSE_REDUCTION:
2239 break;
2240 case OMP_CLAUSE_LASTPRIVATE:
2241 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2243 lastprivate_firstprivate = true;
2244 if (pass != 0)
2245 continue;
2247 break;
2248 default:
2249 continue;
2252 new_var = var = OMP_CLAUSE_DECL (c);
2253 if (c_kind != OMP_CLAUSE_COPYIN)
2254 new_var = lookup_decl (var, ctx);
2256 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2258 if (pass != 0)
2259 continue;
2261 else if (is_variable_sized (var))
2263 /* For variable sized types, we need to allocate the
2264 actual storage here. Call alloca and store the
2265 result in the pointer decl that we created elsewhere. */
2266 if (pass == 0)
2267 continue;
2269 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2271 gimple stmt;
2272 tree tmp;
2274 ptr = DECL_VALUE_EXPR (new_var);
2275 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2276 ptr = TREE_OPERAND (ptr, 0);
2277 gcc_assert (DECL_P (ptr));
2278 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2280 /* void *tmp = __builtin_alloca */
2281 stmt
2282 = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x);
2283 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2284 gimple_add_tmp_var (tmp);
2285 gimple_call_set_lhs (stmt, tmp);
2287 gimple_seq_add_stmt (ilist, stmt);
2289 x = fold_convert (TREE_TYPE (ptr), tmp);
2290 gimplify_assign (ptr, x, ilist);
2293 else if (is_reference (var))
2295 /* For references that are being privatized for Fortran,
2296 allocate new backing storage for the new pointer
2297 variable. This allows us to avoid changing all the
2298 code that expects a pointer to something that expects
2299 a direct variable. Note that this doesn't apply to
2300 C++, since reference types are disallowed in data
2301 sharing clauses there, except for NRV optimized
2302 return values. */
2303 if (pass == 0)
2304 continue;
2306 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2307 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2309 x = build_receiver_ref (var, false, ctx);
2310 x = build_fold_addr_expr (x);
2312 else if (TREE_CONSTANT (x))
2314 const char *name = NULL;
2315 if (DECL_NAME (var))
2316 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2318 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2319 name);
2320 gimple_add_tmp_var (x);
2321 TREE_ADDRESSABLE (x) = 1;
2322 x = build_fold_addr_expr (x);
2324 else
2326 x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
2329 x = fold_convert (TREE_TYPE (new_var), x);
2330 gimplify_assign (new_var, x, ilist);
2332 new_var = build_fold_indirect_ref (new_var);
2334 else if (c_kind == OMP_CLAUSE_REDUCTION
2335 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2337 if (pass == 0)
2338 continue;
2340 else if (pass != 0)
2341 continue;
2343 switch (OMP_CLAUSE_CODE (c))
2345 case OMP_CLAUSE_SHARED:
2346 /* Shared global vars are just accessed directly. */
2347 if (is_global_var (new_var))
2348 break;
2349 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2350 needs to be delayed until after fixup_child_record_type so
2351 that we get the correct type during the dereference. */
2352 by_ref = use_pointer_for_field (var, ctx);
2353 x = build_receiver_ref (var, by_ref, ctx);
2354 SET_DECL_VALUE_EXPR (new_var, x);
2355 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2357 /* ??? If VAR is not passed by reference, and the variable
2358 hasn't been initialized yet, then we'll get a warning for
2359 the store into the omp_data_s structure. Ideally, we'd be
2360 able to notice this and not store anything at all, but
2361 we're generating code too early. Suppress the warning. */
2362 if (!by_ref)
2363 TREE_NO_WARNING (var) = 1;
2364 break;
2366 case OMP_CLAUSE_LASTPRIVATE:
2367 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2368 break;
2369 /* FALLTHRU */
2371 case OMP_CLAUSE_PRIVATE:
2372 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2373 x = build_outer_var_ref (var, ctx);
2374 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2376 if (is_task_ctx (ctx))
2377 x = build_receiver_ref (var, false, ctx);
2378 else
2379 x = build_outer_var_ref (var, ctx);
2381 else
2382 x = NULL;
2383 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2384 if (x)
2385 gimplify_and_add (x, ilist);
2386 /* FALLTHRU */
2388 do_dtor:
2389 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2390 if (x)
2392 gimple_seq tseq = NULL;
2394 dtor = x;
2395 gimplify_stmt (&dtor, &tseq);
2396 gsi_insert_seq_before (&diter, tseq, GSI_SAME_STMT);
2398 break;
2400 case OMP_CLAUSE_FIRSTPRIVATE:
2401 if (is_task_ctx (ctx))
2403 if (is_reference (var) || is_variable_sized (var))
2404 goto do_dtor;
2405 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2406 ctx))
2407 || use_pointer_for_field (var, NULL))
2409 x = build_receiver_ref (var, false, ctx);
2410 SET_DECL_VALUE_EXPR (new_var, x);
2411 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2412 goto do_dtor;
2415 x = build_outer_var_ref (var, ctx);
2416 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2417 gimplify_and_add (x, ilist);
2418 goto do_dtor;
2419 break;
2421 case OMP_CLAUSE_COPYIN:
2422 by_ref = use_pointer_for_field (var, NULL);
2423 x = build_receiver_ref (var, by_ref, ctx);
2424 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2425 append_to_statement_list (x, &copyin_seq);
2426 copyin_by_ref |= by_ref;
2427 break;
2429 case OMP_CLAUSE_REDUCTION:
2430 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2432 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2433 x = build_outer_var_ref (var, ctx);
2435 if (is_reference (var))
2436 x = build_fold_addr_expr (x);
2437 SET_DECL_VALUE_EXPR (placeholder, x);
2438 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2439 lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2440 gimple_seq_add_seq (ilist,
2441 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2442 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
2443 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2445 else
2447 x = omp_reduction_init (c, TREE_TYPE (new_var));
2448 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2449 gimplify_assign (new_var, x, ilist);
2451 break;
2453 default:
2454 gcc_unreachable ();
2459 /* The copyin sequence is not to be executed by the main thread, since
2460 that would result in self-copies. Perhaps not visible to scalars,
2461 but it certainly is to C++ operator=. */
2462 if (copyin_seq)
2464 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2465 x = build2 (NE_EXPR, boolean_type_node, x,
2466 build_int_cst (TREE_TYPE (x), 0));
2467 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2468 gimplify_and_add (x, ilist);
2471 /* If any copyin variable is passed by reference, we must ensure the
2472 master thread doesn't modify it before it is copied over in all
2473 threads. Similarly for variables in both firstprivate and
2474 lastprivate clauses we need to ensure the lastprivate copying
2475 happens after firstprivate copying in all threads. */
2476 if (copyin_by_ref || lastprivate_firstprivate)
2477 gimplify_and_add (build_omp_barrier (), ilist);
2481 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2482 both parallel and workshare constructs. PREDICATE may be NULL if it's
2483 always true. */
2485 static void
2486 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2487 omp_context *ctx)
2489 tree x, c, label = NULL;
2490 bool par_clauses = false;
2492 /* Early exit if there are no lastprivate clauses. */
2493 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
2494 if (clauses == NULL)
2496 /* If this was a workshare clause, see if it had been combined
2497 with its parallel. In that case, look for the clauses on the
2498 parallel statement itself. */
2499 if (is_parallel_ctx (ctx))
2500 return;
2502 ctx = ctx->outer;
2503 if (ctx == NULL || !is_parallel_ctx (ctx))
2504 return;
2506 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2507 OMP_CLAUSE_LASTPRIVATE);
2508 if (clauses == NULL)
2509 return;
2510 par_clauses = true;
2513 if (predicate)
2515 gimple stmt;
2516 tree label_true, arm1, arm2;
2518 label = create_artificial_label ();
2519 label_true = create_artificial_label ();
2520 arm1 = TREE_OPERAND (predicate, 0);
2521 arm2 = TREE_OPERAND (predicate, 1);
2522 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2523 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2524 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2525 label_true, label);
2526 gimple_seq_add_stmt (stmt_list, stmt);
2527 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2530 for (c = clauses; c ;)
2532 tree var, new_var;
2534 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2536 var = OMP_CLAUSE_DECL (c);
2537 new_var = lookup_decl (var, ctx);
2539 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2541 lower_omp (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2542 gimple_seq_add_seq (stmt_list,
2543 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
2545 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
2547 x = build_outer_var_ref (var, ctx);
2548 if (is_reference (var))
2549 new_var = build_fold_indirect_ref (new_var);
2550 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2551 gimplify_and_add (x, stmt_list);
2553 c = OMP_CLAUSE_CHAIN (c);
2554 if (c == NULL && !par_clauses)
2556 /* If this was a workshare clause, see if it had been combined
2557 with its parallel. In that case, continue looking for the
2558 clauses also on the parallel statement itself. */
2559 if (is_parallel_ctx (ctx))
2560 break;
2562 ctx = ctx->outer;
2563 if (ctx == NULL || !is_parallel_ctx (ctx))
2564 break;
2566 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2567 OMP_CLAUSE_LASTPRIVATE);
2568 par_clauses = true;
2572 if (label)
2573 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
2577 /* Generate code to implement the REDUCTION clauses. */
2579 static void
2580 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
2582 gimple_seq sub_seq = NULL;
2583 gimple stmt;
2584 tree x, c;
2585 int count = 0;
2587 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
2588 update in that case, otherwise use a lock. */
2589 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
2590 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2592 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2594 /* Never use OMP_ATOMIC for array reductions. */
2595 count = -1;
2596 break;
2598 count++;
2601 if (count == 0)
2602 return;
2604 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2606 tree var, ref, new_var;
2607 enum tree_code code;
2609 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
2610 continue;
2612 var = OMP_CLAUSE_DECL (c);
2613 new_var = lookup_decl (var, ctx);
2614 if (is_reference (var))
2615 new_var = build_fold_indirect_ref (new_var);
2616 ref = build_outer_var_ref (var, ctx);
2617 code = OMP_CLAUSE_REDUCTION_CODE (c);
2619 /* reduction(-:var) sums up the partial results, so it acts
2620 identically to reduction(+:var). */
2621 if (code == MINUS_EXPR)
2622 code = PLUS_EXPR;
2624 if (count == 1)
2626 tree addr = build_fold_addr_expr (ref);
2628 addr = save_expr (addr);
2629 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
2630 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
2631 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
2632 gimplify_and_add (x, stmt_seqp);
2633 return;
2636 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2638 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2640 if (is_reference (var))
2641 ref = build_fold_addr_expr (ref);
2642 SET_DECL_VALUE_EXPR (placeholder, ref);
2643 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2644 lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2645 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
2646 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
2647 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2649 else
2651 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2652 ref = build_outer_var_ref (var, ctx);
2653 gimplify_assign (ref, x, &sub_seq);
2657 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
2658 gimple_seq_add_stmt (stmt_seqp, stmt);
2660 gimple_seq_add_seq (stmt_seqp, sub_seq);
2662 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
2663 gimple_seq_add_stmt (stmt_seqp, stmt);
2667 /* Generate code to implement the COPYPRIVATE clauses. */
2669 static void
2670 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
2671 omp_context *ctx)
2673 tree c;
2675 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2677 tree var, ref, x;
2678 bool by_ref;
2680 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2681 continue;
2683 var = OMP_CLAUSE_DECL (c);
2684 by_ref = use_pointer_for_field (var, NULL);
2686 ref = build_sender_ref (var, ctx);
2687 x = lookup_decl_in_outer_ctx (var, ctx);
2688 x = by_ref ? build_fold_addr_expr (x) : x;
2689 gimplify_assign (ref, x, slist);
2691 ref = build_receiver_ref (var, by_ref, ctx);
2692 if (is_reference (var))
2694 ref = build_fold_indirect_ref (ref);
2695 var = build_fold_indirect_ref (var);
2697 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2698 gimplify_and_add (x, rlist);
2703 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2704 and REDUCTION from the sender (aka parent) side. */
2706 static void
2707 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
2708 omp_context *ctx)
2710 tree c;
2712 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2714 tree val, ref, x, var;
2715 bool by_ref, do_in = false, do_out = false;
2717 switch (OMP_CLAUSE_CODE (c))
2719 case OMP_CLAUSE_PRIVATE:
2720 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2721 break;
2722 continue;
2723 case OMP_CLAUSE_FIRSTPRIVATE:
2724 case OMP_CLAUSE_COPYIN:
2725 case OMP_CLAUSE_LASTPRIVATE:
2726 case OMP_CLAUSE_REDUCTION:
2727 break;
2728 default:
2729 continue;
2732 val = OMP_CLAUSE_DECL (c);
2733 var = lookup_decl_in_outer_ctx (val, ctx);
2735 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2736 && is_global_var (var))
2737 continue;
2738 if (is_variable_sized (val))
2739 continue;
2740 by_ref = use_pointer_for_field (val, NULL);
2742 switch (OMP_CLAUSE_CODE (c))
2744 case OMP_CLAUSE_PRIVATE:
2745 case OMP_CLAUSE_FIRSTPRIVATE:
2746 case OMP_CLAUSE_COPYIN:
2747 do_in = true;
2748 break;
2750 case OMP_CLAUSE_LASTPRIVATE:
2751 if (by_ref || is_reference (val))
2753 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2754 continue;
2755 do_in = true;
2757 else
2759 do_out = true;
2760 if (lang_hooks.decls.omp_private_outer_ref (val))
2761 do_in = true;
2763 break;
2765 case OMP_CLAUSE_REDUCTION:
2766 do_in = true;
2767 do_out = !(by_ref || is_reference (val));
2768 break;
2770 default:
2771 gcc_unreachable ();
2774 if (do_in)
2776 ref = build_sender_ref (val, ctx);
2777 x = by_ref ? build_fold_addr_expr (var) : var;
2778 gimplify_assign (ref, x, ilist);
2779 if (is_task_ctx (ctx))
2780 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
2783 if (do_out)
2785 ref = build_sender_ref (val, ctx);
2786 gimplify_assign (var, ref, olist);
2791 /* Generate code to implement SHARED from the sender (aka parent)
2792 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
2793 list things that got automatically shared. */
2795 static void
2796 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
2798 tree var, ovar, nvar, f, x, record_type;
2800 if (ctx->record_type == NULL)
2801 return;
2803 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
2804 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
2806 ovar = DECL_ABSTRACT_ORIGIN (f);
2807 nvar = maybe_lookup_decl (ovar, ctx);
2808 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2809 continue;
2811 /* If CTX is a nested parallel directive. Find the immediately
2812 enclosing parallel or workshare construct that contains a
2813 mapping for OVAR. */
2814 var = lookup_decl_in_outer_ctx (ovar, ctx);
2816 if (use_pointer_for_field (ovar, ctx))
2818 x = build_sender_ref (ovar, ctx);
2819 var = build_fold_addr_expr (var);
2820 gimplify_assign (x, var, ilist);
2822 else
2824 x = build_sender_ref (ovar, ctx);
2825 gimplify_assign (x, var, ilist);
2827 if (!TREE_READONLY (var)
2828 /* We don't need to receive a new reference to a result
2829 or parm decl. In fact we may not store to it as we will
2830 invalidate any pending RSO and generate wrong gimple
2831 during inlining. */
2832 && !((TREE_CODE (var) == RESULT_DECL
2833 || TREE_CODE (var) == PARM_DECL)
2834 && DECL_BY_REFERENCE (var)))
2836 x = build_sender_ref (ovar, ctx);
2837 gimplify_assign (var, x, olist);
2844 /* A convenience function to build an empty GIMPLE_COND with just the
2845 condition. */
2847 static gimple
2848 gimple_build_cond_empty (tree cond)
2850 enum tree_code pred_code;
2851 tree lhs, rhs;
2853 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
2854 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
2858 /* Build the function calls to GOMP_parallel_start etc to actually
2859 generate the parallel operation. REGION is the parallel region
2860 being expanded. BB is the block where to insert the code. WS_ARGS
2861 will be set if this is a call to a combined parallel+workshare
2862 construct, it contains the list of additional arguments needed by
2863 the workshare construct. */
2865 static void
2866 expand_parallel_call (struct omp_region *region, basic_block bb,
2867 gimple entry_stmt, tree ws_args)
2869 tree t, t1, t2, val, cond, c, clauses;
2870 gimple_stmt_iterator gsi;
2871 gimple stmt;
2872 int start_ix;
2874 clauses = gimple_omp_parallel_clauses (entry_stmt);
2876 /* Determine what flavor of GOMP_parallel_start we will be
2877 emitting. */
2878 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2879 if (is_combined_parallel (region))
2881 switch (region->inner->type)
2883 case GIMPLE_OMP_FOR:
2884 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
2885 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2886 + (region->inner->sched_kind
2887 == OMP_CLAUSE_SCHEDULE_RUNTIME
2888 ? 3 : region->inner->sched_kind);
2889 break;
2890 case GIMPLE_OMP_SECTIONS:
2891 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2892 break;
2893 default:
2894 gcc_unreachable ();
2898 /* By default, the value of NUM_THREADS is zero (selected at run time)
2899 and there is no conditional. */
2900 cond = NULL_TREE;
2901 val = build_int_cst (unsigned_type_node, 0);
2903 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2904 if (c)
2905 cond = OMP_CLAUSE_IF_EXPR (c);
2907 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2908 if (c)
2909 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2911 /* Ensure 'val' is of the correct type. */
2912 val = fold_convert (unsigned_type_node, val);
2914 /* If we found the clause 'if (cond)', build either
2915 (cond != 0) or (cond ? val : 1u). */
2916 if (cond)
2918 gimple_stmt_iterator gsi;
2920 cond = gimple_boolify (cond);
2922 if (integer_zerop (val))
2923 val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
2924 build_int_cst (TREE_TYPE (cond), 0));
2925 else
2927 basic_block cond_bb, then_bb, else_bb;
2928 edge e, e_then, e_else;
2929 tree tmp_then, tmp_else, tmp_join, tmp_var;
2931 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
2932 if (gimple_in_ssa_p (cfun))
2934 tmp_then = make_ssa_name (tmp_var, NULL);
2935 tmp_else = make_ssa_name (tmp_var, NULL);
2936 tmp_join = make_ssa_name (tmp_var, NULL);
2938 else
2940 tmp_then = tmp_var;
2941 tmp_else = tmp_var;
2942 tmp_join = tmp_var;
2945 e = split_block (bb, NULL);
2946 cond_bb = e->src;
2947 bb = e->dest;
2948 remove_edge (e);
2950 then_bb = create_empty_bb (cond_bb);
2951 else_bb = create_empty_bb (then_bb);
2952 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
2953 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
2955 stmt = gimple_build_cond_empty (cond);
2956 gsi = gsi_start_bb (cond_bb);
2957 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2959 gsi = gsi_start_bb (then_bb);
2960 stmt = gimple_build_assign (tmp_then, val);
2961 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2963 gsi = gsi_start_bb (else_bb);
2964 stmt = gimple_build_assign
2965 (tmp_else, build_int_cst (unsigned_type_node, 1));
2966 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
2968 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2969 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2970 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
2971 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
2973 if (gimple_in_ssa_p (cfun))
2975 gimple phi = create_phi_node (tmp_join, bb);
2976 SSA_NAME_DEF_STMT (tmp_join) = phi;
2977 add_phi_arg (phi, tmp_then, e_then);
2978 add_phi_arg (phi, tmp_else, e_else);
2981 val = tmp_join;
2984 gsi = gsi_start_bb (bb);
2985 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
2986 false, GSI_CONTINUE_LINKING);
2989 gsi = gsi_last_bb (bb);
2990 t = gimple_omp_parallel_data_arg (entry_stmt);
2991 if (t == NULL)
2992 t1 = null_pointer_node;
2993 else
2994 t1 = build_fold_addr_expr (t);
2995 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
2997 if (ws_args)
2999 tree args = tree_cons (NULL, t2,
3000 tree_cons (NULL, t1,
3001 tree_cons (NULL, val, ws_args)));
3002 t = build_function_call_expr (built_in_decls[start_ix], args);
3004 else
3005 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
3007 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3008 false, GSI_CONTINUE_LINKING);
3010 t = gimple_omp_parallel_data_arg (entry_stmt);
3011 if (t == NULL)
3012 t = null_pointer_node;
3013 else
3014 t = build_fold_addr_expr (t);
3015 t = build_call_expr (gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3016 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3017 false, GSI_CONTINUE_LINKING);
3019 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
3020 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3021 false, GSI_CONTINUE_LINKING);
3025 /* Build the function call to GOMP_task to actually
3026 generate the task operation. BB is the block where to insert the code. */
3028 static void
3029 expand_task_call (basic_block bb, gimple entry_stmt)
3031 tree t, t1, t2, t3, flags, cond, c, clauses;
3032 gimple_stmt_iterator gsi;
3034 clauses = gimple_omp_task_clauses (entry_stmt);
3036 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3037 if (c)
3038 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3039 else
3040 cond = boolean_true_node;
3042 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3043 flags = build_int_cst (unsigned_type_node, (c ? 1 : 0));
3045 gsi = gsi_last_bb (bb);
3046 t = gimple_omp_task_data_arg (entry_stmt);
3047 if (t == NULL)
3048 t2 = null_pointer_node;
3049 else
3050 t2 = build_fold_addr_expr (t);
3051 t1 = build_fold_addr_expr (gimple_omp_task_child_fn (entry_stmt));
3052 t = gimple_omp_task_copy_fn (entry_stmt);
3053 if (t == NULL)
3054 t3 = null_pointer_node;
3055 else
3056 t3 = build_fold_addr_expr (t);
3058 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
3059 gimple_omp_task_arg_size (entry_stmt),
3060 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3062 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3063 false, GSI_CONTINUE_LINKING);
3067 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3068 catch handler and return it. This prevents programs from violating the
3069 structured block semantics with throws. */
3071 static gimple_seq
3072 maybe_catch_exception (gimple_seq body)
3074 gimple f, t;
3076 if (!flag_exceptions)
3077 return body;
3079 if (lang_protect_cleanup_actions)
3080 t = lang_protect_cleanup_actions ();
3081 else
3082 t = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
3084 f = gimple_build_eh_filter (NULL, gimple_seq_alloc_with_stmt (t));
3085 gimple_eh_filter_set_must_not_throw (f, true);
3087 t = gimple_build_try (body, gimple_seq_alloc_with_stmt (f),
3088 GIMPLE_TRY_CATCH);
3090 return gimple_seq_alloc_with_stmt (t);
3093 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3095 static tree
3096 list2chain (tree list)
3098 tree t;
3100 for (t = list; t; t = TREE_CHAIN (t))
3102 tree var = TREE_VALUE (t);
3103 if (TREE_CHAIN (t))
3104 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
3105 else
3106 TREE_CHAIN (var) = NULL_TREE;
3109 return list ? TREE_VALUE (list) : NULL_TREE;
3113 /* Remove barriers in REGION->EXIT's block. Note that this is only
3114 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3115 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3116 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3117 removed. */
3119 static void
3120 remove_exit_barrier (struct omp_region *region)
3122 gimple_stmt_iterator gsi;
3123 basic_block exit_bb;
3124 edge_iterator ei;
3125 edge e;
3126 gimple stmt;
3127 int any_addressable_vars = -1;
3129 exit_bb = region->exit;
3131 /* If the parallel region doesn't return, we don't have REGION->EXIT
3132 block at all. */
3133 if (! exit_bb)
3134 return;
3136 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3137 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3138 statements that can appear in between are extremely limited -- no
3139 memory operations at all. Here, we allow nothing at all, so the
3140 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3141 gsi = gsi_last_bb (exit_bb);
3142 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3143 gsi_prev (&gsi);
3144 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3145 return;
3147 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3149 gsi = gsi_last_bb (e->src);
3150 if (gsi_end_p (gsi))
3151 continue;
3152 stmt = gsi_stmt (gsi);
3153 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3154 && !gimple_omp_return_nowait_p (stmt))
3156 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3157 in many cases. If there could be tasks queued, the barrier
3158 might be needed to let the tasks run before some local
3159 variable of the parallel that the task uses as shared
3160 runs out of scope. The task can be spawned either
3161 from within current function (this would be easy to check)
3162 or from some function it calls and gets passed an address
3163 of such a variable. */
3164 if (any_addressable_vars < 0)
3166 gimple parallel_stmt = last_stmt (region->entry);
3167 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3168 tree local_decls = DECL_STRUCT_FUNCTION (child_fun)->local_decls;
3169 tree block;
3171 any_addressable_vars = 0;
3172 for (; local_decls; local_decls = TREE_CHAIN (local_decls))
3173 if (TREE_ADDRESSABLE (TREE_VALUE (local_decls)))
3175 any_addressable_vars = 1;
3176 break;
3178 for (block = gimple_block (stmt);
3179 !any_addressable_vars
3180 && block
3181 && TREE_CODE (block) == BLOCK;
3182 block = BLOCK_SUPERCONTEXT (block))
3184 for (local_decls = BLOCK_VARS (block);
3185 local_decls;
3186 local_decls = TREE_CHAIN (local_decls))
3187 if (TREE_ADDRESSABLE (local_decls))
3189 any_addressable_vars = 1;
3190 break;
3192 if (block == gimple_block (parallel_stmt))
3193 break;
3196 if (!any_addressable_vars)
3197 gimple_omp_return_set_nowait (stmt);
3202 static void
3203 remove_exit_barriers (struct omp_region *region)
3205 if (region->type == GIMPLE_OMP_PARALLEL)
3206 remove_exit_barrier (region);
3208 if (region->inner)
3210 region = region->inner;
3211 remove_exit_barriers (region);
3212 while (region->next)
3214 region = region->next;
3215 remove_exit_barriers (region);
3220 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3221 calls. These can't be declared as const functions, but
3222 within one parallel body they are constant, so they can be
3223 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3224 which are declared const. Similarly for task body, except
3225 that in untied task omp_get_thread_num () can change at any task
3226 scheduling point. */
3228 static void
3229 optimize_omp_library_calls (gimple entry_stmt)
3231 basic_block bb;
3232 gimple_stmt_iterator gsi;
3233 tree thr_num_id
3234 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
3235 tree num_thr_id
3236 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
3237 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3238 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3239 OMP_CLAUSE_UNTIED) != NULL);
3241 FOR_EACH_BB (bb)
3242 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3244 gimple call = gsi_stmt (gsi);
3245 tree decl;
3247 if (is_gimple_call (call)
3248 && (decl = gimple_call_fndecl (call))
3249 && DECL_EXTERNAL (decl)
3250 && TREE_PUBLIC (decl)
3251 && DECL_INITIAL (decl) == NULL)
3253 tree built_in;
3255 if (DECL_NAME (decl) == thr_num_id)
3257 /* In #pragma omp task untied omp_get_thread_num () can change
3258 during the execution of the task region. */
3259 if (untied_task)
3260 continue;
3261 built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
3263 else if (DECL_NAME (decl) == num_thr_id)
3264 built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
3265 else
3266 continue;
3268 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3269 || gimple_call_num_args (call) != 0)
3270 continue;
3272 if (flag_exceptions && !TREE_NOTHROW (decl))
3273 continue;
3275 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3276 || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
3277 != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
3278 continue;
3280 gimple_call_set_fndecl (call, built_in);
3285 /* Expand the OpenMP parallel or task directive starting at REGION. */
3287 static void
3288 expand_omp_taskreg (struct omp_region *region)
3290 basic_block entry_bb, exit_bb, new_bb;
3291 struct function *child_cfun;
3292 tree child_fn, block, t, ws_args, *tp;
3293 tree save_current;
3294 gimple_stmt_iterator gsi;
3295 gimple entry_stmt, stmt;
3296 edge e;
3298 entry_stmt = last_stmt (region->entry);
3299 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3300 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3301 /* If this function has been already instrumented, make sure
3302 the child function isn't instrumented again. */
3303 child_cfun->after_tree_profile = cfun->after_tree_profile;
3305 entry_bb = region->entry;
3306 exit_bb = region->exit;
3308 if (is_combined_parallel (region))
3309 ws_args = region->ws_args;
3310 else
3311 ws_args = NULL_TREE;
3313 if (child_cfun->cfg)
3315 /* Due to inlining, it may happen that we have already outlined
3316 the region, in which case all we need to do is make the
3317 sub-graph unreachable and emit the parallel call. */
3318 edge entry_succ_e, exit_succ_e;
3319 gimple_stmt_iterator gsi;
3321 entry_succ_e = single_succ_edge (entry_bb);
3323 gsi = gsi_last_bb (entry_bb);
3324 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3325 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3326 gsi_remove (&gsi, true);
3328 new_bb = entry_bb;
3329 if (exit_bb)
3331 exit_succ_e = single_succ_edge (exit_bb);
3332 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3334 remove_edge_and_dominated_blocks (entry_succ_e);
3336 else
3338 /* If the parallel region needs data sent from the parent
3339 function, then the very first statement (except possible
3340 tree profile counter updates) of the parallel body
3341 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3342 &.OMP_DATA_O is passed as an argument to the child function,
3343 we need to replace it with the argument as seen by the child
3344 function.
3346 In most cases, this will end up being the identity assignment
3347 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3348 a function call that has been inlined, the original PARM_DECL
3349 .OMP_DATA_I may have been converted into a different local
3350 variable. In which case, we need to keep the assignment. */
3351 if (gimple_omp_taskreg_data_arg (entry_stmt))
3353 basic_block entry_succ_bb = single_succ (entry_bb);
3354 gimple_stmt_iterator gsi;
3355 tree arg, narg;
3356 gimple parcopy_stmt = NULL;
3358 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3360 gimple stmt;
3362 gcc_assert (!gsi_end_p (gsi));
3363 stmt = gsi_stmt (gsi);
3364 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3365 continue;
3367 if (gimple_num_ops (stmt) == 2)
3369 tree arg = gimple_assign_rhs1 (stmt);
3371 /* We're ignore the subcode because we're
3372 effectively doing a STRIP_NOPS. */
3374 if (TREE_CODE (arg) == ADDR_EXPR
3375 && TREE_OPERAND (arg, 0)
3376 == gimple_omp_taskreg_data_arg (entry_stmt))
3378 parcopy_stmt = stmt;
3379 break;
3384 gcc_assert (parcopy_stmt != NULL);
3385 arg = DECL_ARGUMENTS (child_fn);
3387 if (!gimple_in_ssa_p (cfun))
3389 if (gimple_assign_lhs (parcopy_stmt) == arg)
3390 gsi_remove (&gsi, true);
3391 else
3393 /* ?? Is setting the subcode really necessary ?? */
3394 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3395 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3398 else
3400 /* If we are in ssa form, we must load the value from the default
3401 definition of the argument. That should not be defined now,
3402 since the argument is not used uninitialized. */
3403 gcc_assert (gimple_default_def (cfun, arg) == NULL);
3404 narg = make_ssa_name (arg, gimple_build_nop ());
3405 set_default_def (arg, narg);
3406 /* ?? Is setting the subcode really necessary ?? */
3407 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3408 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3409 update_stmt (parcopy_stmt);
3413 /* Declare local variables needed in CHILD_CFUN. */
3414 block = DECL_INITIAL (child_fn);
3415 BLOCK_VARS (block) = list2chain (child_cfun->local_decls);
3416 /* The gimplifier could record temporaries in parallel/task block
3417 rather than in containing function's local_decls chain,
3418 which would mean cgraph missed finalizing them. Do it now. */
3419 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
3420 if (TREE_CODE (t) == VAR_DECL
3421 && TREE_STATIC (t)
3422 && !DECL_EXTERNAL (t))
3423 varpool_finalize_decl (t);
3424 DECL_SAVED_TREE (child_fn) = NULL;
3425 gimple_set_body (child_fn, bb_seq (single_succ (entry_bb)));
3426 TREE_USED (block) = 1;
3428 /* Reset DECL_CONTEXT on function arguments. */
3429 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
3430 DECL_CONTEXT (t) = child_fn;
3432 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3433 so that it can be moved to the child function. */
3434 gsi = gsi_last_bb (entry_bb);
3435 stmt = gsi_stmt (gsi);
3436 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3437 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3438 gsi_remove (&gsi, true);
3439 e = split_block (entry_bb, stmt);
3440 entry_bb = e->dest;
3441 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3443 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3444 if (exit_bb)
3446 gsi = gsi_last_bb (exit_bb);
3447 gcc_assert (!gsi_end_p (gsi)
3448 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3449 stmt = gimple_build_return (NULL);
3450 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3451 gsi_remove (&gsi, true);
3454 /* Move the parallel region into CHILD_CFUN. */
3456 if (gimple_in_ssa_p (cfun))
3458 push_cfun (child_cfun);
3459 init_tree_ssa (child_cfun);
3460 init_ssa_operands ();
3461 cfun->gimple_df->in_ssa_p = true;
3462 pop_cfun ();
3463 block = NULL_TREE;
3465 else
3466 block = gimple_block (entry_stmt);
3468 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3469 if (exit_bb)
3470 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3472 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3473 for (tp = &child_cfun->local_decls; *tp; )
3474 if (DECL_CONTEXT (TREE_VALUE (*tp)) != cfun->decl)
3475 tp = &TREE_CHAIN (*tp);
3476 else
3477 *tp = TREE_CHAIN (*tp);
3479 /* Inform the callgraph about the new function. */
3480 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
3481 = cfun->curr_properties;
3482 cgraph_add_new_function (child_fn, true);
3484 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3485 fixed in a following pass. */
3486 push_cfun (child_cfun);
3487 save_current = current_function_decl;
3488 current_function_decl = child_fn;
3489 if (optimize)
3490 optimize_omp_library_calls (entry_stmt);
3491 rebuild_cgraph_edges ();
3493 /* Some EH regions might become dead, see PR34608. If
3494 pass_cleanup_cfg isn't the first pass to happen with the
3495 new child, these dead EH edges might cause problems.
3496 Clean them up now. */
3497 if (flag_exceptions)
3499 basic_block bb;
3500 bool changed = false;
3502 FOR_EACH_BB (bb)
3503 changed |= gimple_purge_dead_eh_edges (bb);
3504 if (changed)
3505 cleanup_tree_cfg ();
3507 if (gimple_in_ssa_p (cfun))
3508 update_ssa (TODO_update_ssa);
3509 current_function_decl = save_current;
3510 pop_cfun ();
3513 /* Emit a library call to launch the children threads. */
3514 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
3515 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3516 else
3517 expand_task_call (new_bb, entry_stmt);
3518 update_ssa (TODO_update_ssa_only_virtuals);
3522 /* A subroutine of expand_omp_for. Generate code for a parallel
3523 loop with any schedule. Given parameters:
3525 for (V = N1; V cond N2; V += STEP) BODY;
3527 where COND is "<" or ">", we generate pseudocode
3529 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3530 if (more) goto L0; else goto L3;
3532 V = istart0;
3533 iend = iend0;
3535 BODY;
3536 V += STEP;
3537 if (V cond iend) goto L1; else goto L2;
3539 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3542 If this is a combined omp parallel loop, instead of the call to
3543 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3545 For collapsed loops, given parameters:
3546 collapse(3)
3547 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3548 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3549 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3550 BODY;
3552 we generate pseudocode
3554 if (cond3 is <)
3555 adj = STEP3 - 1;
3556 else
3557 adj = STEP3 + 1;
3558 count3 = (adj + N32 - N31) / STEP3;
3559 if (cond2 is <)
3560 adj = STEP2 - 1;
3561 else
3562 adj = STEP2 + 1;
3563 count2 = (adj + N22 - N21) / STEP2;
3564 if (cond1 is <)
3565 adj = STEP1 - 1;
3566 else
3567 adj = STEP1 + 1;
3568 count1 = (adj + N12 - N11) / STEP1;
3569 count = count1 * count2 * count3;
3570 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3571 if (more) goto L0; else goto L3;
3573 V = istart0;
3574 T = V;
3575 V3 = N31 + (T % count3) * STEP3;
3576 T = T / count3;
3577 V2 = N21 + (T % count2) * STEP2;
3578 T = T / count2;
3579 V1 = N11 + T * STEP1;
3580 iend = iend0;
3582 BODY;
3583 V += 1;
3584 if (V < iend) goto L10; else goto L2;
3585 L10:
3586 V3 += STEP3;
3587 if (V3 cond3 N32) goto L1; else goto L11;
3588 L11:
3589 V3 = N31;
3590 V2 += STEP2;
3591 if (V2 cond2 N22) goto L1; else goto L12;
3592 L12:
3593 V2 = N21;
3594 V1 += STEP1;
3595 goto L1;
3597 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3602 static void
3603 expand_omp_for_generic (struct omp_region *region,
3604 struct omp_for_data *fd,
3605 enum built_in_function start_fn,
3606 enum built_in_function next_fn)
3608 tree type, istart0, iend0, iend;
3609 tree t, vmain, vback, bias = NULL_TREE;
3610 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3611 basic_block l2_bb = NULL, l3_bb = NULL;
3612 gimple_stmt_iterator gsi;
3613 gimple stmt;
3614 bool in_combined_parallel = is_combined_parallel (region);
3615 bool broken_loop = region->cont == NULL;
3616 edge e, ne;
3617 tree *counts = NULL;
3618 int i;
3620 gcc_assert (!broken_loop || !in_combined_parallel);
3621 gcc_assert (fd->iter_type == long_integer_type_node
3622 || !in_combined_parallel);
3624 type = TREE_TYPE (fd->loop.v);
3625 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3626 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3627 TREE_ADDRESSABLE (istart0) = 1;
3628 TREE_ADDRESSABLE (iend0) = 1;
3629 if (gimple_in_ssa_p (cfun))
3631 add_referenced_var (istart0);
3632 add_referenced_var (iend0);
3635 /* See if we need to bias by LLONG_MIN. */
3636 if (fd->iter_type == long_long_unsigned_type_node
3637 && TREE_CODE (type) == INTEGER_TYPE
3638 && !TYPE_UNSIGNED (type))
3640 tree n1, n2;
3642 if (fd->loop.cond_code == LT_EXPR)
3644 n1 = fd->loop.n1;
3645 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3647 else
3649 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3650 n2 = fd->loop.n1;
3652 if (TREE_CODE (n1) != INTEGER_CST
3653 || TREE_CODE (n2) != INTEGER_CST
3654 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3655 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3658 entry_bb = region->entry;
3659 cont_bb = region->cont;
3660 collapse_bb = NULL;
3661 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3662 gcc_assert (broken_loop
3663 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3664 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3665 l1_bb = single_succ (l0_bb);
3666 if (!broken_loop)
3668 l2_bb = create_empty_bb (cont_bb);
3669 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3670 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3672 else
3673 l2_bb = NULL;
3674 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3675 exit_bb = region->exit;
3677 gsi = gsi_last_bb (entry_bb);
3679 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
3680 if (fd->collapse > 1)
3682 /* collapsed loops need work for expansion in SSA form. */
3683 gcc_assert (!gimple_in_ssa_p (cfun));
3684 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3685 for (i = 0; i < fd->collapse; i++)
3687 tree itype = TREE_TYPE (fd->loops[i].v);
3689 if (POINTER_TYPE_P (itype))
3690 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
3691 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3692 ? -1 : 1));
3693 t = fold_build2 (PLUS_EXPR, itype,
3694 fold_convert (itype, fd->loops[i].step), t);
3695 t = fold_build2 (PLUS_EXPR, itype, t,
3696 fold_convert (itype, fd->loops[i].n2));
3697 t = fold_build2 (MINUS_EXPR, itype, t,
3698 fold_convert (itype, fd->loops[i].n1));
3699 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3700 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3701 fold_build1 (NEGATE_EXPR, itype, t),
3702 fold_build1 (NEGATE_EXPR, itype,
3703 fold_convert (itype,
3704 fd->loops[i].step)));
3705 else
3706 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3707 fold_convert (itype, fd->loops[i].step));
3708 t = fold_convert (type, t);
3709 if (TREE_CODE (t) == INTEGER_CST)
3710 counts[i] = t;
3711 else
3713 counts[i] = create_tmp_var (type, ".count");
3714 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3715 true, GSI_SAME_STMT);
3716 stmt = gimple_build_assign (counts[i], t);
3717 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3719 if (SSA_VAR_P (fd->loop.n2))
3721 if (i == 0)
3722 t = counts[0];
3723 else
3725 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3726 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3727 true, GSI_SAME_STMT);
3729 stmt = gimple_build_assign (fd->loop.n2, t);
3730 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3734 if (in_combined_parallel)
3736 /* In a combined parallel loop, emit a call to
3737 GOMP_loop_foo_next. */
3738 t = build_call_expr (built_in_decls[next_fn], 2,
3739 build_fold_addr_expr (istart0),
3740 build_fold_addr_expr (iend0));
3742 else
3744 tree t0, t1, t2, t3, t4;
3745 /* If this is not a combined parallel loop, emit a call to
3746 GOMP_loop_foo_start in ENTRY_BB. */
3747 t4 = build_fold_addr_expr (iend0);
3748 t3 = build_fold_addr_expr (istart0);
3749 t2 = fold_convert (fd->iter_type, fd->loop.step);
3750 if (POINTER_TYPE_P (type)
3751 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
3753 /* Avoid casting pointers to integer of a different size. */
3754 tree itype
3755 = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
3756 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
3757 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
3759 else
3761 t1 = fold_convert (fd->iter_type, fd->loop.n2);
3762 t0 = fold_convert (fd->iter_type, fd->loop.n1);
3764 if (bias)
3766 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
3767 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
3769 if (fd->iter_type == long_integer_type_node)
3771 if (fd->chunk_size)
3773 t = fold_convert (fd->iter_type, fd->chunk_size);
3774 t = build_call_expr (built_in_decls[start_fn], 6,
3775 t0, t1, t2, t, t3, t4);
3777 else
3778 t = build_call_expr (built_in_decls[start_fn], 5,
3779 t0, t1, t2, t3, t4);
3781 else
3783 tree t5;
3784 tree c_bool_type;
3786 /* The GOMP_loop_ull_*start functions have additional boolean
3787 argument, true for < loops and false for > loops.
3788 In Fortran, the C bool type can be different from
3789 boolean_type_node. */
3790 c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
3791 t5 = build_int_cst (c_bool_type,
3792 fd->loop.cond_code == LT_EXPR ? 1 : 0);
3793 if (fd->chunk_size)
3795 t = fold_convert (fd->iter_type, fd->chunk_size);
3796 t = build_call_expr (built_in_decls[start_fn], 7,
3797 t5, t0, t1, t2, t, t3, t4);
3799 else
3800 t = build_call_expr (built_in_decls[start_fn], 6,
3801 t5, t0, t1, t2, t3, t4);
3804 if (TREE_TYPE (t) != boolean_type_node)
3805 t = fold_build2 (NE_EXPR, boolean_type_node,
3806 t, build_int_cst (TREE_TYPE (t), 0));
3807 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3808 true, GSI_SAME_STMT);
3809 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
3811 /* Remove the GIMPLE_OMP_FOR statement. */
3812 gsi_remove (&gsi, true);
3814 /* Iteration setup for sequential loop goes in L0_BB. */
3815 gsi = gsi_start_bb (l0_bb);
3816 t = istart0;
3817 if (bias)
3818 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3819 if (POINTER_TYPE_P (type))
3820 t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type),
3821 0), t);
3822 t = fold_convert (type, t);
3823 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3824 false, GSI_CONTINUE_LINKING);
3825 stmt = gimple_build_assign (fd->loop.v, t);
3826 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3828 t = iend0;
3829 if (bias)
3830 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3831 if (POINTER_TYPE_P (type))
3832 t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type),
3833 0), t);
3834 t = fold_convert (type, t);
3835 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3836 false, GSI_CONTINUE_LINKING);
3837 if (fd->collapse > 1)
3839 tree tem = create_tmp_var (type, ".tem");
3841 stmt = gimple_build_assign (tem, fd->loop.v);
3842 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3843 for (i = fd->collapse - 1; i >= 0; i--)
3845 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
3846 itype = vtype;
3847 if (POINTER_TYPE_P (vtype))
3848 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (vtype), 0);
3849 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
3850 t = fold_convert (itype, t);
3851 t = fold_build2 (MULT_EXPR, itype, t,
3852 fold_convert (itype, fd->loops[i].step));
3853 if (POINTER_TYPE_P (vtype))
3854 t = fold_build2 (POINTER_PLUS_EXPR, vtype,
3855 fd->loops[i].n1, fold_convert (sizetype, t));
3856 else
3857 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3858 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3859 false, GSI_CONTINUE_LINKING);
3860 stmt = gimple_build_assign (fd->loops[i].v, t);
3861 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3862 if (i != 0)
3864 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3865 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3866 false, GSI_CONTINUE_LINKING);
3867 stmt = gimple_build_assign (tem, t);
3868 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3873 if (!broken_loop)
3875 /* Code to control the increment and predicate for the sequential
3876 loop goes in the CONT_BB. */
3877 gsi = gsi_last_bb (cont_bb);
3878 stmt = gsi_stmt (gsi);
3879 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
3880 vmain = gimple_omp_continue_control_use (stmt);
3881 vback = gimple_omp_continue_control_def (stmt);
3883 if (POINTER_TYPE_P (type))
3884 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
3885 fold_convert (sizetype, fd->loop.step));
3886 else
3887 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3888 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3889 true, GSI_SAME_STMT);
3890 stmt = gimple_build_assign (vback, t);
3891 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3893 t = build2 (fd->loop.cond_code, boolean_type_node, vback, iend);
3894 stmt = gimple_build_cond_empty (t);
3895 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3897 /* Remove GIMPLE_OMP_CONTINUE. */
3898 gsi_remove (&gsi, true);
3900 if (fd->collapse > 1)
3902 basic_block last_bb, bb;
3904 last_bb = cont_bb;
3905 for (i = fd->collapse - 1; i >= 0; i--)
3907 tree vtype = TREE_TYPE (fd->loops[i].v);
3909 bb = create_empty_bb (last_bb);
3910 gsi = gsi_start_bb (bb);
3912 if (i < fd->collapse - 1)
3914 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
3915 e->probability = REG_BR_PROB_BASE / 8;
3917 t = fd->loops[i + 1].n1;
3918 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3919 false, GSI_CONTINUE_LINKING);
3920 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
3921 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3923 else
3924 collapse_bb = bb;
3926 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
3928 if (POINTER_TYPE_P (vtype))
3929 t = fold_build2 (POINTER_PLUS_EXPR, vtype,
3930 fd->loops[i].v,
3931 fold_convert (sizetype, fd->loops[i].step));
3932 else
3933 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
3934 fd->loops[i].step);
3935 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3936 false, GSI_CONTINUE_LINKING);
3937 stmt = gimple_build_assign (fd->loops[i].v, t);
3938 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3940 if (i > 0)
3942 t = fd->loops[i].n2;
3943 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3944 false, GSI_CONTINUE_LINKING);
3945 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
3946 fd->loops[i].v, t);
3947 stmt = gimple_build_cond_empty (t);
3948 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3949 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
3950 e->probability = REG_BR_PROB_BASE * 7 / 8;
3952 else
3953 make_edge (bb, l1_bb, EDGE_FALLTHRU);
3954 last_bb = bb;
3958 /* Emit code to get the next parallel iteration in L2_BB. */
3959 gsi = gsi_start_bb (l2_bb);
3961 t = build_call_expr (built_in_decls[next_fn], 2,
3962 build_fold_addr_expr (istart0),
3963 build_fold_addr_expr (iend0));
3964 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3965 false, GSI_CONTINUE_LINKING);
3966 if (TREE_TYPE (t) != boolean_type_node)
3967 t = fold_build2 (NE_EXPR, boolean_type_node,
3968 t, build_int_cst (TREE_TYPE (t), 0));
3969 stmt = gimple_build_cond_empty (t);
3970 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3973 /* Add the loop cleanup function. */
3974 gsi = gsi_last_bb (exit_bb);
3975 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
3976 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
3977 else
3978 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
3979 stmt = gimple_build_call (t, 0);
3980 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3981 gsi_remove (&gsi, true);
3983 /* Connect the new blocks. */
3984 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
3985 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
3987 if (!broken_loop)
3989 gimple_seq phis;
3991 e = find_edge (cont_bb, l3_bb);
3992 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
3994 phis = phi_nodes (l3_bb);
3995 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
3997 gimple phi = gsi_stmt (gsi);
3998 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
3999 PHI_ARG_DEF_FROM_EDGE (phi, e));
4001 remove_edge (e);
4003 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4004 if (fd->collapse > 1)
4006 e = find_edge (cont_bb, l1_bb);
4007 remove_edge (e);
4008 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4010 else
4012 e = find_edge (cont_bb, l1_bb);
4013 e->flags = EDGE_TRUE_VALUE;
4015 e->probability = REG_BR_PROB_BASE * 7 / 8;
4016 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4017 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4019 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4020 recompute_dominator (CDI_DOMINATORS, l2_bb));
4021 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4022 recompute_dominator (CDI_DOMINATORS, l3_bb));
4023 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4024 recompute_dominator (CDI_DOMINATORS, l0_bb));
4025 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4026 recompute_dominator (CDI_DOMINATORS, l1_bb));
4031 /* A subroutine of expand_omp_for. Generate code for a parallel
4032 loop with static schedule and no specified chunk size. Given
4033 parameters:
4035 for (V = N1; V cond N2; V += STEP) BODY;
4037 where COND is "<" or ">", we generate pseudocode
4039 if (cond is <)
4040 adj = STEP - 1;
4041 else
4042 adj = STEP + 1;
4043 if ((__typeof (V)) -1 > 0 && cond is >)
4044 n = -(adj + N2 - N1) / -STEP;
4045 else
4046 n = (adj + N2 - N1) / STEP;
4047 q = n / nthreads;
4048 q += (q * nthreads != n);
4049 s0 = q * threadid;
4050 e0 = min(s0 + q, n);
4051 V = s0 * STEP + N1;
4052 if (s0 >= e0) goto L2; else goto L0;
4054 e = e0 * STEP + N1;
4056 BODY;
4057 V += STEP;
4058 if (V cond e) goto L1;
4062 static void
4063 expand_omp_for_static_nochunk (struct omp_region *region,
4064 struct omp_for_data *fd)
4066 tree n, q, s0, e0, e, t, nthreads, threadid;
4067 tree type, itype, vmain, vback;
4068 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
4069 basic_block fin_bb;
4070 gimple_stmt_iterator gsi;
4071 gimple stmt;
4073 itype = type = TREE_TYPE (fd->loop.v);
4074 if (POINTER_TYPE_P (type))
4075 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
4077 entry_bb = region->entry;
4078 cont_bb = region->cont;
4079 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4080 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4081 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4082 body_bb = single_succ (seq_start_bb);
4083 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4084 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4085 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4086 exit_bb = region->exit;
4088 /* Iteration space partitioning goes in ENTRY_BB. */
4089 gsi = gsi_last_bb (entry_bb);
4090 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4092 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
4093 t = fold_convert (itype, t);
4094 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4095 true, GSI_SAME_STMT);
4097 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
4098 t = fold_convert (itype, t);
4099 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4100 true, GSI_SAME_STMT);
4102 fd->loop.n1
4103 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4104 true, NULL_TREE, true, GSI_SAME_STMT);
4105 fd->loop.n2
4106 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4107 true, NULL_TREE, true, GSI_SAME_STMT);
4108 fd->loop.step
4109 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4110 true, NULL_TREE, true, GSI_SAME_STMT);
4112 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4113 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4114 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4115 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4116 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4117 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4118 fold_build1 (NEGATE_EXPR, itype, t),
4119 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4120 else
4121 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4122 t = fold_convert (itype, t);
4123 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4125 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4126 q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4128 t = fold_build2 (MULT_EXPR, itype, q, nthreads);
4129 t = fold_build2 (NE_EXPR, itype, t, n);
4130 t = fold_build2 (PLUS_EXPR, itype, q, t);
4131 q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4133 t = build2 (MULT_EXPR, itype, q, threadid);
4134 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4136 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4137 t = fold_build2 (MIN_EXPR, itype, t, n);
4138 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4140 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4141 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4143 /* Remove the GIMPLE_OMP_FOR statement. */
4144 gsi_remove (&gsi, true);
4146 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4147 gsi = gsi_start_bb (seq_start_bb);
4149 t = fold_convert (itype, s0);
4150 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4151 if (POINTER_TYPE_P (type))
4152 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4153 fold_convert (sizetype, t));
4154 else
4155 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4156 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4157 false, GSI_CONTINUE_LINKING);
4158 stmt = gimple_build_assign (fd->loop.v, t);
4159 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4161 t = fold_convert (itype, e0);
4162 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4163 if (POINTER_TYPE_P (type))
4164 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4165 fold_convert (sizetype, t));
4166 else
4167 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4168 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4169 false, GSI_CONTINUE_LINKING);
4171 /* The code controlling the sequential loop replaces the
4172 GIMPLE_OMP_CONTINUE. */
4173 gsi = gsi_last_bb (cont_bb);
4174 stmt = gsi_stmt (gsi);
4175 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4176 vmain = gimple_omp_continue_control_use (stmt);
4177 vback = gimple_omp_continue_control_def (stmt);
4179 if (POINTER_TYPE_P (type))
4180 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain,
4181 fold_convert (sizetype, fd->loop.step));
4182 else
4183 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4184 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4185 true, GSI_SAME_STMT);
4186 stmt = gimple_build_assign (vback, t);
4187 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4189 t = build2 (fd->loop.cond_code, boolean_type_node, vback, e);
4190 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4192 /* Remove the GIMPLE_OMP_CONTINUE statement. */
4193 gsi_remove (&gsi, true);
4195 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4196 gsi = gsi_last_bb (exit_bb);
4197 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4198 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
4199 false, GSI_SAME_STMT);
4200 gsi_remove (&gsi, true);
4202 /* Connect all the blocks. */
4203 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
4204 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
4206 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4207 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4209 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
4210 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4211 recompute_dominator (CDI_DOMINATORS, body_bb));
4212 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4213 recompute_dominator (CDI_DOMINATORS, fin_bb));
4217 /* A subroutine of expand_omp_for. Generate code for a parallel
4218 loop with static schedule and a specified chunk size. Given
4219 parameters:
4221 for (V = N1; V cond N2; V += STEP) BODY;
4223 where COND is "<" or ">", we generate pseudocode
4225 if (cond is <)
4226 adj = STEP - 1;
4227 else
4228 adj = STEP + 1;
4229 if ((__typeof (V)) -1 > 0 && cond is >)
4230 n = -(adj + N2 - N1) / -STEP;
4231 else
4232 n = (adj + N2 - N1) / STEP;
4233 trip = 0;
4234 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4235 here so that V is defined
4236 if the loop is not entered
4238 s0 = (trip * nthreads + threadid) * CHUNK;
4239 e0 = min(s0 + CHUNK, n);
4240 if (s0 < n) goto L1; else goto L4;
4242 V = s0 * STEP + N1;
4243 e = e0 * STEP + N1;
4245 BODY;
4246 V += STEP;
4247 if (V cond e) goto L2; else goto L3;
4249 trip += 1;
4250 goto L0;
4254 static void
4255 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
4257 tree n, s0, e0, e, t;
4258 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4259 tree type, itype, v_main, v_back, v_extra;
4260 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4261 basic_block trip_update_bb, cont_bb, fin_bb;
4262 gimple_stmt_iterator si;
4263 gimple stmt;
4264 edge se;
4266 itype = type = TREE_TYPE (fd->loop.v);
4267 if (POINTER_TYPE_P (type))
4268 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
4270 entry_bb = region->entry;
4271 se = split_block (entry_bb, last_stmt (entry_bb));
4272 entry_bb = se->src;
4273 iter_part_bb = se->dest;
4274 cont_bb = region->cont;
4275 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4276 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4277 == FALLTHRU_EDGE (cont_bb)->dest);
4278 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4279 body_bb = single_succ (seq_start_bb);
4280 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4281 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4282 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4283 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4284 exit_bb = region->exit;
4286 /* Trip and adjustment setup goes in ENTRY_BB. */
4287 si = gsi_last_bb (entry_bb);
4288 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
4290 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
4291 t = fold_convert (itype, t);
4292 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4293 true, GSI_SAME_STMT);
4295 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
4296 t = fold_convert (itype, t);
4297 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4298 true, GSI_SAME_STMT);
4300 fd->loop.n1
4301 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
4302 true, NULL_TREE, true, GSI_SAME_STMT);
4303 fd->loop.n2
4304 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
4305 true, NULL_TREE, true, GSI_SAME_STMT);
4306 fd->loop.step
4307 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
4308 true, NULL_TREE, true, GSI_SAME_STMT);
4309 fd->chunk_size
4310 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
4311 true, NULL_TREE, true, GSI_SAME_STMT);
4313 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4314 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4315 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4316 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4317 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4318 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4319 fold_build1 (NEGATE_EXPR, itype, t),
4320 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4321 else
4322 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4323 t = fold_convert (itype, t);
4324 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4325 true, GSI_SAME_STMT);
4327 trip_var = create_tmp_var (itype, ".trip");
4328 if (gimple_in_ssa_p (cfun))
4330 add_referenced_var (trip_var);
4331 trip_init = make_ssa_name (trip_var, NULL);
4332 trip_main = make_ssa_name (trip_var, NULL);
4333 trip_back = make_ssa_name (trip_var, NULL);
4335 else
4337 trip_init = trip_var;
4338 trip_main = trip_var;
4339 trip_back = trip_var;
4342 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
4343 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4345 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4346 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4347 if (POINTER_TYPE_P (type))
4348 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4349 fold_convert (sizetype, t));
4350 else
4351 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4352 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4353 true, GSI_SAME_STMT);
4355 /* Remove the GIMPLE_OMP_FOR. */
4356 gsi_remove (&si, true);
4358 /* Iteration space partitioning goes in ITER_PART_BB. */
4359 si = gsi_last_bb (iter_part_bb);
4361 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4362 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4363 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4364 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4365 false, GSI_CONTINUE_LINKING);
4367 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4368 t = fold_build2 (MIN_EXPR, itype, t, n);
4369 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4370 false, GSI_CONTINUE_LINKING);
4372 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4373 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
4375 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4376 si = gsi_start_bb (seq_start_bb);
4378 t = fold_convert (itype, s0);
4379 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4380 if (POINTER_TYPE_P (type))
4381 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4382 fold_convert (sizetype, t));
4383 else
4384 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4385 t = force_gimple_operand_gsi (&si, t, false, NULL_TREE,
4386 false, GSI_CONTINUE_LINKING);
4387 stmt = gimple_build_assign (fd->loop.v, t);
4388 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4390 t = fold_convert (itype, e0);
4391 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4392 if (POINTER_TYPE_P (type))
4393 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1,
4394 fold_convert (sizetype, t));
4395 else
4396 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4397 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4398 false, GSI_CONTINUE_LINKING);
4400 /* The code controlling the sequential loop goes in CONT_BB,
4401 replacing the GIMPLE_OMP_CONTINUE. */
4402 si = gsi_last_bb (cont_bb);
4403 stmt = gsi_stmt (si);
4404 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4405 v_main = gimple_omp_continue_control_use (stmt);
4406 v_back = gimple_omp_continue_control_def (stmt);
4408 if (POINTER_TYPE_P (type))
4409 t = fold_build2 (POINTER_PLUS_EXPR, type, v_main,
4410 fold_convert (sizetype, fd->loop.step));
4411 else
4412 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4413 stmt = gimple_build_assign (v_back, t);
4414 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4416 t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
4417 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
4419 /* Remove GIMPLE_OMP_CONTINUE. */
4420 gsi_remove (&si, true);
4422 /* Trip update code goes into TRIP_UPDATE_BB. */
4423 si = gsi_start_bb (trip_update_bb);
4425 t = build_int_cst (itype, 1);
4426 t = build2 (PLUS_EXPR, itype, trip_main, t);
4427 stmt = gimple_build_assign (trip_back, t);
4428 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4430 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4431 si = gsi_last_bb (exit_bb);
4432 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
4433 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4434 false, GSI_SAME_STMT);
4435 gsi_remove (&si, true);
4437 /* Connect the new blocks. */
4438 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4439 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4441 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4442 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4444 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4446 if (gimple_in_ssa_p (cfun))
4448 gimple_stmt_iterator psi;
4449 gimple phi;
4450 edge re, ene;
4451 edge_var_map_vector head;
4452 edge_var_map *vm;
4453 size_t i;
4455 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4456 remove arguments of the phi nodes in fin_bb. We need to create
4457 appropriate phi nodes in iter_part_bb instead. */
4458 se = single_pred_edge (fin_bb);
4459 re = single_succ_edge (trip_update_bb);
4460 head = redirect_edge_var_map_vector (re);
4461 ene = single_succ_edge (entry_bb);
4463 psi = gsi_start_phis (fin_bb);
4464 for (i = 0; !gsi_end_p (psi) && VEC_iterate (edge_var_map, head, i, vm);
4465 gsi_next (&psi), ++i)
4467 gimple nphi;
4469 phi = gsi_stmt (psi);
4470 t = gimple_phi_result (phi);
4471 gcc_assert (t == redirect_edge_var_map_result (vm));
4472 nphi = create_phi_node (t, iter_part_bb);
4473 SSA_NAME_DEF_STMT (t) = nphi;
4475 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4476 /* A special case -- fd->loop.v is not yet computed in
4477 iter_part_bb, we need to use v_extra instead. */
4478 if (t == fd->loop.v)
4479 t = v_extra;
4480 add_phi_arg (nphi, t, ene);
4481 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re);
4483 gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
4484 redirect_edge_var_map_clear (re);
4485 while (1)
4487 psi = gsi_start_phis (fin_bb);
4488 if (gsi_end_p (psi))
4489 break;
4490 remove_phi_node (&psi, false);
4493 /* Make phi node for trip. */
4494 phi = create_phi_node (trip_main, iter_part_bb);
4495 SSA_NAME_DEF_STMT (trip_main) = phi;
4496 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
4497 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
4500 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4501 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4502 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4503 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4504 recompute_dominator (CDI_DOMINATORS, fin_bb));
4505 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4506 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4507 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4508 recompute_dominator (CDI_DOMINATORS, body_bb));
4512 /* Expand the OpenMP loop defined by REGION. */
4514 static void
4515 expand_omp_for (struct omp_region *region)
4517 struct omp_for_data fd;
4518 struct omp_for_data_loop *loops;
4520 loops
4521 = (struct omp_for_data_loop *)
4522 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
4523 * sizeof (struct omp_for_data_loop));
4524 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4525 region->sched_kind = fd.sched_kind;
4527 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4528 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4529 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4530 if (region->cont)
4532 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4533 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4534 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4537 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4538 && !fd.have_ordered
4539 && fd.collapse == 1
4540 && region->cont != NULL)
4542 if (fd.chunk_size == NULL)
4543 expand_omp_for_static_nochunk (region, &fd);
4544 else
4545 expand_omp_for_static_chunk (region, &fd);
4547 else
4549 int fn_index, start_ix, next_ix;
4551 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4552 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4553 ? 3 : fd.sched_kind;
4554 fn_index += fd.have_ordered * 4;
4555 start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
4556 next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
4557 if (fd.iter_type == long_long_unsigned_type_node)
4559 start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4560 - BUILT_IN_GOMP_LOOP_STATIC_START;
4561 next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4562 - BUILT_IN_GOMP_LOOP_STATIC_NEXT;
4564 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
4565 (enum built_in_function) next_ix);
4568 update_ssa (TODO_update_ssa_only_virtuals);
4572 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4574 v = GOMP_sections_start (n);
4576 switch (v)
4578 case 0:
4579 goto L2;
4580 case 1:
4581 section 1;
4582 goto L1;
4583 case 2:
4585 case n:
4587 default:
4588 abort ();
4591 v = GOMP_sections_next ();
4592 goto L0;
4594 reduction;
4596 If this is a combined parallel sections, replace the call to
4597 GOMP_sections_start with call to GOMP_sections_next. */
4599 static void
4600 expand_omp_sections (struct omp_region *region)
4602 tree t, u, vin = NULL, vmain, vnext, l1, l2;
4603 VEC (tree,heap) *label_vec;
4604 unsigned len;
4605 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
4606 gimple_stmt_iterator si, switch_si;
4607 gimple sections_stmt, stmt, cont;
4608 edge_iterator ei;
4609 edge e;
4610 struct omp_region *inner;
4611 unsigned i, casei;
4612 bool exit_reachable = region->cont != NULL;
4614 gcc_assert (exit_reachable == (region->exit != NULL));
4615 entry_bb = region->entry;
4616 l0_bb = single_succ (entry_bb);
4617 l1_bb = region->cont;
4618 l2_bb = region->exit;
4619 if (exit_reachable)
4621 if (single_pred (l2_bb) == l0_bb)
4622 l2 = gimple_block_label (l2_bb);
4623 else
4625 /* This can happen if there are reductions. */
4626 len = EDGE_COUNT (l0_bb->succs);
4627 gcc_assert (len > 0);
4628 e = EDGE_SUCC (l0_bb, len - 1);
4629 si = gsi_last_bb (e->dest);
4630 l2 = NULL_TREE;
4631 if (gsi_end_p (si)
4632 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4633 l2 = gimple_block_label (e->dest);
4634 else
4635 FOR_EACH_EDGE (e, ei, l0_bb->succs)
4637 si = gsi_last_bb (e->dest);
4638 if (gsi_end_p (si)
4639 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4641 l2 = gimple_block_label (e->dest);
4642 break;
4646 default_bb = create_empty_bb (l1_bb->prev_bb);
4647 l1 = gimple_block_label (l1_bb);
4649 else
4651 default_bb = create_empty_bb (l0_bb);
4652 l1 = NULL_TREE;
4653 l2 = gimple_block_label (default_bb);
4656 /* We will build a switch() with enough cases for all the
4657 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
4658 and a default case to abort if something goes wrong. */
4659 len = EDGE_COUNT (l0_bb->succs);
4661 /* Use VEC_quick_push on label_vec throughout, since we know the size
4662 in advance. */
4663 label_vec = VEC_alloc (tree, heap, len);
4665 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
4666 GIMPLE_OMP_SECTIONS statement. */
4667 si = gsi_last_bb (entry_bb);
4668 sections_stmt = gsi_stmt (si);
4669 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
4670 vin = gimple_omp_sections_control (sections_stmt);
4671 if (!is_combined_parallel (region))
4673 /* If we are not inside a combined parallel+sections region,
4674 call GOMP_sections_start. */
4675 t = build_int_cst (unsigned_type_node,
4676 exit_reachable ? len - 1 : len);
4677 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
4678 stmt = gimple_build_call (u, 1, t);
4680 else
4682 /* Otherwise, call GOMP_sections_next. */
4683 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
4684 stmt = gimple_build_call (u, 0);
4686 gimple_call_set_lhs (stmt, vin);
4687 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4688 gsi_remove (&si, true);
4690 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
4691 L0_BB. */
4692 switch_si = gsi_last_bb (l0_bb);
4693 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
4694 if (exit_reachable)
4696 cont = last_stmt (l1_bb);
4697 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
4698 vmain = gimple_omp_continue_control_use (cont);
4699 vnext = gimple_omp_continue_control_def (cont);
4701 else
4703 vmain = vin;
4704 vnext = NULL_TREE;
4707 i = 0;
4708 if (exit_reachable)
4710 t = build3 (CASE_LABEL_EXPR, void_type_node,
4711 build_int_cst (unsigned_type_node, 0), NULL, l2);
4712 VEC_quick_push (tree, label_vec, t);
4713 i++;
4716 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
4717 for (inner = region->inner, casei = 1;
4718 inner;
4719 inner = inner->next, i++, casei++)
4721 basic_block s_entry_bb, s_exit_bb;
4723 /* Skip optional reduction region. */
4724 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
4726 --i;
4727 --casei;
4728 continue;
4731 s_entry_bb = inner->entry;
4732 s_exit_bb = inner->exit;
4734 t = gimple_block_label (s_entry_bb);
4735 u = build_int_cst (unsigned_type_node, casei);
4736 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
4737 VEC_quick_push (tree, label_vec, u);
4739 si = gsi_last_bb (s_entry_bb);
4740 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
4741 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
4742 gsi_remove (&si, true);
4743 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
4745 if (s_exit_bb == NULL)
4746 continue;
4748 si = gsi_last_bb (s_exit_bb);
4749 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4750 gsi_remove (&si, true);
4752 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
4755 /* Error handling code goes in DEFAULT_BB. */
4756 t = gimple_block_label (default_bb);
4757 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
4758 make_edge (l0_bb, default_bb, 0);
4760 stmt = gimple_build_switch_vec (vmain, u, label_vec);
4761 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
4762 gsi_remove (&switch_si, true);
4763 VEC_free (tree, heap, label_vec);
4765 si = gsi_start_bb (default_bb);
4766 stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
4767 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4769 if (exit_reachable)
4771 /* Code to get the next section goes in L1_BB. */
4772 si = gsi_last_bb (l1_bb);
4773 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
4775 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
4776 gimple_call_set_lhs (stmt, vnext);
4777 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4778 gsi_remove (&si, true);
4780 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
4782 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
4783 si = gsi_last_bb (l2_bb);
4784 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
4785 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
4786 else
4787 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
4788 stmt = gimple_build_call (t, 0);
4789 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4790 gsi_remove (&si, true);
4793 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
4797 /* Expand code for an OpenMP single directive. We've already expanded
4798 much of the code, here we simply place the GOMP_barrier call. */
4800 static void
4801 expand_omp_single (struct omp_region *region)
4803 basic_block entry_bb, exit_bb;
4804 gimple_stmt_iterator si;
4805 bool need_barrier = false;
4807 entry_bb = region->entry;
4808 exit_bb = region->exit;
4810 si = gsi_last_bb (entry_bb);
4811 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
4812 be removed. We need to ensure that the thread that entered the single
4813 does not exit before the data is copied out by the other threads. */
4814 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
4815 OMP_CLAUSE_COPYPRIVATE))
4816 need_barrier = true;
4817 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
4818 gsi_remove (&si, true);
4819 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4821 si = gsi_last_bb (exit_bb);
4822 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
4823 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4824 false, GSI_SAME_STMT);
4825 gsi_remove (&si, true);
4826 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4830 /* Generic expansion for OpenMP synchronization directives: master,
4831 ordered and critical. All we need to do here is remove the entry
4832 and exit markers for REGION. */
4834 static void
4835 expand_omp_synch (struct omp_region *region)
4837 basic_block entry_bb, exit_bb;
4838 gimple_stmt_iterator si;
4840 entry_bb = region->entry;
4841 exit_bb = region->exit;
4843 si = gsi_last_bb (entry_bb);
4844 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
4845 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
4846 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
4847 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
4848 gsi_remove (&si, true);
4849 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4851 if (exit_bb)
4853 si = gsi_last_bb (exit_bb);
4854 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4855 gsi_remove (&si, true);
4856 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4860 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
4861 operation as a __sync_fetch_and_op builtin. INDEX is log2 of the
4862 size of the data type, and thus usable to find the index of the builtin
4863 decl. Returns false if the expression is not of the proper form. */
4865 static bool
4866 expand_omp_atomic_fetch_op (basic_block load_bb,
4867 tree addr, tree loaded_val,
4868 tree stored_val, int index)
4870 enum built_in_function base;
4871 tree decl, itype, call;
4872 enum insn_code *optab;
4873 tree rhs;
4874 basic_block store_bb = single_succ (load_bb);
4875 gimple_stmt_iterator gsi;
4876 gimple stmt;
4878 /* We expect to find the following sequences:
4880 load_bb:
4881 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
4883 store_bb:
4884 val = tmp OP something; (or: something OP tmp)
4885 GIMPLE_OMP_STORE (val)
4887 ???FIXME: Allow a more flexible sequence.
4888 Perhaps use data flow to pick the statements.
4892 gsi = gsi_after_labels (store_bb);
4893 stmt = gsi_stmt (gsi);
4894 if (!is_gimple_assign (stmt))
4895 return false;
4896 gsi_next (&gsi);
4897 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
4898 return false;
4900 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
4901 return false;
4903 /* Check for one of the supported fetch-op operations. */
4904 switch (gimple_assign_rhs_code (stmt))
4906 case PLUS_EXPR:
4907 case POINTER_PLUS_EXPR:
4908 base = BUILT_IN_FETCH_AND_ADD_N;
4909 optab = sync_add_optab;
4910 break;
4911 case MINUS_EXPR:
4912 base = BUILT_IN_FETCH_AND_SUB_N;
4913 optab = sync_add_optab;
4914 break;
4915 case BIT_AND_EXPR:
4916 base = BUILT_IN_FETCH_AND_AND_N;
4917 optab = sync_and_optab;
4918 break;
4919 case BIT_IOR_EXPR:
4920 base = BUILT_IN_FETCH_AND_OR_N;
4921 optab = sync_ior_optab;
4922 break;
4923 case BIT_XOR_EXPR:
4924 base = BUILT_IN_FETCH_AND_XOR_N;
4925 optab = sync_xor_optab;
4926 break;
4927 default:
4928 return false;
4930 /* Make sure the expression is of the proper form. */
4931 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
4932 rhs = gimple_assign_rhs2 (stmt);
4933 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
4934 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
4935 rhs = gimple_assign_rhs1 (stmt);
4936 else
4937 return false;
4939 decl = built_in_decls[base + index + 1];
4940 itype = TREE_TYPE (TREE_TYPE (decl));
4942 if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing)
4943 return false;
4945 gsi = gsi_last_bb (load_bb);
4946 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
4947 call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
4948 call = fold_convert (void_type_node, call);
4949 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
4950 gsi_remove (&gsi, true);
4952 gsi = gsi_last_bb (store_bb);
4953 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
4954 gsi_remove (&gsi, true);
4955 gsi = gsi_last_bb (store_bb);
4956 gsi_remove (&gsi, true);
4958 if (gimple_in_ssa_p (cfun))
4959 update_ssa (TODO_update_ssa_no_phi);
4961 return true;
4964 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
4966 oldval = *addr;
4967 repeat:
4968 newval = rhs; // with oldval replacing *addr in rhs
4969 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
4970 if (oldval != newval)
4971 goto repeat;
4973 INDEX is log2 of the size of the data type, and thus usable to find the
4974 index of the builtin decl. */
4976 static bool
4977 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
4978 tree addr, tree loaded_val, tree stored_val,
4979 int index)
4981 tree loadedi, storedi, initial, new_storedi, old_vali;
4982 tree type, itype, cmpxchg, iaddr;
4983 gimple_stmt_iterator si;
4984 basic_block loop_header = single_succ (load_bb);
4985 gimple phi, stmt;
4986 edge e;
4988 cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1];
4989 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
4990 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
4992 if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing)
4993 return false;
4995 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
4996 si = gsi_last_bb (load_bb);
4997 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
4999 /* For floating-point values, we'll need to view-convert them to integers
5000 so that we can perform the atomic compare and swap. Simplify the
5001 following code by always setting up the "i"ntegral variables. */
5002 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
5004 tree iaddr_val;
5006 iaddr = create_tmp_var (build_pointer_type (itype), NULL);
5007 iaddr_val
5008 = force_gimple_operand_gsi (&si,
5009 fold_convert (TREE_TYPE (iaddr), addr),
5010 false, NULL_TREE, true, GSI_SAME_STMT);
5011 stmt = gimple_build_assign (iaddr, iaddr_val);
5012 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5013 DECL_NO_TBAA_P (iaddr) = 1;
5014 DECL_POINTER_ALIAS_SET (iaddr) = 0;
5015 loadedi = create_tmp_var (itype, NULL);
5016 if (gimple_in_ssa_p (cfun))
5018 add_referenced_var (iaddr);
5019 add_referenced_var (loadedi);
5020 loadedi = make_ssa_name (loadedi, NULL);
5023 else
5025 iaddr = addr;
5026 loadedi = loaded_val;
5029 initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr),
5030 true, NULL_TREE, true, GSI_SAME_STMT);
5032 /* Move the value to the LOADEDI temporary. */
5033 if (gimple_in_ssa_p (cfun))
5035 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
5036 phi = create_phi_node (loadedi, loop_header);
5037 SSA_NAME_DEF_STMT (loadedi) = phi;
5038 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
5039 initial);
5041 else
5042 gsi_insert_before (&si,
5043 gimple_build_assign (loadedi, initial),
5044 GSI_SAME_STMT);
5045 if (loadedi != loaded_val)
5047 gimple_stmt_iterator gsi2;
5048 tree x;
5050 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
5051 gsi2 = gsi_start_bb (loop_header);
5052 if (gimple_in_ssa_p (cfun))
5054 gimple stmt;
5055 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5056 true, GSI_SAME_STMT);
5057 stmt = gimple_build_assign (loaded_val, x);
5058 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
5060 else
5062 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
5063 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5064 true, GSI_SAME_STMT);
5067 gsi_remove (&si, true);
5069 si = gsi_last_bb (store_bb);
5070 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5072 if (iaddr == addr)
5073 storedi = stored_val;
5074 else
5075 storedi =
5076 force_gimple_operand_gsi (&si,
5077 build1 (VIEW_CONVERT_EXPR, itype,
5078 stored_val), true, NULL_TREE, true,
5079 GSI_SAME_STMT);
5081 /* Build the compare&swap statement. */
5082 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
5083 new_storedi = force_gimple_operand_gsi (&si,
5084 fold_convert (TREE_TYPE (loadedi),
5085 new_storedi),
5086 true, NULL_TREE,
5087 true, GSI_SAME_STMT);
5089 if (gimple_in_ssa_p (cfun))
5090 old_vali = loadedi;
5091 else
5093 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
5094 if (gimple_in_ssa_p (cfun))
5095 add_referenced_var (old_vali);
5096 stmt = gimple_build_assign (old_vali, loadedi);
5097 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5099 stmt = gimple_build_assign (loadedi, new_storedi);
5100 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5103 /* Note that we always perform the comparison as an integer, even for
5104 floating point. This allows the atomic operation to properly
5105 succeed even with NaNs and -0.0. */
5106 stmt = gimple_build_cond_empty
5107 (build2 (NE_EXPR, boolean_type_node,
5108 new_storedi, old_vali));
5109 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5111 /* Update cfg. */
5112 e = single_succ_edge (store_bb);
5113 e->flags &= ~EDGE_FALLTHRU;
5114 e->flags |= EDGE_FALSE_VALUE;
5116 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
5118 /* Copy the new value to loadedi (we already did that before the condition
5119 if we are not in SSA). */
5120 if (gimple_in_ssa_p (cfun))
5122 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
5123 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
5126 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
5127 gsi_remove (&si, true);
5129 if (gimple_in_ssa_p (cfun))
5130 update_ssa (TODO_update_ssa_no_phi);
5132 return true;
5135 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5137 GOMP_atomic_start ();
5138 *addr = rhs;
5139 GOMP_atomic_end ();
5141 The result is not globally atomic, but works so long as all parallel
5142 references are within #pragma omp atomic directives. According to
5143 responses received from omp@openmp.org, appears to be within spec.
5144 Which makes sense, since that's how several other compilers handle
5145 this situation as well.
5146 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
5147 expanding. STORED_VAL is the operand of the matching
5148 GIMPLE_OMP_ATOMIC_STORE.
5150 We replace
5151 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
5152 loaded_val = *addr;
5154 and replace
5155 GIMPLE_OMP_ATOMIC_ATORE (stored_val) with
5156 *addr = stored_val;
5159 static bool
5160 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
5161 tree addr, tree loaded_val, tree stored_val)
5163 gimple_stmt_iterator si;
5164 gimple stmt;
5165 tree t;
5167 si = gsi_last_bb (load_bb);
5168 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5170 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
5171 t = build_function_call_expr (t, 0);
5172 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5174 stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr));
5175 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5176 gsi_remove (&si, true);
5178 si = gsi_last_bb (store_bb);
5179 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5181 stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)),
5182 stored_val);
5183 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5185 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
5186 t = build_function_call_expr (t, 0);
5187 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5188 gsi_remove (&si, true);
5190 if (gimple_in_ssa_p (cfun))
5191 update_ssa (TODO_update_ssa_no_phi);
5192 return true;
5195 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
5196 using expand_omp_atomic_fetch_op. If it failed, we try to
5197 call expand_omp_atomic_pipeline, and if it fails too, the
5198 ultimate fallback is wrapping the operation in a mutex
5199 (expand_omp_atomic_mutex). REGION is the atomic region built
5200 by build_omp_regions_1(). */
5202 static void
5203 expand_omp_atomic (struct omp_region *region)
5205 basic_block load_bb = region->entry, store_bb = region->exit;
5206 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
5207 tree loaded_val = gimple_omp_atomic_load_lhs (load);
5208 tree addr = gimple_omp_atomic_load_rhs (load);
5209 tree stored_val = gimple_omp_atomic_store_val (store);
5210 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5211 HOST_WIDE_INT index;
5213 /* Make sure the type is one of the supported sizes. */
5214 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
5215 index = exact_log2 (index);
5216 if (index >= 0 && index <= 4)
5218 unsigned int align = TYPE_ALIGN_UNIT (type);
5220 /* __sync builtins require strict data alignment. */
5221 if (exact_log2 (align) >= index)
5223 /* When possible, use specialized atomic update functions. */
5224 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5225 && store_bb == single_succ (load_bb))
5227 if (expand_omp_atomic_fetch_op (load_bb, addr,
5228 loaded_val, stored_val, index))
5229 return;
5232 /* If we don't have specialized __sync builtins, try and implement
5233 as a compare and swap loop. */
5234 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5235 loaded_val, stored_val, index))
5236 return;
5240 /* The ultimate fallback is wrapping the operation in a mutex. */
5241 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5245 /* Expand the parallel region tree rooted at REGION. Expansion
5246 proceeds in depth-first order. Innermost regions are expanded
5247 first. This way, parallel regions that require a new function to
5248 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
5249 internal dependencies in their body. */
5251 static void
5252 expand_omp (struct omp_region *region)
5254 while (region)
5256 location_t saved_location;
5258 /* First, determine whether this is a combined parallel+workshare
5259 region. */
5260 if (region->type == GIMPLE_OMP_PARALLEL)
5261 determine_parallel_type (region);
5263 if (region->inner)
5264 expand_omp (region->inner);
5266 saved_location = input_location;
5267 if (gimple_has_location (last_stmt (region->entry)))
5268 input_location = gimple_location (last_stmt (region->entry));
5270 switch (region->type)
5272 case GIMPLE_OMP_PARALLEL:
5273 case GIMPLE_OMP_TASK:
5274 expand_omp_taskreg (region);
5275 break;
5277 case GIMPLE_OMP_FOR:
5278 expand_omp_for (region);
5279 break;
5281 case GIMPLE_OMP_SECTIONS:
5282 expand_omp_sections (region);
5283 break;
5285 case GIMPLE_OMP_SECTION:
5286 /* Individual omp sections are handled together with their
5287 parent GIMPLE_OMP_SECTIONS region. */
5288 break;
5290 case GIMPLE_OMP_SINGLE:
5291 expand_omp_single (region);
5292 break;
5294 case GIMPLE_OMP_MASTER:
5295 case GIMPLE_OMP_ORDERED:
5296 case GIMPLE_OMP_CRITICAL:
5297 expand_omp_synch (region);
5298 break;
5300 case GIMPLE_OMP_ATOMIC_LOAD:
5301 expand_omp_atomic (region);
5302 break;
5304 default:
5305 gcc_unreachable ();
5308 input_location = saved_location;
5309 region = region->next;
5314 /* Helper for build_omp_regions. Scan the dominator tree starting at
5315 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5316 true, the function ends once a single tree is built (otherwise, whole
5317 forest of OMP constructs may be built). */
5319 static void
5320 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5321 bool single_tree)
5323 gimple_stmt_iterator gsi;
5324 gimple stmt;
5325 basic_block son;
5327 gsi = gsi_last_bb (bb);
5328 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
5330 struct omp_region *region;
5331 enum gimple_code code;
5333 stmt = gsi_stmt (gsi);
5334 code = gimple_code (stmt);
5335 if (code == GIMPLE_OMP_RETURN)
5337 /* STMT is the return point out of region PARENT. Mark it
5338 as the exit point and make PARENT the immediately
5339 enclosing region. */
5340 gcc_assert (parent);
5341 region = parent;
5342 region->exit = bb;
5343 parent = parent->outer;
5345 else if (code == GIMPLE_OMP_ATOMIC_STORE)
5347 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
5348 GIMPLE_OMP_RETURN, but matches with
5349 GIMPLE_OMP_ATOMIC_LOAD. */
5350 gcc_assert (parent);
5351 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
5352 region = parent;
5353 region->exit = bb;
5354 parent = parent->outer;
5357 else if (code == GIMPLE_OMP_CONTINUE)
5359 gcc_assert (parent);
5360 parent->cont = bb;
5362 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
5364 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
5365 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
5368 else
5370 /* Otherwise, this directive becomes the parent for a new
5371 region. */
5372 region = new_omp_region (bb, code, parent);
5373 parent = region;
5377 if (single_tree && !parent)
5378 return;
5380 for (son = first_dom_son (CDI_DOMINATORS, bb);
5381 son;
5382 son = next_dom_son (CDI_DOMINATORS, son))
5383 build_omp_regions_1 (son, parent, single_tree);
5386 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5387 root_omp_region. */
5389 static void
5390 build_omp_regions_root (basic_block root)
5392 gcc_assert (root_omp_region == NULL);
5393 build_omp_regions_1 (root, NULL, true);
5394 gcc_assert (root_omp_region != NULL);
5397 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5399 void
5400 omp_expand_local (basic_block head)
5402 build_omp_regions_root (head);
5403 if (dump_file && (dump_flags & TDF_DETAILS))
5405 fprintf (dump_file, "\nOMP region tree\n\n");
5406 dump_omp_region (dump_file, root_omp_region, 0);
5407 fprintf (dump_file, "\n");
5410 remove_exit_barriers (root_omp_region);
5411 expand_omp (root_omp_region);
5413 free_omp_regions ();
5416 /* Scan the CFG and build a tree of OMP regions. Return the root of
5417 the OMP region tree. */
5419 static void
5420 build_omp_regions (void)
5422 gcc_assert (root_omp_region == NULL);
5423 calculate_dominance_info (CDI_DOMINATORS);
5424 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5427 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5429 static unsigned int
5430 execute_expand_omp (void)
5432 build_omp_regions ();
5434 if (!root_omp_region)
5435 return 0;
5437 if (dump_file)
5439 fprintf (dump_file, "\nOMP region tree\n\n");
5440 dump_omp_region (dump_file, root_omp_region, 0);
5441 fprintf (dump_file, "\n");
5444 remove_exit_barriers (root_omp_region);
5446 expand_omp (root_omp_region);
5448 cleanup_tree_cfg ();
5450 free_omp_regions ();
5452 return 0;
5455 /* OMP expansion -- the default pass, run before creation of SSA form. */
5457 static bool
5458 gate_expand_omp (void)
5460 return (flag_openmp != 0 && errorcount == 0);
5463 struct gimple_opt_pass pass_expand_omp =
5466 GIMPLE_PASS,
5467 "ompexp", /* name */
5468 gate_expand_omp, /* gate */
5469 execute_expand_omp, /* execute */
5470 NULL, /* sub */
5471 NULL, /* next */
5472 0, /* static_pass_number */
5473 TV_NONE, /* tv_id */
5474 PROP_gimple_any, /* properties_required */
5475 0, /* properties_provided */
5476 0, /* properties_destroyed */
5477 0, /* todo_flags_start */
5478 TODO_dump_func /* todo_flags_finish */
5482 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
5484 /* Lower the OpenMP sections directive in the current statement in GSI_P.
5485 CTX is the enclosing OMP context for the current statement. */
5487 static void
5488 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5490 tree block, control;
5491 gimple_stmt_iterator tgsi;
5492 unsigned i, len;
5493 gimple stmt, new_stmt, bind, t;
5494 gimple_seq ilist, dlist, olist, new_body, body;
5495 struct gimplify_ctx gctx;
5497 stmt = gsi_stmt (*gsi_p);
5499 push_gimplify_context (&gctx);
5501 dlist = NULL;
5502 ilist = NULL;
5503 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
5504 &ilist, &dlist, ctx);
5506 tgsi = gsi_start (gimple_omp_body (stmt));
5507 for (len = 0; !gsi_end_p (tgsi); len++, gsi_next (&tgsi))
5508 continue;
5510 tgsi = gsi_start (gimple_omp_body (stmt));
5511 body = NULL;
5512 for (i = 0; i < len; i++, gsi_next (&tgsi))
5514 omp_context *sctx;
5515 gimple sec_start;
5517 sec_start = gsi_stmt (tgsi);
5518 sctx = maybe_lookup_ctx (sec_start);
5519 gcc_assert (sctx);
5521 gimple_seq_add_stmt (&body, sec_start);
5523 lower_omp (gimple_omp_body (sec_start), sctx);
5524 gimple_seq_add_seq (&body, gimple_omp_body (sec_start));
5525 gimple_omp_set_body (sec_start, NULL);
5527 if (i == len - 1)
5529 gimple_seq l = NULL;
5530 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
5531 &l, ctx);
5532 gimple_seq_add_seq (&body, l);
5533 gimple_omp_section_set_last (sec_start);
5536 gimple_seq_add_stmt (&body, gimple_build_omp_return (false));
5539 block = make_node (BLOCK);
5540 bind = gimple_build_bind (NULL, body, block);
5542 olist = NULL;
5543 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
5545 block = make_node (BLOCK);
5546 new_stmt = gimple_build_bind (NULL, NULL, block);
5548 pop_gimplify_context (new_stmt);
5549 gimple_bind_append_vars (new_stmt, ctx->block_vars);
5550 BLOCK_VARS (block) = gimple_bind_vars (bind);
5551 if (BLOCK_VARS (block))
5552 TREE_USED (block) = 1;
5554 new_body = NULL;
5555 gimple_seq_add_seq (&new_body, ilist);
5556 gimple_seq_add_stmt (&new_body, stmt);
5557 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
5558 gimple_seq_add_stmt (&new_body, bind);
5560 control = create_tmp_var (unsigned_type_node, ".section");
5561 t = gimple_build_omp_continue (control, control);
5562 gimple_omp_sections_set_control (stmt, control);
5563 gimple_seq_add_stmt (&new_body, t);
5565 gimple_seq_add_seq (&new_body, olist);
5566 gimple_seq_add_seq (&new_body, dlist);
5568 new_body = maybe_catch_exception (new_body);
5570 t = gimple_build_omp_return
5571 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
5572 OMP_CLAUSE_NOWAIT));
5573 gimple_seq_add_stmt (&new_body, t);
5575 gimple_bind_set_body (new_stmt, new_body);
5576 gimple_omp_set_body (stmt, NULL);
5578 gsi_replace (gsi_p, new_stmt, true);
5582 /* A subroutine of lower_omp_single. Expand the simple form of
5583 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
5585 if (GOMP_single_start ())
5586 BODY;
5587 [ GOMP_barrier (); ] -> unless 'nowait' is present.
5589 FIXME. It may be better to delay expanding the logic of this until
5590 pass_expand_omp. The expanded logic may make the job more difficult
5591 to a synchronization analysis pass. */
5593 static void
5594 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
5596 tree tlabel = create_artificial_label ();
5597 tree flabel = create_artificial_label ();
5598 gimple call, cond;
5599 tree lhs, decl;
5601 decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
5602 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
5603 call = gimple_build_call (decl, 0);
5604 gimple_call_set_lhs (call, lhs);
5605 gimple_seq_add_stmt (pre_p, call);
5607 cond = gimple_build_cond (EQ_EXPR, lhs,
5608 fold_convert (TREE_TYPE (lhs), boolean_true_node),
5609 tlabel, flabel);
5610 gimple_seq_add_stmt (pre_p, cond);
5611 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
5612 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5613 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
5617 /* A subroutine of lower_omp_single. Expand the simple form of
5618 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
5620 #pragma omp single copyprivate (a, b, c)
5622 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
5625 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
5627 BODY;
5628 copyout.a = a;
5629 copyout.b = b;
5630 copyout.c = c;
5631 GOMP_single_copy_end (&copyout);
5633 else
5635 a = copyout_p->a;
5636 b = copyout_p->b;
5637 c = copyout_p->c;
5639 GOMP_barrier ();
5642 FIXME. It may be better to delay expanding the logic of this until
5643 pass_expand_omp. The expanded logic may make the job more difficult
5644 to a synchronization analysis pass. */
5646 static void
5647 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
5649 tree ptr_type, t, l0, l1, l2;
5650 gimple_seq copyin_seq;
5652 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
5654 ptr_type = build_pointer_type (ctx->record_type);
5655 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
5657 l0 = create_artificial_label ();
5658 l1 = create_artificial_label ();
5659 l2 = create_artificial_label ();
5661 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
5662 t = fold_convert (ptr_type, t);
5663 gimplify_assign (ctx->receiver_decl, t, pre_p);
5665 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
5666 build_int_cst (ptr_type, 0));
5667 t = build3 (COND_EXPR, void_type_node, t,
5668 build_and_jump (&l0), build_and_jump (&l1));
5669 gimplify_and_add (t, pre_p);
5671 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
5673 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5675 copyin_seq = NULL;
5676 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
5677 &copyin_seq, ctx);
5679 t = build_fold_addr_expr (ctx->sender_decl);
5680 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
5681 gimplify_and_add (t, pre_p);
5683 t = build_and_jump (&l2);
5684 gimplify_and_add (t, pre_p);
5686 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
5688 gimple_seq_add_seq (pre_p, copyin_seq);
5690 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
5694 /* Expand code for an OpenMP single directive. */
5696 static void
5697 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5699 tree block;
5700 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
5701 gimple_seq bind_body, dlist;
5702 struct gimplify_ctx gctx;
5704 push_gimplify_context (&gctx);
5706 bind_body = NULL;
5707 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
5708 &bind_body, &dlist, ctx);
5709 lower_omp (gimple_omp_body (single_stmt), ctx);
5711 gimple_seq_add_stmt (&bind_body, single_stmt);
5713 if (ctx->record_type)
5714 lower_omp_single_copy (single_stmt, &bind_body, ctx);
5715 else
5716 lower_omp_single_simple (single_stmt, &bind_body);
5718 gimple_omp_set_body (single_stmt, NULL);
5720 gimple_seq_add_seq (&bind_body, dlist);
5722 bind_body = maybe_catch_exception (bind_body);
5724 t = gimple_build_omp_return
5725 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
5726 OMP_CLAUSE_NOWAIT));
5727 gimple_seq_add_stmt (&bind_body, t);
5729 block = make_node (BLOCK);
5730 bind = gimple_build_bind (NULL, bind_body, block);
5732 pop_gimplify_context (bind);
5734 gimple_bind_append_vars (bind, ctx->block_vars);
5735 BLOCK_VARS (block) = ctx->block_vars;
5736 gsi_replace (gsi_p, bind, true);
5737 if (BLOCK_VARS (block))
5738 TREE_USED (block) = 1;
5742 /* Expand code for an OpenMP master directive. */
5744 static void
5745 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5747 tree block, lab = NULL, x;
5748 gimple stmt = gsi_stmt (*gsi_p), bind;
5749 gimple_seq tseq;
5750 struct gimplify_ctx gctx;
5752 push_gimplify_context (&gctx);
5754 block = make_node (BLOCK);
5755 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
5756 block);
5758 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
5759 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
5760 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
5761 tseq = NULL;
5762 gimplify_and_add (x, &tseq);
5763 gimple_bind_add_seq (bind, tseq);
5765 lower_omp (gimple_omp_body (stmt), ctx);
5766 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
5767 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
5768 gimple_omp_set_body (stmt, NULL);
5770 gimple_bind_add_stmt (bind, gimple_build_label (lab));
5772 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
5774 pop_gimplify_context (bind);
5776 gimple_bind_append_vars (bind, ctx->block_vars);
5777 BLOCK_VARS (block) = ctx->block_vars;
5778 gsi_replace (gsi_p, bind, true);
5782 /* Expand code for an OpenMP ordered directive. */
5784 static void
5785 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5787 tree block;
5788 gimple stmt = gsi_stmt (*gsi_p), bind, x;
5789 struct gimplify_ctx gctx;
5791 push_gimplify_context (&gctx);
5793 block = make_node (BLOCK);
5794 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
5795 block);
5797 x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
5798 gimple_bind_add_stmt (bind, x);
5800 lower_omp (gimple_omp_body (stmt), ctx);
5801 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
5802 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
5803 gimple_omp_set_body (stmt, NULL);
5805 x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
5806 gimple_bind_add_stmt (bind, x);
5808 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
5810 pop_gimplify_context (bind);
5812 gimple_bind_append_vars (bind, ctx->block_vars);
5813 BLOCK_VARS (block) = gimple_bind_vars (bind);
5814 gsi_replace (gsi_p, bind, true);
5818 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
5819 substitution of a couple of function calls. But in the NAMED case,
5820 requires that languages coordinate a symbol name. It is therefore
5821 best put here in common code. */
5823 static GTY((param1_is (tree), param2_is (tree)))
5824 splay_tree critical_name_mutexes;
5826 static void
5827 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5829 tree block;
5830 tree name, lock, unlock;
5831 gimple stmt = gsi_stmt (*gsi_p), bind;
5832 gimple_seq tbody;
5833 struct gimplify_ctx gctx;
5835 name = gimple_omp_critical_name (stmt);
5836 if (name)
5838 tree decl;
5839 splay_tree_node n;
5841 if (!critical_name_mutexes)
5842 critical_name_mutexes
5843 = splay_tree_new_ggc (splay_tree_compare_pointers);
5845 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
5846 if (n == NULL)
5848 char *new_str;
5850 decl = create_tmp_var_raw (ptr_type_node, NULL);
5852 new_str = ACONCAT ((".gomp_critical_user_",
5853 IDENTIFIER_POINTER (name), NULL));
5854 DECL_NAME (decl) = get_identifier (new_str);
5855 TREE_PUBLIC (decl) = 1;
5856 TREE_STATIC (decl) = 1;
5857 DECL_COMMON (decl) = 1;
5858 DECL_ARTIFICIAL (decl) = 1;
5859 DECL_IGNORED_P (decl) = 1;
5860 varpool_finalize_decl (decl);
5862 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
5863 (splay_tree_value) decl);
5865 else
5866 decl = (tree) n->value;
5868 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
5869 lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
5871 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
5872 unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
5874 else
5876 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
5877 lock = build_call_expr (lock, 0);
5879 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
5880 unlock = build_call_expr (unlock, 0);
5883 push_gimplify_context (&gctx);
5885 block = make_node (BLOCK);
5886 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt), block);
5888 tbody = gimple_bind_body (bind);
5889 gimplify_and_add (lock, &tbody);
5890 gimple_bind_set_body (bind, tbody);
5892 lower_omp (gimple_omp_body (stmt), ctx);
5893 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
5894 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
5895 gimple_omp_set_body (stmt, NULL);
5897 tbody = gimple_bind_body (bind);
5898 gimplify_and_add (unlock, &tbody);
5899 gimple_bind_set_body (bind, tbody);
5901 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
5903 pop_gimplify_context (bind);
5904 gimple_bind_append_vars (bind, ctx->block_vars);
5905 BLOCK_VARS (block) = gimple_bind_vars (bind);
5906 gsi_replace (gsi_p, bind, true);
5910 /* A subroutine of lower_omp_for. Generate code to emit the predicate
5911 for a lastprivate clause. Given a loop control predicate of (V
5912 cond N2), we gate the clause on (!(V cond N2)). The lowered form
5913 is appended to *DLIST, iterator initialization is appended to
5914 *BODY_P. */
5916 static void
5917 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
5918 gimple_seq *dlist, struct omp_context *ctx)
5920 tree clauses, cond, vinit;
5921 enum tree_code cond_code;
5922 gimple_seq stmts;
5924 cond_code = fd->loop.cond_code;
5925 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
5927 /* When possible, use a strict equality expression. This can let VRP
5928 type optimizations deduce the value and remove a copy. */
5929 if (host_integerp (fd->loop.step, 0))
5931 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
5932 if (step == 1 || step == -1)
5933 cond_code = EQ_EXPR;
5936 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
5938 clauses = gimple_omp_for_clauses (fd->for_stmt);
5939 stmts = NULL;
5940 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
5941 if (!gimple_seq_empty_p (stmts))
5943 gimple_seq_add_seq (&stmts, *dlist);
5944 *dlist = stmts;
5946 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
5947 vinit = fd->loop.n1;
5948 if (cond_code == EQ_EXPR
5949 && host_integerp (fd->loop.n2, 0)
5950 && ! integer_zerop (fd->loop.n2))
5951 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
5953 /* Initialize the iterator variable, so that threads that don't execute
5954 any iterations don't execute the lastprivate clauses by accident. */
5955 gimplify_assign (fd->loop.v, vinit, body_p);
5960 /* Lower code for an OpenMP loop directive. */
5962 static void
5963 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5965 tree *rhs_p, block;
5966 struct omp_for_data fd;
5967 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
5968 gimple_seq omp_for_body, body, dlist, ilist;
5969 size_t i;
5970 struct gimplify_ctx gctx;
5972 push_gimplify_context (&gctx);
5974 lower_omp (gimple_omp_for_pre_body (stmt), ctx);
5975 lower_omp (gimple_omp_body (stmt), ctx);
5977 block = make_node (BLOCK);
5978 new_stmt = gimple_build_bind (NULL, NULL, block);
5980 /* Move declaration of temporaries in the loop body before we make
5981 it go away. */
5982 omp_for_body = gimple_omp_body (stmt);
5983 if (!gimple_seq_empty_p (omp_for_body)
5984 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
5986 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
5987 gimple_bind_append_vars (new_stmt, vars);
5990 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
5991 ilist = NULL;
5992 dlist = NULL;
5993 body = NULL;
5994 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
5995 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
5997 /* Lower the header expressions. At this point, we can assume that
5998 the header is of the form:
6000 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
6002 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
6003 using the .omp_data_s mapping, if needed. */
6004 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
6006 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
6007 if (!is_gimple_min_invariant (*rhs_p))
6008 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6010 rhs_p = gimple_omp_for_final_ptr (stmt, i);
6011 if (!is_gimple_min_invariant (*rhs_p))
6012 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6014 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
6015 if (!is_gimple_min_invariant (*rhs_p))
6016 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6019 /* Once lowered, extract the bounds and clauses. */
6020 extract_omp_for_data (stmt, &fd, NULL);
6022 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
6024 gimple_seq_add_stmt (&body, stmt);
6025 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
6027 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
6028 fd.loop.v));
6030 /* After the loop, add exit clauses. */
6031 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
6032 gimple_seq_add_seq (&body, dlist);
6034 body = maybe_catch_exception (body);
6036 /* Region exit marker goes at the end of the loop body. */
6037 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
6039 pop_gimplify_context (new_stmt);
6041 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6042 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
6043 if (BLOCK_VARS (block))
6044 TREE_USED (block) = 1;
6046 gimple_bind_set_body (new_stmt, body);
6047 gimple_omp_set_body (stmt, NULL);
6048 gimple_omp_for_set_pre_body (stmt, NULL);
6049 gsi_replace (gsi_p, new_stmt, true);
6052 /* Callback for walk_stmts. Check if the current statement only contains
6053 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
6055 static tree
6056 check_combined_parallel (gimple_stmt_iterator *gsi_p,
6057 bool *handled_ops_p,
6058 struct walk_stmt_info *wi)
6060 int *info = (int *) wi->info;
6061 gimple stmt = gsi_stmt (*gsi_p);
6063 *handled_ops_p = true;
6064 switch (gimple_code (stmt))
6066 WALK_SUBSTMTS;
6068 case GIMPLE_OMP_FOR:
6069 case GIMPLE_OMP_SECTIONS:
6070 *info = *info == 0 ? 1 : -1;
6071 break;
6072 default:
6073 *info = -1;
6074 break;
6076 return NULL;
6079 struct omp_taskcopy_context
6081 /* This field must be at the beginning, as we do "inheritance": Some
6082 callback functions for tree-inline.c (e.g., omp_copy_decl)
6083 receive a copy_body_data pointer that is up-casted to an
6084 omp_context pointer. */
6085 copy_body_data cb;
6086 omp_context *ctx;
6089 static tree
6090 task_copyfn_copy_decl (tree var, copy_body_data *cb)
6092 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
6094 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
6095 return create_tmp_var (TREE_TYPE (var), NULL);
6097 return var;
6100 static tree
6101 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
6103 tree name, new_fields = NULL, type, f;
6105 type = lang_hooks.types.make_type (RECORD_TYPE);
6106 name = DECL_NAME (TYPE_NAME (orig_type));
6107 name = build_decl (TYPE_DECL, name, type);
6108 TYPE_NAME (type) = name;
6110 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
6112 tree new_f = copy_node (f);
6113 DECL_CONTEXT (new_f) = type;
6114 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
6115 TREE_CHAIN (new_f) = new_fields;
6116 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6117 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6118 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
6119 &tcctx->cb, NULL);
6120 new_fields = new_f;
6121 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
6123 TYPE_FIELDS (type) = nreverse (new_fields);
6124 layout_type (type);
6125 return type;
6128 /* Create task copyfn. */
6130 static void
6131 create_task_copyfn (gimple task_stmt, omp_context *ctx)
6133 struct function *child_cfun;
6134 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
6135 tree record_type, srecord_type, bind, list;
6136 bool record_needs_remap = false, srecord_needs_remap = false;
6137 splay_tree_node n;
6138 struct omp_taskcopy_context tcctx;
6139 struct gimplify_ctx gctx;
6141 child_fn = gimple_omp_task_copy_fn (task_stmt);
6142 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6143 gcc_assert (child_cfun->cfg == NULL);
6144 child_cfun->dont_save_pending_sizes_p = 1;
6145 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
6147 /* Reset DECL_CONTEXT on function arguments. */
6148 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
6149 DECL_CONTEXT (t) = child_fn;
6151 /* Populate the function. */
6152 push_gimplify_context (&gctx);
6153 current_function_decl = child_fn;
6155 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6156 TREE_SIDE_EFFECTS (bind) = 1;
6157 list = NULL;
6158 DECL_SAVED_TREE (child_fn) = bind;
6159 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
6161 /* Remap src and dst argument types if needed. */
6162 record_type = ctx->record_type;
6163 srecord_type = ctx->srecord_type;
6164 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
6165 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6167 record_needs_remap = true;
6168 break;
6170 for (f = TYPE_FIELDS (srecord_type); f ; f = TREE_CHAIN (f))
6171 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6173 srecord_needs_remap = true;
6174 break;
6177 if (record_needs_remap || srecord_needs_remap)
6179 memset (&tcctx, '\0', sizeof (tcctx));
6180 tcctx.cb.src_fn = ctx->cb.src_fn;
6181 tcctx.cb.dst_fn = child_fn;
6182 tcctx.cb.src_node = cgraph_node (tcctx.cb.src_fn);
6183 tcctx.cb.dst_node = tcctx.cb.src_node;
6184 tcctx.cb.src_cfun = ctx->cb.src_cfun;
6185 tcctx.cb.copy_decl = task_copyfn_copy_decl;
6186 tcctx.cb.eh_region = -1;
6187 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
6188 tcctx.cb.decl_map = pointer_map_create ();
6189 tcctx.ctx = ctx;
6191 if (record_needs_remap)
6192 record_type = task_copyfn_remap_type (&tcctx, record_type);
6193 if (srecord_needs_remap)
6194 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
6196 else
6197 tcctx.cb.decl_map = NULL;
6199 push_cfun (child_cfun);
6201 arg = DECL_ARGUMENTS (child_fn);
6202 TREE_TYPE (arg) = build_pointer_type (record_type);
6203 sarg = TREE_CHAIN (arg);
6204 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
6206 /* First pass: initialize temporaries used in record_type and srecord_type
6207 sizes and field offsets. */
6208 if (tcctx.cb.decl_map)
6209 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6210 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6212 tree *p;
6214 decl = OMP_CLAUSE_DECL (c);
6215 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
6216 if (p == NULL)
6217 continue;
6218 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6219 sf = (tree) n->value;
6220 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6221 src = build_fold_indirect_ref (sarg);
6222 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6223 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
6224 append_to_statement_list (t, &list);
6227 /* Second pass: copy shared var pointers and copy construct non-VLA
6228 firstprivate vars. */
6229 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6230 switch (OMP_CLAUSE_CODE (c))
6232 case OMP_CLAUSE_SHARED:
6233 decl = OMP_CLAUSE_DECL (c);
6234 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6235 if (n == NULL)
6236 break;
6237 f = (tree) n->value;
6238 if (tcctx.cb.decl_map)
6239 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6240 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6241 sf = (tree) n->value;
6242 if (tcctx.cb.decl_map)
6243 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6244 src = build_fold_indirect_ref (sarg);
6245 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6246 dst = build_fold_indirect_ref (arg);
6247 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6248 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6249 append_to_statement_list (t, &list);
6250 break;
6251 case OMP_CLAUSE_FIRSTPRIVATE:
6252 decl = OMP_CLAUSE_DECL (c);
6253 if (is_variable_sized (decl))
6254 break;
6255 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6256 if (n == NULL)
6257 break;
6258 f = (tree) n->value;
6259 if (tcctx.cb.decl_map)
6260 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6261 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6262 if (n != NULL)
6264 sf = (tree) n->value;
6265 if (tcctx.cb.decl_map)
6266 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6267 src = build_fold_indirect_ref (sarg);
6268 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6269 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6270 src = build_fold_indirect_ref (src);
6272 else
6273 src = decl;
6274 dst = build_fold_indirect_ref (arg);
6275 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6276 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6277 append_to_statement_list (t, &list);
6278 break;
6279 case OMP_CLAUSE_PRIVATE:
6280 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6281 break;
6282 decl = OMP_CLAUSE_DECL (c);
6283 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6284 f = (tree) n->value;
6285 if (tcctx.cb.decl_map)
6286 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6287 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6288 if (n != NULL)
6290 sf = (tree) n->value;
6291 if (tcctx.cb.decl_map)
6292 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6293 src = build_fold_indirect_ref (sarg);
6294 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6295 if (use_pointer_for_field (decl, NULL))
6296 src = build_fold_indirect_ref (src);
6298 else
6299 src = decl;
6300 dst = build_fold_indirect_ref (arg);
6301 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6302 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6303 append_to_statement_list (t, &list);
6304 break;
6305 default:
6306 break;
6309 /* Last pass: handle VLA firstprivates. */
6310 if (tcctx.cb.decl_map)
6311 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6312 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6314 tree ind, ptr, df;
6316 decl = OMP_CLAUSE_DECL (c);
6317 if (!is_variable_sized (decl))
6318 continue;
6319 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6320 if (n == NULL)
6321 continue;
6322 f = (tree) n->value;
6323 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6324 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6325 ind = DECL_VALUE_EXPR (decl);
6326 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6327 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6328 n = splay_tree_lookup (ctx->sfield_map,
6329 (splay_tree_key) TREE_OPERAND (ind, 0));
6330 sf = (tree) n->value;
6331 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6332 src = build_fold_indirect_ref (sarg);
6333 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
6334 src = build_fold_indirect_ref (src);
6335 dst = build_fold_indirect_ref (arg);
6336 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
6337 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6338 append_to_statement_list (t, &list);
6339 n = splay_tree_lookup (ctx->field_map,
6340 (splay_tree_key) TREE_OPERAND (ind, 0));
6341 df = (tree) n->value;
6342 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6343 ptr = build_fold_indirect_ref (arg);
6344 ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
6345 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
6346 build_fold_addr_expr (dst));
6347 append_to_statement_list (t, &list);
6350 t = build1 (RETURN_EXPR, void_type_node, NULL);
6351 append_to_statement_list (t, &list);
6353 if (tcctx.cb.decl_map)
6354 pointer_map_destroy (tcctx.cb.decl_map);
6355 pop_gimplify_context (NULL);
6356 BIND_EXPR_BODY (bind) = list;
6357 pop_cfun ();
6358 current_function_decl = ctx->cb.src_fn;
6361 /* Lower the OpenMP parallel or task directive in the current statement
6362 in GSI_P. CTX holds context information for the directive. */
6364 static void
6365 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6367 tree clauses;
6368 tree child_fn, t;
6369 gimple stmt = gsi_stmt (*gsi_p);
6370 gimple par_bind, bind;
6371 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
6372 struct gimplify_ctx gctx;
6374 clauses = gimple_omp_taskreg_clauses (stmt);
6375 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
6376 par_body = gimple_bind_body (par_bind);
6377 child_fn = ctx->cb.dst_fn;
6378 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6379 && !gimple_omp_parallel_combined_p (stmt))
6381 struct walk_stmt_info wi;
6382 int ws_num = 0;
6384 memset (&wi, 0, sizeof (wi));
6385 wi.info = &ws_num;
6386 wi.val_only = true;
6387 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
6388 if (ws_num == 1)
6389 gimple_omp_parallel_set_combined_p (stmt, true);
6391 if (ctx->srecord_type)
6392 create_task_copyfn (stmt, ctx);
6394 push_gimplify_context (&gctx);
6396 par_olist = NULL;
6397 par_ilist = NULL;
6398 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6399 lower_omp (par_body, ctx);
6400 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
6401 lower_reduction_clauses (clauses, &par_olist, ctx);
6403 /* Declare all the variables created by mapping and the variables
6404 declared in the scope of the parallel body. */
6405 record_vars_into (ctx->block_vars, child_fn);
6406 record_vars_into (gimple_bind_vars (par_bind), child_fn);
6408 if (ctx->record_type)
6410 ctx->sender_decl
6411 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6412 : ctx->record_type, ".omp_data_o");
6413 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
6414 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
6417 olist = NULL;
6418 ilist = NULL;
6419 lower_send_clauses (clauses, &ilist, &olist, ctx);
6420 lower_send_shared_vars (&ilist, &olist, ctx);
6422 /* Once all the expansions are done, sequence all the different
6423 fragments inside gimple_omp_body. */
6425 new_body = NULL;
6427 if (ctx->record_type)
6429 t = build_fold_addr_expr (ctx->sender_decl);
6430 /* fixup_child_record_type might have changed receiver_decl's type. */
6431 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
6432 gimple_seq_add_stmt (&new_body,
6433 gimple_build_assign (ctx->receiver_decl, t));
6436 gimple_seq_add_seq (&new_body, par_ilist);
6437 gimple_seq_add_seq (&new_body, par_body);
6438 gimple_seq_add_seq (&new_body, par_olist);
6439 new_body = maybe_catch_exception (new_body);
6440 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
6441 gimple_omp_set_body (stmt, new_body);
6443 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
6444 gimple_bind_add_stmt (bind, stmt);
6445 if (ilist || olist)
6447 gimple_seq_add_stmt (&ilist, bind);
6448 gimple_seq_add_seq (&ilist, olist);
6449 bind = gimple_build_bind (NULL, ilist, NULL);
6452 gsi_replace (gsi_p, bind, true);
6454 pop_gimplify_context (NULL);
6457 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
6458 regimplified. If DATA is non-NULL, lower_omp_1 is outside
6459 of OpenMP context, but with task_shared_vars set. */
6461 static tree
6462 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
6463 void *data)
6465 tree t = *tp;
6467 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6468 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
6469 return t;
6471 if (task_shared_vars
6472 && DECL_P (t)
6473 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
6474 return t;
6476 /* If a global variable has been privatized, TREE_CONSTANT on
6477 ADDR_EXPR might be wrong. */
6478 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
6479 recompute_tree_invariant_for_addr_expr (t);
6481 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6482 return NULL_TREE;
6485 static void
6486 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6488 gimple stmt = gsi_stmt (*gsi_p);
6489 struct walk_stmt_info wi;
6491 if (gimple_has_location (stmt))
6492 input_location = gimple_location (stmt);
6494 if (task_shared_vars)
6495 memset (&wi, '\0', sizeof (wi));
6497 /* If we have issued syntax errors, avoid doing any heavy lifting.
6498 Just replace the OpenMP directives with a NOP to avoid
6499 confusing RTL expansion. */
6500 if (errorcount && is_gimple_omp (stmt))
6502 gsi_replace (gsi_p, gimple_build_nop (), true);
6503 return;
6506 switch (gimple_code (stmt))
6508 case GIMPLE_COND:
6509 if ((ctx || task_shared_vars)
6510 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
6511 ctx ? NULL : &wi, NULL)
6512 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
6513 ctx ? NULL : &wi, NULL)))
6514 gimple_regimplify_operands (stmt, gsi_p);
6515 break;
6516 case GIMPLE_CATCH:
6517 lower_omp (gimple_catch_handler (stmt), ctx);
6518 break;
6519 case GIMPLE_EH_FILTER:
6520 lower_omp (gimple_eh_filter_failure (stmt), ctx);
6521 break;
6522 case GIMPLE_TRY:
6523 lower_omp (gimple_try_eval (stmt), ctx);
6524 lower_omp (gimple_try_cleanup (stmt), ctx);
6525 break;
6526 case GIMPLE_BIND:
6527 lower_omp (gimple_bind_body (stmt), ctx);
6528 break;
6529 case GIMPLE_OMP_PARALLEL:
6530 case GIMPLE_OMP_TASK:
6531 ctx = maybe_lookup_ctx (stmt);
6532 lower_omp_taskreg (gsi_p, ctx);
6533 break;
6534 case GIMPLE_OMP_FOR:
6535 ctx = maybe_lookup_ctx (stmt);
6536 gcc_assert (ctx);
6537 lower_omp_for (gsi_p, ctx);
6538 break;
6539 case GIMPLE_OMP_SECTIONS:
6540 ctx = maybe_lookup_ctx (stmt);
6541 gcc_assert (ctx);
6542 lower_omp_sections (gsi_p, ctx);
6543 break;
6544 case GIMPLE_OMP_SINGLE:
6545 ctx = maybe_lookup_ctx (stmt);
6546 gcc_assert (ctx);
6547 lower_omp_single (gsi_p, ctx);
6548 break;
6549 case GIMPLE_OMP_MASTER:
6550 ctx = maybe_lookup_ctx (stmt);
6551 gcc_assert (ctx);
6552 lower_omp_master (gsi_p, ctx);
6553 break;
6554 case GIMPLE_OMP_ORDERED:
6555 ctx = maybe_lookup_ctx (stmt);
6556 gcc_assert (ctx);
6557 lower_omp_ordered (gsi_p, ctx);
6558 break;
6559 case GIMPLE_OMP_CRITICAL:
6560 ctx = maybe_lookup_ctx (stmt);
6561 gcc_assert (ctx);
6562 lower_omp_critical (gsi_p, ctx);
6563 break;
6564 case GIMPLE_OMP_ATOMIC_LOAD:
6565 if ((ctx || task_shared_vars)
6566 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
6567 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
6568 gimple_regimplify_operands (stmt, gsi_p);
6569 break;
6570 default:
6571 if ((ctx || task_shared_vars)
6572 && walk_gimple_op (stmt, lower_omp_regimplify_p,
6573 ctx ? NULL : &wi))
6574 gimple_regimplify_operands (stmt, gsi_p);
6575 break;
6579 static void
6580 lower_omp (gimple_seq body, omp_context *ctx)
6582 location_t saved_location = input_location;
6583 gimple_stmt_iterator gsi = gsi_start (body);
6584 for (gsi = gsi_start (body); !gsi_end_p (gsi); gsi_next (&gsi))
6585 lower_omp_1 (&gsi, ctx);
6586 input_location = saved_location;
6589 /* Main entry point. */
6591 static unsigned int
6592 execute_lower_omp (void)
6594 gimple_seq body;
6596 /* This pass always runs, to provide PROP_gimple_lomp.
6597 But there is nothing to do unless -fopenmp is given. */
6598 if (flag_openmp == 0)
6599 return 0;
6601 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
6602 delete_omp_context);
6604 body = gimple_body (current_function_decl);
6605 scan_omp (body, NULL);
6606 gcc_assert (taskreg_nesting_level == 0);
6608 if (all_contexts->root)
6610 struct gimplify_ctx gctx;
6612 if (task_shared_vars)
6613 push_gimplify_context (&gctx);
6614 lower_omp (body, NULL);
6615 if (task_shared_vars)
6616 pop_gimplify_context (NULL);
6619 if (all_contexts)
6621 splay_tree_delete (all_contexts);
6622 all_contexts = NULL;
6624 BITMAP_FREE (task_shared_vars);
6625 return 0;
6628 struct gimple_opt_pass pass_lower_omp =
6631 GIMPLE_PASS,
6632 "omplower", /* name */
6633 NULL, /* gate */
6634 execute_lower_omp, /* execute */
6635 NULL, /* sub */
6636 NULL, /* next */
6637 0, /* static_pass_number */
6638 TV_NONE, /* tv_id */
6639 PROP_gimple_any, /* properties_required */
6640 PROP_gimple_lomp, /* properties_provided */
6641 0, /* properties_destroyed */
6642 0, /* todo_flags_start */
6643 TODO_dump_func /* todo_flags_finish */
6647 /* The following is a utility to diagnose OpenMP structured block violations.
6648 It is not part of the "omplower" pass, as that's invoked too late. It
6649 should be invoked by the respective front ends after gimplification. */
6651 static splay_tree all_labels;
6653 /* Check for mismatched contexts and generate an error if needed. Return
6654 true if an error is detected. */
6656 static bool
6657 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
6658 gimple branch_ctx, gimple label_ctx)
6660 if (label_ctx == branch_ctx)
6661 return false;
6665 Previously we kept track of the label's entire context in diagnose_sb_[12]
6666 so we could traverse it and issue a correct "exit" or "enter" error
6667 message upon a structured block violation.
6669 We built the context by building a list with tree_cons'ing, but there is
6670 no easy counterpart in gimple tuples. It seems like far too much work
6671 for issuing exit/enter error messages. If someone really misses the
6672 distinct error message... patches welcome.
6675 #if 0
6676 /* Try to avoid confusing the user by producing and error message
6677 with correct "exit" or "enter" verbiage. We prefer "exit"
6678 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
6679 if (branch_ctx == NULL)
6680 exit_p = false;
6681 else
6683 while (label_ctx)
6685 if (TREE_VALUE (label_ctx) == branch_ctx)
6687 exit_p = false;
6688 break;
6690 label_ctx = TREE_CHAIN (label_ctx);
6694 if (exit_p)
6695 error ("invalid exit from OpenMP structured block");
6696 else
6697 error ("invalid entry to OpenMP structured block");
6698 #endif
6700 /* If it's obvious we have an invalid entry, be specific about the error. */
6701 if (branch_ctx == NULL)
6702 error ("invalid entry to OpenMP structured block");
6703 else
6704 /* Otherwise, be vague and lazy, but efficient. */
6705 error ("invalid branch to/from an OpenMP structured block");
6707 gsi_replace (gsi_p, gimple_build_nop (), false);
6708 return true;
6711 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
6712 where each label is found. */
6714 static tree
6715 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
6716 struct walk_stmt_info *wi)
6718 gimple context = (gimple) wi->info;
6719 gimple inner_context;
6720 gimple stmt = gsi_stmt (*gsi_p);
6722 *handled_ops_p = true;
6724 switch (gimple_code (stmt))
6726 WALK_SUBSTMTS;
6728 case GIMPLE_OMP_PARALLEL:
6729 case GIMPLE_OMP_TASK:
6730 case GIMPLE_OMP_SECTIONS:
6731 case GIMPLE_OMP_SINGLE:
6732 case GIMPLE_OMP_SECTION:
6733 case GIMPLE_OMP_MASTER:
6734 case GIMPLE_OMP_ORDERED:
6735 case GIMPLE_OMP_CRITICAL:
6736 /* The minimal context here is just the current OMP construct. */
6737 inner_context = stmt;
6738 wi->info = inner_context;
6739 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
6740 wi->info = context;
6741 break;
6743 case GIMPLE_OMP_FOR:
6744 inner_context = stmt;
6745 wi->info = inner_context;
6746 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
6747 walk them. */
6748 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
6749 diagnose_sb_1, NULL, wi);
6750 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
6751 wi->info = context;
6752 break;
6754 case GIMPLE_LABEL:
6755 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
6756 (splay_tree_value) context);
6757 break;
6759 default:
6760 break;
6763 return NULL_TREE;
6766 /* Pass 2: Check each branch and see if its context differs from that of
6767 the destination label's context. */
6769 static tree
6770 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
6771 struct walk_stmt_info *wi)
6773 gimple context = (gimple) wi->info;
6774 splay_tree_node n;
6775 gimple stmt = gsi_stmt (*gsi_p);
6777 *handled_ops_p = true;
6779 switch (gimple_code (stmt))
6781 WALK_SUBSTMTS;
6783 case GIMPLE_OMP_PARALLEL:
6784 case GIMPLE_OMP_TASK:
6785 case GIMPLE_OMP_SECTIONS:
6786 case GIMPLE_OMP_SINGLE:
6787 case GIMPLE_OMP_SECTION:
6788 case GIMPLE_OMP_MASTER:
6789 case GIMPLE_OMP_ORDERED:
6790 case GIMPLE_OMP_CRITICAL:
6791 wi->info = stmt;
6792 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
6793 wi->info = context;
6794 break;
6796 case GIMPLE_OMP_FOR:
6797 wi->info = stmt;
6798 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
6799 walk them. */
6800 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
6801 diagnose_sb_2, NULL, wi);
6802 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
6803 wi->info = context;
6804 break;
6806 case GIMPLE_GOTO:
6808 tree lab = gimple_goto_dest (stmt);
6809 if (TREE_CODE (lab) != LABEL_DECL)
6810 break;
6812 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
6813 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
6815 break;
6817 case GIMPLE_SWITCH:
6819 unsigned int i;
6820 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
6822 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
6823 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
6824 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
6825 break;
6828 break;
6830 case GIMPLE_RETURN:
6831 diagnose_sb_0 (gsi_p, context, NULL);
6832 break;
6834 default:
6835 break;
6838 return NULL_TREE;
6841 void
6842 diagnose_omp_structured_block_errors (tree fndecl)
6844 tree save_current = current_function_decl;
6845 struct walk_stmt_info wi;
6846 struct function *old_cfun = cfun;
6847 gimple_seq body = gimple_body (fndecl);
6849 current_function_decl = fndecl;
6850 set_cfun (DECL_STRUCT_FUNCTION (fndecl));
6852 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
6854 memset (&wi, 0, sizeof (wi));
6855 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
6857 memset (&wi, 0, sizeof (wi));
6858 wi.want_locations = true;
6859 walk_gimple_seq (body, diagnose_sb_2, NULL, &wi);
6861 splay_tree_delete (all_labels);
6862 all_labels = NULL;
6864 set_cfun (old_cfun);
6865 current_function_decl = save_current;
6868 #include "gt-omp-low.h"