2013-04-26 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / omp-low.c
blob81ae5b4e5c1ca777db2f8ce6eccf3be1dd407e03
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-2013 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-core.h"
35 #include "tree-flow.h"
36 #include "flags.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "tree-pass.h"
40 #include "ggc.h"
41 #include "except.h"
42 #include "splay-tree.h"
43 #include "optabs.h"
44 #include "cfgloop.h"
47 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
48 phases. The first phase scans the function looking for OMP statements
49 and then for variables that must be replaced to satisfy data sharing
50 clauses. The second phase expands code for the constructs, as well as
51 re-gimplifying things when variables have been replaced with complex
52 expressions.
54 Final code generation is done by pass_expand_omp. The flowgraph is
55 scanned for parallel regions which are then moved to a new
56 function, to be invoked by the thread library. */
58 /* Context structure. Used to store information about each parallel
59 directive in the code. */
61 typedef struct omp_context
63 /* This field must be at the beginning, as we do "inheritance": Some
64 callback functions for tree-inline.c (e.g., omp_copy_decl)
65 receive a copy_body_data pointer that is up-casted to an
66 omp_context pointer. */
67 copy_body_data cb;
69 /* The tree of contexts corresponding to the encountered constructs. */
70 struct omp_context *outer;
71 gimple stmt;
73 /* Map variables to fields in a structure that allows communication
74 between sending and receiving threads. */
75 splay_tree field_map;
76 tree record_type;
77 tree sender_decl;
78 tree receiver_decl;
80 /* These are used just by task contexts, if task firstprivate fn is
81 needed. srecord_type is used to communicate from the thread
82 that encountered the task construct to task firstprivate fn,
83 record_type is allocated by GOMP_task, initialized by task firstprivate
84 fn and passed to the task body fn. */
85 splay_tree sfield_map;
86 tree srecord_type;
88 /* A chain of variables to add to the top-level block surrounding the
89 construct. In the case of a parallel, this is in the child function. */
90 tree block_vars;
92 /* What to do with variables with implicitly determined sharing
93 attributes. */
94 enum omp_clause_default_kind default_kind;
96 /* Nesting depth of this context. Used to beautify error messages re
97 invalid gotos. The outermost ctx is depth 1, with depth 0 being
98 reserved for the main body of the function. */
99 int depth;
101 /* True if this parallel directive is nested within another. */
102 bool is_nested;
103 } omp_context;
106 struct omp_for_data_loop
108 tree v, n1, n2, step;
109 enum tree_code cond_code;
112 /* A structure describing the main elements of a parallel loop. */
114 struct omp_for_data
116 struct omp_for_data_loop loop;
117 tree chunk_size;
118 gimple for_stmt;
119 tree pre, iter_type;
120 int collapse;
121 bool have_nowait, have_ordered;
122 enum omp_clause_schedule_kind sched_kind;
123 struct omp_for_data_loop *loops;
127 static splay_tree all_contexts;
128 static int taskreg_nesting_level;
129 struct omp_region *root_omp_region;
130 static bitmap task_shared_vars;
132 static void scan_omp (gimple_seq *, omp_context *);
133 static tree scan_omp_1_op (tree *, int *, void *);
135 #define WALK_SUBSTMTS \
136 case GIMPLE_BIND: \
137 case GIMPLE_TRY: \
138 case GIMPLE_CATCH: \
139 case GIMPLE_EH_FILTER: \
140 case GIMPLE_TRANSACTION: \
141 /* The sub-statements for these should be walked. */ \
142 *handled_ops_p = false; \
143 break;
145 /* Convenience function for calling scan_omp_1_op on tree operands. */
147 static inline tree
148 scan_omp_op (tree *tp, omp_context *ctx)
150 struct walk_stmt_info wi;
152 memset (&wi, 0, sizeof (wi));
153 wi.info = ctx;
154 wi.want_locations = true;
156 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
159 static void lower_omp (gimple_seq *, omp_context *);
160 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
161 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
163 /* Find an OpenMP clause of type KIND within CLAUSES. */
165 tree
166 find_omp_clause (tree clauses, enum omp_clause_code kind)
168 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
169 if (OMP_CLAUSE_CODE (clauses) == kind)
170 return clauses;
172 return NULL_TREE;
175 /* Return true if CTX is for an omp parallel. */
177 static inline bool
178 is_parallel_ctx (omp_context *ctx)
180 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
184 /* Return true if CTX is for an omp task. */
186 static inline bool
187 is_task_ctx (omp_context *ctx)
189 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
193 /* Return true if CTX is for an omp parallel or omp task. */
195 static inline bool
196 is_taskreg_ctx (omp_context *ctx)
198 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
199 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
203 /* Return true if REGION is a combined parallel+workshare region. */
205 static inline bool
206 is_combined_parallel (struct omp_region *region)
208 return region->is_combined_parallel;
212 /* Extract the header elements of parallel loop FOR_STMT and store
213 them into *FD. */
215 static void
216 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
217 struct omp_for_data_loop *loops)
219 tree t, var, *collapse_iter, *collapse_count;
220 tree count = NULL_TREE, iter_type = long_integer_type_node;
221 struct omp_for_data_loop *loop;
222 int i;
223 struct omp_for_data_loop dummy_loop;
224 location_t loc = gimple_location (for_stmt);
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_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
313 else
314 loop->n2 = fold_build2_loc (loc,
315 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_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
322 else
323 loop->n2 = fold_build2_loc (loc,
324 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 loop->step = TREE_OPERAND (t, 1);
338 break;
339 case POINTER_PLUS_EXPR:
340 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
341 break;
342 case MINUS_EXPR:
343 loop->step = TREE_OPERAND (t, 1);
344 loop->step = fold_build1_loc (loc,
345 NEGATE_EXPR, TREE_TYPE (loop->step),
346 loop->step);
347 break;
348 default:
349 gcc_unreachable ();
352 if (iter_type != long_long_unsigned_type_node)
354 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
355 iter_type = long_long_unsigned_type_node;
356 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
357 && TYPE_PRECISION (TREE_TYPE (loop->v))
358 >= TYPE_PRECISION (iter_type))
360 tree n;
362 if (loop->cond_code == LT_EXPR)
363 n = fold_build2_loc (loc,
364 PLUS_EXPR, TREE_TYPE (loop->v),
365 loop->n2, loop->step);
366 else
367 n = loop->n1;
368 if (TREE_CODE (n) != INTEGER_CST
369 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
370 iter_type = long_long_unsigned_type_node;
372 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
373 > TYPE_PRECISION (iter_type))
375 tree n1, n2;
377 if (loop->cond_code == LT_EXPR)
379 n1 = loop->n1;
380 n2 = fold_build2_loc (loc,
381 PLUS_EXPR, TREE_TYPE (loop->v),
382 loop->n2, loop->step);
384 else
386 n1 = fold_build2_loc (loc,
387 MINUS_EXPR, TREE_TYPE (loop->v),
388 loop->n2, loop->step);
389 n2 = loop->n1;
391 if (TREE_CODE (n1) != INTEGER_CST
392 || TREE_CODE (n2) != INTEGER_CST
393 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
394 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
395 iter_type = long_long_unsigned_type_node;
399 if (collapse_count && *collapse_count == NULL)
401 if ((i == 0 || count != NULL_TREE)
402 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
403 && TREE_CONSTANT (loop->n1)
404 && TREE_CONSTANT (loop->n2)
405 && TREE_CODE (loop->step) == INTEGER_CST)
407 tree itype = TREE_TYPE (loop->v);
409 if (POINTER_TYPE_P (itype))
410 itype = signed_type_for (itype);
411 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
412 t = fold_build2_loc (loc,
413 PLUS_EXPR, itype,
414 fold_convert_loc (loc, itype, loop->step), t);
415 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
416 fold_convert_loc (loc, itype, loop->n2));
417 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
418 fold_convert_loc (loc, itype, loop->n1));
419 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
420 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
421 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
422 fold_build1_loc (loc, NEGATE_EXPR, itype,
423 fold_convert_loc (loc, itype,
424 loop->step)));
425 else
426 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
427 fold_convert_loc (loc, itype, loop->step));
428 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
429 if (count != NULL_TREE)
430 count = fold_build2_loc (loc,
431 MULT_EXPR, long_long_unsigned_type_node,
432 count, t);
433 else
434 count = t;
435 if (TREE_CODE (count) != INTEGER_CST)
436 count = NULL_TREE;
438 else
439 count = NULL_TREE;
443 if (count)
445 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
446 iter_type = long_long_unsigned_type_node;
447 else
448 iter_type = long_integer_type_node;
450 else if (collapse_iter && *collapse_iter != NULL)
451 iter_type = TREE_TYPE (*collapse_iter);
452 fd->iter_type = iter_type;
453 if (collapse_iter && *collapse_iter == NULL)
454 *collapse_iter = create_tmp_var (iter_type, ".iter");
455 if (collapse_count && *collapse_count == NULL)
457 if (count)
458 *collapse_count = fold_convert_loc (loc, iter_type, count);
459 else
460 *collapse_count = create_tmp_var (iter_type, ".count");
463 if (fd->collapse > 1)
465 fd->loop.v = *collapse_iter;
466 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
467 fd->loop.n2 = *collapse_count;
468 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
469 fd->loop.cond_code = LT_EXPR;
474 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
475 is the immediate dominator of PAR_ENTRY_BB, return true if there
476 are no data dependencies that would prevent expanding the parallel
477 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
479 When expanding a combined parallel+workshare region, the call to
480 the child function may need additional arguments in the case of
481 GIMPLE_OMP_FOR regions. In some cases, these arguments are
482 computed out of variables passed in from the parent to the child
483 via 'struct .omp_data_s'. For instance:
485 #pragma omp parallel for schedule (guided, i * 4)
486 for (j ...)
488 Is lowered into:
490 # BLOCK 2 (PAR_ENTRY_BB)
491 .omp_data_o.i = i;
492 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
494 # BLOCK 3 (WS_ENTRY_BB)
495 .omp_data_i = &.omp_data_o;
496 D.1667 = .omp_data_i->i;
497 D.1598 = D.1667 * 4;
498 #pragma omp for schedule (guided, D.1598)
500 When we outline the parallel region, the call to the child function
501 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
502 that value is computed *after* the call site. So, in principle we
503 cannot do the transformation.
505 To see whether the code in WS_ENTRY_BB blocks the combined
506 parallel+workshare call, we collect all the variables used in the
507 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
508 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
509 call.
511 FIXME. If we had the SSA form built at this point, we could merely
512 hoist the code in block 3 into block 2 and be done with it. But at
513 this point we don't have dataflow information and though we could
514 hack something up here, it is really not worth the aggravation. */
516 static bool
517 workshare_safe_to_combine_p (basic_block ws_entry_bb)
519 struct omp_for_data fd;
520 gimple ws_stmt = last_stmt (ws_entry_bb);
522 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
523 return true;
525 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
527 extract_omp_for_data (ws_stmt, &fd, NULL);
529 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
530 return false;
531 if (fd.iter_type != long_integer_type_node)
532 return false;
534 /* FIXME. We give up too easily here. If any of these arguments
535 are not constants, they will likely involve variables that have
536 been mapped into fields of .omp_data_s for sharing with the child
537 function. With appropriate data flow, it would be possible to
538 see through this. */
539 if (!is_gimple_min_invariant (fd.loop.n1)
540 || !is_gimple_min_invariant (fd.loop.n2)
541 || !is_gimple_min_invariant (fd.loop.step)
542 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
543 return false;
545 return true;
549 /* Collect additional arguments needed to emit a combined
550 parallel+workshare call. WS_STMT is the workshare directive being
551 expanded. */
553 static vec<tree, va_gc> *
554 get_ws_args_for (gimple ws_stmt)
556 tree t;
557 location_t loc = gimple_location (ws_stmt);
558 vec<tree, va_gc> *ws_args;
560 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
562 struct omp_for_data fd;
564 extract_omp_for_data (ws_stmt, &fd, NULL);
566 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
568 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
569 ws_args->quick_push (t);
571 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
572 ws_args->quick_push (t);
574 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
575 ws_args->quick_push (t);
577 if (fd.chunk_size)
579 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
580 ws_args->quick_push (t);
583 return ws_args;
585 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
587 /* Number of sections is equal to the number of edges from the
588 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
589 the exit of the sections region. */
590 basic_block bb = single_succ (gimple_bb (ws_stmt));
591 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
592 vec_alloc (ws_args, 1);
593 ws_args->quick_push (t);
594 return ws_args;
597 gcc_unreachable ();
601 /* Discover whether REGION is a combined parallel+workshare region. */
603 static void
604 determine_parallel_type (struct omp_region *region)
606 basic_block par_entry_bb, par_exit_bb;
607 basic_block ws_entry_bb, ws_exit_bb;
609 if (region == NULL || region->inner == NULL
610 || region->exit == NULL || region->inner->exit == NULL
611 || region->inner->cont == NULL)
612 return;
614 /* We only support parallel+for and parallel+sections. */
615 if (region->type != GIMPLE_OMP_PARALLEL
616 || (region->inner->type != GIMPLE_OMP_FOR
617 && region->inner->type != GIMPLE_OMP_SECTIONS))
618 return;
620 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
621 WS_EXIT_BB -> PAR_EXIT_BB. */
622 par_entry_bb = region->entry;
623 par_exit_bb = region->exit;
624 ws_entry_bb = region->inner->entry;
625 ws_exit_bb = region->inner->exit;
627 if (single_succ (par_entry_bb) == ws_entry_bb
628 && single_succ (ws_exit_bb) == par_exit_bb
629 && workshare_safe_to_combine_p (ws_entry_bb)
630 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
631 || (last_and_only_stmt (ws_entry_bb)
632 && last_and_only_stmt (par_exit_bb))))
634 gimple ws_stmt = last_stmt (ws_entry_bb);
636 if (region->inner->type == GIMPLE_OMP_FOR)
638 /* If this is a combined parallel loop, we need to determine
639 whether or not to use the combined library calls. There
640 are two cases where we do not apply the transformation:
641 static loops and any kind of ordered loop. In the first
642 case, we already open code the loop so there is no need
643 to do anything else. In the latter case, the combined
644 parallel loop call would still need extra synchronization
645 to implement ordered semantics, so there would not be any
646 gain in using the combined call. */
647 tree clauses = gimple_omp_for_clauses (ws_stmt);
648 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
649 if (c == NULL
650 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
651 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
653 region->is_combined_parallel = false;
654 region->inner->is_combined_parallel = false;
655 return;
659 region->is_combined_parallel = true;
660 region->inner->is_combined_parallel = true;
661 region->ws_args = get_ws_args_for (ws_stmt);
666 /* Return true if EXPR is variable sized. */
668 static inline bool
669 is_variable_sized (const_tree expr)
671 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
674 /* Return true if DECL is a reference type. */
676 static inline bool
677 is_reference (tree decl)
679 return lang_hooks.decls.omp_privatize_by_reference (decl);
682 /* Lookup variables in the decl or field splay trees. The "maybe" form
683 allows for the variable form to not have been entered, otherwise we
684 assert that the variable must have been entered. */
686 static inline tree
687 lookup_decl (tree var, omp_context *ctx)
689 tree *n;
690 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
691 return *n;
694 static inline tree
695 maybe_lookup_decl (const_tree var, omp_context *ctx)
697 tree *n;
698 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
699 return n ? *n : NULL_TREE;
702 static inline tree
703 lookup_field (tree var, omp_context *ctx)
705 splay_tree_node n;
706 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
707 return (tree) n->value;
710 static inline tree
711 lookup_sfield (tree var, omp_context *ctx)
713 splay_tree_node n;
714 n = splay_tree_lookup (ctx->sfield_map
715 ? ctx->sfield_map : ctx->field_map,
716 (splay_tree_key) var);
717 return (tree) n->value;
720 static inline tree
721 maybe_lookup_field (tree var, omp_context *ctx)
723 splay_tree_node n;
724 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
725 return n ? (tree) n->value : NULL_TREE;
728 /* Return true if DECL should be copied by pointer. SHARED_CTX is
729 the parallel context if DECL is to be shared. */
731 static bool
732 use_pointer_for_field (tree decl, omp_context *shared_ctx)
734 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
735 return true;
737 /* We can only use copy-in/copy-out semantics for shared variables
738 when we know the value is not accessible from an outer scope. */
739 if (shared_ctx)
741 /* ??? Trivially accessible from anywhere. But why would we even
742 be passing an address in this case? Should we simply assert
743 this to be false, or should we have a cleanup pass that removes
744 these from the list of mappings? */
745 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
746 return true;
748 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
749 without analyzing the expression whether or not its location
750 is accessible to anyone else. In the case of nested parallel
751 regions it certainly may be. */
752 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
753 return true;
755 /* Do not use copy-in/copy-out for variables that have their
756 address taken. */
757 if (TREE_ADDRESSABLE (decl))
758 return true;
760 /* lower_send_shared_vars only uses copy-in, but not copy-out
761 for these. */
762 if (TREE_READONLY (decl)
763 || ((TREE_CODE (decl) == RESULT_DECL
764 || TREE_CODE (decl) == PARM_DECL)
765 && DECL_BY_REFERENCE (decl)))
766 return false;
768 /* Disallow copy-in/out in nested parallel if
769 decl is shared in outer parallel, otherwise
770 each thread could store the shared variable
771 in its own copy-in location, making the
772 variable no longer really shared. */
773 if (shared_ctx->is_nested)
775 omp_context *up;
777 for (up = shared_ctx->outer; up; up = up->outer)
778 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
779 break;
781 if (up)
783 tree c;
785 for (c = gimple_omp_taskreg_clauses (up->stmt);
786 c; c = OMP_CLAUSE_CHAIN (c))
787 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
788 && OMP_CLAUSE_DECL (c) == decl)
789 break;
791 if (c)
792 goto maybe_mark_addressable_and_ret;
796 /* For tasks avoid using copy-in/out. As tasks can be
797 deferred or executed in different thread, when GOMP_task
798 returns, the task hasn't necessarily terminated. */
799 if (is_task_ctx (shared_ctx))
801 tree outer;
802 maybe_mark_addressable_and_ret:
803 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
804 if (is_gimple_reg (outer))
806 /* Taking address of OUTER in lower_send_shared_vars
807 might need regimplification of everything that uses the
808 variable. */
809 if (!task_shared_vars)
810 task_shared_vars = BITMAP_ALLOC (NULL);
811 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
812 TREE_ADDRESSABLE (outer) = 1;
814 return true;
818 return false;
821 /* Create a new VAR_DECL and copy information from VAR to it. */
823 tree
824 copy_var_decl (tree var, tree name, tree type)
826 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
828 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
829 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
830 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
831 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
832 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
833 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
834 TREE_USED (copy) = 1;
835 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
837 return copy;
840 /* Construct a new automatic decl similar to VAR. */
842 static tree
843 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
845 tree copy = copy_var_decl (var, name, type);
847 DECL_CONTEXT (copy) = current_function_decl;
848 DECL_CHAIN (copy) = ctx->block_vars;
849 ctx->block_vars = copy;
851 return copy;
854 static tree
855 omp_copy_decl_1 (tree var, omp_context *ctx)
857 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
860 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
861 as appropriate. */
862 static tree
863 omp_build_component_ref (tree obj, tree field)
865 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
866 if (TREE_THIS_VOLATILE (field))
867 TREE_THIS_VOLATILE (ret) |= 1;
868 if (TREE_READONLY (field))
869 TREE_READONLY (ret) |= 1;
870 return ret;
873 /* Build tree nodes to access the field for VAR on the receiver side. */
875 static tree
876 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
878 tree x, field = lookup_field (var, ctx);
880 /* If the receiver record type was remapped in the child function,
881 remap the field into the new record type. */
882 x = maybe_lookup_field (field, ctx);
883 if (x != NULL)
884 field = x;
886 x = build_simple_mem_ref (ctx->receiver_decl);
887 x = omp_build_component_ref (x, field);
888 if (by_ref)
889 x = build_simple_mem_ref (x);
891 return x;
894 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
895 of a parallel, this is a component reference; for workshare constructs
896 this is some variable. */
898 static tree
899 build_outer_var_ref (tree var, omp_context *ctx)
901 tree x;
903 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
904 x = var;
905 else if (is_variable_sized (var))
907 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
908 x = build_outer_var_ref (x, ctx);
909 x = build_simple_mem_ref (x);
911 else if (is_taskreg_ctx (ctx))
913 bool by_ref = use_pointer_for_field (var, NULL);
914 x = build_receiver_ref (var, by_ref, ctx);
916 else if (ctx->outer)
917 x = lookup_decl (var, ctx->outer);
918 else if (is_reference (var))
919 /* This can happen with orphaned constructs. If var is reference, it is
920 possible it is shared and as such valid. */
921 x = var;
922 else
923 gcc_unreachable ();
925 if (is_reference (var))
926 x = build_simple_mem_ref (x);
928 return x;
931 /* Build tree nodes to access the field for VAR on the sender side. */
933 static tree
934 build_sender_ref (tree var, omp_context *ctx)
936 tree field = lookup_sfield (var, ctx);
937 return omp_build_component_ref (ctx->sender_decl, field);
940 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
942 static void
943 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
945 tree field, type, sfield = NULL_TREE;
947 gcc_assert ((mask & 1) == 0
948 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
949 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
950 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
952 type = TREE_TYPE (var);
953 if (by_ref)
954 type = build_pointer_type (type);
955 else if ((mask & 3) == 1 && is_reference (var))
956 type = TREE_TYPE (type);
958 field = build_decl (DECL_SOURCE_LOCATION (var),
959 FIELD_DECL, DECL_NAME (var), type);
961 /* Remember what variable this field was created for. This does have a
962 side effect of making dwarf2out ignore this member, so for helpful
963 debugging we clear it later in delete_omp_context. */
964 DECL_ABSTRACT_ORIGIN (field) = var;
965 if (type == TREE_TYPE (var))
967 DECL_ALIGN (field) = DECL_ALIGN (var);
968 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
969 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
971 else
972 DECL_ALIGN (field) = TYPE_ALIGN (type);
974 if ((mask & 3) == 3)
976 insert_field_into_struct (ctx->record_type, field);
977 if (ctx->srecord_type)
979 sfield = build_decl (DECL_SOURCE_LOCATION (var),
980 FIELD_DECL, DECL_NAME (var), type);
981 DECL_ABSTRACT_ORIGIN (sfield) = var;
982 DECL_ALIGN (sfield) = DECL_ALIGN (field);
983 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
984 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
985 insert_field_into_struct (ctx->srecord_type, sfield);
988 else
990 if (ctx->srecord_type == NULL_TREE)
992 tree t;
994 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
995 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
996 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
998 sfield = build_decl (DECL_SOURCE_LOCATION (var),
999 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1000 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1001 insert_field_into_struct (ctx->srecord_type, sfield);
1002 splay_tree_insert (ctx->sfield_map,
1003 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1004 (splay_tree_value) sfield);
1007 sfield = field;
1008 insert_field_into_struct ((mask & 1) ? ctx->record_type
1009 : ctx->srecord_type, field);
1012 if (mask & 1)
1013 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1014 (splay_tree_value) field);
1015 if ((mask & 2) && ctx->sfield_map)
1016 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1017 (splay_tree_value) sfield);
1020 static tree
1021 install_var_local (tree var, omp_context *ctx)
1023 tree new_var = omp_copy_decl_1 (var, ctx);
1024 insert_decl_map (&ctx->cb, var, new_var);
1025 return new_var;
1028 /* Adjust the replacement for DECL in CTX for the new context. This means
1029 copying the DECL_VALUE_EXPR, and fixing up the type. */
1031 static void
1032 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1034 tree new_decl, size;
1036 new_decl = lookup_decl (decl, ctx);
1038 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1040 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1041 && DECL_HAS_VALUE_EXPR_P (decl))
1043 tree ve = DECL_VALUE_EXPR (decl);
1044 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1045 SET_DECL_VALUE_EXPR (new_decl, ve);
1046 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1049 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1051 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1052 if (size == error_mark_node)
1053 size = TYPE_SIZE (TREE_TYPE (new_decl));
1054 DECL_SIZE (new_decl) = size;
1056 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1057 if (size == error_mark_node)
1058 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1059 DECL_SIZE_UNIT (new_decl) = size;
1063 /* The callback for remap_decl. Search all containing contexts for a
1064 mapping of the variable; this avoids having to duplicate the splay
1065 tree ahead of time. We know a mapping doesn't already exist in the
1066 given context. Create new mappings to implement default semantics. */
1068 static tree
1069 omp_copy_decl (tree var, copy_body_data *cb)
1071 omp_context *ctx = (omp_context *) cb;
1072 tree new_var;
1074 if (TREE_CODE (var) == LABEL_DECL)
1076 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1077 DECL_CONTEXT (new_var) = current_function_decl;
1078 insert_decl_map (&ctx->cb, var, new_var);
1079 return new_var;
1082 while (!is_taskreg_ctx (ctx))
1084 ctx = ctx->outer;
1085 if (ctx == NULL)
1086 return var;
1087 new_var = maybe_lookup_decl (var, ctx);
1088 if (new_var)
1089 return new_var;
1092 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1093 return var;
1095 return error_mark_node;
1099 /* Return the parallel region associated with STMT. */
1101 /* Debugging dumps for parallel regions. */
1102 void dump_omp_region (FILE *, struct omp_region *, int);
1103 void debug_omp_region (struct omp_region *);
1104 void debug_all_omp_regions (void);
1106 /* Dump the parallel region tree rooted at REGION. */
1108 void
1109 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1111 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1112 gimple_code_name[region->type]);
1114 if (region->inner)
1115 dump_omp_region (file, region->inner, indent + 4);
1117 if (region->cont)
1119 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1120 region->cont->index);
1123 if (region->exit)
1124 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1125 region->exit->index);
1126 else
1127 fprintf (file, "%*s[no exit marker]\n", indent, "");
1129 if (region->next)
1130 dump_omp_region (file, region->next, indent);
1133 DEBUG_FUNCTION void
1134 debug_omp_region (struct omp_region *region)
1136 dump_omp_region (stderr, region, 0);
1139 DEBUG_FUNCTION void
1140 debug_all_omp_regions (void)
1142 dump_omp_region (stderr, root_omp_region, 0);
1146 /* Create a new parallel region starting at STMT inside region PARENT. */
1148 struct omp_region *
1149 new_omp_region (basic_block bb, enum gimple_code type,
1150 struct omp_region *parent)
1152 struct omp_region *region = XCNEW (struct omp_region);
1154 region->outer = parent;
1155 region->entry = bb;
1156 region->type = type;
1158 if (parent)
1160 /* This is a nested region. Add it to the list of inner
1161 regions in PARENT. */
1162 region->next = parent->inner;
1163 parent->inner = region;
1165 else
1167 /* This is a toplevel region. Add it to the list of toplevel
1168 regions in ROOT_OMP_REGION. */
1169 region->next = root_omp_region;
1170 root_omp_region = region;
1173 return region;
1176 /* Release the memory associated with the region tree rooted at REGION. */
1178 static void
1179 free_omp_region_1 (struct omp_region *region)
1181 struct omp_region *i, *n;
1183 for (i = region->inner; i ; i = n)
1185 n = i->next;
1186 free_omp_region_1 (i);
1189 free (region);
1192 /* Release the memory for the entire omp region tree. */
1194 void
1195 free_omp_regions (void)
1197 struct omp_region *r, *n;
1198 for (r = root_omp_region; r ; r = n)
1200 n = r->next;
1201 free_omp_region_1 (r);
1203 root_omp_region = NULL;
1207 /* Create a new context, with OUTER_CTX being the surrounding context. */
1209 static omp_context *
1210 new_omp_context (gimple stmt, omp_context *outer_ctx)
1212 omp_context *ctx = XCNEW (omp_context);
1214 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1215 (splay_tree_value) ctx);
1216 ctx->stmt = stmt;
1218 if (outer_ctx)
1220 ctx->outer = outer_ctx;
1221 ctx->cb = outer_ctx->cb;
1222 ctx->cb.block = NULL;
1223 ctx->depth = outer_ctx->depth + 1;
1225 else
1227 ctx->cb.src_fn = current_function_decl;
1228 ctx->cb.dst_fn = current_function_decl;
1229 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1230 gcc_checking_assert (ctx->cb.src_node);
1231 ctx->cb.dst_node = ctx->cb.src_node;
1232 ctx->cb.src_cfun = cfun;
1233 ctx->cb.copy_decl = omp_copy_decl;
1234 ctx->cb.eh_lp_nr = 0;
1235 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1236 ctx->depth = 1;
1239 ctx->cb.decl_map = pointer_map_create ();
1241 return ctx;
1244 static gimple_seq maybe_catch_exception (gimple_seq);
1246 /* Finalize task copyfn. */
1248 static void
1249 finalize_task_copyfn (gimple task_stmt)
1251 struct function *child_cfun;
1252 tree child_fn;
1253 gimple_seq seq = NULL, new_seq;
1254 gimple bind;
1256 child_fn = gimple_omp_task_copy_fn (task_stmt);
1257 if (child_fn == NULL_TREE)
1258 return;
1260 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1261 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1263 push_cfun (child_cfun);
1264 bind = gimplify_body (child_fn, false);
1265 gimple_seq_add_stmt (&seq, bind);
1266 new_seq = maybe_catch_exception (seq);
1267 if (new_seq != seq)
1269 bind = gimple_build_bind (NULL, new_seq, NULL);
1270 seq = NULL;
1271 gimple_seq_add_stmt (&seq, bind);
1273 gimple_set_body (child_fn, seq);
1274 pop_cfun ();
1276 /* Inform the callgraph about the new function. */
1277 cgraph_add_new_function (child_fn, false);
1280 /* Destroy a omp_context data structures. Called through the splay tree
1281 value delete callback. */
1283 static void
1284 delete_omp_context (splay_tree_value value)
1286 omp_context *ctx = (omp_context *) value;
1288 pointer_map_destroy (ctx->cb.decl_map);
1290 if (ctx->field_map)
1291 splay_tree_delete (ctx->field_map);
1292 if (ctx->sfield_map)
1293 splay_tree_delete (ctx->sfield_map);
1295 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1296 it produces corrupt debug information. */
1297 if (ctx->record_type)
1299 tree t;
1300 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1301 DECL_ABSTRACT_ORIGIN (t) = NULL;
1303 if (ctx->srecord_type)
1305 tree t;
1306 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1307 DECL_ABSTRACT_ORIGIN (t) = NULL;
1310 if (is_task_ctx (ctx))
1311 finalize_task_copyfn (ctx->stmt);
1313 XDELETE (ctx);
1316 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1317 context. */
1319 static void
1320 fixup_child_record_type (omp_context *ctx)
1322 tree f, type = ctx->record_type;
1324 /* ??? It isn't sufficient to just call remap_type here, because
1325 variably_modified_type_p doesn't work the way we expect for
1326 record types. Testing each field for whether it needs remapping
1327 and creating a new record by hand works, however. */
1328 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1329 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1330 break;
1331 if (f)
1333 tree name, new_fields = NULL;
1335 type = lang_hooks.types.make_type (RECORD_TYPE);
1336 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1337 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1338 TYPE_DECL, name, type);
1339 TYPE_NAME (type) = name;
1341 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1343 tree new_f = copy_node (f);
1344 DECL_CONTEXT (new_f) = type;
1345 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1346 DECL_CHAIN (new_f) = new_fields;
1347 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1348 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1349 &ctx->cb, NULL);
1350 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1351 &ctx->cb, NULL);
1352 new_fields = new_f;
1354 /* Arrange to be able to look up the receiver field
1355 given the sender field. */
1356 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1357 (splay_tree_value) new_f);
1359 TYPE_FIELDS (type) = nreverse (new_fields);
1360 layout_type (type);
1363 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1366 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1367 specified by CLAUSES. */
1369 static void
1370 scan_sharing_clauses (tree clauses, omp_context *ctx)
1372 tree c, decl;
1373 bool scan_array_reductions = false;
1375 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1377 bool by_ref;
1379 switch (OMP_CLAUSE_CODE (c))
1381 case OMP_CLAUSE_PRIVATE:
1382 decl = OMP_CLAUSE_DECL (c);
1383 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1384 goto do_private;
1385 else if (!is_variable_sized (decl))
1386 install_var_local (decl, ctx);
1387 break;
1389 case OMP_CLAUSE_SHARED:
1390 gcc_assert (is_taskreg_ctx (ctx));
1391 decl = OMP_CLAUSE_DECL (c);
1392 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1393 || !is_variable_sized (decl));
1394 /* Global variables don't need to be copied,
1395 the receiver side will use them directly. */
1396 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1397 break;
1398 by_ref = use_pointer_for_field (decl, ctx);
1399 if (! TREE_READONLY (decl)
1400 || TREE_ADDRESSABLE (decl)
1401 || by_ref
1402 || is_reference (decl))
1404 install_var_field (decl, by_ref, 3, ctx);
1405 install_var_local (decl, ctx);
1406 break;
1408 /* We don't need to copy const scalar vars back. */
1409 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1410 goto do_private;
1412 case OMP_CLAUSE_LASTPRIVATE:
1413 /* Let the corresponding firstprivate clause create
1414 the variable. */
1415 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1416 break;
1417 /* FALLTHRU */
1419 case OMP_CLAUSE_FIRSTPRIVATE:
1420 case OMP_CLAUSE_REDUCTION:
1421 decl = OMP_CLAUSE_DECL (c);
1422 do_private:
1423 if (is_variable_sized (decl))
1425 if (is_task_ctx (ctx))
1426 install_var_field (decl, false, 1, ctx);
1427 break;
1429 else if (is_taskreg_ctx (ctx))
1431 bool global
1432 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1433 by_ref = use_pointer_for_field (decl, NULL);
1435 if (is_task_ctx (ctx)
1436 && (global || by_ref || is_reference (decl)))
1438 install_var_field (decl, false, 1, ctx);
1439 if (!global)
1440 install_var_field (decl, by_ref, 2, ctx);
1442 else if (!global)
1443 install_var_field (decl, by_ref, 3, ctx);
1445 install_var_local (decl, ctx);
1446 break;
1448 case OMP_CLAUSE_COPYPRIVATE:
1449 case OMP_CLAUSE_COPYIN:
1450 decl = OMP_CLAUSE_DECL (c);
1451 by_ref = use_pointer_for_field (decl, NULL);
1452 install_var_field (decl, by_ref, 3, ctx);
1453 break;
1455 case OMP_CLAUSE_DEFAULT:
1456 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1457 break;
1459 case OMP_CLAUSE_FINAL:
1460 case OMP_CLAUSE_IF:
1461 case OMP_CLAUSE_NUM_THREADS:
1462 case OMP_CLAUSE_SCHEDULE:
1463 if (ctx->outer)
1464 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1465 break;
1467 case OMP_CLAUSE_NOWAIT:
1468 case OMP_CLAUSE_ORDERED:
1469 case OMP_CLAUSE_COLLAPSE:
1470 case OMP_CLAUSE_UNTIED:
1471 case OMP_CLAUSE_MERGEABLE:
1472 break;
1474 default:
1475 gcc_unreachable ();
1479 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1481 switch (OMP_CLAUSE_CODE (c))
1483 case OMP_CLAUSE_LASTPRIVATE:
1484 /* Let the corresponding firstprivate clause create
1485 the variable. */
1486 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1487 scan_array_reductions = true;
1488 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1489 break;
1490 /* FALLTHRU */
1492 case OMP_CLAUSE_PRIVATE:
1493 case OMP_CLAUSE_FIRSTPRIVATE:
1494 case OMP_CLAUSE_REDUCTION:
1495 decl = OMP_CLAUSE_DECL (c);
1496 if (is_variable_sized (decl))
1497 install_var_local (decl, ctx);
1498 fixup_remapped_decl (decl, ctx,
1499 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1500 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1501 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1502 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1503 scan_array_reductions = true;
1504 break;
1506 case OMP_CLAUSE_SHARED:
1507 decl = OMP_CLAUSE_DECL (c);
1508 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1509 fixup_remapped_decl (decl, ctx, false);
1510 break;
1512 case OMP_CLAUSE_COPYPRIVATE:
1513 case OMP_CLAUSE_COPYIN:
1514 case OMP_CLAUSE_DEFAULT:
1515 case OMP_CLAUSE_IF:
1516 case OMP_CLAUSE_NUM_THREADS:
1517 case OMP_CLAUSE_SCHEDULE:
1518 case OMP_CLAUSE_NOWAIT:
1519 case OMP_CLAUSE_ORDERED:
1520 case OMP_CLAUSE_COLLAPSE:
1521 case OMP_CLAUSE_UNTIED:
1522 case OMP_CLAUSE_FINAL:
1523 case OMP_CLAUSE_MERGEABLE:
1524 break;
1526 default:
1527 gcc_unreachable ();
1531 if (scan_array_reductions)
1532 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1533 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1534 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1536 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1537 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1539 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1540 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1541 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1544 /* Create a new name for omp child function. Returns an identifier. */
1546 static GTY(()) unsigned int tmp_ompfn_id_num;
1548 static tree
1549 create_omp_child_function_name (bool task_copy)
1551 return (clone_function_name (current_function_decl,
1552 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1555 /* Build a decl for the omp child function. It'll not contain a body
1556 yet, just the bare decl. */
1558 static void
1559 create_omp_child_function (omp_context *ctx, bool task_copy)
1561 tree decl, type, name, t;
1563 name = create_omp_child_function_name (task_copy);
1564 if (task_copy)
1565 type = build_function_type_list (void_type_node, ptr_type_node,
1566 ptr_type_node, NULL_TREE);
1567 else
1568 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1570 decl = build_decl (gimple_location (ctx->stmt),
1571 FUNCTION_DECL, name, type);
1573 if (!task_copy)
1574 ctx->cb.dst_fn = decl;
1575 else
1576 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1578 TREE_STATIC (decl) = 1;
1579 TREE_USED (decl) = 1;
1580 DECL_ARTIFICIAL (decl) = 1;
1581 DECL_NAMELESS (decl) = 1;
1582 DECL_IGNORED_P (decl) = 0;
1583 TREE_PUBLIC (decl) = 0;
1584 DECL_UNINLINABLE (decl) = 1;
1585 DECL_EXTERNAL (decl) = 0;
1586 DECL_CONTEXT (decl) = NULL_TREE;
1587 DECL_INITIAL (decl) = make_node (BLOCK);
1589 t = build_decl (DECL_SOURCE_LOCATION (decl),
1590 RESULT_DECL, NULL_TREE, void_type_node);
1591 DECL_ARTIFICIAL (t) = 1;
1592 DECL_IGNORED_P (t) = 1;
1593 DECL_CONTEXT (t) = decl;
1594 DECL_RESULT (decl) = t;
1596 t = build_decl (DECL_SOURCE_LOCATION (decl),
1597 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1598 DECL_ARTIFICIAL (t) = 1;
1599 DECL_NAMELESS (t) = 1;
1600 DECL_ARG_TYPE (t) = ptr_type_node;
1601 DECL_CONTEXT (t) = current_function_decl;
1602 TREE_USED (t) = 1;
1603 DECL_ARGUMENTS (decl) = t;
1604 if (!task_copy)
1605 ctx->receiver_decl = t;
1606 else
1608 t = build_decl (DECL_SOURCE_LOCATION (decl),
1609 PARM_DECL, get_identifier (".omp_data_o"),
1610 ptr_type_node);
1611 DECL_ARTIFICIAL (t) = 1;
1612 DECL_NAMELESS (t) = 1;
1613 DECL_ARG_TYPE (t) = ptr_type_node;
1614 DECL_CONTEXT (t) = current_function_decl;
1615 TREE_USED (t) = 1;
1616 TREE_ADDRESSABLE (t) = 1;
1617 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1618 DECL_ARGUMENTS (decl) = t;
1621 /* Allocate memory for the function structure. The call to
1622 allocate_struct_function clobbers CFUN, so we need to restore
1623 it afterward. */
1624 push_struct_function (decl);
1625 cfun->function_end_locus = gimple_location (ctx->stmt);
1626 pop_cfun ();
1630 /* Scan an OpenMP parallel directive. */
1632 static void
1633 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1635 omp_context *ctx;
1636 tree name;
1637 gimple stmt = gsi_stmt (*gsi);
1639 /* Ignore parallel directives with empty bodies, unless there
1640 are copyin clauses. */
1641 if (optimize > 0
1642 && empty_body_p (gimple_omp_body (stmt))
1643 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1644 OMP_CLAUSE_COPYIN) == NULL)
1646 gsi_replace (gsi, gimple_build_nop (), false);
1647 return;
1650 ctx = new_omp_context (stmt, outer_ctx);
1651 if (taskreg_nesting_level > 1)
1652 ctx->is_nested = true;
1653 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1654 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1655 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1656 name = create_tmp_var_name (".omp_data_s");
1657 name = build_decl (gimple_location (stmt),
1658 TYPE_DECL, name, ctx->record_type);
1659 DECL_ARTIFICIAL (name) = 1;
1660 DECL_NAMELESS (name) = 1;
1661 TYPE_NAME (ctx->record_type) = name;
1662 create_omp_child_function (ctx, false);
1663 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1665 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1666 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1668 if (TYPE_FIELDS (ctx->record_type) == NULL)
1669 ctx->record_type = ctx->receiver_decl = NULL;
1670 else
1672 layout_type (ctx->record_type);
1673 fixup_child_record_type (ctx);
1677 /* Scan an OpenMP task directive. */
1679 static void
1680 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1682 omp_context *ctx;
1683 tree name, t;
1684 gimple stmt = gsi_stmt (*gsi);
1685 location_t loc = gimple_location (stmt);
1687 /* Ignore task directives with empty bodies. */
1688 if (optimize > 0
1689 && empty_body_p (gimple_omp_body (stmt)))
1691 gsi_replace (gsi, gimple_build_nop (), false);
1692 return;
1695 ctx = new_omp_context (stmt, outer_ctx);
1696 if (taskreg_nesting_level > 1)
1697 ctx->is_nested = true;
1698 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1699 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1700 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1701 name = create_tmp_var_name (".omp_data_s");
1702 name = build_decl (gimple_location (stmt),
1703 TYPE_DECL, name, ctx->record_type);
1704 DECL_ARTIFICIAL (name) = 1;
1705 DECL_NAMELESS (name) = 1;
1706 TYPE_NAME (ctx->record_type) = name;
1707 create_omp_child_function (ctx, false);
1708 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
1710 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
1712 if (ctx->srecord_type)
1714 name = create_tmp_var_name (".omp_data_a");
1715 name = build_decl (gimple_location (stmt),
1716 TYPE_DECL, name, ctx->srecord_type);
1717 DECL_ARTIFICIAL (name) = 1;
1718 DECL_NAMELESS (name) = 1;
1719 TYPE_NAME (ctx->srecord_type) = name;
1720 create_omp_child_function (ctx, true);
1723 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1725 if (TYPE_FIELDS (ctx->record_type) == NULL)
1727 ctx->record_type = ctx->receiver_decl = NULL;
1728 t = build_int_cst (long_integer_type_node, 0);
1729 gimple_omp_task_set_arg_size (stmt, t);
1730 t = build_int_cst (long_integer_type_node, 1);
1731 gimple_omp_task_set_arg_align (stmt, t);
1733 else
1735 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1736 /* Move VLA fields to the end. */
1737 p = &TYPE_FIELDS (ctx->record_type);
1738 while (*p)
1739 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1740 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1742 *q = *p;
1743 *p = TREE_CHAIN (*p);
1744 TREE_CHAIN (*q) = NULL_TREE;
1745 q = &TREE_CHAIN (*q);
1747 else
1748 p = &DECL_CHAIN (*p);
1749 *p = vla_fields;
1750 layout_type (ctx->record_type);
1751 fixup_child_record_type (ctx);
1752 if (ctx->srecord_type)
1753 layout_type (ctx->srecord_type);
1754 t = fold_convert_loc (loc, long_integer_type_node,
1755 TYPE_SIZE_UNIT (ctx->record_type));
1756 gimple_omp_task_set_arg_size (stmt, t);
1757 t = build_int_cst (long_integer_type_node,
1758 TYPE_ALIGN_UNIT (ctx->record_type));
1759 gimple_omp_task_set_arg_align (stmt, t);
1764 /* Scan an OpenMP loop directive. */
1766 static void
1767 scan_omp_for (gimple stmt, omp_context *outer_ctx)
1769 omp_context *ctx;
1770 size_t i;
1772 ctx = new_omp_context (stmt, outer_ctx);
1774 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1776 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
1777 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
1779 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1780 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1781 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1782 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
1784 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1787 /* Scan an OpenMP sections directive. */
1789 static void
1790 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1792 omp_context *ctx;
1794 ctx = new_omp_context (stmt, outer_ctx);
1795 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
1796 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1799 /* Scan an OpenMP single directive. */
1801 static void
1802 scan_omp_single (gimple stmt, omp_context *outer_ctx)
1804 omp_context *ctx;
1805 tree name;
1807 ctx = new_omp_context (stmt, outer_ctx);
1808 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1809 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1810 name = create_tmp_var_name (".omp_copy_s");
1811 name = build_decl (gimple_location (stmt),
1812 TYPE_DECL, name, ctx->record_type);
1813 TYPE_NAME (ctx->record_type) = name;
1815 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
1816 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1818 if (TYPE_FIELDS (ctx->record_type) == NULL)
1819 ctx->record_type = NULL;
1820 else
1821 layout_type (ctx->record_type);
1825 /* Check OpenMP nesting restrictions. */
1826 static bool
1827 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
1829 switch (gimple_code (stmt))
1831 case GIMPLE_OMP_FOR:
1832 case GIMPLE_OMP_SECTIONS:
1833 case GIMPLE_OMP_SINGLE:
1834 case GIMPLE_CALL:
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_ORDERED:
1842 case GIMPLE_OMP_MASTER:
1843 case GIMPLE_OMP_TASK:
1844 if (is_gimple_call (stmt))
1846 error_at (gimple_location (stmt),
1847 "barrier region may not be closely nested inside "
1848 "of work-sharing, critical, ordered, master or "
1849 "explicit task region");
1850 return false;
1852 error_at (gimple_location (stmt),
1853 "work-sharing region may not be closely nested inside "
1854 "of work-sharing, critical, ordered, master or explicit "
1855 "task region");
1856 return false;
1857 case GIMPLE_OMP_PARALLEL:
1858 return true;
1859 default:
1860 break;
1862 break;
1863 case GIMPLE_OMP_MASTER:
1864 for (; ctx != NULL; ctx = ctx->outer)
1865 switch (gimple_code (ctx->stmt))
1867 case GIMPLE_OMP_FOR:
1868 case GIMPLE_OMP_SECTIONS:
1869 case GIMPLE_OMP_SINGLE:
1870 case GIMPLE_OMP_TASK:
1871 error_at (gimple_location (stmt),
1872 "master region may not be closely nested inside "
1873 "of work-sharing or explicit task region");
1874 return false;
1875 case GIMPLE_OMP_PARALLEL:
1876 return true;
1877 default:
1878 break;
1880 break;
1881 case GIMPLE_OMP_ORDERED:
1882 for (; ctx != NULL; ctx = ctx->outer)
1883 switch (gimple_code (ctx->stmt))
1885 case GIMPLE_OMP_CRITICAL:
1886 case GIMPLE_OMP_TASK:
1887 error_at (gimple_location (stmt),
1888 "ordered region may not be closely nested inside "
1889 "of critical or explicit task region");
1890 return false;
1891 case GIMPLE_OMP_FOR:
1892 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
1893 OMP_CLAUSE_ORDERED) == NULL)
1895 error_at (gimple_location (stmt),
1896 "ordered region must be closely nested inside "
1897 "a loop region with an ordered clause");
1898 return false;
1900 return true;
1901 case GIMPLE_OMP_PARALLEL:
1902 return true;
1903 default:
1904 break;
1906 break;
1907 case GIMPLE_OMP_CRITICAL:
1908 for (; ctx != NULL; ctx = ctx->outer)
1909 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1910 && (gimple_omp_critical_name (stmt)
1911 == gimple_omp_critical_name (ctx->stmt)))
1913 error_at (gimple_location (stmt),
1914 "critical region may not be nested inside a critical "
1915 "region with the same name");
1916 return false;
1918 break;
1919 default:
1920 break;
1922 return true;
1926 /* Helper function scan_omp.
1928 Callback for walk_tree or operators in walk_gimple_stmt used to
1929 scan for OpenMP directives in TP. */
1931 static tree
1932 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1934 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1935 omp_context *ctx = (omp_context *) wi->info;
1936 tree t = *tp;
1938 switch (TREE_CODE (t))
1940 case VAR_DECL:
1941 case PARM_DECL:
1942 case LABEL_DECL:
1943 case RESULT_DECL:
1944 if (ctx)
1945 *tp = remap_decl (t, &ctx->cb);
1946 break;
1948 default:
1949 if (ctx && TYPE_P (t))
1950 *tp = remap_type (t, &ctx->cb);
1951 else if (!DECL_P (t))
1953 *walk_subtrees = 1;
1954 if (ctx)
1956 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
1957 if (tem != TREE_TYPE (t))
1959 if (TREE_CODE (t) == INTEGER_CST)
1960 *tp = build_int_cst_wide (tem,
1961 TREE_INT_CST_LOW (t),
1962 TREE_INT_CST_HIGH (t));
1963 else
1964 TREE_TYPE (t) = tem;
1968 break;
1971 return NULL_TREE;
1975 /* Helper function for scan_omp.
1977 Callback for walk_gimple_stmt used to scan for OpenMP directives in
1978 the current statement in GSI. */
1980 static tree
1981 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1982 struct walk_stmt_info *wi)
1984 gimple stmt = gsi_stmt (*gsi);
1985 omp_context *ctx = (omp_context *) wi->info;
1987 if (gimple_has_location (stmt))
1988 input_location = gimple_location (stmt);
1990 /* Check the OpenMP nesting restrictions. */
1991 if (ctx != NULL)
1993 bool remove = false;
1994 if (is_gimple_omp (stmt))
1995 remove = !check_omp_nesting_restrictions (stmt, ctx);
1996 else if (is_gimple_call (stmt))
1998 tree fndecl = gimple_call_fndecl (stmt);
1999 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2000 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
2001 remove = !check_omp_nesting_restrictions (stmt, ctx);
2003 if (remove)
2005 stmt = gimple_build_nop ();
2006 gsi_replace (gsi, stmt, false);
2010 *handled_ops_p = true;
2012 switch (gimple_code (stmt))
2014 case GIMPLE_OMP_PARALLEL:
2015 taskreg_nesting_level++;
2016 scan_omp_parallel (gsi, ctx);
2017 taskreg_nesting_level--;
2018 break;
2020 case GIMPLE_OMP_TASK:
2021 taskreg_nesting_level++;
2022 scan_omp_task (gsi, ctx);
2023 taskreg_nesting_level--;
2024 break;
2026 case GIMPLE_OMP_FOR:
2027 scan_omp_for (stmt, ctx);
2028 break;
2030 case GIMPLE_OMP_SECTIONS:
2031 scan_omp_sections (stmt, ctx);
2032 break;
2034 case GIMPLE_OMP_SINGLE:
2035 scan_omp_single (stmt, ctx);
2036 break;
2038 case GIMPLE_OMP_SECTION:
2039 case GIMPLE_OMP_MASTER:
2040 case GIMPLE_OMP_ORDERED:
2041 case GIMPLE_OMP_CRITICAL:
2042 ctx = new_omp_context (stmt, ctx);
2043 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2044 break;
2046 case GIMPLE_BIND:
2048 tree var;
2050 *handled_ops_p = false;
2051 if (ctx)
2052 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2053 insert_decl_map (&ctx->cb, var, var);
2055 break;
2056 default:
2057 *handled_ops_p = false;
2058 break;
2061 return NULL_TREE;
2065 /* Scan all the statements starting at the current statement. CTX
2066 contains context information about the OpenMP directives and
2067 clauses found during the scan. */
2069 static void
2070 scan_omp (gimple_seq *body_p, omp_context *ctx)
2072 location_t saved_location;
2073 struct walk_stmt_info wi;
2075 memset (&wi, 0, sizeof (wi));
2076 wi.info = ctx;
2077 wi.want_locations = true;
2079 saved_location = input_location;
2080 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2081 input_location = saved_location;
2084 /* Re-gimplification and code generation routines. */
2086 /* Build a call to GOMP_barrier. */
2088 static tree
2089 build_omp_barrier (void)
2091 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
2094 /* If a context was created for STMT when it was scanned, return it. */
2096 static omp_context *
2097 maybe_lookup_ctx (gimple stmt)
2099 splay_tree_node n;
2100 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2101 return n ? (omp_context *) n->value : NULL;
2105 /* Find the mapping for DECL in CTX or the immediately enclosing
2106 context that has a mapping for DECL.
2108 If CTX is a nested parallel directive, we may have to use the decl
2109 mappings created in CTX's parent context. Suppose that we have the
2110 following parallel nesting (variable UIDs showed for clarity):
2112 iD.1562 = 0;
2113 #omp parallel shared(iD.1562) -> outer parallel
2114 iD.1562 = iD.1562 + 1;
2116 #omp parallel shared (iD.1562) -> inner parallel
2117 iD.1562 = iD.1562 - 1;
2119 Each parallel structure will create a distinct .omp_data_s structure
2120 for copying iD.1562 in/out of the directive:
2122 outer parallel .omp_data_s.1.i -> iD.1562
2123 inner parallel .omp_data_s.2.i -> iD.1562
2125 A shared variable mapping will produce a copy-out operation before
2126 the parallel directive and a copy-in operation after it. So, in
2127 this case we would have:
2129 iD.1562 = 0;
2130 .omp_data_o.1.i = iD.1562;
2131 #omp parallel shared(iD.1562) -> outer parallel
2132 .omp_data_i.1 = &.omp_data_o.1
2133 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2135 .omp_data_o.2.i = iD.1562; -> **
2136 #omp parallel shared(iD.1562) -> inner parallel
2137 .omp_data_i.2 = &.omp_data_o.2
2138 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2141 ** This is a problem. The symbol iD.1562 cannot be referenced
2142 inside the body of the outer parallel region. But since we are
2143 emitting this copy operation while expanding the inner parallel
2144 directive, we need to access the CTX structure of the outer
2145 parallel directive to get the correct mapping:
2147 .omp_data_o.2.i = .omp_data_i.1->i
2149 Since there may be other workshare or parallel directives enclosing
2150 the parallel directive, it may be necessary to walk up the context
2151 parent chain. This is not a problem in general because nested
2152 parallelism happens only rarely. */
2154 static tree
2155 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2157 tree t;
2158 omp_context *up;
2160 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2161 t = maybe_lookup_decl (decl, up);
2163 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2165 return t ? t : decl;
2169 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2170 in outer contexts. */
2172 static tree
2173 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2175 tree t = NULL;
2176 omp_context *up;
2178 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2179 t = maybe_lookup_decl (decl, up);
2181 return t ? t : decl;
2185 /* Construct the initialization value for reduction CLAUSE. */
2187 tree
2188 omp_reduction_init (tree clause, tree type)
2190 location_t loc = OMP_CLAUSE_LOCATION (clause);
2191 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2193 case PLUS_EXPR:
2194 case MINUS_EXPR:
2195 case BIT_IOR_EXPR:
2196 case BIT_XOR_EXPR:
2197 case TRUTH_OR_EXPR:
2198 case TRUTH_ORIF_EXPR:
2199 case TRUTH_XOR_EXPR:
2200 case NE_EXPR:
2201 return build_zero_cst (type);
2203 case MULT_EXPR:
2204 case TRUTH_AND_EXPR:
2205 case TRUTH_ANDIF_EXPR:
2206 case EQ_EXPR:
2207 return fold_convert_loc (loc, type, integer_one_node);
2209 case BIT_AND_EXPR:
2210 return fold_convert_loc (loc, type, integer_minus_one_node);
2212 case MAX_EXPR:
2213 if (SCALAR_FLOAT_TYPE_P (type))
2215 REAL_VALUE_TYPE max, min;
2216 if (HONOR_INFINITIES (TYPE_MODE (type)))
2218 real_inf (&max);
2219 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2221 else
2222 real_maxval (&min, 1, TYPE_MODE (type));
2223 return build_real (type, min);
2225 else
2227 gcc_assert (INTEGRAL_TYPE_P (type));
2228 return TYPE_MIN_VALUE (type);
2231 case MIN_EXPR:
2232 if (SCALAR_FLOAT_TYPE_P (type))
2234 REAL_VALUE_TYPE max;
2235 if (HONOR_INFINITIES (TYPE_MODE (type)))
2236 real_inf (&max);
2237 else
2238 real_maxval (&max, 0, TYPE_MODE (type));
2239 return build_real (type, max);
2241 else
2243 gcc_assert (INTEGRAL_TYPE_P (type));
2244 return TYPE_MAX_VALUE (type);
2247 default:
2248 gcc_unreachable ();
2252 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2253 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2254 private variables. Initialization statements go in ILIST, while calls
2255 to destructors go in DLIST. */
2257 static void
2258 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2259 omp_context *ctx)
2261 tree c, dtor, copyin_seq, x, ptr;
2262 bool copyin_by_ref = false;
2263 bool lastprivate_firstprivate = false;
2264 int pass;
2266 copyin_seq = NULL;
2268 /* Do all the fixed sized types in the first pass, and the variable sized
2269 types in the second pass. This makes sure that the scalar arguments to
2270 the variable sized types are processed before we use them in the
2271 variable sized operations. */
2272 for (pass = 0; pass < 2; ++pass)
2274 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2276 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2277 tree var, new_var;
2278 bool by_ref;
2279 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2281 switch (c_kind)
2283 case OMP_CLAUSE_PRIVATE:
2284 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2285 continue;
2286 break;
2287 case OMP_CLAUSE_SHARED:
2288 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2290 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2291 continue;
2293 case OMP_CLAUSE_FIRSTPRIVATE:
2294 case OMP_CLAUSE_COPYIN:
2295 case OMP_CLAUSE_REDUCTION:
2296 break;
2297 case OMP_CLAUSE_LASTPRIVATE:
2298 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2300 lastprivate_firstprivate = true;
2301 if (pass != 0)
2302 continue;
2304 break;
2305 default:
2306 continue;
2309 new_var = var = OMP_CLAUSE_DECL (c);
2310 if (c_kind != OMP_CLAUSE_COPYIN)
2311 new_var = lookup_decl (var, ctx);
2313 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2315 if (pass != 0)
2316 continue;
2318 else if (is_variable_sized (var))
2320 /* For variable sized types, we need to allocate the
2321 actual storage here. Call alloca and store the
2322 result in the pointer decl that we created elsewhere. */
2323 if (pass == 0)
2324 continue;
2326 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2328 gimple stmt;
2329 tree tmp, atmp;
2331 ptr = DECL_VALUE_EXPR (new_var);
2332 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2333 ptr = TREE_OPERAND (ptr, 0);
2334 gcc_assert (DECL_P (ptr));
2335 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2337 /* void *tmp = __builtin_alloca */
2338 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2339 stmt = gimple_build_call (atmp, 1, x);
2340 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2341 gimple_add_tmp_var (tmp);
2342 gimple_call_set_lhs (stmt, tmp);
2344 gimple_seq_add_stmt (ilist, stmt);
2346 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
2347 gimplify_assign (ptr, x, ilist);
2350 else if (is_reference (var))
2352 /* For references that are being privatized for Fortran,
2353 allocate new backing storage for the new pointer
2354 variable. This allows us to avoid changing all the
2355 code that expects a pointer to something that expects
2356 a direct variable. Note that this doesn't apply to
2357 C++, since reference types are disallowed in data
2358 sharing clauses there, except for NRV optimized
2359 return values. */
2360 if (pass == 0)
2361 continue;
2363 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2364 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2366 x = build_receiver_ref (var, false, ctx);
2367 x = build_fold_addr_expr_loc (clause_loc, x);
2369 else if (TREE_CONSTANT (x))
2371 const char *name = NULL;
2372 if (DECL_NAME (var))
2373 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2375 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2376 name);
2377 gimple_add_tmp_var (x);
2378 TREE_ADDRESSABLE (x) = 1;
2379 x = build_fold_addr_expr_loc (clause_loc, x);
2381 else
2383 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2384 x = build_call_expr_loc (clause_loc, atmp, 1, x);
2387 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
2388 gimplify_assign (new_var, x, ilist);
2390 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2392 else if (c_kind == OMP_CLAUSE_REDUCTION
2393 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2395 if (pass == 0)
2396 continue;
2398 else if (pass != 0)
2399 continue;
2401 switch (OMP_CLAUSE_CODE (c))
2403 case OMP_CLAUSE_SHARED:
2404 /* Shared global vars are just accessed directly. */
2405 if (is_global_var (new_var))
2406 break;
2407 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2408 needs to be delayed until after fixup_child_record_type so
2409 that we get the correct type during the dereference. */
2410 by_ref = use_pointer_for_field (var, ctx);
2411 x = build_receiver_ref (var, by_ref, ctx);
2412 SET_DECL_VALUE_EXPR (new_var, x);
2413 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2415 /* ??? If VAR is not passed by reference, and the variable
2416 hasn't been initialized yet, then we'll get a warning for
2417 the store into the omp_data_s structure. Ideally, we'd be
2418 able to notice this and not store anything at all, but
2419 we're generating code too early. Suppress the warning. */
2420 if (!by_ref)
2421 TREE_NO_WARNING (var) = 1;
2422 break;
2424 case OMP_CLAUSE_LASTPRIVATE:
2425 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2426 break;
2427 /* FALLTHRU */
2429 case OMP_CLAUSE_PRIVATE:
2430 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2431 x = build_outer_var_ref (var, ctx);
2432 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2434 if (is_task_ctx (ctx))
2435 x = build_receiver_ref (var, false, ctx);
2436 else
2437 x = build_outer_var_ref (var, ctx);
2439 else
2440 x = NULL;
2441 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2442 if (x)
2443 gimplify_and_add (x, ilist);
2444 /* FALLTHRU */
2446 do_dtor:
2447 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2448 if (x)
2450 gimple_seq tseq = NULL;
2452 dtor = x;
2453 gimplify_stmt (&dtor, &tseq);
2454 gimple_seq_add_seq (dlist, tseq);
2456 break;
2458 case OMP_CLAUSE_FIRSTPRIVATE:
2459 if (is_task_ctx (ctx))
2461 if (is_reference (var) || is_variable_sized (var))
2462 goto do_dtor;
2463 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2464 ctx))
2465 || use_pointer_for_field (var, NULL))
2467 x = build_receiver_ref (var, false, ctx);
2468 SET_DECL_VALUE_EXPR (new_var, x);
2469 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2470 goto do_dtor;
2473 x = build_outer_var_ref (var, ctx);
2474 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2475 gimplify_and_add (x, ilist);
2476 goto do_dtor;
2477 break;
2479 case OMP_CLAUSE_COPYIN:
2480 by_ref = use_pointer_for_field (var, NULL);
2481 x = build_receiver_ref (var, by_ref, ctx);
2482 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2483 append_to_statement_list (x, &copyin_seq);
2484 copyin_by_ref |= by_ref;
2485 break;
2487 case OMP_CLAUSE_REDUCTION:
2488 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2490 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2491 x = build_outer_var_ref (var, ctx);
2493 if (is_reference (var))
2494 x = build_fold_addr_expr_loc (clause_loc, x);
2495 SET_DECL_VALUE_EXPR (placeholder, x);
2496 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2497 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2498 gimple_seq_add_seq (ilist,
2499 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2500 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
2501 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2503 else
2505 x = omp_reduction_init (c, TREE_TYPE (new_var));
2506 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2507 gimplify_assign (new_var, x, ilist);
2509 break;
2511 default:
2512 gcc_unreachable ();
2517 /* The copyin sequence is not to be executed by the main thread, since
2518 that would result in self-copies. Perhaps not visible to scalars,
2519 but it certainly is to C++ operator=. */
2520 if (copyin_seq)
2522 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
2524 x = build2 (NE_EXPR, boolean_type_node, x,
2525 build_int_cst (TREE_TYPE (x), 0));
2526 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2527 gimplify_and_add (x, ilist);
2530 /* If any copyin variable is passed by reference, we must ensure the
2531 master thread doesn't modify it before it is copied over in all
2532 threads. Similarly for variables in both firstprivate and
2533 lastprivate clauses we need to ensure the lastprivate copying
2534 happens after firstprivate copying in all threads. */
2535 if (copyin_by_ref || lastprivate_firstprivate)
2536 gimplify_and_add (build_omp_barrier (), ilist);
2540 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2541 both parallel and workshare constructs. PREDICATE may be NULL if it's
2542 always true. */
2544 static void
2545 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2546 omp_context *ctx)
2548 tree x, c, label = NULL;
2549 bool par_clauses = false;
2551 /* Early exit if there are no lastprivate clauses. */
2552 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
2553 if (clauses == NULL)
2555 /* If this was a workshare clause, see if it had been combined
2556 with its parallel. In that case, look for the clauses on the
2557 parallel statement itself. */
2558 if (is_parallel_ctx (ctx))
2559 return;
2561 ctx = ctx->outer;
2562 if (ctx == NULL || !is_parallel_ctx (ctx))
2563 return;
2565 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2566 OMP_CLAUSE_LASTPRIVATE);
2567 if (clauses == NULL)
2568 return;
2569 par_clauses = true;
2572 if (predicate)
2574 gimple stmt;
2575 tree label_true, arm1, arm2;
2577 label = create_artificial_label (UNKNOWN_LOCATION);
2578 label_true = create_artificial_label (UNKNOWN_LOCATION);
2579 arm1 = TREE_OPERAND (predicate, 0);
2580 arm2 = TREE_OPERAND (predicate, 1);
2581 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2582 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2583 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2584 label_true, label);
2585 gimple_seq_add_stmt (stmt_list, stmt);
2586 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2589 for (c = clauses; c ;)
2591 tree var, new_var;
2592 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2594 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2596 var = OMP_CLAUSE_DECL (c);
2597 new_var = lookup_decl (var, ctx);
2599 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2601 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2602 gimple_seq_add_seq (stmt_list,
2603 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
2605 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
2607 x = build_outer_var_ref (var, ctx);
2608 if (is_reference (var))
2609 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2610 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2611 gimplify_and_add (x, stmt_list);
2613 c = OMP_CLAUSE_CHAIN (c);
2614 if (c == NULL && !par_clauses)
2616 /* If this was a workshare clause, see if it had been combined
2617 with its parallel. In that case, continue looking for the
2618 clauses also on the parallel statement itself. */
2619 if (is_parallel_ctx (ctx))
2620 break;
2622 ctx = ctx->outer;
2623 if (ctx == NULL || !is_parallel_ctx (ctx))
2624 break;
2626 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2627 OMP_CLAUSE_LASTPRIVATE);
2628 par_clauses = true;
2632 if (label)
2633 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
2637 /* Generate code to implement the REDUCTION clauses. */
2639 static void
2640 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
2642 gimple_seq sub_seq = NULL;
2643 gimple stmt;
2644 tree x, c;
2645 int count = 0;
2647 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
2648 update in that case, otherwise use a lock. */
2649 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
2650 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2652 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2654 /* Never use OMP_ATOMIC for array reductions. */
2655 count = -1;
2656 break;
2658 count++;
2661 if (count == 0)
2662 return;
2664 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2666 tree var, ref, new_var;
2667 enum tree_code code;
2668 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2670 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
2671 continue;
2673 var = OMP_CLAUSE_DECL (c);
2674 new_var = lookup_decl (var, ctx);
2675 if (is_reference (var))
2676 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2677 ref = build_outer_var_ref (var, ctx);
2678 code = OMP_CLAUSE_REDUCTION_CODE (c);
2680 /* reduction(-:var) sums up the partial results, so it acts
2681 identically to reduction(+:var). */
2682 if (code == MINUS_EXPR)
2683 code = PLUS_EXPR;
2685 if (count == 1)
2687 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
2689 addr = save_expr (addr);
2690 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
2691 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
2692 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
2693 gimplify_and_add (x, stmt_seqp);
2694 return;
2697 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2699 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2701 if (is_reference (var))
2702 ref = build_fold_addr_expr_loc (clause_loc, ref);
2703 SET_DECL_VALUE_EXPR (placeholder, ref);
2704 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2705 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2706 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
2707 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
2708 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2710 else
2712 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2713 ref = build_outer_var_ref (var, ctx);
2714 gimplify_assign (ref, x, &sub_seq);
2718 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
2720 gimple_seq_add_stmt (stmt_seqp, stmt);
2722 gimple_seq_add_seq (stmt_seqp, sub_seq);
2724 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
2726 gimple_seq_add_stmt (stmt_seqp, stmt);
2730 /* Generate code to implement the COPYPRIVATE clauses. */
2732 static void
2733 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
2734 omp_context *ctx)
2736 tree c;
2738 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2740 tree var, new_var, ref, x;
2741 bool by_ref;
2742 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2744 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2745 continue;
2747 var = OMP_CLAUSE_DECL (c);
2748 by_ref = use_pointer_for_field (var, NULL);
2750 ref = build_sender_ref (var, ctx);
2751 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
2752 if (by_ref)
2754 x = build_fold_addr_expr_loc (clause_loc, new_var);
2755 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
2757 gimplify_assign (ref, x, slist);
2759 ref = build_receiver_ref (var, false, ctx);
2760 if (by_ref)
2762 ref = fold_convert_loc (clause_loc,
2763 build_pointer_type (TREE_TYPE (new_var)),
2764 ref);
2765 ref = build_fold_indirect_ref_loc (clause_loc, ref);
2767 if (is_reference (var))
2769 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
2770 ref = build_simple_mem_ref_loc (clause_loc, ref);
2771 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2773 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
2774 gimplify_and_add (x, rlist);
2779 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2780 and REDUCTION from the sender (aka parent) side. */
2782 static void
2783 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
2784 omp_context *ctx)
2786 tree c;
2788 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2790 tree val, ref, x, var;
2791 bool by_ref, do_in = false, do_out = false;
2792 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2794 switch (OMP_CLAUSE_CODE (c))
2796 case OMP_CLAUSE_PRIVATE:
2797 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2798 break;
2799 continue;
2800 case OMP_CLAUSE_FIRSTPRIVATE:
2801 case OMP_CLAUSE_COPYIN:
2802 case OMP_CLAUSE_LASTPRIVATE:
2803 case OMP_CLAUSE_REDUCTION:
2804 break;
2805 default:
2806 continue;
2809 val = OMP_CLAUSE_DECL (c);
2810 var = lookup_decl_in_outer_ctx (val, ctx);
2812 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2813 && is_global_var (var))
2814 continue;
2815 if (is_variable_sized (val))
2816 continue;
2817 by_ref = use_pointer_for_field (val, NULL);
2819 switch (OMP_CLAUSE_CODE (c))
2821 case OMP_CLAUSE_PRIVATE:
2822 case OMP_CLAUSE_FIRSTPRIVATE:
2823 case OMP_CLAUSE_COPYIN:
2824 do_in = true;
2825 break;
2827 case OMP_CLAUSE_LASTPRIVATE:
2828 if (by_ref || is_reference (val))
2830 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2831 continue;
2832 do_in = true;
2834 else
2836 do_out = true;
2837 if (lang_hooks.decls.omp_private_outer_ref (val))
2838 do_in = true;
2840 break;
2842 case OMP_CLAUSE_REDUCTION:
2843 do_in = true;
2844 do_out = !(by_ref || is_reference (val));
2845 break;
2847 default:
2848 gcc_unreachable ();
2851 if (do_in)
2853 ref = build_sender_ref (val, ctx);
2854 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
2855 gimplify_assign (ref, x, ilist);
2856 if (is_task_ctx (ctx))
2857 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
2860 if (do_out)
2862 ref = build_sender_ref (val, ctx);
2863 gimplify_assign (var, ref, olist);
2868 /* Generate code to implement SHARED from the sender (aka parent)
2869 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
2870 list things that got automatically shared. */
2872 static void
2873 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
2875 tree var, ovar, nvar, f, x, record_type;
2877 if (ctx->record_type == NULL)
2878 return;
2880 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
2881 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
2883 ovar = DECL_ABSTRACT_ORIGIN (f);
2884 nvar = maybe_lookup_decl (ovar, ctx);
2885 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2886 continue;
2888 /* If CTX is a nested parallel directive. Find the immediately
2889 enclosing parallel or workshare construct that contains a
2890 mapping for OVAR. */
2891 var = lookup_decl_in_outer_ctx (ovar, ctx);
2893 if (use_pointer_for_field (ovar, ctx))
2895 x = build_sender_ref (ovar, ctx);
2896 var = build_fold_addr_expr (var);
2897 gimplify_assign (x, var, ilist);
2899 else
2901 x = build_sender_ref (ovar, ctx);
2902 gimplify_assign (x, var, ilist);
2904 if (!TREE_READONLY (var)
2905 /* We don't need to receive a new reference to a result
2906 or parm decl. In fact we may not store to it as we will
2907 invalidate any pending RSO and generate wrong gimple
2908 during inlining. */
2909 && !((TREE_CODE (var) == RESULT_DECL
2910 || TREE_CODE (var) == PARM_DECL)
2911 && DECL_BY_REFERENCE (var)))
2913 x = build_sender_ref (ovar, ctx);
2914 gimplify_assign (var, x, olist);
2921 /* A convenience function to build an empty GIMPLE_COND with just the
2922 condition. */
2924 static gimple
2925 gimple_build_cond_empty (tree cond)
2927 enum tree_code pred_code;
2928 tree lhs, rhs;
2930 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
2931 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
2935 /* Build the function calls to GOMP_parallel_start etc to actually
2936 generate the parallel operation. REGION is the parallel region
2937 being expanded. BB is the block where to insert the code. WS_ARGS
2938 will be set if this is a call to a combined parallel+workshare
2939 construct, it contains the list of additional arguments needed by
2940 the workshare construct. */
2942 static void
2943 expand_parallel_call (struct omp_region *region, basic_block bb,
2944 gimple entry_stmt, vec<tree, va_gc> *ws_args)
2946 tree t, t1, t2, val, cond, c, clauses;
2947 gimple_stmt_iterator gsi;
2948 gimple stmt;
2949 enum built_in_function start_ix;
2950 int start_ix2;
2951 location_t clause_loc;
2952 vec<tree, va_gc> *args;
2954 clauses = gimple_omp_parallel_clauses (entry_stmt);
2956 /* Determine what flavor of GOMP_parallel_start we will be
2957 emitting. */
2958 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2959 if (is_combined_parallel (region))
2961 switch (region->inner->type)
2963 case GIMPLE_OMP_FOR:
2964 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
2965 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2966 + (region->inner->sched_kind
2967 == OMP_CLAUSE_SCHEDULE_RUNTIME
2968 ? 3 : region->inner->sched_kind));
2969 start_ix = (enum built_in_function)start_ix2;
2970 break;
2971 case GIMPLE_OMP_SECTIONS:
2972 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2973 break;
2974 default:
2975 gcc_unreachable ();
2979 /* By default, the value of NUM_THREADS is zero (selected at run time)
2980 and there is no conditional. */
2981 cond = NULL_TREE;
2982 val = build_int_cst (unsigned_type_node, 0);
2984 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2985 if (c)
2986 cond = OMP_CLAUSE_IF_EXPR (c);
2988 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2989 if (c)
2991 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2992 clause_loc = OMP_CLAUSE_LOCATION (c);
2994 else
2995 clause_loc = gimple_location (entry_stmt);
2997 /* Ensure 'val' is of the correct type. */
2998 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
3000 /* If we found the clause 'if (cond)', build either
3001 (cond != 0) or (cond ? val : 1u). */
3002 if (cond)
3004 gimple_stmt_iterator gsi;
3006 cond = gimple_boolify (cond);
3008 if (integer_zerop (val))
3009 val = fold_build2_loc (clause_loc,
3010 EQ_EXPR, unsigned_type_node, cond,
3011 build_int_cst (TREE_TYPE (cond), 0));
3012 else
3014 basic_block cond_bb, then_bb, else_bb;
3015 edge e, e_then, e_else;
3016 tree tmp_then, tmp_else, tmp_join, tmp_var;
3018 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
3019 if (gimple_in_ssa_p (cfun))
3021 tmp_then = make_ssa_name (tmp_var, NULL);
3022 tmp_else = make_ssa_name (tmp_var, NULL);
3023 tmp_join = make_ssa_name (tmp_var, NULL);
3025 else
3027 tmp_then = tmp_var;
3028 tmp_else = tmp_var;
3029 tmp_join = tmp_var;
3032 e = split_block (bb, NULL);
3033 cond_bb = e->src;
3034 bb = e->dest;
3035 remove_edge (e);
3037 then_bb = create_empty_bb (cond_bb);
3038 else_bb = create_empty_bb (then_bb);
3039 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
3040 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
3042 stmt = gimple_build_cond_empty (cond);
3043 gsi = gsi_start_bb (cond_bb);
3044 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3046 gsi = gsi_start_bb (then_bb);
3047 stmt = gimple_build_assign (tmp_then, val);
3048 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3050 gsi = gsi_start_bb (else_bb);
3051 stmt = gimple_build_assign
3052 (tmp_else, build_int_cst (unsigned_type_node, 1));
3053 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3055 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
3056 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
3057 if (current_loops)
3059 add_bb_to_loop (then_bb, cond_bb->loop_father);
3060 add_bb_to_loop (else_bb, cond_bb->loop_father);
3062 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3063 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
3065 if (gimple_in_ssa_p (cfun))
3067 gimple phi = create_phi_node (tmp_join, bb);
3068 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3069 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
3072 val = tmp_join;
3075 gsi = gsi_start_bb (bb);
3076 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3077 false, GSI_CONTINUE_LINKING);
3080 gsi = gsi_last_bb (bb);
3081 t = gimple_omp_parallel_data_arg (entry_stmt);
3082 if (t == NULL)
3083 t1 = null_pointer_node;
3084 else
3085 t1 = build_fold_addr_expr (t);
3086 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
3088 vec_alloc (args, 3 + vec_safe_length (ws_args));
3089 args->quick_push (t2);
3090 args->quick_push (t1);
3091 args->quick_push (val);
3092 if (ws_args)
3093 args->splice (*ws_args);
3095 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
3096 builtin_decl_explicit (start_ix), args);
3098 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3099 false, GSI_CONTINUE_LINKING);
3101 t = gimple_omp_parallel_data_arg (entry_stmt);
3102 if (t == NULL)
3103 t = null_pointer_node;
3104 else
3105 t = build_fold_addr_expr (t);
3106 t = build_call_expr_loc (gimple_location (entry_stmt),
3107 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3108 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3109 false, GSI_CONTINUE_LINKING);
3111 t = build_call_expr_loc (gimple_location (entry_stmt),
3112 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3114 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3115 false, GSI_CONTINUE_LINKING);
3119 /* Build the function call to GOMP_task to actually
3120 generate the task operation. BB is the block where to insert the code. */
3122 static void
3123 expand_task_call (basic_block bb, gimple entry_stmt)
3125 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
3126 gimple_stmt_iterator gsi;
3127 location_t loc = gimple_location (entry_stmt);
3129 clauses = gimple_omp_task_clauses (entry_stmt);
3131 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3132 if (c)
3133 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3134 else
3135 cond = boolean_true_node;
3137 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3138 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3139 flags = build_int_cst (unsigned_type_node,
3140 (c ? 1 : 0) + (c2 ? 4 : 0));
3142 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3143 if (c)
3145 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3146 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3147 build_int_cst (unsigned_type_node, 2),
3148 build_int_cst (unsigned_type_node, 0));
3149 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3152 gsi = gsi_last_bb (bb);
3153 t = gimple_omp_task_data_arg (entry_stmt);
3154 if (t == NULL)
3155 t2 = null_pointer_node;
3156 else
3157 t2 = build_fold_addr_expr_loc (loc, t);
3158 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
3159 t = gimple_omp_task_copy_fn (entry_stmt);
3160 if (t == NULL)
3161 t3 = null_pointer_node;
3162 else
3163 t3 = build_fold_addr_expr_loc (loc, t);
3165 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3166 7, t1, t2, t3,
3167 gimple_omp_task_arg_size (entry_stmt),
3168 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3170 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3171 false, GSI_CONTINUE_LINKING);
3175 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3176 catch handler and return it. This prevents programs from violating the
3177 structured block semantics with throws. */
3179 static gimple_seq
3180 maybe_catch_exception (gimple_seq body)
3182 gimple g;
3183 tree decl;
3185 if (!flag_exceptions)
3186 return body;
3188 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3189 decl = lang_hooks.eh_protect_cleanup_actions ();
3190 else
3191 decl = builtin_decl_explicit (BUILT_IN_TRAP);
3193 g = gimple_build_eh_must_not_throw (decl);
3194 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
3195 GIMPLE_TRY_CATCH);
3197 return gimple_seq_alloc_with_stmt (g);
3200 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3202 static tree
3203 vec2chain (vec<tree, va_gc> *v)
3205 tree chain = NULL_TREE, t;
3206 unsigned ix;
3208 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
3210 DECL_CHAIN (t) = chain;
3211 chain = t;
3214 return chain;
3218 /* Remove barriers in REGION->EXIT's block. Note that this is only
3219 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3220 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3221 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3222 removed. */
3224 static void
3225 remove_exit_barrier (struct omp_region *region)
3227 gimple_stmt_iterator gsi;
3228 basic_block exit_bb;
3229 edge_iterator ei;
3230 edge e;
3231 gimple stmt;
3232 int any_addressable_vars = -1;
3234 exit_bb = region->exit;
3236 /* If the parallel region doesn't return, we don't have REGION->EXIT
3237 block at all. */
3238 if (! exit_bb)
3239 return;
3241 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3242 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3243 statements that can appear in between are extremely limited -- no
3244 memory operations at all. Here, we allow nothing at all, so the
3245 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3246 gsi = gsi_last_bb (exit_bb);
3247 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3248 gsi_prev (&gsi);
3249 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3250 return;
3252 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3254 gsi = gsi_last_bb (e->src);
3255 if (gsi_end_p (gsi))
3256 continue;
3257 stmt = gsi_stmt (gsi);
3258 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3259 && !gimple_omp_return_nowait_p (stmt))
3261 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3262 in many cases. If there could be tasks queued, the barrier
3263 might be needed to let the tasks run before some local
3264 variable of the parallel that the task uses as shared
3265 runs out of scope. The task can be spawned either
3266 from within current function (this would be easy to check)
3267 or from some function it calls and gets passed an address
3268 of such a variable. */
3269 if (any_addressable_vars < 0)
3271 gimple parallel_stmt = last_stmt (region->entry);
3272 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3273 tree local_decls, block, decl;
3274 unsigned ix;
3276 any_addressable_vars = 0;
3277 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3278 if (TREE_ADDRESSABLE (decl))
3280 any_addressable_vars = 1;
3281 break;
3283 for (block = gimple_block (stmt);
3284 !any_addressable_vars
3285 && block
3286 && TREE_CODE (block) == BLOCK;
3287 block = BLOCK_SUPERCONTEXT (block))
3289 for (local_decls = BLOCK_VARS (block);
3290 local_decls;
3291 local_decls = DECL_CHAIN (local_decls))
3292 if (TREE_ADDRESSABLE (local_decls))
3294 any_addressable_vars = 1;
3295 break;
3297 if (block == gimple_block (parallel_stmt))
3298 break;
3301 if (!any_addressable_vars)
3302 gimple_omp_return_set_nowait (stmt);
3307 static void
3308 remove_exit_barriers (struct omp_region *region)
3310 if (region->type == GIMPLE_OMP_PARALLEL)
3311 remove_exit_barrier (region);
3313 if (region->inner)
3315 region = region->inner;
3316 remove_exit_barriers (region);
3317 while (region->next)
3319 region = region->next;
3320 remove_exit_barriers (region);
3325 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3326 calls. These can't be declared as const functions, but
3327 within one parallel body they are constant, so they can be
3328 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3329 which are declared const. Similarly for task body, except
3330 that in untied task omp_get_thread_num () can change at any task
3331 scheduling point. */
3333 static void
3334 optimize_omp_library_calls (gimple entry_stmt)
3336 basic_block bb;
3337 gimple_stmt_iterator gsi;
3338 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3339 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3340 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3341 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
3342 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3343 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3344 OMP_CLAUSE_UNTIED) != NULL);
3346 FOR_EACH_BB (bb)
3347 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3349 gimple call = gsi_stmt (gsi);
3350 tree decl;
3352 if (is_gimple_call (call)
3353 && (decl = gimple_call_fndecl (call))
3354 && DECL_EXTERNAL (decl)
3355 && TREE_PUBLIC (decl)
3356 && DECL_INITIAL (decl) == NULL)
3358 tree built_in;
3360 if (DECL_NAME (decl) == thr_num_id)
3362 /* In #pragma omp task untied omp_get_thread_num () can change
3363 during the execution of the task region. */
3364 if (untied_task)
3365 continue;
3366 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3368 else if (DECL_NAME (decl) == num_thr_id)
3369 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3370 else
3371 continue;
3373 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3374 || gimple_call_num_args (call) != 0)
3375 continue;
3377 if (flag_exceptions && !TREE_NOTHROW (decl))
3378 continue;
3380 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3381 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3382 TREE_TYPE (TREE_TYPE (built_in))))
3383 continue;
3385 gimple_call_set_fndecl (call, built_in);
3390 /* Expand the OpenMP parallel or task directive starting at REGION. */
3392 static void
3393 expand_omp_taskreg (struct omp_region *region)
3395 basic_block entry_bb, exit_bb, new_bb;
3396 struct function *child_cfun;
3397 tree child_fn, block, t;
3398 gimple_stmt_iterator gsi;
3399 gimple entry_stmt, stmt;
3400 edge e;
3401 vec<tree, va_gc> *ws_args;
3403 entry_stmt = last_stmt (region->entry);
3404 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3405 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3407 entry_bb = region->entry;
3408 exit_bb = region->exit;
3410 if (is_combined_parallel (region))
3411 ws_args = region->ws_args;
3412 else
3413 ws_args = NULL;
3415 if (child_cfun->cfg)
3417 /* Due to inlining, it may happen that we have already outlined
3418 the region, in which case all we need to do is make the
3419 sub-graph unreachable and emit the parallel call. */
3420 edge entry_succ_e, exit_succ_e;
3421 gimple_stmt_iterator gsi;
3423 entry_succ_e = single_succ_edge (entry_bb);
3425 gsi = gsi_last_bb (entry_bb);
3426 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3427 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3428 gsi_remove (&gsi, true);
3430 new_bb = entry_bb;
3431 if (exit_bb)
3433 exit_succ_e = single_succ_edge (exit_bb);
3434 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3436 remove_edge_and_dominated_blocks (entry_succ_e);
3438 else
3440 unsigned srcidx, dstidx, num;
3442 /* If the parallel region needs data sent from the parent
3443 function, then the very first statement (except possible
3444 tree profile counter updates) of the parallel body
3445 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3446 &.OMP_DATA_O is passed as an argument to the child function,
3447 we need to replace it with the argument as seen by the child
3448 function.
3450 In most cases, this will end up being the identity assignment
3451 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3452 a function call that has been inlined, the original PARM_DECL
3453 .OMP_DATA_I may have been converted into a different local
3454 variable. In which case, we need to keep the assignment. */
3455 if (gimple_omp_taskreg_data_arg (entry_stmt))
3457 basic_block entry_succ_bb = single_succ (entry_bb);
3458 gimple_stmt_iterator gsi;
3459 tree arg, narg;
3460 gimple parcopy_stmt = NULL;
3462 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3464 gimple stmt;
3466 gcc_assert (!gsi_end_p (gsi));
3467 stmt = gsi_stmt (gsi);
3468 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3469 continue;
3471 if (gimple_num_ops (stmt) == 2)
3473 tree arg = gimple_assign_rhs1 (stmt);
3475 /* We're ignore the subcode because we're
3476 effectively doing a STRIP_NOPS. */
3478 if (TREE_CODE (arg) == ADDR_EXPR
3479 && TREE_OPERAND (arg, 0)
3480 == gimple_omp_taskreg_data_arg (entry_stmt))
3482 parcopy_stmt = stmt;
3483 break;
3488 gcc_assert (parcopy_stmt != NULL);
3489 arg = DECL_ARGUMENTS (child_fn);
3491 if (!gimple_in_ssa_p (cfun))
3493 if (gimple_assign_lhs (parcopy_stmt) == arg)
3494 gsi_remove (&gsi, true);
3495 else
3497 /* ?? Is setting the subcode really necessary ?? */
3498 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3499 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3502 else
3504 /* If we are in ssa form, we must load the value from the default
3505 definition of the argument. That should not be defined now,
3506 since the argument is not used uninitialized. */
3507 gcc_assert (ssa_default_def (cfun, arg) == NULL);
3508 narg = make_ssa_name (arg, gimple_build_nop ());
3509 set_ssa_default_def (cfun, arg, narg);
3510 /* ?? Is setting the subcode really necessary ?? */
3511 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3512 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3513 update_stmt (parcopy_stmt);
3517 /* Declare local variables needed in CHILD_CFUN. */
3518 block = DECL_INITIAL (child_fn);
3519 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
3520 /* The gimplifier could record temporaries in parallel/task block
3521 rather than in containing function's local_decls chain,
3522 which would mean cgraph missed finalizing them. Do it now. */
3523 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
3524 if (TREE_CODE (t) == VAR_DECL
3525 && TREE_STATIC (t)
3526 && !DECL_EXTERNAL (t))
3527 varpool_finalize_decl (t);
3528 DECL_SAVED_TREE (child_fn) = NULL;
3529 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3530 gimple_set_body (child_fn, NULL);
3531 TREE_USED (block) = 1;
3533 /* Reset DECL_CONTEXT on function arguments. */
3534 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
3535 DECL_CONTEXT (t) = child_fn;
3537 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3538 so that it can be moved to the child function. */
3539 gsi = gsi_last_bb (entry_bb);
3540 stmt = gsi_stmt (gsi);
3541 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3542 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3543 gsi_remove (&gsi, true);
3544 e = split_block (entry_bb, stmt);
3545 entry_bb = e->dest;
3546 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3548 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3549 if (exit_bb)
3551 gsi = gsi_last_bb (exit_bb);
3552 gcc_assert (!gsi_end_p (gsi)
3553 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3554 stmt = gimple_build_return (NULL);
3555 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3556 gsi_remove (&gsi, true);
3559 /* Move the parallel region into CHILD_CFUN. */
3561 if (gimple_in_ssa_p (cfun))
3563 init_tree_ssa (child_cfun);
3564 init_ssa_operands (child_cfun);
3565 child_cfun->gimple_df->in_ssa_p = true;
3566 block = NULL_TREE;
3568 else
3569 block = gimple_block (entry_stmt);
3571 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3572 if (exit_bb)
3573 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3574 /* ??? As the OMP expansion process does not update the loop
3575 tree of the original function before outlining the region to
3576 the new child function we need to discover loops in the child.
3577 Arrange for that. */
3578 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
3580 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3581 num = vec_safe_length (child_cfun->local_decls);
3582 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3584 t = (*child_cfun->local_decls)[srcidx];
3585 if (DECL_CONTEXT (t) == cfun->decl)
3586 continue;
3587 if (srcidx != dstidx)
3588 (*child_cfun->local_decls)[dstidx] = t;
3589 dstidx++;
3591 if (dstidx != num)
3592 vec_safe_truncate (child_cfun->local_decls, dstidx);
3594 /* Inform the callgraph about the new function. */
3595 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
3596 cgraph_add_new_function (child_fn, true);
3598 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3599 fixed in a following pass. */
3600 push_cfun (child_cfun);
3601 if (optimize)
3602 optimize_omp_library_calls (entry_stmt);
3603 rebuild_cgraph_edges ();
3605 /* Some EH regions might become dead, see PR34608. If
3606 pass_cleanup_cfg isn't the first pass to happen with the
3607 new child, these dead EH edges might cause problems.
3608 Clean them up now. */
3609 if (flag_exceptions)
3611 basic_block bb;
3612 bool changed = false;
3614 FOR_EACH_BB (bb)
3615 changed |= gimple_purge_dead_eh_edges (bb);
3616 if (changed)
3617 cleanup_tree_cfg ();
3619 if (gimple_in_ssa_p (cfun))
3620 update_ssa (TODO_update_ssa);
3621 pop_cfun ();
3624 /* Emit a library call to launch the children threads. */
3625 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
3626 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3627 else
3628 expand_task_call (new_bb, entry_stmt);
3629 if (gimple_in_ssa_p (cfun))
3630 update_ssa (TODO_update_ssa_only_virtuals);
3634 /* A subroutine of expand_omp_for. Generate code for a parallel
3635 loop with any schedule. Given parameters:
3637 for (V = N1; V cond N2; V += STEP) BODY;
3639 where COND is "<" or ">", we generate pseudocode
3641 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3642 if (more) goto L0; else goto L3;
3644 V = istart0;
3645 iend = iend0;
3647 BODY;
3648 V += STEP;
3649 if (V cond iend) goto L1; else goto L2;
3651 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3654 If this is a combined omp parallel loop, instead of the call to
3655 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3657 For collapsed loops, given parameters:
3658 collapse(3)
3659 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3660 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3661 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3662 BODY;
3664 we generate pseudocode
3666 if (cond3 is <)
3667 adj = STEP3 - 1;
3668 else
3669 adj = STEP3 + 1;
3670 count3 = (adj + N32 - N31) / STEP3;
3671 if (cond2 is <)
3672 adj = STEP2 - 1;
3673 else
3674 adj = STEP2 + 1;
3675 count2 = (adj + N22 - N21) / STEP2;
3676 if (cond1 is <)
3677 adj = STEP1 - 1;
3678 else
3679 adj = STEP1 + 1;
3680 count1 = (adj + N12 - N11) / STEP1;
3681 count = count1 * count2 * count3;
3682 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3683 if (more) goto L0; else goto L3;
3685 V = istart0;
3686 T = V;
3687 V3 = N31 + (T % count3) * STEP3;
3688 T = T / count3;
3689 V2 = N21 + (T % count2) * STEP2;
3690 T = T / count2;
3691 V1 = N11 + T * STEP1;
3692 iend = iend0;
3694 BODY;
3695 V += 1;
3696 if (V < iend) goto L10; else goto L2;
3697 L10:
3698 V3 += STEP3;
3699 if (V3 cond3 N32) goto L1; else goto L11;
3700 L11:
3701 V3 = N31;
3702 V2 += STEP2;
3703 if (V2 cond2 N22) goto L1; else goto L12;
3704 L12:
3705 V2 = N21;
3706 V1 += STEP1;
3707 goto L1;
3709 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3714 static void
3715 expand_omp_for_generic (struct omp_region *region,
3716 struct omp_for_data *fd,
3717 enum built_in_function start_fn,
3718 enum built_in_function next_fn)
3720 tree type, istart0, iend0, iend;
3721 tree t, vmain, vback, bias = NULL_TREE;
3722 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3723 basic_block l2_bb = NULL, l3_bb = NULL;
3724 gimple_stmt_iterator gsi;
3725 gimple stmt;
3726 bool in_combined_parallel = is_combined_parallel (region);
3727 bool broken_loop = region->cont == NULL;
3728 edge e, ne;
3729 tree *counts = NULL;
3730 int i;
3732 gcc_assert (!broken_loop || !in_combined_parallel);
3733 gcc_assert (fd->iter_type == long_integer_type_node
3734 || !in_combined_parallel);
3736 type = TREE_TYPE (fd->loop.v);
3737 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3738 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3739 TREE_ADDRESSABLE (istart0) = 1;
3740 TREE_ADDRESSABLE (iend0) = 1;
3742 /* See if we need to bias by LLONG_MIN. */
3743 if (fd->iter_type == long_long_unsigned_type_node
3744 && TREE_CODE (type) == INTEGER_TYPE
3745 && !TYPE_UNSIGNED (type))
3747 tree n1, n2;
3749 if (fd->loop.cond_code == LT_EXPR)
3751 n1 = fd->loop.n1;
3752 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3754 else
3756 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3757 n2 = fd->loop.n1;
3759 if (TREE_CODE (n1) != INTEGER_CST
3760 || TREE_CODE (n2) != INTEGER_CST
3761 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3762 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3765 entry_bb = region->entry;
3766 cont_bb = region->cont;
3767 collapse_bb = NULL;
3768 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3769 gcc_assert (broken_loop
3770 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3771 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3772 l1_bb = single_succ (l0_bb);
3773 if (!broken_loop)
3775 l2_bb = create_empty_bb (cont_bb);
3776 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3777 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3779 else
3780 l2_bb = NULL;
3781 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3782 exit_bb = region->exit;
3784 gsi = gsi_last_bb (entry_bb);
3786 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
3787 if (fd->collapse > 1)
3789 /* collapsed loops need work for expansion in SSA form. */
3790 gcc_assert (!gimple_in_ssa_p (cfun));
3791 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3792 for (i = 0; i < fd->collapse; i++)
3794 tree itype = TREE_TYPE (fd->loops[i].v);
3796 if (POINTER_TYPE_P (itype))
3797 itype = signed_type_for (itype);
3798 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3799 ? -1 : 1));
3800 t = fold_build2 (PLUS_EXPR, itype,
3801 fold_convert (itype, fd->loops[i].step), t);
3802 t = fold_build2 (PLUS_EXPR, itype, t,
3803 fold_convert (itype, fd->loops[i].n2));
3804 t = fold_build2 (MINUS_EXPR, itype, t,
3805 fold_convert (itype, fd->loops[i].n1));
3806 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3807 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3808 fold_build1 (NEGATE_EXPR, itype, t),
3809 fold_build1 (NEGATE_EXPR, itype,
3810 fold_convert (itype,
3811 fd->loops[i].step)));
3812 else
3813 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3814 fold_convert (itype, fd->loops[i].step));
3815 t = fold_convert (type, t);
3816 if (TREE_CODE (t) == INTEGER_CST)
3817 counts[i] = t;
3818 else
3820 counts[i] = create_tmp_reg (type, ".count");
3821 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3822 true, GSI_SAME_STMT);
3823 stmt = gimple_build_assign (counts[i], t);
3824 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3826 if (SSA_VAR_P (fd->loop.n2))
3828 if (i == 0)
3829 t = counts[0];
3830 else
3832 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3833 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3834 true, GSI_SAME_STMT);
3836 stmt = gimple_build_assign (fd->loop.n2, t);
3837 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3841 if (in_combined_parallel)
3843 /* In a combined parallel loop, emit a call to
3844 GOMP_loop_foo_next. */
3845 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
3846 build_fold_addr_expr (istart0),
3847 build_fold_addr_expr (iend0));
3849 else
3851 tree t0, t1, t2, t3, t4;
3852 /* If this is not a combined parallel loop, emit a call to
3853 GOMP_loop_foo_start in ENTRY_BB. */
3854 t4 = build_fold_addr_expr (iend0);
3855 t3 = build_fold_addr_expr (istart0);
3856 t2 = fold_convert (fd->iter_type, fd->loop.step);
3857 if (POINTER_TYPE_P (type)
3858 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
3860 /* Avoid casting pointers to integer of a different size. */
3861 tree itype = signed_type_for (type);
3862 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
3863 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
3865 else
3867 t1 = fold_convert (fd->iter_type, fd->loop.n2);
3868 t0 = fold_convert (fd->iter_type, fd->loop.n1);
3870 if (bias)
3872 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
3873 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
3875 if (fd->iter_type == long_integer_type_node)
3877 if (fd->chunk_size)
3879 t = fold_convert (fd->iter_type, fd->chunk_size);
3880 t = build_call_expr (builtin_decl_explicit (start_fn),
3881 6, t0, t1, t2, t, t3, t4);
3883 else
3884 t = build_call_expr (builtin_decl_explicit (start_fn),
3885 5, t0, t1, t2, t3, t4);
3887 else
3889 tree t5;
3890 tree c_bool_type;
3891 tree bfn_decl;
3893 /* The GOMP_loop_ull_*start functions have additional boolean
3894 argument, true for < loops and false for > loops.
3895 In Fortran, the C bool type can be different from
3896 boolean_type_node. */
3897 bfn_decl = builtin_decl_explicit (start_fn);
3898 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
3899 t5 = build_int_cst (c_bool_type,
3900 fd->loop.cond_code == LT_EXPR ? 1 : 0);
3901 if (fd->chunk_size)
3903 tree bfn_decl = builtin_decl_explicit (start_fn);
3904 t = fold_convert (fd->iter_type, fd->chunk_size);
3905 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
3907 else
3908 t = build_call_expr (builtin_decl_explicit (start_fn),
3909 6, t5, t0, t1, t2, t3, t4);
3912 if (TREE_TYPE (t) != boolean_type_node)
3913 t = fold_build2 (NE_EXPR, boolean_type_node,
3914 t, build_int_cst (TREE_TYPE (t), 0));
3915 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3916 true, GSI_SAME_STMT);
3917 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
3919 /* Remove the GIMPLE_OMP_FOR statement. */
3920 gsi_remove (&gsi, true);
3922 /* Iteration setup for sequential loop goes in L0_BB. */
3923 gsi = gsi_start_bb (l0_bb);
3924 t = istart0;
3925 if (bias)
3926 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3927 if (POINTER_TYPE_P (type))
3928 t = fold_convert (signed_type_for (type), t);
3929 t = fold_convert (type, t);
3930 t = force_gimple_operand_gsi (&gsi, t,
3931 DECL_P (fd->loop.v)
3932 && TREE_ADDRESSABLE (fd->loop.v),
3933 NULL_TREE, false, GSI_CONTINUE_LINKING);
3934 stmt = gimple_build_assign (fd->loop.v, t);
3935 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3937 t = iend0;
3938 if (bias)
3939 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3940 if (POINTER_TYPE_P (type))
3941 t = fold_convert (signed_type_for (type), t);
3942 t = fold_convert (type, t);
3943 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3944 false, GSI_CONTINUE_LINKING);
3945 if (fd->collapse > 1)
3947 tree tem = create_tmp_reg (type, ".tem");
3948 stmt = gimple_build_assign (tem, fd->loop.v);
3949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3950 for (i = fd->collapse - 1; i >= 0; i--)
3952 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
3953 itype = vtype;
3954 if (POINTER_TYPE_P (vtype))
3955 itype = signed_type_for (vtype);
3956 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
3957 t = fold_convert (itype, t);
3958 t = fold_build2 (MULT_EXPR, itype, t,
3959 fold_convert (itype, fd->loops[i].step));
3960 if (POINTER_TYPE_P (vtype))
3961 t = fold_build_pointer_plus (fd->loops[i].n1, t);
3962 else
3963 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3964 t = force_gimple_operand_gsi (&gsi, t,
3965 DECL_P (fd->loops[i].v)
3966 && TREE_ADDRESSABLE (fd->loops[i].v),
3967 NULL_TREE, false,
3968 GSI_CONTINUE_LINKING);
3969 stmt = gimple_build_assign (fd->loops[i].v, t);
3970 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3971 if (i != 0)
3973 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3974 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3975 false, GSI_CONTINUE_LINKING);
3976 stmt = gimple_build_assign (tem, t);
3977 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3982 if (!broken_loop)
3984 /* Code to control the increment and predicate for the sequential
3985 loop goes in the CONT_BB. */
3986 gsi = gsi_last_bb (cont_bb);
3987 stmt = gsi_stmt (gsi);
3988 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
3989 vmain = gimple_omp_continue_control_use (stmt);
3990 vback = gimple_omp_continue_control_def (stmt);
3992 if (POINTER_TYPE_P (type))
3993 t = fold_build_pointer_plus (vmain, fd->loop.step);
3994 else
3995 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3996 t = force_gimple_operand_gsi (&gsi, t,
3997 DECL_P (vback) && TREE_ADDRESSABLE (vback),
3998 NULL_TREE, true, GSI_SAME_STMT);
3999 stmt = gimple_build_assign (vback, t);
4000 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4002 t = build2 (fd->loop.cond_code, boolean_type_node,
4003 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
4004 iend);
4005 stmt = gimple_build_cond_empty (t);
4006 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4008 /* Remove GIMPLE_OMP_CONTINUE. */
4009 gsi_remove (&gsi, true);
4011 if (fd->collapse > 1)
4013 basic_block last_bb, bb;
4015 last_bb = cont_bb;
4016 for (i = fd->collapse - 1; i >= 0; i--)
4018 tree vtype = TREE_TYPE (fd->loops[i].v);
4020 bb = create_empty_bb (last_bb);
4021 if (current_loops)
4022 add_bb_to_loop (bb, last_bb->loop_father);
4023 gsi = gsi_start_bb (bb);
4025 if (i < fd->collapse - 1)
4027 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4028 e->probability = REG_BR_PROB_BASE / 8;
4030 t = fd->loops[i + 1].n1;
4031 t = force_gimple_operand_gsi (&gsi, t,
4032 DECL_P (fd->loops[i + 1].v)
4033 && TREE_ADDRESSABLE
4034 (fd->loops[i + 1].v),
4035 NULL_TREE, false,
4036 GSI_CONTINUE_LINKING);
4037 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4038 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4040 else
4041 collapse_bb = bb;
4043 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4045 if (POINTER_TYPE_P (vtype))
4046 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4047 else
4048 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
4049 fd->loops[i].step);
4050 t = force_gimple_operand_gsi (&gsi, t,
4051 DECL_P (fd->loops[i].v)
4052 && TREE_ADDRESSABLE (fd->loops[i].v),
4053 NULL_TREE, false,
4054 GSI_CONTINUE_LINKING);
4055 stmt = gimple_build_assign (fd->loops[i].v, t);
4056 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4058 if (i > 0)
4060 t = fd->loops[i].n2;
4061 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4062 false, GSI_CONTINUE_LINKING);
4063 tree v = fd->loops[i].v;
4064 if (DECL_P (v) && TREE_ADDRESSABLE (v))
4065 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
4066 false, GSI_CONTINUE_LINKING);
4067 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
4068 v, t);
4069 stmt = gimple_build_cond_empty (t);
4070 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4071 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
4072 e->probability = REG_BR_PROB_BASE * 7 / 8;
4074 else
4075 make_edge (bb, l1_bb, EDGE_FALLTHRU);
4076 last_bb = bb;
4080 /* Emit code to get the next parallel iteration in L2_BB. */
4081 gsi = gsi_start_bb (l2_bb);
4083 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4084 build_fold_addr_expr (istart0),
4085 build_fold_addr_expr (iend0));
4086 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4087 false, GSI_CONTINUE_LINKING);
4088 if (TREE_TYPE (t) != boolean_type_node)
4089 t = fold_build2 (NE_EXPR, boolean_type_node,
4090 t, build_int_cst (TREE_TYPE (t), 0));
4091 stmt = gimple_build_cond_empty (t);
4092 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4095 /* Add the loop cleanup function. */
4096 gsi = gsi_last_bb (exit_bb);
4097 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4098 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4099 else
4100 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4101 stmt = gimple_build_call (t, 0);
4102 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4103 gsi_remove (&gsi, true);
4105 /* Connect the new blocks. */
4106 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4107 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4109 if (!broken_loop)
4111 gimple_seq phis;
4113 e = find_edge (cont_bb, l3_bb);
4114 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4116 phis = phi_nodes (l3_bb);
4117 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4119 gimple phi = gsi_stmt (gsi);
4120 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4121 PHI_ARG_DEF_FROM_EDGE (phi, e));
4123 remove_edge (e);
4125 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4126 if (current_loops)
4127 add_bb_to_loop (l2_bb, cont_bb->loop_father);
4128 if (fd->collapse > 1)
4130 e = find_edge (cont_bb, l1_bb);
4131 remove_edge (e);
4132 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4134 else
4136 e = find_edge (cont_bb, l1_bb);
4137 e->flags = EDGE_TRUE_VALUE;
4139 e->probability = REG_BR_PROB_BASE * 7 / 8;
4140 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4141 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4143 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4144 recompute_dominator (CDI_DOMINATORS, l2_bb));
4145 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4146 recompute_dominator (CDI_DOMINATORS, l3_bb));
4147 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4148 recompute_dominator (CDI_DOMINATORS, l0_bb));
4149 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4150 recompute_dominator (CDI_DOMINATORS, l1_bb));
4155 /* A subroutine of expand_omp_for. Generate code for a parallel
4156 loop with static schedule and no specified chunk size. Given
4157 parameters:
4159 for (V = N1; V cond N2; V += STEP) BODY;
4161 where COND is "<" or ">", we generate pseudocode
4163 if (cond is <)
4164 adj = STEP - 1;
4165 else
4166 adj = STEP + 1;
4167 if ((__typeof (V)) -1 > 0 && cond is >)
4168 n = -(adj + N2 - N1) / -STEP;
4169 else
4170 n = (adj + N2 - N1) / STEP;
4171 q = n / nthreads;
4172 tt = n % nthreads;
4173 if (threadid < tt) goto L3; else goto L4;
4175 tt = 0;
4176 q = q + 1;
4178 s0 = q * threadid + tt;
4179 e0 = s0 + q;
4180 V = s0 * STEP + N1;
4181 if (s0 >= e0) goto L2; else goto L0;
4183 e = e0 * STEP + N1;
4185 BODY;
4186 V += STEP;
4187 if (V cond e) goto L1;
4191 static void
4192 expand_omp_for_static_nochunk (struct omp_region *region,
4193 struct omp_for_data *fd)
4195 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
4196 tree type, itype, vmain, vback;
4197 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4198 basic_block body_bb, cont_bb;
4199 basic_block fin_bb;
4200 gimple_stmt_iterator gsi;
4201 gimple stmt;
4202 edge ep;
4204 itype = type = TREE_TYPE (fd->loop.v);
4205 if (POINTER_TYPE_P (type))
4206 itype = signed_type_for (type);
4208 entry_bb = region->entry;
4209 cont_bb = region->cont;
4210 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4211 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4212 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4213 body_bb = single_succ (seq_start_bb);
4214 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4215 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4216 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4217 exit_bb = region->exit;
4219 /* Iteration space partitioning goes in ENTRY_BB. */
4220 gsi = gsi_last_bb (entry_bb);
4221 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4223 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4224 t = fold_convert (itype, t);
4225 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4226 true, GSI_SAME_STMT);
4228 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4229 t = fold_convert (itype, t);
4230 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4231 true, GSI_SAME_STMT);
4233 fd->loop.n1
4234 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4235 true, NULL_TREE, true, GSI_SAME_STMT);
4236 fd->loop.n2
4237 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4238 true, NULL_TREE, true, GSI_SAME_STMT);
4239 fd->loop.step
4240 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4241 true, NULL_TREE, true, GSI_SAME_STMT);
4243 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4244 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4245 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4246 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4247 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4248 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4249 fold_build1 (NEGATE_EXPR, itype, t),
4250 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4251 else
4252 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4253 t = fold_convert (itype, t);
4254 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4256 q = create_tmp_reg (itype, "q");
4257 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4258 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4259 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4261 tt = create_tmp_reg (itype, "tt");
4262 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4263 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4264 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
4266 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4267 stmt = gimple_build_cond_empty (t);
4268 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4270 second_bb = split_block (entry_bb, stmt)->dest;
4271 gsi = gsi_last_bb (second_bb);
4272 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4274 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4275 GSI_SAME_STMT);
4276 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4277 build_int_cst (itype, 1));
4278 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4280 third_bb = split_block (second_bb, stmt)->dest;
4281 gsi = gsi_last_bb (third_bb);
4282 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4284 t = build2 (MULT_EXPR, itype, q, threadid);
4285 t = build2 (PLUS_EXPR, itype, t, tt);
4286 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4288 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4289 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4291 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4292 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4294 /* Remove the GIMPLE_OMP_FOR statement. */
4295 gsi_remove (&gsi, true);
4297 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4298 gsi = gsi_start_bb (seq_start_bb);
4300 t = fold_convert (itype, s0);
4301 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4302 if (POINTER_TYPE_P (type))
4303 t = fold_build_pointer_plus (fd->loop.n1, t);
4304 else
4305 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4306 t = force_gimple_operand_gsi (&gsi, t,
4307 DECL_P (fd->loop.v)
4308 && TREE_ADDRESSABLE (fd->loop.v),
4309 NULL_TREE, false, GSI_CONTINUE_LINKING);
4310 stmt = gimple_build_assign (fd->loop.v, t);
4311 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4313 t = fold_convert (itype, e0);
4314 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4315 if (POINTER_TYPE_P (type))
4316 t = fold_build_pointer_plus (fd->loop.n1, t);
4317 else
4318 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4319 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4320 false, GSI_CONTINUE_LINKING);
4322 /* The code controlling the sequential loop replaces the
4323 GIMPLE_OMP_CONTINUE. */
4324 gsi = gsi_last_bb (cont_bb);
4325 stmt = gsi_stmt (gsi);
4326 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4327 vmain = gimple_omp_continue_control_use (stmt);
4328 vback = gimple_omp_continue_control_def (stmt);
4330 if (POINTER_TYPE_P (type))
4331 t = fold_build_pointer_plus (vmain, fd->loop.step);
4332 else
4333 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4334 t = force_gimple_operand_gsi (&gsi, t,
4335 DECL_P (vback) && TREE_ADDRESSABLE (vback),
4336 NULL_TREE, true, GSI_SAME_STMT);
4337 stmt = gimple_build_assign (vback, t);
4338 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4340 t = build2 (fd->loop.cond_code, boolean_type_node,
4341 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback, e);
4342 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4344 /* Remove the GIMPLE_OMP_CONTINUE statement. */
4345 gsi_remove (&gsi, true);
4347 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4348 gsi = gsi_last_bb (exit_bb);
4349 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4350 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
4351 false, GSI_SAME_STMT);
4352 gsi_remove (&gsi, true);
4354 /* Connect all the blocks. */
4355 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
4356 ep->probability = REG_BR_PROB_BASE / 4 * 3;
4357 ep = find_edge (entry_bb, second_bb);
4358 ep->flags = EDGE_TRUE_VALUE;
4359 ep->probability = REG_BR_PROB_BASE / 4;
4360 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
4361 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
4363 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4364 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4366 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
4367 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
4368 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
4369 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4370 recompute_dominator (CDI_DOMINATORS, body_bb));
4371 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4372 recompute_dominator (CDI_DOMINATORS, fin_bb));
4376 /* A subroutine of expand_omp_for. Generate code for a parallel
4377 loop with static schedule and a specified chunk size. Given
4378 parameters:
4380 for (V = N1; V cond N2; V += STEP) BODY;
4382 where COND is "<" or ">", we generate pseudocode
4384 if (cond is <)
4385 adj = STEP - 1;
4386 else
4387 adj = STEP + 1;
4388 if ((__typeof (V)) -1 > 0 && cond is >)
4389 n = -(adj + N2 - N1) / -STEP;
4390 else
4391 n = (adj + N2 - N1) / STEP;
4392 trip = 0;
4393 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4394 here so that V is defined
4395 if the loop is not entered
4397 s0 = (trip * nthreads + threadid) * CHUNK;
4398 e0 = min(s0 + CHUNK, n);
4399 if (s0 < n) goto L1; else goto L4;
4401 V = s0 * STEP + N1;
4402 e = e0 * STEP + N1;
4404 BODY;
4405 V += STEP;
4406 if (V cond e) goto L2; else goto L3;
4408 trip += 1;
4409 goto L0;
4413 static void
4414 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
4416 tree n, s0, e0, e, t;
4417 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4418 tree type, itype, v_main, v_back, v_extra;
4419 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4420 basic_block trip_update_bb, cont_bb, fin_bb;
4421 gimple_stmt_iterator si;
4422 gimple stmt;
4423 edge se;
4425 itype = type = TREE_TYPE (fd->loop.v);
4426 if (POINTER_TYPE_P (type))
4427 itype = signed_type_for (type);
4429 entry_bb = region->entry;
4430 se = split_block (entry_bb, last_stmt (entry_bb));
4431 entry_bb = se->src;
4432 iter_part_bb = se->dest;
4433 cont_bb = region->cont;
4434 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4435 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4436 == FALLTHRU_EDGE (cont_bb)->dest);
4437 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4438 body_bb = single_succ (seq_start_bb);
4439 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4440 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4441 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4442 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4443 exit_bb = region->exit;
4445 /* Trip and adjustment setup goes in ENTRY_BB. */
4446 si = gsi_last_bb (entry_bb);
4447 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
4449 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4450 t = fold_convert (itype, t);
4451 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4452 true, GSI_SAME_STMT);
4454 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4455 t = fold_convert (itype, t);
4456 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4457 true, GSI_SAME_STMT);
4459 fd->loop.n1
4460 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
4461 true, NULL_TREE, true, GSI_SAME_STMT);
4462 fd->loop.n2
4463 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
4464 true, NULL_TREE, true, GSI_SAME_STMT);
4465 fd->loop.step
4466 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
4467 true, NULL_TREE, true, GSI_SAME_STMT);
4468 fd->chunk_size
4469 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
4470 true, NULL_TREE, true, GSI_SAME_STMT);
4472 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4473 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4474 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4475 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4476 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4477 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4478 fold_build1 (NEGATE_EXPR, itype, t),
4479 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4480 else
4481 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4482 t = fold_convert (itype, t);
4483 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4484 true, GSI_SAME_STMT);
4486 trip_var = create_tmp_reg (itype, ".trip");
4487 if (gimple_in_ssa_p (cfun))
4489 trip_init = make_ssa_name (trip_var, NULL);
4490 trip_main = make_ssa_name (trip_var, NULL);
4491 trip_back = make_ssa_name (trip_var, NULL);
4493 else
4495 trip_init = trip_var;
4496 trip_main = trip_var;
4497 trip_back = trip_var;
4500 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
4501 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4503 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4504 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4505 if (POINTER_TYPE_P (type))
4506 t = fold_build_pointer_plus (fd->loop.n1, t);
4507 else
4508 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4509 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4510 true, GSI_SAME_STMT);
4512 /* Remove the GIMPLE_OMP_FOR. */
4513 gsi_remove (&si, true);
4515 /* Iteration space partitioning goes in ITER_PART_BB. */
4516 si = gsi_last_bb (iter_part_bb);
4518 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4519 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4520 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4521 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4522 false, GSI_CONTINUE_LINKING);
4524 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4525 t = fold_build2 (MIN_EXPR, itype, t, n);
4526 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4527 false, GSI_CONTINUE_LINKING);
4529 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4530 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
4532 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4533 si = gsi_start_bb (seq_start_bb);
4535 t = fold_convert (itype, s0);
4536 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4537 if (POINTER_TYPE_P (type))
4538 t = fold_build_pointer_plus (fd->loop.n1, t);
4539 else
4540 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4541 t = force_gimple_operand_gsi (&si, t,
4542 DECL_P (fd->loop.v)
4543 && TREE_ADDRESSABLE (fd->loop.v),
4544 NULL_TREE, false, GSI_CONTINUE_LINKING);
4545 stmt = gimple_build_assign (fd->loop.v, t);
4546 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4548 t = fold_convert (itype, e0);
4549 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4550 if (POINTER_TYPE_P (type))
4551 t = fold_build_pointer_plus (fd->loop.n1, t);
4552 else
4553 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4554 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4555 false, GSI_CONTINUE_LINKING);
4557 /* The code controlling the sequential loop goes in CONT_BB,
4558 replacing the GIMPLE_OMP_CONTINUE. */
4559 si = gsi_last_bb (cont_bb);
4560 stmt = gsi_stmt (si);
4561 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4562 v_main = gimple_omp_continue_control_use (stmt);
4563 v_back = gimple_omp_continue_control_def (stmt);
4565 if (POINTER_TYPE_P (type))
4566 t = fold_build_pointer_plus (v_main, fd->loop.step);
4567 else
4568 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4569 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
4570 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4571 true, GSI_SAME_STMT);
4572 stmt = gimple_build_assign (v_back, t);
4573 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4575 t = build2 (fd->loop.cond_code, boolean_type_node,
4576 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
4577 ? t : v_back, e);
4578 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
4580 /* Remove GIMPLE_OMP_CONTINUE. */
4581 gsi_remove (&si, true);
4583 /* Trip update code goes into TRIP_UPDATE_BB. */
4584 si = gsi_start_bb (trip_update_bb);
4586 t = build_int_cst (itype, 1);
4587 t = build2 (PLUS_EXPR, itype, trip_main, t);
4588 stmt = gimple_build_assign (trip_back, t);
4589 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4591 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4592 si = gsi_last_bb (exit_bb);
4593 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
4594 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4595 false, GSI_SAME_STMT);
4596 gsi_remove (&si, true);
4598 /* Connect the new blocks. */
4599 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4600 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4602 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4603 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4605 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4607 if (gimple_in_ssa_p (cfun))
4609 gimple_stmt_iterator psi;
4610 gimple phi;
4611 edge re, ene;
4612 edge_var_map_vector *head;
4613 edge_var_map *vm;
4614 size_t i;
4616 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4617 remove arguments of the phi nodes in fin_bb. We need to create
4618 appropriate phi nodes in iter_part_bb instead. */
4619 se = single_pred_edge (fin_bb);
4620 re = single_succ_edge (trip_update_bb);
4621 head = redirect_edge_var_map_vector (re);
4622 ene = single_succ_edge (entry_bb);
4624 psi = gsi_start_phis (fin_bb);
4625 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
4626 gsi_next (&psi), ++i)
4628 gimple nphi;
4629 source_location locus;
4631 phi = gsi_stmt (psi);
4632 t = gimple_phi_result (phi);
4633 gcc_assert (t == redirect_edge_var_map_result (vm));
4634 nphi = create_phi_node (t, iter_part_bb);
4636 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4637 locus = gimple_phi_arg_location_from_edge (phi, se);
4639 /* A special case -- fd->loop.v is not yet computed in
4640 iter_part_bb, we need to use v_extra instead. */
4641 if (t == fd->loop.v)
4642 t = v_extra;
4643 add_phi_arg (nphi, t, ene, locus);
4644 locus = redirect_edge_var_map_location (vm);
4645 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
4647 gcc_assert (!gsi_end_p (psi) && i == head->length ());
4648 redirect_edge_var_map_clear (re);
4649 while (1)
4651 psi = gsi_start_phis (fin_bb);
4652 if (gsi_end_p (psi))
4653 break;
4654 remove_phi_node (&psi, false);
4657 /* Make phi node for trip. */
4658 phi = create_phi_node (trip_main, iter_part_bb);
4659 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
4660 UNKNOWN_LOCATION);
4661 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
4662 UNKNOWN_LOCATION);
4665 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4666 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4667 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4668 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4669 recompute_dominator (CDI_DOMINATORS, fin_bb));
4670 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4671 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4672 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4673 recompute_dominator (CDI_DOMINATORS, body_bb));
4677 /* Expand the OpenMP loop defined by REGION. */
4679 static void
4680 expand_omp_for (struct omp_region *region)
4682 struct omp_for_data fd;
4683 struct omp_for_data_loop *loops;
4685 loops
4686 = (struct omp_for_data_loop *)
4687 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
4688 * sizeof (struct omp_for_data_loop));
4689 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4690 region->sched_kind = fd.sched_kind;
4692 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4693 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4694 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4695 if (region->cont)
4697 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4698 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4699 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4702 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4703 && !fd.have_ordered
4704 && fd.collapse == 1
4705 && region->cont != NULL)
4707 if (fd.chunk_size == NULL)
4708 expand_omp_for_static_nochunk (region, &fd);
4709 else
4710 expand_omp_for_static_chunk (region, &fd);
4712 else
4714 int fn_index, start_ix, next_ix;
4716 if (fd.chunk_size == NULL
4717 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
4718 fd.chunk_size = integer_zero_node;
4719 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4720 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4721 ? 3 : fd.sched_kind;
4722 fn_index += fd.have_ordered * 4;
4723 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
4724 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
4725 if (fd.iter_type == long_long_unsigned_type_node)
4727 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4728 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
4729 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4730 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
4732 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
4733 (enum built_in_function) next_ix);
4736 if (gimple_in_ssa_p (cfun))
4737 update_ssa (TODO_update_ssa_only_virtuals);
4741 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4743 v = GOMP_sections_start (n);
4745 switch (v)
4747 case 0:
4748 goto L2;
4749 case 1:
4750 section 1;
4751 goto L1;
4752 case 2:
4754 case n:
4756 default:
4757 abort ();
4760 v = GOMP_sections_next ();
4761 goto L0;
4763 reduction;
4765 If this is a combined parallel sections, replace the call to
4766 GOMP_sections_start with call to GOMP_sections_next. */
4768 static void
4769 expand_omp_sections (struct omp_region *region)
4771 tree t, u, vin = NULL, vmain, vnext, l2;
4772 vec<tree> label_vec;
4773 unsigned len;
4774 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
4775 gimple_stmt_iterator si, switch_si;
4776 gimple sections_stmt, stmt, cont;
4777 edge_iterator ei;
4778 edge e;
4779 struct omp_region *inner;
4780 unsigned i, casei;
4781 bool exit_reachable = region->cont != NULL;
4783 gcc_assert (region->exit != NULL);
4784 entry_bb = region->entry;
4785 l0_bb = single_succ (entry_bb);
4786 l1_bb = region->cont;
4787 l2_bb = region->exit;
4788 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
4789 l2 = gimple_block_label (l2_bb);
4790 else
4792 /* This can happen if there are reductions. */
4793 len = EDGE_COUNT (l0_bb->succs);
4794 gcc_assert (len > 0);
4795 e = EDGE_SUCC (l0_bb, len - 1);
4796 si = gsi_last_bb (e->dest);
4797 l2 = NULL_TREE;
4798 if (gsi_end_p (si)
4799 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4800 l2 = gimple_block_label (e->dest);
4801 else
4802 FOR_EACH_EDGE (e, ei, l0_bb->succs)
4804 si = gsi_last_bb (e->dest);
4805 if (gsi_end_p (si)
4806 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4808 l2 = gimple_block_label (e->dest);
4809 break;
4813 if (exit_reachable)
4814 default_bb = create_empty_bb (l1_bb->prev_bb);
4815 else
4816 default_bb = create_empty_bb (l0_bb);
4818 /* We will build a switch() with enough cases for all the
4819 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
4820 and a default case to abort if something goes wrong. */
4821 len = EDGE_COUNT (l0_bb->succs);
4823 /* Use vec::quick_push on label_vec throughout, since we know the size
4824 in advance. */
4825 label_vec.create (len);
4827 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
4828 GIMPLE_OMP_SECTIONS statement. */
4829 si = gsi_last_bb (entry_bb);
4830 sections_stmt = gsi_stmt (si);
4831 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
4832 vin = gimple_omp_sections_control (sections_stmt);
4833 if (!is_combined_parallel (region))
4835 /* If we are not inside a combined parallel+sections region,
4836 call GOMP_sections_start. */
4837 t = build_int_cst (unsigned_type_node,
4838 exit_reachable ? len - 1 : len);
4839 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
4840 stmt = gimple_build_call (u, 1, t);
4842 else
4844 /* Otherwise, call GOMP_sections_next. */
4845 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4846 stmt = gimple_build_call (u, 0);
4848 gimple_call_set_lhs (stmt, vin);
4849 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4850 gsi_remove (&si, true);
4852 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
4853 L0_BB. */
4854 switch_si = gsi_last_bb (l0_bb);
4855 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
4856 if (exit_reachable)
4858 cont = last_stmt (l1_bb);
4859 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
4860 vmain = gimple_omp_continue_control_use (cont);
4861 vnext = gimple_omp_continue_control_def (cont);
4863 else
4865 vmain = vin;
4866 vnext = NULL_TREE;
4869 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
4870 label_vec.quick_push (t);
4871 i = 1;
4873 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
4874 for (inner = region->inner, casei = 1;
4875 inner;
4876 inner = inner->next, i++, casei++)
4878 basic_block s_entry_bb, s_exit_bb;
4880 /* Skip optional reduction region. */
4881 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
4883 --i;
4884 --casei;
4885 continue;
4888 s_entry_bb = inner->entry;
4889 s_exit_bb = inner->exit;
4891 t = gimple_block_label (s_entry_bb);
4892 u = build_int_cst (unsigned_type_node, casei);
4893 u = build_case_label (u, NULL, t);
4894 label_vec.quick_push (u);
4896 si = gsi_last_bb (s_entry_bb);
4897 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
4898 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
4899 gsi_remove (&si, true);
4900 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
4902 if (s_exit_bb == NULL)
4903 continue;
4905 si = gsi_last_bb (s_exit_bb);
4906 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4907 gsi_remove (&si, true);
4909 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
4912 /* Error handling code goes in DEFAULT_BB. */
4913 t = gimple_block_label (default_bb);
4914 u = build_case_label (NULL, NULL, t);
4915 make_edge (l0_bb, default_bb, 0);
4916 if (current_loops)
4917 add_bb_to_loop (default_bb, l0_bb->loop_father);
4919 stmt = gimple_build_switch (vmain, u, label_vec);
4920 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
4921 gsi_remove (&switch_si, true);
4922 label_vec.release ();
4924 si = gsi_start_bb (default_bb);
4925 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
4926 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4928 if (exit_reachable)
4930 tree bfn_decl;
4932 /* Code to get the next section goes in L1_BB. */
4933 si = gsi_last_bb (l1_bb);
4934 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
4936 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4937 stmt = gimple_build_call (bfn_decl, 0);
4938 gimple_call_set_lhs (stmt, vnext);
4939 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4940 gsi_remove (&si, true);
4942 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
4945 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
4946 si = gsi_last_bb (l2_bb);
4947 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
4948 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
4949 else
4950 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
4951 stmt = gimple_build_call (t, 0);
4952 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4953 gsi_remove (&si, true);
4955 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
4959 /* Expand code for an OpenMP single directive. We've already expanded
4960 much of the code, here we simply place the GOMP_barrier call. */
4962 static void
4963 expand_omp_single (struct omp_region *region)
4965 basic_block entry_bb, exit_bb;
4966 gimple_stmt_iterator si;
4967 bool need_barrier = false;
4969 entry_bb = region->entry;
4970 exit_bb = region->exit;
4972 si = gsi_last_bb (entry_bb);
4973 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
4974 be removed. We need to ensure that the thread that entered the single
4975 does not exit before the data is copied out by the other threads. */
4976 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
4977 OMP_CLAUSE_COPYPRIVATE))
4978 need_barrier = true;
4979 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
4980 gsi_remove (&si, true);
4981 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4983 si = gsi_last_bb (exit_bb);
4984 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
4985 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4986 false, GSI_SAME_STMT);
4987 gsi_remove (&si, true);
4988 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4992 /* Generic expansion for OpenMP synchronization directives: master,
4993 ordered and critical. All we need to do here is remove the entry
4994 and exit markers for REGION. */
4996 static void
4997 expand_omp_synch (struct omp_region *region)
4999 basic_block entry_bb, exit_bb;
5000 gimple_stmt_iterator si;
5002 entry_bb = region->entry;
5003 exit_bb = region->exit;
5005 si = gsi_last_bb (entry_bb);
5006 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
5007 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
5008 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
5009 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
5010 gsi_remove (&si, true);
5011 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5013 if (exit_bb)
5015 si = gsi_last_bb (exit_bb);
5016 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
5017 gsi_remove (&si, true);
5018 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
5022 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5023 operation as a normal volatile load. */
5025 static bool
5026 expand_omp_atomic_load (basic_block load_bb, tree addr,
5027 tree loaded_val, int index)
5029 enum built_in_function tmpbase;
5030 gimple_stmt_iterator gsi;
5031 basic_block store_bb;
5032 location_t loc;
5033 gimple stmt;
5034 tree decl, call, type, itype;
5036 gsi = gsi_last_bb (load_bb);
5037 stmt = gsi_stmt (gsi);
5038 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5039 loc = gimple_location (stmt);
5041 /* ??? If the target does not implement atomic_load_optab[mode], and mode
5042 is smaller than word size, then expand_atomic_load assumes that the load
5043 is atomic. We could avoid the builtin entirely in this case. */
5045 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
5046 decl = builtin_decl_explicit (tmpbase);
5047 if (decl == NULL_TREE)
5048 return false;
5050 type = TREE_TYPE (loaded_val);
5051 itype = TREE_TYPE (TREE_TYPE (decl));
5053 call = build_call_expr_loc (loc, decl, 2, addr,
5054 build_int_cst (NULL, MEMMODEL_RELAXED));
5055 if (!useless_type_conversion_p (type, itype))
5056 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5057 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5059 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5060 gsi_remove (&gsi, true);
5062 store_bb = single_succ (load_bb);
5063 gsi = gsi_last_bb (store_bb);
5064 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5065 gsi_remove (&gsi, true);
5067 if (gimple_in_ssa_p (cfun))
5068 update_ssa (TODO_update_ssa_no_phi);
5070 return true;
5073 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5074 operation as a normal volatile store. */
5076 static bool
5077 expand_omp_atomic_store (basic_block load_bb, tree addr,
5078 tree loaded_val, tree stored_val, int index)
5080 enum built_in_function tmpbase;
5081 gimple_stmt_iterator gsi;
5082 basic_block store_bb = single_succ (load_bb);
5083 location_t loc;
5084 gimple stmt;
5085 tree decl, call, type, itype;
5086 enum machine_mode imode;
5087 bool exchange;
5089 gsi = gsi_last_bb (load_bb);
5090 stmt = gsi_stmt (gsi);
5091 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5093 /* If the load value is needed, then this isn't a store but an exchange. */
5094 exchange = gimple_omp_atomic_need_value_p (stmt);
5096 gsi = gsi_last_bb (store_bb);
5097 stmt = gsi_stmt (gsi);
5098 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
5099 loc = gimple_location (stmt);
5101 /* ??? If the target does not implement atomic_store_optab[mode], and mode
5102 is smaller than word size, then expand_atomic_store assumes that the store
5103 is atomic. We could avoid the builtin entirely in this case. */
5105 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
5106 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
5107 decl = builtin_decl_explicit (tmpbase);
5108 if (decl == NULL_TREE)
5109 return false;
5111 type = TREE_TYPE (stored_val);
5113 /* Dig out the type of the function's second argument. */
5114 itype = TREE_TYPE (decl);
5115 itype = TYPE_ARG_TYPES (itype);
5116 itype = TREE_CHAIN (itype);
5117 itype = TREE_VALUE (itype);
5118 imode = TYPE_MODE (itype);
5120 if (exchange && !can_atomic_exchange_p (imode, true))
5121 return false;
5123 if (!useless_type_conversion_p (itype, type))
5124 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
5125 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
5126 build_int_cst (NULL, MEMMODEL_RELAXED));
5127 if (exchange)
5129 if (!useless_type_conversion_p (type, itype))
5130 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5131 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5134 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5135 gsi_remove (&gsi, true);
5137 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
5138 gsi = gsi_last_bb (load_bb);
5139 gsi_remove (&gsi, true);
5141 if (gimple_in_ssa_p (cfun))
5142 update_ssa (TODO_update_ssa_no_phi);
5144 return true;
5147 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5148 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
5149 size of the data type, and thus usable to find the index of the builtin
5150 decl. Returns false if the expression is not of the proper form. */
5152 static bool
5153 expand_omp_atomic_fetch_op (basic_block load_bb,
5154 tree addr, tree loaded_val,
5155 tree stored_val, int index)
5157 enum built_in_function oldbase, newbase, tmpbase;
5158 tree decl, itype, call;
5159 tree lhs, rhs;
5160 basic_block store_bb = single_succ (load_bb);
5161 gimple_stmt_iterator gsi;
5162 gimple stmt;
5163 location_t loc;
5164 enum tree_code code;
5165 bool need_old, need_new;
5166 enum machine_mode imode;
5168 /* We expect to find the following sequences:
5170 load_bb:
5171 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
5173 store_bb:
5174 val = tmp OP something; (or: something OP tmp)
5175 GIMPLE_OMP_STORE (val)
5177 ???FIXME: Allow a more flexible sequence.
5178 Perhaps use data flow to pick the statements.
5182 gsi = gsi_after_labels (store_bb);
5183 stmt = gsi_stmt (gsi);
5184 loc = gimple_location (stmt);
5185 if (!is_gimple_assign (stmt))
5186 return false;
5187 gsi_next (&gsi);
5188 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
5189 return false;
5190 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
5191 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
5192 gcc_checking_assert (!need_old || !need_new);
5194 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
5195 return false;
5197 /* Check for one of the supported fetch-op operations. */
5198 code = gimple_assign_rhs_code (stmt);
5199 switch (code)
5201 case PLUS_EXPR:
5202 case POINTER_PLUS_EXPR:
5203 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
5204 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
5205 break;
5206 case MINUS_EXPR:
5207 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
5208 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
5209 break;
5210 case BIT_AND_EXPR:
5211 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
5212 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
5213 break;
5214 case BIT_IOR_EXPR:
5215 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
5216 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
5217 break;
5218 case BIT_XOR_EXPR:
5219 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
5220 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
5221 break;
5222 default:
5223 return false;
5226 /* Make sure the expression is of the proper form. */
5227 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
5228 rhs = gimple_assign_rhs2 (stmt);
5229 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
5230 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
5231 rhs = gimple_assign_rhs1 (stmt);
5232 else
5233 return false;
5235 tmpbase = ((enum built_in_function)
5236 ((need_new ? newbase : oldbase) + index + 1));
5237 decl = builtin_decl_explicit (tmpbase);
5238 if (decl == NULL_TREE)
5239 return false;
5240 itype = TREE_TYPE (TREE_TYPE (decl));
5241 imode = TYPE_MODE (itype);
5243 /* We could test all of the various optabs involved, but the fact of the
5244 matter is that (with the exception of i486 vs i586 and xadd) all targets
5245 that support any atomic operaton optab also implements compare-and-swap.
5246 Let optabs.c take care of expanding any compare-and-swap loop. */
5247 if (!can_compare_and_swap_p (imode, true))
5248 return false;
5250 gsi = gsi_last_bb (load_bb);
5251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
5253 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
5254 It only requires that the operation happen atomically. Thus we can
5255 use the RELAXED memory model. */
5256 call = build_call_expr_loc (loc, decl, 3, addr,
5257 fold_convert_loc (loc, itype, rhs),
5258 build_int_cst (NULL, MEMMODEL_RELAXED));
5260 if (need_old || need_new)
5262 lhs = need_old ? loaded_val : stored_val;
5263 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
5264 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
5266 else
5267 call = fold_convert_loc (loc, void_type_node, call);
5268 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5269 gsi_remove (&gsi, true);
5271 gsi = gsi_last_bb (store_bb);
5272 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5273 gsi_remove (&gsi, true);
5274 gsi = gsi_last_bb (store_bb);
5275 gsi_remove (&gsi, true);
5277 if (gimple_in_ssa_p (cfun))
5278 update_ssa (TODO_update_ssa_no_phi);
5280 return true;
5283 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5285 oldval = *addr;
5286 repeat:
5287 newval = rhs; // with oldval replacing *addr in rhs
5288 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
5289 if (oldval != newval)
5290 goto repeat;
5292 INDEX is log2 of the size of the data type, and thus usable to find the
5293 index of the builtin decl. */
5295 static bool
5296 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
5297 tree addr, tree loaded_val, tree stored_val,
5298 int index)
5300 tree loadedi, storedi, initial, new_storedi, old_vali;
5301 tree type, itype, cmpxchg, iaddr;
5302 gimple_stmt_iterator si;
5303 basic_block loop_header = single_succ (load_bb);
5304 gimple phi, stmt;
5305 edge e;
5306 enum built_in_function fncode;
5308 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
5309 order to use the RELAXED memory model effectively. */
5310 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
5311 + index + 1);
5312 cmpxchg = builtin_decl_explicit (fncode);
5313 if (cmpxchg == NULL_TREE)
5314 return false;
5315 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5316 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
5318 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
5319 return false;
5321 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
5322 si = gsi_last_bb (load_bb);
5323 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5325 /* For floating-point values, we'll need to view-convert them to integers
5326 so that we can perform the atomic compare and swap. Simplify the
5327 following code by always setting up the "i"ntegral variables. */
5328 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
5330 tree iaddr_val;
5332 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
5333 true), NULL);
5334 iaddr_val
5335 = force_gimple_operand_gsi (&si,
5336 fold_convert (TREE_TYPE (iaddr), addr),
5337 false, NULL_TREE, true, GSI_SAME_STMT);
5338 stmt = gimple_build_assign (iaddr, iaddr_val);
5339 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5340 loadedi = create_tmp_var (itype, NULL);
5341 if (gimple_in_ssa_p (cfun))
5342 loadedi = make_ssa_name (loadedi, NULL);
5344 else
5346 iaddr = addr;
5347 loadedi = loaded_val;
5350 initial
5351 = force_gimple_operand_gsi (&si,
5352 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
5353 iaddr,
5354 build_int_cst (TREE_TYPE (iaddr), 0)),
5355 true, NULL_TREE, true, GSI_SAME_STMT);
5357 /* Move the value to the LOADEDI temporary. */
5358 if (gimple_in_ssa_p (cfun))
5360 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
5361 phi = create_phi_node (loadedi, loop_header);
5362 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
5363 initial);
5365 else
5366 gsi_insert_before (&si,
5367 gimple_build_assign (loadedi, initial),
5368 GSI_SAME_STMT);
5369 if (loadedi != loaded_val)
5371 gimple_stmt_iterator gsi2;
5372 tree x;
5374 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
5375 gsi2 = gsi_start_bb (loop_header);
5376 if (gimple_in_ssa_p (cfun))
5378 gimple stmt;
5379 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5380 true, GSI_SAME_STMT);
5381 stmt = gimple_build_assign (loaded_val, x);
5382 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
5384 else
5386 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
5387 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5388 true, GSI_SAME_STMT);
5391 gsi_remove (&si, true);
5393 si = gsi_last_bb (store_bb);
5394 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5396 if (iaddr == addr)
5397 storedi = stored_val;
5398 else
5399 storedi =
5400 force_gimple_operand_gsi (&si,
5401 build1 (VIEW_CONVERT_EXPR, itype,
5402 stored_val), true, NULL_TREE, true,
5403 GSI_SAME_STMT);
5405 /* Build the compare&swap statement. */
5406 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
5407 new_storedi = force_gimple_operand_gsi (&si,
5408 fold_convert (TREE_TYPE (loadedi),
5409 new_storedi),
5410 true, NULL_TREE,
5411 true, GSI_SAME_STMT);
5413 if (gimple_in_ssa_p (cfun))
5414 old_vali = loadedi;
5415 else
5417 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
5418 stmt = gimple_build_assign (old_vali, loadedi);
5419 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5421 stmt = gimple_build_assign (loadedi, new_storedi);
5422 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5425 /* Note that we always perform the comparison as an integer, even for
5426 floating point. This allows the atomic operation to properly
5427 succeed even with NaNs and -0.0. */
5428 stmt = gimple_build_cond_empty
5429 (build2 (NE_EXPR, boolean_type_node,
5430 new_storedi, old_vali));
5431 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5433 /* Update cfg. */
5434 e = single_succ_edge (store_bb);
5435 e->flags &= ~EDGE_FALLTHRU;
5436 e->flags |= EDGE_FALSE_VALUE;
5438 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
5440 /* Copy the new value to loadedi (we already did that before the condition
5441 if we are not in SSA). */
5442 if (gimple_in_ssa_p (cfun))
5444 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
5445 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
5448 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
5449 gsi_remove (&si, true);
5451 if (gimple_in_ssa_p (cfun))
5452 update_ssa (TODO_update_ssa_no_phi);
5454 /* ??? The above could use loop construction primitives. */
5455 if (current_loops)
5456 loops_state_set (LOOPS_NEED_FIXUP);
5458 return true;
5461 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5463 GOMP_atomic_start ();
5464 *addr = rhs;
5465 GOMP_atomic_end ();
5467 The result is not globally atomic, but works so long as all parallel
5468 references are within #pragma omp atomic directives. According to
5469 responses received from omp@openmp.org, appears to be within spec.
5470 Which makes sense, since that's how several other compilers handle
5471 this situation as well.
5472 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
5473 expanding. STORED_VAL is the operand of the matching
5474 GIMPLE_OMP_ATOMIC_STORE.
5476 We replace
5477 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
5478 loaded_val = *addr;
5480 and replace
5481 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
5482 *addr = stored_val;
5485 static bool
5486 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
5487 tree addr, tree loaded_val, tree stored_val)
5489 gimple_stmt_iterator si;
5490 gimple stmt;
5491 tree t;
5493 si = gsi_last_bb (load_bb);
5494 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5496 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
5497 t = build_call_expr (t, 0);
5498 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5500 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
5501 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5502 gsi_remove (&si, true);
5504 si = gsi_last_bb (store_bb);
5505 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5507 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
5508 stored_val);
5509 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5511 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
5512 t = build_call_expr (t, 0);
5513 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5514 gsi_remove (&si, true);
5516 if (gimple_in_ssa_p (cfun))
5517 update_ssa (TODO_update_ssa_no_phi);
5518 return true;
5521 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
5522 using expand_omp_atomic_fetch_op. If it failed, we try to
5523 call expand_omp_atomic_pipeline, and if it fails too, the
5524 ultimate fallback is wrapping the operation in a mutex
5525 (expand_omp_atomic_mutex). REGION is the atomic region built
5526 by build_omp_regions_1(). */
5528 static void
5529 expand_omp_atomic (struct omp_region *region)
5531 basic_block load_bb = region->entry, store_bb = region->exit;
5532 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
5533 tree loaded_val = gimple_omp_atomic_load_lhs (load);
5534 tree addr = gimple_omp_atomic_load_rhs (load);
5535 tree stored_val = gimple_omp_atomic_store_val (store);
5536 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5537 HOST_WIDE_INT index;
5539 /* Make sure the type is one of the supported sizes. */
5540 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
5541 index = exact_log2 (index);
5542 if (index >= 0 && index <= 4)
5544 unsigned int align = TYPE_ALIGN_UNIT (type);
5546 /* __sync builtins require strict data alignment. */
5547 if (exact_log2 (align) >= index)
5549 /* Atomic load. */
5550 if (loaded_val == stored_val
5551 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5552 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5553 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5554 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
5555 return;
5557 /* Atomic store. */
5558 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5559 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5560 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5561 && store_bb == single_succ (load_bb)
5562 && first_stmt (store_bb) == store
5563 && expand_omp_atomic_store (load_bb, addr, loaded_val,
5564 stored_val, index))
5565 return;
5567 /* When possible, use specialized atomic update functions. */
5568 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5569 && store_bb == single_succ (load_bb)
5570 && expand_omp_atomic_fetch_op (load_bb, addr,
5571 loaded_val, stored_val, index))
5572 return;
5574 /* If we don't have specialized __sync builtins, try and implement
5575 as a compare and swap loop. */
5576 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5577 loaded_val, stored_val, index))
5578 return;
5582 /* The ultimate fallback is wrapping the operation in a mutex. */
5583 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5587 /* Expand the parallel region tree rooted at REGION. Expansion
5588 proceeds in depth-first order. Innermost regions are expanded
5589 first. This way, parallel regions that require a new function to
5590 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
5591 internal dependencies in their body. */
5593 static void
5594 expand_omp (struct omp_region *region)
5596 while (region)
5598 location_t saved_location;
5600 /* First, determine whether this is a combined parallel+workshare
5601 region. */
5602 if (region->type == GIMPLE_OMP_PARALLEL)
5603 determine_parallel_type (region);
5605 if (region->inner)
5606 expand_omp (region->inner);
5608 saved_location = input_location;
5609 if (gimple_has_location (last_stmt (region->entry)))
5610 input_location = gimple_location (last_stmt (region->entry));
5612 switch (region->type)
5614 case GIMPLE_OMP_PARALLEL:
5615 case GIMPLE_OMP_TASK:
5616 expand_omp_taskreg (region);
5617 break;
5619 case GIMPLE_OMP_FOR:
5620 expand_omp_for (region);
5621 break;
5623 case GIMPLE_OMP_SECTIONS:
5624 expand_omp_sections (region);
5625 break;
5627 case GIMPLE_OMP_SECTION:
5628 /* Individual omp sections are handled together with their
5629 parent GIMPLE_OMP_SECTIONS region. */
5630 break;
5632 case GIMPLE_OMP_SINGLE:
5633 expand_omp_single (region);
5634 break;
5636 case GIMPLE_OMP_MASTER:
5637 case GIMPLE_OMP_ORDERED:
5638 case GIMPLE_OMP_CRITICAL:
5639 expand_omp_synch (region);
5640 break;
5642 case GIMPLE_OMP_ATOMIC_LOAD:
5643 expand_omp_atomic (region);
5644 break;
5646 default:
5647 gcc_unreachable ();
5650 input_location = saved_location;
5651 region = region->next;
5656 /* Helper for build_omp_regions. Scan the dominator tree starting at
5657 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5658 true, the function ends once a single tree is built (otherwise, whole
5659 forest of OMP constructs may be built). */
5661 static void
5662 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5663 bool single_tree)
5665 gimple_stmt_iterator gsi;
5666 gimple stmt;
5667 basic_block son;
5669 gsi = gsi_last_bb (bb);
5670 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
5672 struct omp_region *region;
5673 enum gimple_code code;
5675 stmt = gsi_stmt (gsi);
5676 code = gimple_code (stmt);
5677 if (code == GIMPLE_OMP_RETURN)
5679 /* STMT is the return point out of region PARENT. Mark it
5680 as the exit point and make PARENT the immediately
5681 enclosing region. */
5682 gcc_assert (parent);
5683 region = parent;
5684 region->exit = bb;
5685 parent = parent->outer;
5687 else if (code == GIMPLE_OMP_ATOMIC_STORE)
5689 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
5690 GIMPLE_OMP_RETURN, but matches with
5691 GIMPLE_OMP_ATOMIC_LOAD. */
5692 gcc_assert (parent);
5693 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
5694 region = parent;
5695 region->exit = bb;
5696 parent = parent->outer;
5699 else if (code == GIMPLE_OMP_CONTINUE)
5701 gcc_assert (parent);
5702 parent->cont = bb;
5704 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
5706 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
5707 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
5710 else
5712 /* Otherwise, this directive becomes the parent for a new
5713 region. */
5714 region = new_omp_region (bb, code, parent);
5715 parent = region;
5719 if (single_tree && !parent)
5720 return;
5722 for (son = first_dom_son (CDI_DOMINATORS, bb);
5723 son;
5724 son = next_dom_son (CDI_DOMINATORS, son))
5725 build_omp_regions_1 (son, parent, single_tree);
5728 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5729 root_omp_region. */
5731 static void
5732 build_omp_regions_root (basic_block root)
5734 gcc_assert (root_omp_region == NULL);
5735 build_omp_regions_1 (root, NULL, true);
5736 gcc_assert (root_omp_region != NULL);
5739 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5741 void
5742 omp_expand_local (basic_block head)
5744 build_omp_regions_root (head);
5745 if (dump_file && (dump_flags & TDF_DETAILS))
5747 fprintf (dump_file, "\nOMP region tree\n\n");
5748 dump_omp_region (dump_file, root_omp_region, 0);
5749 fprintf (dump_file, "\n");
5752 remove_exit_barriers (root_omp_region);
5753 expand_omp (root_omp_region);
5755 free_omp_regions ();
5758 /* Scan the CFG and build a tree of OMP regions. Return the root of
5759 the OMP region tree. */
5761 static void
5762 build_omp_regions (void)
5764 gcc_assert (root_omp_region == NULL);
5765 calculate_dominance_info (CDI_DOMINATORS);
5766 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5769 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5771 static unsigned int
5772 execute_expand_omp (void)
5774 build_omp_regions ();
5776 if (!root_omp_region)
5777 return 0;
5779 if (dump_file)
5781 fprintf (dump_file, "\nOMP region tree\n\n");
5782 dump_omp_region (dump_file, root_omp_region, 0);
5783 fprintf (dump_file, "\n");
5786 remove_exit_barriers (root_omp_region);
5788 expand_omp (root_omp_region);
5790 cleanup_tree_cfg ();
5792 free_omp_regions ();
5794 return 0;
5797 /* OMP expansion -- the default pass, run before creation of SSA form. */
5799 static bool
5800 gate_expand_omp (void)
5802 return (flag_openmp != 0 && !seen_error ());
5805 struct gimple_opt_pass pass_expand_omp =
5808 GIMPLE_PASS,
5809 "ompexp", /* name */
5810 OPTGROUP_NONE, /* optinfo_flags */
5811 gate_expand_omp, /* gate */
5812 execute_expand_omp, /* execute */
5813 NULL, /* sub */
5814 NULL, /* next */
5815 0, /* static_pass_number */
5816 TV_NONE, /* tv_id */
5817 PROP_gimple_any, /* properties_required */
5818 0, /* properties_provided */
5819 0, /* properties_destroyed */
5820 0, /* todo_flags_start */
5821 0 /* todo_flags_finish */
5825 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
5827 /* Lower the OpenMP sections directive in the current statement in GSI_P.
5828 CTX is the enclosing OMP context for the current statement. */
5830 static void
5831 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5833 tree block, control;
5834 gimple_stmt_iterator tgsi;
5835 gimple stmt, new_stmt, bind, t;
5836 gimple_seq ilist, dlist, olist, new_body;
5837 struct gimplify_ctx gctx;
5839 stmt = gsi_stmt (*gsi_p);
5841 push_gimplify_context (&gctx);
5843 dlist = NULL;
5844 ilist = NULL;
5845 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
5846 &ilist, &dlist, ctx);
5848 new_body = gimple_omp_body (stmt);
5849 gimple_omp_set_body (stmt, NULL);
5850 tgsi = gsi_start (new_body);
5851 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
5853 omp_context *sctx;
5854 gimple sec_start;
5856 sec_start = gsi_stmt (tgsi);
5857 sctx = maybe_lookup_ctx (sec_start);
5858 gcc_assert (sctx);
5860 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
5861 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
5862 GSI_CONTINUE_LINKING);
5863 gimple_omp_set_body (sec_start, NULL);
5865 if (gsi_one_before_end_p (tgsi))
5867 gimple_seq l = NULL;
5868 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
5869 &l, ctx);
5870 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
5871 gimple_omp_section_set_last (sec_start);
5874 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
5875 GSI_CONTINUE_LINKING);
5878 block = make_node (BLOCK);
5879 bind = gimple_build_bind (NULL, new_body, block);
5881 olist = NULL;
5882 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
5884 block = make_node (BLOCK);
5885 new_stmt = gimple_build_bind (NULL, NULL, block);
5886 gsi_replace (gsi_p, new_stmt, true);
5888 pop_gimplify_context (new_stmt);
5889 gimple_bind_append_vars (new_stmt, ctx->block_vars);
5890 BLOCK_VARS (block) = gimple_bind_vars (bind);
5891 if (BLOCK_VARS (block))
5892 TREE_USED (block) = 1;
5894 new_body = NULL;
5895 gimple_seq_add_seq (&new_body, ilist);
5896 gimple_seq_add_stmt (&new_body, stmt);
5897 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
5898 gimple_seq_add_stmt (&new_body, bind);
5900 control = create_tmp_var (unsigned_type_node, ".section");
5901 t = gimple_build_omp_continue (control, control);
5902 gimple_omp_sections_set_control (stmt, control);
5903 gimple_seq_add_stmt (&new_body, t);
5905 gimple_seq_add_seq (&new_body, olist);
5906 gimple_seq_add_seq (&new_body, dlist);
5908 new_body = maybe_catch_exception (new_body);
5910 t = gimple_build_omp_return
5911 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
5912 OMP_CLAUSE_NOWAIT));
5913 gimple_seq_add_stmt (&new_body, t);
5915 gimple_bind_set_body (new_stmt, new_body);
5919 /* A subroutine of lower_omp_single. Expand the simple form of
5920 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
5922 if (GOMP_single_start ())
5923 BODY;
5924 [ GOMP_barrier (); ] -> unless 'nowait' is present.
5926 FIXME. It may be better to delay expanding the logic of this until
5927 pass_expand_omp. The expanded logic may make the job more difficult
5928 to a synchronization analysis pass. */
5930 static void
5931 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
5933 location_t loc = gimple_location (single_stmt);
5934 tree tlabel = create_artificial_label (loc);
5935 tree flabel = create_artificial_label (loc);
5936 gimple call, cond;
5937 tree lhs, decl;
5939 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
5940 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
5941 call = gimple_build_call (decl, 0);
5942 gimple_call_set_lhs (call, lhs);
5943 gimple_seq_add_stmt (pre_p, call);
5945 cond = gimple_build_cond (EQ_EXPR, lhs,
5946 fold_convert_loc (loc, TREE_TYPE (lhs),
5947 boolean_true_node),
5948 tlabel, flabel);
5949 gimple_seq_add_stmt (pre_p, cond);
5950 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
5951 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5952 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
5956 /* A subroutine of lower_omp_single. Expand the simple form of
5957 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
5959 #pragma omp single copyprivate (a, b, c)
5961 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
5964 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
5966 BODY;
5967 copyout.a = a;
5968 copyout.b = b;
5969 copyout.c = c;
5970 GOMP_single_copy_end (&copyout);
5972 else
5974 a = copyout_p->a;
5975 b = copyout_p->b;
5976 c = copyout_p->c;
5978 GOMP_barrier ();
5981 FIXME. It may be better to delay expanding the logic of this until
5982 pass_expand_omp. The expanded logic may make the job more difficult
5983 to a synchronization analysis pass. */
5985 static void
5986 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
5988 tree ptr_type, t, l0, l1, l2, bfn_decl;
5989 gimple_seq copyin_seq;
5990 location_t loc = gimple_location (single_stmt);
5992 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
5994 ptr_type = build_pointer_type (ctx->record_type);
5995 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
5997 l0 = create_artificial_label (loc);
5998 l1 = create_artificial_label (loc);
5999 l2 = create_artificial_label (loc);
6001 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
6002 t = build_call_expr_loc (loc, bfn_decl, 0);
6003 t = fold_convert_loc (loc, ptr_type, t);
6004 gimplify_assign (ctx->receiver_decl, t, pre_p);
6006 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
6007 build_int_cst (ptr_type, 0));
6008 t = build3 (COND_EXPR, void_type_node, t,
6009 build_and_jump (&l0), build_and_jump (&l1));
6010 gimplify_and_add (t, pre_p);
6012 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
6014 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
6016 copyin_seq = NULL;
6017 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
6018 &copyin_seq, ctx);
6020 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6021 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
6022 t = build_call_expr_loc (loc, bfn_decl, 1, t);
6023 gimplify_and_add (t, pre_p);
6025 t = build_and_jump (&l2);
6026 gimplify_and_add (t, pre_p);
6028 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
6030 gimple_seq_add_seq (pre_p, copyin_seq);
6032 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
6036 /* Expand code for an OpenMP single directive. */
6038 static void
6039 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6041 tree block;
6042 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
6043 gimple_seq bind_body, dlist;
6044 struct gimplify_ctx gctx;
6046 push_gimplify_context (&gctx);
6048 block = make_node (BLOCK);
6049 bind = gimple_build_bind (NULL, NULL, block);
6050 gsi_replace (gsi_p, bind, true);
6051 bind_body = NULL;
6052 dlist = NULL;
6053 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
6054 &bind_body, &dlist, ctx);
6055 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
6057 gimple_seq_add_stmt (&bind_body, single_stmt);
6059 if (ctx->record_type)
6060 lower_omp_single_copy (single_stmt, &bind_body, ctx);
6061 else
6062 lower_omp_single_simple (single_stmt, &bind_body);
6064 gimple_omp_set_body (single_stmt, NULL);
6066 gimple_seq_add_seq (&bind_body, dlist);
6068 bind_body = maybe_catch_exception (bind_body);
6070 t = gimple_build_omp_return
6071 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
6072 OMP_CLAUSE_NOWAIT));
6073 gimple_seq_add_stmt (&bind_body, t);
6074 gimple_bind_set_body (bind, bind_body);
6076 pop_gimplify_context (bind);
6078 gimple_bind_append_vars (bind, ctx->block_vars);
6079 BLOCK_VARS (block) = ctx->block_vars;
6080 if (BLOCK_VARS (block))
6081 TREE_USED (block) = 1;
6085 /* Expand code for an OpenMP master directive. */
6087 static void
6088 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6090 tree block, lab = NULL, x, bfn_decl;
6091 gimple stmt = gsi_stmt (*gsi_p), bind;
6092 location_t loc = gimple_location (stmt);
6093 gimple_seq tseq;
6094 struct gimplify_ctx gctx;
6096 push_gimplify_context (&gctx);
6098 block = make_node (BLOCK);
6099 bind = gimple_build_bind (NULL, NULL, block);
6100 gsi_replace (gsi_p, bind, true);
6101 gimple_bind_add_stmt (bind, stmt);
6103 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6104 x = build_call_expr_loc (loc, bfn_decl, 0);
6105 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
6106 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
6107 tseq = NULL;
6108 gimplify_and_add (x, &tseq);
6109 gimple_bind_add_seq (bind, tseq);
6111 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6112 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6113 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6114 gimple_omp_set_body (stmt, NULL);
6116 gimple_bind_add_stmt (bind, gimple_build_label (lab));
6118 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6120 pop_gimplify_context (bind);
6122 gimple_bind_append_vars (bind, ctx->block_vars);
6123 BLOCK_VARS (block) = ctx->block_vars;
6127 /* Expand code for an OpenMP ordered directive. */
6129 static void
6130 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6132 tree block;
6133 gimple stmt = gsi_stmt (*gsi_p), bind, x;
6134 struct gimplify_ctx gctx;
6136 push_gimplify_context (&gctx);
6138 block = make_node (BLOCK);
6139 bind = gimple_build_bind (NULL, NULL, block);
6140 gsi_replace (gsi_p, bind, true);
6141 gimple_bind_add_stmt (bind, stmt);
6143 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
6145 gimple_bind_add_stmt (bind, x);
6147 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6148 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6149 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6150 gimple_omp_set_body (stmt, NULL);
6152 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
6153 gimple_bind_add_stmt (bind, x);
6155 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6157 pop_gimplify_context (bind);
6159 gimple_bind_append_vars (bind, ctx->block_vars);
6160 BLOCK_VARS (block) = gimple_bind_vars (bind);
6164 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
6165 substitution of a couple of function calls. But in the NAMED case,
6166 requires that languages coordinate a symbol name. It is therefore
6167 best put here in common code. */
6169 static GTY((param1_is (tree), param2_is (tree)))
6170 splay_tree critical_name_mutexes;
6172 static void
6173 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6175 tree block;
6176 tree name, lock, unlock;
6177 gimple stmt = gsi_stmt (*gsi_p), bind;
6178 location_t loc = gimple_location (stmt);
6179 gimple_seq tbody;
6180 struct gimplify_ctx gctx;
6182 name = gimple_omp_critical_name (stmt);
6183 if (name)
6185 tree decl;
6186 splay_tree_node n;
6188 if (!critical_name_mutexes)
6189 critical_name_mutexes
6190 = splay_tree_new_ggc (splay_tree_compare_pointers,
6191 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
6192 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
6194 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
6195 if (n == NULL)
6197 char *new_str;
6199 decl = create_tmp_var_raw (ptr_type_node, NULL);
6201 new_str = ACONCAT ((".gomp_critical_user_",
6202 IDENTIFIER_POINTER (name), NULL));
6203 DECL_NAME (decl) = get_identifier (new_str);
6204 TREE_PUBLIC (decl) = 1;
6205 TREE_STATIC (decl) = 1;
6206 DECL_COMMON (decl) = 1;
6207 DECL_ARTIFICIAL (decl) = 1;
6208 DECL_IGNORED_P (decl) = 1;
6209 varpool_finalize_decl (decl);
6211 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
6212 (splay_tree_value) decl);
6214 else
6215 decl = (tree) n->value;
6217 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
6218 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
6220 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
6221 unlock = build_call_expr_loc (loc, unlock, 1,
6222 build_fold_addr_expr_loc (loc, decl));
6224 else
6226 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
6227 lock = build_call_expr_loc (loc, lock, 0);
6229 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
6230 unlock = build_call_expr_loc (loc, unlock, 0);
6233 push_gimplify_context (&gctx);
6235 block = make_node (BLOCK);
6236 bind = gimple_build_bind (NULL, NULL, block);
6237 gsi_replace (gsi_p, bind, true);
6238 gimple_bind_add_stmt (bind, stmt);
6240 tbody = gimple_bind_body (bind);
6241 gimplify_and_add (lock, &tbody);
6242 gimple_bind_set_body (bind, tbody);
6244 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6245 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6246 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6247 gimple_omp_set_body (stmt, NULL);
6249 tbody = gimple_bind_body (bind);
6250 gimplify_and_add (unlock, &tbody);
6251 gimple_bind_set_body (bind, tbody);
6253 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6255 pop_gimplify_context (bind);
6256 gimple_bind_append_vars (bind, ctx->block_vars);
6257 BLOCK_VARS (block) = gimple_bind_vars (bind);
6261 /* A subroutine of lower_omp_for. Generate code to emit the predicate
6262 for a lastprivate clause. Given a loop control predicate of (V
6263 cond N2), we gate the clause on (!(V cond N2)). The lowered form
6264 is appended to *DLIST, iterator initialization is appended to
6265 *BODY_P. */
6267 static void
6268 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
6269 gimple_seq *dlist, struct omp_context *ctx)
6271 tree clauses, cond, vinit;
6272 enum tree_code cond_code;
6273 gimple_seq stmts;
6275 cond_code = fd->loop.cond_code;
6276 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
6278 /* When possible, use a strict equality expression. This can let VRP
6279 type optimizations deduce the value and remove a copy. */
6280 if (host_integerp (fd->loop.step, 0))
6282 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
6283 if (step == 1 || step == -1)
6284 cond_code = EQ_EXPR;
6287 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
6289 clauses = gimple_omp_for_clauses (fd->for_stmt);
6290 stmts = NULL;
6291 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
6292 if (!gimple_seq_empty_p (stmts))
6294 gimple_seq_add_seq (&stmts, *dlist);
6295 *dlist = stmts;
6297 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
6298 vinit = fd->loop.n1;
6299 if (cond_code == EQ_EXPR
6300 && host_integerp (fd->loop.n2, 0)
6301 && ! integer_zerop (fd->loop.n2))
6302 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
6304 /* Initialize the iterator variable, so that threads that don't execute
6305 any iterations don't execute the lastprivate clauses by accident. */
6306 gimplify_assign (fd->loop.v, vinit, body_p);
6311 /* Lower code for an OpenMP loop directive. */
6313 static void
6314 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6316 tree *rhs_p, block;
6317 struct omp_for_data fd;
6318 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
6319 gimple_seq omp_for_body, body, dlist;
6320 size_t i;
6321 struct gimplify_ctx gctx;
6323 push_gimplify_context (&gctx);
6325 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
6326 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6328 block = make_node (BLOCK);
6329 new_stmt = gimple_build_bind (NULL, NULL, block);
6330 /* Replace at gsi right away, so that 'stmt' is no member
6331 of a sequence anymore as we're going to add to to a different
6332 one below. */
6333 gsi_replace (gsi_p, new_stmt, true);
6335 /* Move declaration of temporaries in the loop body before we make
6336 it go away. */
6337 omp_for_body = gimple_omp_body (stmt);
6338 if (!gimple_seq_empty_p (omp_for_body)
6339 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
6341 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
6342 gimple_bind_append_vars (new_stmt, vars);
6345 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
6346 dlist = NULL;
6347 body = NULL;
6348 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
6349 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
6351 /* Lower the header expressions. At this point, we can assume that
6352 the header is of the form:
6354 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
6356 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
6357 using the .omp_data_s mapping, if needed. */
6358 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
6360 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
6361 if (!is_gimple_min_invariant (*rhs_p))
6362 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6364 rhs_p = gimple_omp_for_final_ptr (stmt, i);
6365 if (!is_gimple_min_invariant (*rhs_p))
6366 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6368 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
6369 if (!is_gimple_min_invariant (*rhs_p))
6370 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6373 /* Once lowered, extract the bounds and clauses. */
6374 extract_omp_for_data (stmt, &fd, NULL);
6376 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
6378 gimple_seq_add_stmt (&body, stmt);
6379 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
6381 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
6382 fd.loop.v));
6384 /* After the loop, add exit clauses. */
6385 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
6386 gimple_seq_add_seq (&body, dlist);
6388 body = maybe_catch_exception (body);
6390 /* Region exit marker goes at the end of the loop body. */
6391 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
6393 pop_gimplify_context (new_stmt);
6395 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6396 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
6397 if (BLOCK_VARS (block))
6398 TREE_USED (block) = 1;
6400 gimple_bind_set_body (new_stmt, body);
6401 gimple_omp_set_body (stmt, NULL);
6402 gimple_omp_for_set_pre_body (stmt, NULL);
6405 /* Callback for walk_stmts. Check if the current statement only contains
6406 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
6408 static tree
6409 check_combined_parallel (gimple_stmt_iterator *gsi_p,
6410 bool *handled_ops_p,
6411 struct walk_stmt_info *wi)
6413 int *info = (int *) wi->info;
6414 gimple stmt = gsi_stmt (*gsi_p);
6416 *handled_ops_p = true;
6417 switch (gimple_code (stmt))
6419 WALK_SUBSTMTS;
6421 case GIMPLE_OMP_FOR:
6422 case GIMPLE_OMP_SECTIONS:
6423 *info = *info == 0 ? 1 : -1;
6424 break;
6425 default:
6426 *info = -1;
6427 break;
6429 return NULL;
6432 struct omp_taskcopy_context
6434 /* This field must be at the beginning, as we do "inheritance": Some
6435 callback functions for tree-inline.c (e.g., omp_copy_decl)
6436 receive a copy_body_data pointer that is up-casted to an
6437 omp_context pointer. */
6438 copy_body_data cb;
6439 omp_context *ctx;
6442 static tree
6443 task_copyfn_copy_decl (tree var, copy_body_data *cb)
6445 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
6447 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
6448 return create_tmp_var (TREE_TYPE (var), NULL);
6450 return var;
6453 static tree
6454 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
6456 tree name, new_fields = NULL, type, f;
6458 type = lang_hooks.types.make_type (RECORD_TYPE);
6459 name = DECL_NAME (TYPE_NAME (orig_type));
6460 name = build_decl (gimple_location (tcctx->ctx->stmt),
6461 TYPE_DECL, name, type);
6462 TYPE_NAME (type) = name;
6464 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
6466 tree new_f = copy_node (f);
6467 DECL_CONTEXT (new_f) = type;
6468 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
6469 TREE_CHAIN (new_f) = new_fields;
6470 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6471 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6472 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
6473 &tcctx->cb, NULL);
6474 new_fields = new_f;
6475 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
6477 TYPE_FIELDS (type) = nreverse (new_fields);
6478 layout_type (type);
6479 return type;
6482 /* Create task copyfn. */
6484 static void
6485 create_task_copyfn (gimple task_stmt, omp_context *ctx)
6487 struct function *child_cfun;
6488 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
6489 tree record_type, srecord_type, bind, list;
6490 bool record_needs_remap = false, srecord_needs_remap = false;
6491 splay_tree_node n;
6492 struct omp_taskcopy_context tcctx;
6493 struct gimplify_ctx gctx;
6494 location_t loc = gimple_location (task_stmt);
6496 child_fn = gimple_omp_task_copy_fn (task_stmt);
6497 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6498 gcc_assert (child_cfun->cfg == NULL);
6499 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
6501 /* Reset DECL_CONTEXT on function arguments. */
6502 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6503 DECL_CONTEXT (t) = child_fn;
6505 /* Populate the function. */
6506 push_gimplify_context (&gctx);
6507 push_cfun (child_cfun);
6509 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6510 TREE_SIDE_EFFECTS (bind) = 1;
6511 list = NULL;
6512 DECL_SAVED_TREE (child_fn) = bind;
6513 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
6515 /* Remap src and dst argument types if needed. */
6516 record_type = ctx->record_type;
6517 srecord_type = ctx->srecord_type;
6518 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6519 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6521 record_needs_remap = true;
6522 break;
6524 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
6525 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6527 srecord_needs_remap = true;
6528 break;
6531 if (record_needs_remap || srecord_needs_remap)
6533 memset (&tcctx, '\0', sizeof (tcctx));
6534 tcctx.cb.src_fn = ctx->cb.src_fn;
6535 tcctx.cb.dst_fn = child_fn;
6536 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
6537 gcc_checking_assert (tcctx.cb.src_node);
6538 tcctx.cb.dst_node = tcctx.cb.src_node;
6539 tcctx.cb.src_cfun = ctx->cb.src_cfun;
6540 tcctx.cb.copy_decl = task_copyfn_copy_decl;
6541 tcctx.cb.eh_lp_nr = 0;
6542 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
6543 tcctx.cb.decl_map = pointer_map_create ();
6544 tcctx.ctx = ctx;
6546 if (record_needs_remap)
6547 record_type = task_copyfn_remap_type (&tcctx, record_type);
6548 if (srecord_needs_remap)
6549 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
6551 else
6552 tcctx.cb.decl_map = NULL;
6554 arg = DECL_ARGUMENTS (child_fn);
6555 TREE_TYPE (arg) = build_pointer_type (record_type);
6556 sarg = DECL_CHAIN (arg);
6557 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
6559 /* First pass: initialize temporaries used in record_type and srecord_type
6560 sizes and field offsets. */
6561 if (tcctx.cb.decl_map)
6562 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6563 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6565 tree *p;
6567 decl = OMP_CLAUSE_DECL (c);
6568 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
6569 if (p == NULL)
6570 continue;
6571 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6572 sf = (tree) n->value;
6573 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6574 src = build_simple_mem_ref_loc (loc, sarg);
6575 src = omp_build_component_ref (src, sf);
6576 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
6577 append_to_statement_list (t, &list);
6580 /* Second pass: copy shared var pointers and copy construct non-VLA
6581 firstprivate vars. */
6582 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6583 switch (OMP_CLAUSE_CODE (c))
6585 case OMP_CLAUSE_SHARED:
6586 decl = OMP_CLAUSE_DECL (c);
6587 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6588 if (n == NULL)
6589 break;
6590 f = (tree) n->value;
6591 if (tcctx.cb.decl_map)
6592 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6593 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6594 sf = (tree) n->value;
6595 if (tcctx.cb.decl_map)
6596 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6597 src = build_simple_mem_ref_loc (loc, sarg);
6598 src = omp_build_component_ref (src, sf);
6599 dst = build_simple_mem_ref_loc (loc, arg);
6600 dst = omp_build_component_ref (dst, f);
6601 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6602 append_to_statement_list (t, &list);
6603 break;
6604 case OMP_CLAUSE_FIRSTPRIVATE:
6605 decl = OMP_CLAUSE_DECL (c);
6606 if (is_variable_sized (decl))
6607 break;
6608 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6609 if (n == NULL)
6610 break;
6611 f = (tree) n->value;
6612 if (tcctx.cb.decl_map)
6613 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6614 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6615 if (n != NULL)
6617 sf = (tree) n->value;
6618 if (tcctx.cb.decl_map)
6619 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6620 src = build_simple_mem_ref_loc (loc, sarg);
6621 src = omp_build_component_ref (src, sf);
6622 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6623 src = build_simple_mem_ref_loc (loc, src);
6625 else
6626 src = decl;
6627 dst = build_simple_mem_ref_loc (loc, arg);
6628 dst = omp_build_component_ref (dst, f);
6629 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6630 append_to_statement_list (t, &list);
6631 break;
6632 case OMP_CLAUSE_PRIVATE:
6633 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6634 break;
6635 decl = OMP_CLAUSE_DECL (c);
6636 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6637 f = (tree) n->value;
6638 if (tcctx.cb.decl_map)
6639 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6640 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6641 if (n != NULL)
6643 sf = (tree) n->value;
6644 if (tcctx.cb.decl_map)
6645 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6646 src = build_simple_mem_ref_loc (loc, sarg);
6647 src = omp_build_component_ref (src, sf);
6648 if (use_pointer_for_field (decl, NULL))
6649 src = build_simple_mem_ref_loc (loc, src);
6651 else
6652 src = decl;
6653 dst = build_simple_mem_ref_loc (loc, arg);
6654 dst = omp_build_component_ref (dst, f);
6655 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6656 append_to_statement_list (t, &list);
6657 break;
6658 default:
6659 break;
6662 /* Last pass: handle VLA firstprivates. */
6663 if (tcctx.cb.decl_map)
6664 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6665 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6667 tree ind, ptr, df;
6669 decl = OMP_CLAUSE_DECL (c);
6670 if (!is_variable_sized (decl))
6671 continue;
6672 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6673 if (n == NULL)
6674 continue;
6675 f = (tree) n->value;
6676 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6677 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6678 ind = DECL_VALUE_EXPR (decl);
6679 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6680 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6681 n = splay_tree_lookup (ctx->sfield_map,
6682 (splay_tree_key) TREE_OPERAND (ind, 0));
6683 sf = (tree) n->value;
6684 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6685 src = build_simple_mem_ref_loc (loc, sarg);
6686 src = omp_build_component_ref (src, sf);
6687 src = build_simple_mem_ref_loc (loc, src);
6688 dst = build_simple_mem_ref_loc (loc, arg);
6689 dst = omp_build_component_ref (dst, f);
6690 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6691 append_to_statement_list (t, &list);
6692 n = splay_tree_lookup (ctx->field_map,
6693 (splay_tree_key) TREE_OPERAND (ind, 0));
6694 df = (tree) n->value;
6695 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6696 ptr = build_simple_mem_ref_loc (loc, arg);
6697 ptr = omp_build_component_ref (ptr, df);
6698 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
6699 build_fold_addr_expr_loc (loc, dst));
6700 append_to_statement_list (t, &list);
6703 t = build1 (RETURN_EXPR, void_type_node, NULL);
6704 append_to_statement_list (t, &list);
6706 if (tcctx.cb.decl_map)
6707 pointer_map_destroy (tcctx.cb.decl_map);
6708 pop_gimplify_context (NULL);
6709 BIND_EXPR_BODY (bind) = list;
6710 pop_cfun ();
6713 /* Lower the OpenMP parallel or task directive in the current statement
6714 in GSI_P. CTX holds context information for the directive. */
6716 static void
6717 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6719 tree clauses;
6720 tree child_fn, t;
6721 gimple stmt = gsi_stmt (*gsi_p);
6722 gimple par_bind, bind;
6723 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
6724 struct gimplify_ctx gctx;
6725 location_t loc = gimple_location (stmt);
6727 clauses = gimple_omp_taskreg_clauses (stmt);
6728 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
6729 par_body = gimple_bind_body (par_bind);
6730 child_fn = ctx->cb.dst_fn;
6731 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6732 && !gimple_omp_parallel_combined_p (stmt))
6734 struct walk_stmt_info wi;
6735 int ws_num = 0;
6737 memset (&wi, 0, sizeof (wi));
6738 wi.info = &ws_num;
6739 wi.val_only = true;
6740 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
6741 if (ws_num == 1)
6742 gimple_omp_parallel_set_combined_p (stmt, true);
6744 if (ctx->srecord_type)
6745 create_task_copyfn (stmt, ctx);
6747 push_gimplify_context (&gctx);
6749 par_olist = NULL;
6750 par_ilist = NULL;
6751 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6752 lower_omp (&par_body, ctx);
6753 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
6754 lower_reduction_clauses (clauses, &par_olist, ctx);
6756 /* Declare all the variables created by mapping and the variables
6757 declared in the scope of the parallel body. */
6758 record_vars_into (ctx->block_vars, child_fn);
6759 record_vars_into (gimple_bind_vars (par_bind), child_fn);
6761 if (ctx->record_type)
6763 ctx->sender_decl
6764 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6765 : ctx->record_type, ".omp_data_o");
6766 DECL_NAMELESS (ctx->sender_decl) = 1;
6767 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
6768 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
6771 olist = NULL;
6772 ilist = NULL;
6773 lower_send_clauses (clauses, &ilist, &olist, ctx);
6774 lower_send_shared_vars (&ilist, &olist, ctx);
6776 /* Once all the expansions are done, sequence all the different
6777 fragments inside gimple_omp_body. */
6779 new_body = NULL;
6781 if (ctx->record_type)
6783 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6784 /* fixup_child_record_type might have changed receiver_decl's type. */
6785 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
6786 gimple_seq_add_stmt (&new_body,
6787 gimple_build_assign (ctx->receiver_decl, t));
6790 gimple_seq_add_seq (&new_body, par_ilist);
6791 gimple_seq_add_seq (&new_body, par_body);
6792 gimple_seq_add_seq (&new_body, par_olist);
6793 new_body = maybe_catch_exception (new_body);
6794 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
6795 gimple_omp_set_body (stmt, new_body);
6797 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
6798 gsi_replace (gsi_p, bind, true);
6799 gimple_bind_add_seq (bind, ilist);
6800 gimple_bind_add_stmt (bind, stmt);
6801 gimple_bind_add_seq (bind, olist);
6803 pop_gimplify_context (NULL);
6806 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
6807 regimplified. If DATA is non-NULL, lower_omp_1 is outside
6808 of OpenMP context, but with task_shared_vars set. */
6810 static tree
6811 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
6812 void *data)
6814 tree t = *tp;
6816 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6817 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
6818 return t;
6820 if (task_shared_vars
6821 && DECL_P (t)
6822 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
6823 return t;
6825 /* If a global variable has been privatized, TREE_CONSTANT on
6826 ADDR_EXPR might be wrong. */
6827 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
6828 recompute_tree_invariant_for_addr_expr (t);
6830 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6831 return NULL_TREE;
6834 static void
6835 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6837 gimple stmt = gsi_stmt (*gsi_p);
6838 struct walk_stmt_info wi;
6840 if (gimple_has_location (stmt))
6841 input_location = gimple_location (stmt);
6843 if (task_shared_vars)
6844 memset (&wi, '\0', sizeof (wi));
6846 /* If we have issued syntax errors, avoid doing any heavy lifting.
6847 Just replace the OpenMP directives with a NOP to avoid
6848 confusing RTL expansion. */
6849 if (seen_error () && is_gimple_omp (stmt))
6851 gsi_replace (gsi_p, gimple_build_nop (), true);
6852 return;
6855 switch (gimple_code (stmt))
6857 case GIMPLE_COND:
6858 if ((ctx || task_shared_vars)
6859 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
6860 ctx ? NULL : &wi, NULL)
6861 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
6862 ctx ? NULL : &wi, NULL)))
6863 gimple_regimplify_operands (stmt, gsi_p);
6864 break;
6865 case GIMPLE_CATCH:
6866 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
6867 break;
6868 case GIMPLE_EH_FILTER:
6869 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
6870 break;
6871 case GIMPLE_TRY:
6872 lower_omp (gimple_try_eval_ptr (stmt), ctx);
6873 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
6874 break;
6875 case GIMPLE_TRANSACTION:
6876 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
6877 break;
6878 case GIMPLE_BIND:
6879 lower_omp (gimple_bind_body_ptr (stmt), ctx);
6880 break;
6881 case GIMPLE_OMP_PARALLEL:
6882 case GIMPLE_OMP_TASK:
6883 ctx = maybe_lookup_ctx (stmt);
6884 lower_omp_taskreg (gsi_p, ctx);
6885 break;
6886 case GIMPLE_OMP_FOR:
6887 ctx = maybe_lookup_ctx (stmt);
6888 gcc_assert (ctx);
6889 lower_omp_for (gsi_p, ctx);
6890 break;
6891 case GIMPLE_OMP_SECTIONS:
6892 ctx = maybe_lookup_ctx (stmt);
6893 gcc_assert (ctx);
6894 lower_omp_sections (gsi_p, ctx);
6895 break;
6896 case GIMPLE_OMP_SINGLE:
6897 ctx = maybe_lookup_ctx (stmt);
6898 gcc_assert (ctx);
6899 lower_omp_single (gsi_p, ctx);
6900 break;
6901 case GIMPLE_OMP_MASTER:
6902 ctx = maybe_lookup_ctx (stmt);
6903 gcc_assert (ctx);
6904 lower_omp_master (gsi_p, ctx);
6905 break;
6906 case GIMPLE_OMP_ORDERED:
6907 ctx = maybe_lookup_ctx (stmt);
6908 gcc_assert (ctx);
6909 lower_omp_ordered (gsi_p, ctx);
6910 break;
6911 case GIMPLE_OMP_CRITICAL:
6912 ctx = maybe_lookup_ctx (stmt);
6913 gcc_assert (ctx);
6914 lower_omp_critical (gsi_p, ctx);
6915 break;
6916 case GIMPLE_OMP_ATOMIC_LOAD:
6917 if ((ctx || task_shared_vars)
6918 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
6919 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
6920 gimple_regimplify_operands (stmt, gsi_p);
6921 break;
6922 default:
6923 if ((ctx || task_shared_vars)
6924 && walk_gimple_op (stmt, lower_omp_regimplify_p,
6925 ctx ? NULL : &wi))
6926 gimple_regimplify_operands (stmt, gsi_p);
6927 break;
6931 static void
6932 lower_omp (gimple_seq *body, omp_context *ctx)
6934 location_t saved_location = input_location;
6935 gimple_stmt_iterator gsi;
6936 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
6937 lower_omp_1 (&gsi, ctx);
6938 input_location = saved_location;
6941 /* Main entry point. */
6943 static unsigned int
6944 execute_lower_omp (void)
6946 gimple_seq body;
6948 /* This pass always runs, to provide PROP_gimple_lomp.
6949 But there is nothing to do unless -fopenmp is given. */
6950 if (flag_openmp == 0)
6951 return 0;
6953 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
6954 delete_omp_context);
6956 body = gimple_body (current_function_decl);
6957 scan_omp (&body, NULL);
6958 gcc_assert (taskreg_nesting_level == 0);
6960 if (all_contexts->root)
6962 struct gimplify_ctx gctx;
6964 if (task_shared_vars)
6965 push_gimplify_context (&gctx);
6966 lower_omp (&body, NULL);
6967 if (task_shared_vars)
6968 pop_gimplify_context (NULL);
6971 if (all_contexts)
6973 splay_tree_delete (all_contexts);
6974 all_contexts = NULL;
6976 BITMAP_FREE (task_shared_vars);
6977 return 0;
6980 struct gimple_opt_pass pass_lower_omp =
6983 GIMPLE_PASS,
6984 "omplower", /* name */
6985 OPTGROUP_NONE, /* optinfo_flags */
6986 NULL, /* gate */
6987 execute_lower_omp, /* execute */
6988 NULL, /* sub */
6989 NULL, /* next */
6990 0, /* static_pass_number */
6991 TV_NONE, /* tv_id */
6992 PROP_gimple_any, /* properties_required */
6993 PROP_gimple_lomp, /* properties_provided */
6994 0, /* properties_destroyed */
6995 0, /* todo_flags_start */
6996 0 /* todo_flags_finish */
7000 /* The following is a utility to diagnose OpenMP structured block violations.
7001 It is not part of the "omplower" pass, as that's invoked too late. It
7002 should be invoked by the respective front ends after gimplification. */
7004 static splay_tree all_labels;
7006 /* Check for mismatched contexts and generate an error if needed. Return
7007 true if an error is detected. */
7009 static bool
7010 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
7011 gimple branch_ctx, gimple label_ctx)
7013 if (label_ctx == branch_ctx)
7014 return false;
7018 Previously we kept track of the label's entire context in diagnose_sb_[12]
7019 so we could traverse it and issue a correct "exit" or "enter" error
7020 message upon a structured block violation.
7022 We built the context by building a list with tree_cons'ing, but there is
7023 no easy counterpart in gimple tuples. It seems like far too much work
7024 for issuing exit/enter error messages. If someone really misses the
7025 distinct error message... patches welcome.
7028 #if 0
7029 /* Try to avoid confusing the user by producing and error message
7030 with correct "exit" or "enter" verbiage. We prefer "exit"
7031 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
7032 if (branch_ctx == NULL)
7033 exit_p = false;
7034 else
7036 while (label_ctx)
7038 if (TREE_VALUE (label_ctx) == branch_ctx)
7040 exit_p = false;
7041 break;
7043 label_ctx = TREE_CHAIN (label_ctx);
7047 if (exit_p)
7048 error ("invalid exit from OpenMP structured block");
7049 else
7050 error ("invalid entry to OpenMP structured block");
7051 #endif
7053 /* If it's obvious we have an invalid entry, be specific about the error. */
7054 if (branch_ctx == NULL)
7055 error ("invalid entry to OpenMP structured block");
7056 else
7057 /* Otherwise, be vague and lazy, but efficient. */
7058 error ("invalid branch to/from an OpenMP structured block");
7060 gsi_replace (gsi_p, gimple_build_nop (), false);
7061 return true;
7064 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
7065 where each label is found. */
7067 static tree
7068 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7069 struct walk_stmt_info *wi)
7071 gimple context = (gimple) wi->info;
7072 gimple inner_context;
7073 gimple stmt = gsi_stmt (*gsi_p);
7075 *handled_ops_p = true;
7077 switch (gimple_code (stmt))
7079 WALK_SUBSTMTS;
7081 case GIMPLE_OMP_PARALLEL:
7082 case GIMPLE_OMP_TASK:
7083 case GIMPLE_OMP_SECTIONS:
7084 case GIMPLE_OMP_SINGLE:
7085 case GIMPLE_OMP_SECTION:
7086 case GIMPLE_OMP_MASTER:
7087 case GIMPLE_OMP_ORDERED:
7088 case GIMPLE_OMP_CRITICAL:
7089 /* The minimal context here is just the current OMP construct. */
7090 inner_context = stmt;
7091 wi->info = inner_context;
7092 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7093 wi->info = context;
7094 break;
7096 case GIMPLE_OMP_FOR:
7097 inner_context = stmt;
7098 wi->info = inner_context;
7099 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7100 walk them. */
7101 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
7102 diagnose_sb_1, NULL, wi);
7103 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7104 wi->info = context;
7105 break;
7107 case GIMPLE_LABEL:
7108 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
7109 (splay_tree_value) context);
7110 break;
7112 default:
7113 break;
7116 return NULL_TREE;
7119 /* Pass 2: Check each branch and see if its context differs from that of
7120 the destination label's context. */
7122 static tree
7123 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7124 struct walk_stmt_info *wi)
7126 gimple context = (gimple) wi->info;
7127 splay_tree_node n;
7128 gimple stmt = gsi_stmt (*gsi_p);
7130 *handled_ops_p = true;
7132 switch (gimple_code (stmt))
7134 WALK_SUBSTMTS;
7136 case GIMPLE_OMP_PARALLEL:
7137 case GIMPLE_OMP_TASK:
7138 case GIMPLE_OMP_SECTIONS:
7139 case GIMPLE_OMP_SINGLE:
7140 case GIMPLE_OMP_SECTION:
7141 case GIMPLE_OMP_MASTER:
7142 case GIMPLE_OMP_ORDERED:
7143 case GIMPLE_OMP_CRITICAL:
7144 wi->info = stmt;
7145 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7146 wi->info = context;
7147 break;
7149 case GIMPLE_OMP_FOR:
7150 wi->info = stmt;
7151 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7152 walk them. */
7153 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
7154 diagnose_sb_2, NULL, wi);
7155 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7156 wi->info = context;
7157 break;
7159 case GIMPLE_COND:
7161 tree lab = gimple_cond_true_label (stmt);
7162 if (lab)
7164 n = splay_tree_lookup (all_labels,
7165 (splay_tree_key) lab);
7166 diagnose_sb_0 (gsi_p, context,
7167 n ? (gimple) n->value : NULL);
7169 lab = gimple_cond_false_label (stmt);
7170 if (lab)
7172 n = splay_tree_lookup (all_labels,
7173 (splay_tree_key) lab);
7174 diagnose_sb_0 (gsi_p, context,
7175 n ? (gimple) n->value : NULL);
7178 break;
7180 case GIMPLE_GOTO:
7182 tree lab = gimple_goto_dest (stmt);
7183 if (TREE_CODE (lab) != LABEL_DECL)
7184 break;
7186 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7187 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
7189 break;
7191 case GIMPLE_SWITCH:
7193 unsigned int i;
7194 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
7196 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
7197 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7198 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
7199 break;
7202 break;
7204 case GIMPLE_RETURN:
7205 diagnose_sb_0 (gsi_p, context, NULL);
7206 break;
7208 default:
7209 break;
7212 return NULL_TREE;
7215 static unsigned int
7216 diagnose_omp_structured_block_errors (void)
7218 struct walk_stmt_info wi;
7219 gimple_seq body = gimple_body (current_function_decl);
7221 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
7223 memset (&wi, 0, sizeof (wi));
7224 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
7226 memset (&wi, 0, sizeof (wi));
7227 wi.want_locations = true;
7228 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
7230 gimple_set_body (current_function_decl, body);
7232 splay_tree_delete (all_labels);
7233 all_labels = NULL;
7235 return 0;
7238 static bool
7239 gate_diagnose_omp_blocks (void)
7241 return flag_openmp != 0;
7244 struct gimple_opt_pass pass_diagnose_omp_blocks =
7247 GIMPLE_PASS,
7248 "*diagnose_omp_blocks", /* name */
7249 OPTGROUP_NONE, /* optinfo_flags */
7250 gate_diagnose_omp_blocks, /* gate */
7251 diagnose_omp_structured_block_errors, /* execute */
7252 NULL, /* sub */
7253 NULL, /* next */
7254 0, /* static_pass_number */
7255 TV_NONE, /* tv_id */
7256 PROP_gimple_any, /* properties_required */
7257 0, /* properties_provided */
7258 0, /* properties_destroyed */
7259 0, /* todo_flags_start */
7260 0, /* todo_flags_finish */
7264 #include "gt-omp-low.h"