* arm.h (TARGET_CPU_CPP_BUILTINS): Remove Maverick support.
[official-gcc.git] / gcc / omp-low.c
blobd51715e2843d40de9e3c0faafe27fa82cdf0dff2
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
7 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "rtl.h"
31 #include "gimple.h"
32 #include "tree-iterator.h"
33 #include "tree-inline.h"
34 #include "langhooks.h"
35 #include "diagnostic-core.h"
36 #include "tree-flow.h"
37 #include "timevar.h"
38 #include "flags.h"
39 #include "function.h"
40 #include "expr.h"
41 #include "tree-pass.h"
42 #include "ggc.h"
43 #include "except.h"
44 #include "splay-tree.h"
45 #include "optabs.h"
46 #include "cfgloop.h"
49 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
50 phases. The first phase scans the function looking for OMP statements
51 and then for variables that must be replaced to satisfy data sharing
52 clauses. The second phase expands code for the constructs, as well as
53 re-gimplifying things when variables have been replaced with complex
54 expressions.
56 Final code generation is done by pass_expand_omp. The flowgraph is
57 scanned for parallel regions which are then moved to a new
58 function, to be invoked by the thread library. */
60 /* Context structure. Used to store information about each parallel
61 directive in the code. */
63 typedef struct omp_context
65 /* This field must be at the beginning, as we do "inheritance": Some
66 callback functions for tree-inline.c (e.g., omp_copy_decl)
67 receive a copy_body_data pointer that is up-casted to an
68 omp_context pointer. */
69 copy_body_data cb;
71 /* The tree of contexts corresponding to the encountered constructs. */
72 struct omp_context *outer;
73 gimple stmt;
75 /* Map variables to fields in a structure that allows communication
76 between sending and receiving threads. */
77 splay_tree field_map;
78 tree record_type;
79 tree sender_decl;
80 tree receiver_decl;
82 /* These are used just by task contexts, if task firstprivate fn is
83 needed. srecord_type is used to communicate from the thread
84 that encountered the task construct to task firstprivate fn,
85 record_type is allocated by GOMP_task, initialized by task firstprivate
86 fn and passed to the task body fn. */
87 splay_tree sfield_map;
88 tree srecord_type;
90 /* A chain of variables to add to the top-level block surrounding the
91 construct. In the case of a parallel, this is in the child function. */
92 tree block_vars;
94 /* What to do with variables with implicitly determined sharing
95 attributes. */
96 enum omp_clause_default_kind default_kind;
98 /* Nesting depth of this context. Used to beautify error messages re
99 invalid gotos. The outermost ctx is depth 1, with depth 0 being
100 reserved for the main body of the function. */
101 int depth;
103 /* True if this parallel directive is nested within another. */
104 bool is_nested;
105 } omp_context;
108 struct omp_for_data_loop
110 tree v, n1, n2, step;
111 enum tree_code cond_code;
114 /* A structure describing the main elements of a parallel loop. */
116 struct omp_for_data
118 struct omp_for_data_loop loop;
119 tree chunk_size;
120 gimple for_stmt;
121 tree pre, iter_type;
122 int collapse;
123 bool have_nowait, have_ordered;
124 enum omp_clause_schedule_kind sched_kind;
125 struct omp_for_data_loop *loops;
129 static splay_tree all_contexts;
130 static int taskreg_nesting_level;
131 struct omp_region *root_omp_region;
132 static bitmap task_shared_vars;
134 static void scan_omp (gimple_seq *, omp_context *);
135 static tree scan_omp_1_op (tree *, int *, void *);
137 #define WALK_SUBSTMTS \
138 case GIMPLE_BIND: \
139 case GIMPLE_TRY: \
140 case GIMPLE_CATCH: \
141 case GIMPLE_EH_FILTER: \
142 case GIMPLE_TRANSACTION: \
143 /* The sub-statements for these should be walked. */ \
144 *handled_ops_p = false; \
145 break;
147 /* Convenience function for calling scan_omp_1_op on tree operands. */
149 static inline tree
150 scan_omp_op (tree *tp, omp_context *ctx)
152 struct walk_stmt_info wi;
154 memset (&wi, 0, sizeof (wi));
155 wi.info = ctx;
156 wi.want_locations = true;
158 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
161 static void lower_omp (gimple_seq *, omp_context *);
162 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
163 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
165 /* Find an OpenMP clause of type KIND within CLAUSES. */
167 tree
168 find_omp_clause (tree clauses, enum omp_clause_code kind)
170 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
171 if (OMP_CLAUSE_CODE (clauses) == kind)
172 return clauses;
174 return NULL_TREE;
177 /* Return true if CTX is for an omp parallel. */
179 static inline bool
180 is_parallel_ctx (omp_context *ctx)
182 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
186 /* Return true if CTX is for an omp task. */
188 static inline bool
189 is_task_ctx (omp_context *ctx)
191 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
195 /* Return true if CTX is for an omp parallel or omp task. */
197 static inline bool
198 is_taskreg_ctx (omp_context *ctx)
200 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
201 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
205 /* Return true if REGION is a combined parallel+workshare region. */
207 static inline bool
208 is_combined_parallel (struct omp_region *region)
210 return region->is_combined_parallel;
214 /* Extract the header elements of parallel loop FOR_STMT and store
215 them into *FD. */
217 static void
218 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
219 struct omp_for_data_loop *loops)
221 tree t, var, *collapse_iter, *collapse_count;
222 tree count = NULL_TREE, iter_type = long_integer_type_node;
223 struct omp_for_data_loop *loop;
224 int i;
225 struct omp_for_data_loop dummy_loop;
226 location_t loc = gimple_location (for_stmt);
228 fd->for_stmt = for_stmt;
229 fd->pre = NULL;
230 fd->collapse = gimple_omp_for_collapse (for_stmt);
231 if (fd->collapse > 1)
232 fd->loops = loops;
233 else
234 fd->loops = &fd->loop;
236 fd->have_nowait = fd->have_ordered = false;
237 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
238 fd->chunk_size = NULL_TREE;
239 collapse_iter = NULL;
240 collapse_count = NULL;
242 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
243 switch (OMP_CLAUSE_CODE (t))
245 case OMP_CLAUSE_NOWAIT:
246 fd->have_nowait = true;
247 break;
248 case OMP_CLAUSE_ORDERED:
249 fd->have_ordered = true;
250 break;
251 case OMP_CLAUSE_SCHEDULE:
252 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
253 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
254 break;
255 case OMP_CLAUSE_COLLAPSE:
256 if (fd->collapse > 1)
258 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
259 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
261 default:
262 break;
265 /* FIXME: for now map schedule(auto) to schedule(static).
266 There should be analysis to determine whether all iterations
267 are approximately the same amount of work (then schedule(static)
268 is best) or if it varies (then schedule(dynamic,N) is better). */
269 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
271 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
272 gcc_assert (fd->chunk_size == NULL);
274 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
275 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
276 gcc_assert (fd->chunk_size == NULL);
277 else if (fd->chunk_size == NULL)
279 /* We only need to compute a default chunk size for ordered
280 static loops and dynamic loops. */
281 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
282 || fd->have_ordered
283 || fd->collapse > 1)
284 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
285 ? integer_zero_node : integer_one_node;
288 for (i = 0; i < fd->collapse; i++)
290 if (fd->collapse == 1)
291 loop = &fd->loop;
292 else if (loops != NULL)
293 loop = loops + i;
294 else
295 loop = &dummy_loop;
298 loop->v = gimple_omp_for_index (for_stmt, i);
299 gcc_assert (SSA_VAR_P (loop->v));
300 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
301 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
302 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
303 loop->n1 = gimple_omp_for_initial (for_stmt, i);
305 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
306 loop->n2 = gimple_omp_for_final (for_stmt, i);
307 switch (loop->cond_code)
309 case LT_EXPR:
310 case GT_EXPR:
311 break;
312 case LE_EXPR:
313 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
314 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
315 else
316 loop->n2 = fold_build2_loc (loc,
317 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
318 build_int_cst (TREE_TYPE (loop->n2), 1));
319 loop->cond_code = LT_EXPR;
320 break;
321 case GE_EXPR:
322 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
323 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
324 else
325 loop->n2 = fold_build2_loc (loc,
326 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
327 build_int_cst (TREE_TYPE (loop->n2), 1));
328 loop->cond_code = GT_EXPR;
329 break;
330 default:
331 gcc_unreachable ();
334 t = gimple_omp_for_incr (for_stmt, i);
335 gcc_assert (TREE_OPERAND (t, 0) == var);
336 switch (TREE_CODE (t))
338 case PLUS_EXPR:
339 loop->step = TREE_OPERAND (t, 1);
340 break;
341 case POINTER_PLUS_EXPR:
342 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
343 break;
344 case MINUS_EXPR:
345 loop->step = TREE_OPERAND (t, 1);
346 loop->step = fold_build1_loc (loc,
347 NEGATE_EXPR, TREE_TYPE (loop->step),
348 loop->step);
349 break;
350 default:
351 gcc_unreachable ();
354 if (iter_type != long_long_unsigned_type_node)
356 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
357 iter_type = long_long_unsigned_type_node;
358 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
359 && TYPE_PRECISION (TREE_TYPE (loop->v))
360 >= TYPE_PRECISION (iter_type))
362 tree n;
364 if (loop->cond_code == LT_EXPR)
365 n = fold_build2_loc (loc,
366 PLUS_EXPR, TREE_TYPE (loop->v),
367 loop->n2, loop->step);
368 else
369 n = loop->n1;
370 if (TREE_CODE (n) != INTEGER_CST
371 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
372 iter_type = long_long_unsigned_type_node;
374 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
375 > TYPE_PRECISION (iter_type))
377 tree n1, n2;
379 if (loop->cond_code == LT_EXPR)
381 n1 = loop->n1;
382 n2 = fold_build2_loc (loc,
383 PLUS_EXPR, TREE_TYPE (loop->v),
384 loop->n2, loop->step);
386 else
388 n1 = fold_build2_loc (loc,
389 MINUS_EXPR, TREE_TYPE (loop->v),
390 loop->n2, loop->step);
391 n2 = loop->n1;
393 if (TREE_CODE (n1) != INTEGER_CST
394 || TREE_CODE (n2) != INTEGER_CST
395 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
396 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
397 iter_type = long_long_unsigned_type_node;
401 if (collapse_count && *collapse_count == NULL)
403 if ((i == 0 || count != NULL_TREE)
404 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
405 && TREE_CONSTANT (loop->n1)
406 && TREE_CONSTANT (loop->n2)
407 && TREE_CODE (loop->step) == INTEGER_CST)
409 tree itype = TREE_TYPE (loop->v);
411 if (POINTER_TYPE_P (itype))
412 itype = signed_type_for (itype);
413 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
414 t = fold_build2_loc (loc,
415 PLUS_EXPR, itype,
416 fold_convert_loc (loc, itype, loop->step), t);
417 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
418 fold_convert_loc (loc, itype, loop->n2));
419 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
420 fold_convert_loc (loc, itype, loop->n1));
421 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
422 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
423 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
424 fold_build1_loc (loc, NEGATE_EXPR, itype,
425 fold_convert_loc (loc, itype,
426 loop->step)));
427 else
428 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
429 fold_convert_loc (loc, itype, loop->step));
430 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
431 if (count != NULL_TREE)
432 count = fold_build2_loc (loc,
433 MULT_EXPR, long_long_unsigned_type_node,
434 count, t);
435 else
436 count = t;
437 if (TREE_CODE (count) != INTEGER_CST)
438 count = NULL_TREE;
440 else
441 count = NULL_TREE;
445 if (count)
447 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
448 iter_type = long_long_unsigned_type_node;
449 else
450 iter_type = long_integer_type_node;
452 else if (collapse_iter && *collapse_iter != NULL)
453 iter_type = TREE_TYPE (*collapse_iter);
454 fd->iter_type = iter_type;
455 if (collapse_iter && *collapse_iter == NULL)
456 *collapse_iter = create_tmp_var (iter_type, ".iter");
457 if (collapse_count && *collapse_count == NULL)
459 if (count)
460 *collapse_count = fold_convert_loc (loc, iter_type, count);
461 else
462 *collapse_count = create_tmp_var (iter_type, ".count");
465 if (fd->collapse > 1)
467 fd->loop.v = *collapse_iter;
468 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
469 fd->loop.n2 = *collapse_count;
470 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
471 fd->loop.cond_code = LT_EXPR;
476 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
477 is the immediate dominator of PAR_ENTRY_BB, return true if there
478 are no data dependencies that would prevent expanding the parallel
479 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
481 When expanding a combined parallel+workshare region, the call to
482 the child function may need additional arguments in the case of
483 GIMPLE_OMP_FOR regions. In some cases, these arguments are
484 computed out of variables passed in from the parent to the child
485 via 'struct .omp_data_s'. For instance:
487 #pragma omp parallel for schedule (guided, i * 4)
488 for (j ...)
490 Is lowered into:
492 # BLOCK 2 (PAR_ENTRY_BB)
493 .omp_data_o.i = i;
494 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
496 # BLOCK 3 (WS_ENTRY_BB)
497 .omp_data_i = &.omp_data_o;
498 D.1667 = .omp_data_i->i;
499 D.1598 = D.1667 * 4;
500 #pragma omp for schedule (guided, D.1598)
502 When we outline the parallel region, the call to the child function
503 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
504 that value is computed *after* the call site. So, in principle we
505 cannot do the transformation.
507 To see whether the code in WS_ENTRY_BB blocks the combined
508 parallel+workshare call, we collect all the variables used in the
509 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
510 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
511 call.
513 FIXME. If we had the SSA form built at this point, we could merely
514 hoist the code in block 3 into block 2 and be done with it. But at
515 this point we don't have dataflow information and though we could
516 hack something up here, it is really not worth the aggravation. */
518 static bool
519 workshare_safe_to_combine_p (basic_block ws_entry_bb)
521 struct omp_for_data fd;
522 gimple ws_stmt = last_stmt (ws_entry_bb);
524 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
525 return true;
527 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
529 extract_omp_for_data (ws_stmt, &fd, NULL);
531 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
532 return false;
533 if (fd.iter_type != long_integer_type_node)
534 return false;
536 /* FIXME. We give up too easily here. If any of these arguments
537 are not constants, they will likely involve variables that have
538 been mapped into fields of .omp_data_s for sharing with the child
539 function. With appropriate data flow, it would be possible to
540 see through this. */
541 if (!is_gimple_min_invariant (fd.loop.n1)
542 || !is_gimple_min_invariant (fd.loop.n2)
543 || !is_gimple_min_invariant (fd.loop.step)
544 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
545 return false;
547 return true;
551 /* Collect additional arguments needed to emit a combined
552 parallel+workshare call. WS_STMT is the workshare directive being
553 expanded. */
555 static VEC(tree,gc) *
556 get_ws_args_for (gimple ws_stmt)
558 tree t;
559 location_t loc = gimple_location (ws_stmt);
560 VEC(tree,gc) *ws_args;
562 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
564 struct omp_for_data fd;
566 extract_omp_for_data (ws_stmt, &fd, NULL);
568 ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0));
570 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
571 VEC_quick_push (tree, ws_args, t);
573 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
574 VEC_quick_push (tree, ws_args, t);
576 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
577 VEC_quick_push (tree, ws_args, t);
579 if (fd.chunk_size)
581 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
582 VEC_quick_push (tree, ws_args, t);
585 return ws_args;
587 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
589 /* Number of sections is equal to the number of edges from the
590 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
591 the exit of the sections region. */
592 basic_block bb = single_succ (gimple_bb (ws_stmt));
593 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
594 ws_args = VEC_alloc (tree, gc, 1);
595 VEC_quick_push (tree, ws_args, t);
596 return ws_args;
599 gcc_unreachable ();
603 /* Discover whether REGION is a combined parallel+workshare region. */
605 static void
606 determine_parallel_type (struct omp_region *region)
608 basic_block par_entry_bb, par_exit_bb;
609 basic_block ws_entry_bb, ws_exit_bb;
611 if (region == NULL || region->inner == NULL
612 || region->exit == NULL || region->inner->exit == NULL
613 || region->inner->cont == NULL)
614 return;
616 /* We only support parallel+for and parallel+sections. */
617 if (region->type != GIMPLE_OMP_PARALLEL
618 || (region->inner->type != GIMPLE_OMP_FOR
619 && region->inner->type != GIMPLE_OMP_SECTIONS))
620 return;
622 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
623 WS_EXIT_BB -> PAR_EXIT_BB. */
624 par_entry_bb = region->entry;
625 par_exit_bb = region->exit;
626 ws_entry_bb = region->inner->entry;
627 ws_exit_bb = region->inner->exit;
629 if (single_succ (par_entry_bb) == ws_entry_bb
630 && single_succ (ws_exit_bb) == par_exit_bb
631 && workshare_safe_to_combine_p (ws_entry_bb)
632 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
633 || (last_and_only_stmt (ws_entry_bb)
634 && last_and_only_stmt (par_exit_bb))))
636 gimple ws_stmt = last_stmt (ws_entry_bb);
638 if (region->inner->type == GIMPLE_OMP_FOR)
640 /* If this is a combined parallel loop, we need to determine
641 whether or not to use the combined library calls. There
642 are two cases where we do not apply the transformation:
643 static loops and any kind of ordered loop. In the first
644 case, we already open code the loop so there is no need
645 to do anything else. In the latter case, the combined
646 parallel loop call would still need extra synchronization
647 to implement ordered semantics, so there would not be any
648 gain in using the combined call. */
649 tree clauses = gimple_omp_for_clauses (ws_stmt);
650 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
651 if (c == NULL
652 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
653 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
655 region->is_combined_parallel = false;
656 region->inner->is_combined_parallel = false;
657 return;
661 region->is_combined_parallel = true;
662 region->inner->is_combined_parallel = true;
663 region->ws_args = get_ws_args_for (ws_stmt);
668 /* Return true if EXPR is variable sized. */
670 static inline bool
671 is_variable_sized (const_tree expr)
673 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
676 /* Return true if DECL is a reference type. */
678 static inline bool
679 is_reference (tree decl)
681 return lang_hooks.decls.omp_privatize_by_reference (decl);
684 /* Lookup variables in the decl or field splay trees. The "maybe" form
685 allows for the variable form to not have been entered, otherwise we
686 assert that the variable must have been entered. */
688 static inline tree
689 lookup_decl (tree var, omp_context *ctx)
691 tree *n;
692 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
693 return *n;
696 static inline tree
697 maybe_lookup_decl (const_tree var, omp_context *ctx)
699 tree *n;
700 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
701 return n ? *n : NULL_TREE;
704 static inline tree
705 lookup_field (tree var, omp_context *ctx)
707 splay_tree_node n;
708 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
709 return (tree) n->value;
712 static inline tree
713 lookup_sfield (tree var, omp_context *ctx)
715 splay_tree_node n;
716 n = splay_tree_lookup (ctx->sfield_map
717 ? ctx->sfield_map : ctx->field_map,
718 (splay_tree_key) var);
719 return (tree) n->value;
722 static inline tree
723 maybe_lookup_field (tree var, omp_context *ctx)
725 splay_tree_node n;
726 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
727 return n ? (tree) n->value : NULL_TREE;
730 /* Return true if DECL should be copied by pointer. SHARED_CTX is
731 the parallel context if DECL is to be shared. */
733 static bool
734 use_pointer_for_field (tree decl, omp_context *shared_ctx)
736 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
737 return true;
739 /* We can only use copy-in/copy-out semantics for shared variables
740 when we know the value is not accessible from an outer scope. */
741 if (shared_ctx)
743 /* ??? Trivially accessible from anywhere. But why would we even
744 be passing an address in this case? Should we simply assert
745 this to be false, or should we have a cleanup pass that removes
746 these from the list of mappings? */
747 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
748 return true;
750 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
751 without analyzing the expression whether or not its location
752 is accessible to anyone else. In the case of nested parallel
753 regions it certainly may be. */
754 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
755 return true;
757 /* Do not use copy-in/copy-out for variables that have their
758 address taken. */
759 if (TREE_ADDRESSABLE (decl))
760 return true;
762 /* Disallow copy-in/out in nested parallel if
763 decl is shared in outer parallel, otherwise
764 each thread could store the shared variable
765 in its own copy-in location, making the
766 variable no longer really shared. */
767 if (!TREE_READONLY (decl) && shared_ctx->is_nested)
769 omp_context *up;
771 for (up = shared_ctx->outer; up; up = up->outer)
772 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
773 break;
775 if (up)
777 tree c;
779 for (c = gimple_omp_taskreg_clauses (up->stmt);
780 c; c = OMP_CLAUSE_CHAIN (c))
781 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
782 && OMP_CLAUSE_DECL (c) == decl)
783 break;
785 if (c)
786 goto maybe_mark_addressable_and_ret;
790 /* For tasks avoid using copy-in/out, unless they are readonly
791 (in which case just copy-in is used). As tasks can be
792 deferred or executed in different thread, when GOMP_task
793 returns, the task hasn't necessarily terminated. */
794 if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
796 tree outer;
797 maybe_mark_addressable_and_ret:
798 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
799 if (is_gimple_reg (outer))
801 /* Taking address of OUTER in lower_send_shared_vars
802 might need regimplification of everything that uses the
803 variable. */
804 if (!task_shared_vars)
805 task_shared_vars = BITMAP_ALLOC (NULL);
806 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
807 TREE_ADDRESSABLE (outer) = 1;
809 return true;
813 return false;
816 /* Create a new VAR_DECL and copy information from VAR to it. */
818 tree
819 copy_var_decl (tree var, tree name, tree type)
821 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
823 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
824 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
825 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
826 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
827 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
828 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
829 TREE_USED (copy) = 1;
830 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
832 return copy;
835 /* Construct a new automatic decl similar to VAR. */
837 static tree
838 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
840 tree copy = copy_var_decl (var, name, type);
842 DECL_CONTEXT (copy) = current_function_decl;
843 DECL_CHAIN (copy) = ctx->block_vars;
844 ctx->block_vars = copy;
846 return copy;
849 static tree
850 omp_copy_decl_1 (tree var, omp_context *ctx)
852 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
855 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
856 as appropriate. */
857 static tree
858 omp_build_component_ref (tree obj, tree field)
860 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
861 if (TREE_THIS_VOLATILE (field))
862 TREE_THIS_VOLATILE (ret) |= 1;
863 if (TREE_READONLY (field))
864 TREE_READONLY (ret) |= 1;
865 return ret;
868 /* Build tree nodes to access the field for VAR on the receiver side. */
870 static tree
871 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
873 tree x, field = lookup_field (var, ctx);
875 /* If the receiver record type was remapped in the child function,
876 remap the field into the new record type. */
877 x = maybe_lookup_field (field, ctx);
878 if (x != NULL)
879 field = x;
881 x = build_simple_mem_ref (ctx->receiver_decl);
882 x = omp_build_component_ref (x, field);
883 if (by_ref)
884 x = build_simple_mem_ref (x);
886 return x;
889 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
890 of a parallel, this is a component reference; for workshare constructs
891 this is some variable. */
893 static tree
894 build_outer_var_ref (tree var, omp_context *ctx)
896 tree x;
898 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
899 x = var;
900 else if (is_variable_sized (var))
902 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
903 x = build_outer_var_ref (x, ctx);
904 x = build_simple_mem_ref (x);
906 else if (is_taskreg_ctx (ctx))
908 bool by_ref = use_pointer_for_field (var, NULL);
909 x = build_receiver_ref (var, by_ref, ctx);
911 else if (ctx->outer)
912 x = lookup_decl (var, ctx->outer);
913 else if (is_reference (var))
914 /* This can happen with orphaned constructs. If var is reference, it is
915 possible it is shared and as such valid. */
916 x = var;
917 else
918 gcc_unreachable ();
920 if (is_reference (var))
921 x = build_simple_mem_ref (x);
923 return x;
926 /* Build tree nodes to access the field for VAR on the sender side. */
928 static tree
929 build_sender_ref (tree var, omp_context *ctx)
931 tree field = lookup_sfield (var, ctx);
932 return omp_build_component_ref (ctx->sender_decl, field);
935 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
937 static void
938 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
940 tree field, type, sfield = NULL_TREE;
942 gcc_assert ((mask & 1) == 0
943 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
944 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
945 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
947 type = TREE_TYPE (var);
948 if (by_ref)
949 type = build_pointer_type (type);
950 else if ((mask & 3) == 1 && is_reference (var))
951 type = TREE_TYPE (type);
953 field = build_decl (DECL_SOURCE_LOCATION (var),
954 FIELD_DECL, DECL_NAME (var), type);
956 /* Remember what variable this field was created for. This does have a
957 side effect of making dwarf2out ignore this member, so for helpful
958 debugging we clear it later in delete_omp_context. */
959 DECL_ABSTRACT_ORIGIN (field) = var;
960 if (type == TREE_TYPE (var))
962 DECL_ALIGN (field) = DECL_ALIGN (var);
963 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
964 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
966 else
967 DECL_ALIGN (field) = TYPE_ALIGN (type);
969 if ((mask & 3) == 3)
971 insert_field_into_struct (ctx->record_type, field);
972 if (ctx->srecord_type)
974 sfield = build_decl (DECL_SOURCE_LOCATION (var),
975 FIELD_DECL, DECL_NAME (var), type);
976 DECL_ABSTRACT_ORIGIN (sfield) = var;
977 DECL_ALIGN (sfield) = DECL_ALIGN (field);
978 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
979 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
980 insert_field_into_struct (ctx->srecord_type, sfield);
983 else
985 if (ctx->srecord_type == NULL_TREE)
987 tree t;
989 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
990 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
991 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
993 sfield = build_decl (DECL_SOURCE_LOCATION (var),
994 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
995 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
996 insert_field_into_struct (ctx->srecord_type, sfield);
997 splay_tree_insert (ctx->sfield_map,
998 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
999 (splay_tree_value) sfield);
1002 sfield = field;
1003 insert_field_into_struct ((mask & 1) ? ctx->record_type
1004 : ctx->srecord_type, field);
1007 if (mask & 1)
1008 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1009 (splay_tree_value) field);
1010 if ((mask & 2) && ctx->sfield_map)
1011 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1012 (splay_tree_value) sfield);
1015 static tree
1016 install_var_local (tree var, omp_context *ctx)
1018 tree new_var = omp_copy_decl_1 (var, ctx);
1019 insert_decl_map (&ctx->cb, var, new_var);
1020 return new_var;
1023 /* Adjust the replacement for DECL in CTX for the new context. This means
1024 copying the DECL_VALUE_EXPR, and fixing up the type. */
1026 static void
1027 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1029 tree new_decl, size;
1031 new_decl = lookup_decl (decl, ctx);
1033 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1035 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1036 && DECL_HAS_VALUE_EXPR_P (decl))
1038 tree ve = DECL_VALUE_EXPR (decl);
1039 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1040 SET_DECL_VALUE_EXPR (new_decl, ve);
1041 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1044 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1046 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1047 if (size == error_mark_node)
1048 size = TYPE_SIZE (TREE_TYPE (new_decl));
1049 DECL_SIZE (new_decl) = size;
1051 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1052 if (size == error_mark_node)
1053 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1054 DECL_SIZE_UNIT (new_decl) = size;
1058 /* The callback for remap_decl. Search all containing contexts for a
1059 mapping of the variable; this avoids having to duplicate the splay
1060 tree ahead of time. We know a mapping doesn't already exist in the
1061 given context. Create new mappings to implement default semantics. */
1063 static tree
1064 omp_copy_decl (tree var, copy_body_data *cb)
1066 omp_context *ctx = (omp_context *) cb;
1067 tree new_var;
1069 if (TREE_CODE (var) == LABEL_DECL)
1071 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1072 DECL_CONTEXT (new_var) = current_function_decl;
1073 insert_decl_map (&ctx->cb, var, new_var);
1074 return new_var;
1077 while (!is_taskreg_ctx (ctx))
1079 ctx = ctx->outer;
1080 if (ctx == NULL)
1081 return var;
1082 new_var = maybe_lookup_decl (var, ctx);
1083 if (new_var)
1084 return new_var;
1087 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1088 return var;
1090 return error_mark_node;
1094 /* Return the parallel region associated with STMT. */
1096 /* Debugging dumps for parallel regions. */
1097 void dump_omp_region (FILE *, struct omp_region *, int);
1098 void debug_omp_region (struct omp_region *);
1099 void debug_all_omp_regions (void);
1101 /* Dump the parallel region tree rooted at REGION. */
1103 void
1104 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1106 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1107 gimple_code_name[region->type]);
1109 if (region->inner)
1110 dump_omp_region (file, region->inner, indent + 4);
1112 if (region->cont)
1114 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1115 region->cont->index);
1118 if (region->exit)
1119 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1120 region->exit->index);
1121 else
1122 fprintf (file, "%*s[no exit marker]\n", indent, "");
1124 if (region->next)
1125 dump_omp_region (file, region->next, indent);
1128 DEBUG_FUNCTION void
1129 debug_omp_region (struct omp_region *region)
1131 dump_omp_region (stderr, region, 0);
1134 DEBUG_FUNCTION void
1135 debug_all_omp_regions (void)
1137 dump_omp_region (stderr, root_omp_region, 0);
1141 /* Create a new parallel region starting at STMT inside region PARENT. */
1143 struct omp_region *
1144 new_omp_region (basic_block bb, enum gimple_code type,
1145 struct omp_region *parent)
1147 struct omp_region *region = XCNEW (struct omp_region);
1149 region->outer = parent;
1150 region->entry = bb;
1151 region->type = type;
1153 if (parent)
1155 /* This is a nested region. Add it to the list of inner
1156 regions in PARENT. */
1157 region->next = parent->inner;
1158 parent->inner = region;
1160 else
1162 /* This is a toplevel region. Add it to the list of toplevel
1163 regions in ROOT_OMP_REGION. */
1164 region->next = root_omp_region;
1165 root_omp_region = region;
1168 return region;
1171 /* Release the memory associated with the region tree rooted at REGION. */
1173 static void
1174 free_omp_region_1 (struct omp_region *region)
1176 struct omp_region *i, *n;
1178 for (i = region->inner; i ; i = n)
1180 n = i->next;
1181 free_omp_region_1 (i);
1184 free (region);
1187 /* Release the memory for the entire omp region tree. */
1189 void
1190 free_omp_regions (void)
1192 struct omp_region *r, *n;
1193 for (r = root_omp_region; r ; r = n)
1195 n = r->next;
1196 free_omp_region_1 (r);
1198 root_omp_region = NULL;
1202 /* Create a new context, with OUTER_CTX being the surrounding context. */
1204 static omp_context *
1205 new_omp_context (gimple stmt, omp_context *outer_ctx)
1207 omp_context *ctx = XCNEW (omp_context);
1209 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1210 (splay_tree_value) ctx);
1211 ctx->stmt = stmt;
1213 if (outer_ctx)
1215 ctx->outer = outer_ctx;
1216 ctx->cb = outer_ctx->cb;
1217 ctx->cb.block = NULL;
1218 ctx->depth = outer_ctx->depth + 1;
1220 else
1222 ctx->cb.src_fn = current_function_decl;
1223 ctx->cb.dst_fn = current_function_decl;
1224 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1225 gcc_checking_assert (ctx->cb.src_node);
1226 ctx->cb.dst_node = ctx->cb.src_node;
1227 ctx->cb.src_cfun = cfun;
1228 ctx->cb.copy_decl = omp_copy_decl;
1229 ctx->cb.eh_lp_nr = 0;
1230 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1231 ctx->depth = 1;
1234 ctx->cb.decl_map = pointer_map_create ();
1236 return ctx;
1239 static gimple_seq maybe_catch_exception (gimple_seq);
1241 /* Finalize task copyfn. */
1243 static void
1244 finalize_task_copyfn (gimple task_stmt)
1246 struct function *child_cfun;
1247 tree child_fn, old_fn;
1248 gimple_seq seq = NULL, new_seq;
1249 gimple bind;
1251 child_fn = gimple_omp_task_copy_fn (task_stmt);
1252 if (child_fn == NULL_TREE)
1253 return;
1255 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1257 /* Inform the callgraph about the new function. */
1258 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
1259 = cfun->curr_properties & ~PROP_loops;
1261 old_fn = current_function_decl;
1262 push_cfun (child_cfun);
1263 current_function_decl = child_fn;
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 ();
1275 current_function_decl = old_fn;
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,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,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 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3058 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
3060 if (gimple_in_ssa_p (cfun))
3062 gimple phi = create_phi_node (tmp_join, bb);
3063 SSA_NAME_DEF_STMT (tmp_join) = phi;
3064 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3065 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
3068 val = tmp_join;
3071 gsi = gsi_start_bb (bb);
3072 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3073 false, GSI_CONTINUE_LINKING);
3076 gsi = gsi_last_bb (bb);
3077 t = gimple_omp_parallel_data_arg (entry_stmt);
3078 if (t == NULL)
3079 t1 = null_pointer_node;
3080 else
3081 t1 = build_fold_addr_expr (t);
3082 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
3084 args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args));
3085 VEC_quick_push (tree, args, t2);
3086 VEC_quick_push (tree, args, t1);
3087 VEC_quick_push (tree, args, val);
3088 VEC_splice (tree, args, ws_args);
3090 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
3091 builtin_decl_explicit (start_ix), args);
3093 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3094 false, GSI_CONTINUE_LINKING);
3096 t = gimple_omp_parallel_data_arg (entry_stmt);
3097 if (t == NULL)
3098 t = null_pointer_node;
3099 else
3100 t = build_fold_addr_expr (t);
3101 t = build_call_expr_loc (gimple_location (entry_stmt),
3102 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3103 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3104 false, GSI_CONTINUE_LINKING);
3106 t = build_call_expr_loc (gimple_location (entry_stmt),
3107 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3109 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3110 false, GSI_CONTINUE_LINKING);
3114 /* Build the function call to GOMP_task to actually
3115 generate the task operation. BB is the block where to insert the code. */
3117 static void
3118 expand_task_call (basic_block bb, gimple entry_stmt)
3120 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
3121 gimple_stmt_iterator gsi;
3122 location_t loc = gimple_location (entry_stmt);
3124 clauses = gimple_omp_task_clauses (entry_stmt);
3126 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3127 if (c)
3128 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3129 else
3130 cond = boolean_true_node;
3132 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3133 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3134 flags = build_int_cst (unsigned_type_node,
3135 (c ? 1 : 0) + (c2 ? 4 : 0));
3137 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3138 if (c)
3140 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3141 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3142 build_int_cst (unsigned_type_node, 2),
3143 build_int_cst (unsigned_type_node, 0));
3144 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3147 gsi = gsi_last_bb (bb);
3148 t = gimple_omp_task_data_arg (entry_stmt);
3149 if (t == NULL)
3150 t2 = null_pointer_node;
3151 else
3152 t2 = build_fold_addr_expr_loc (loc, t);
3153 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
3154 t = gimple_omp_task_copy_fn (entry_stmt);
3155 if (t == NULL)
3156 t3 = null_pointer_node;
3157 else
3158 t3 = build_fold_addr_expr_loc (loc, t);
3160 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3161 7, t1, t2, t3,
3162 gimple_omp_task_arg_size (entry_stmt),
3163 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3165 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3166 false, GSI_CONTINUE_LINKING);
3170 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3171 catch handler and return it. This prevents programs from violating the
3172 structured block semantics with throws. */
3174 static gimple_seq
3175 maybe_catch_exception (gimple_seq body)
3177 gimple g;
3178 tree decl;
3180 if (!flag_exceptions)
3181 return body;
3183 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3184 decl = lang_hooks.eh_protect_cleanup_actions ();
3185 else
3186 decl = builtin_decl_explicit (BUILT_IN_TRAP);
3188 g = gimple_build_eh_must_not_throw (decl);
3189 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
3190 GIMPLE_TRY_CATCH);
3192 return gimple_seq_alloc_with_stmt (g);
3195 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3197 static tree
3198 vec2chain (VEC(tree,gc) *v)
3200 tree chain = NULL_TREE, t;
3201 unsigned ix;
3203 FOR_EACH_VEC_ELT_REVERSE (tree, v, ix, t)
3205 DECL_CHAIN (t) = chain;
3206 chain = t;
3209 return chain;
3213 /* Remove barriers in REGION->EXIT's block. Note that this is only
3214 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3215 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3216 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3217 removed. */
3219 static void
3220 remove_exit_barrier (struct omp_region *region)
3222 gimple_stmt_iterator gsi;
3223 basic_block exit_bb;
3224 edge_iterator ei;
3225 edge e;
3226 gimple stmt;
3227 int any_addressable_vars = -1;
3229 exit_bb = region->exit;
3231 /* If the parallel region doesn't return, we don't have REGION->EXIT
3232 block at all. */
3233 if (! exit_bb)
3234 return;
3236 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3237 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3238 statements that can appear in between are extremely limited -- no
3239 memory operations at all. Here, we allow nothing at all, so the
3240 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3241 gsi = gsi_last_bb (exit_bb);
3242 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3243 gsi_prev (&gsi);
3244 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3245 return;
3247 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3249 gsi = gsi_last_bb (e->src);
3250 if (gsi_end_p (gsi))
3251 continue;
3252 stmt = gsi_stmt (gsi);
3253 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3254 && !gimple_omp_return_nowait_p (stmt))
3256 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3257 in many cases. If there could be tasks queued, the barrier
3258 might be needed to let the tasks run before some local
3259 variable of the parallel that the task uses as shared
3260 runs out of scope. The task can be spawned either
3261 from within current function (this would be easy to check)
3262 or from some function it calls and gets passed an address
3263 of such a variable. */
3264 if (any_addressable_vars < 0)
3266 gimple parallel_stmt = last_stmt (region->entry);
3267 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3268 tree local_decls, block, decl;
3269 unsigned ix;
3271 any_addressable_vars = 0;
3272 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3273 if (TREE_ADDRESSABLE (decl))
3275 any_addressable_vars = 1;
3276 break;
3278 for (block = gimple_block (stmt);
3279 !any_addressable_vars
3280 && block
3281 && TREE_CODE (block) == BLOCK;
3282 block = BLOCK_SUPERCONTEXT (block))
3284 for (local_decls = BLOCK_VARS (block);
3285 local_decls;
3286 local_decls = DECL_CHAIN (local_decls))
3287 if (TREE_ADDRESSABLE (local_decls))
3289 any_addressable_vars = 1;
3290 break;
3292 if (block == gimple_block (parallel_stmt))
3293 break;
3296 if (!any_addressable_vars)
3297 gimple_omp_return_set_nowait (stmt);
3302 static void
3303 remove_exit_barriers (struct omp_region *region)
3305 if (region->type == GIMPLE_OMP_PARALLEL)
3306 remove_exit_barrier (region);
3308 if (region->inner)
3310 region = region->inner;
3311 remove_exit_barriers (region);
3312 while (region->next)
3314 region = region->next;
3315 remove_exit_barriers (region);
3320 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3321 calls. These can't be declared as const functions, but
3322 within one parallel body they are constant, so they can be
3323 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3324 which are declared const. Similarly for task body, except
3325 that in untied task omp_get_thread_num () can change at any task
3326 scheduling point. */
3328 static void
3329 optimize_omp_library_calls (gimple entry_stmt)
3331 basic_block bb;
3332 gimple_stmt_iterator gsi;
3333 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3334 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3335 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3336 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
3337 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3338 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3339 OMP_CLAUSE_UNTIED) != NULL);
3341 FOR_EACH_BB (bb)
3342 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3344 gimple call = gsi_stmt (gsi);
3345 tree decl;
3347 if (is_gimple_call (call)
3348 && (decl = gimple_call_fndecl (call))
3349 && DECL_EXTERNAL (decl)
3350 && TREE_PUBLIC (decl)
3351 && DECL_INITIAL (decl) == NULL)
3353 tree built_in;
3355 if (DECL_NAME (decl) == thr_num_id)
3357 /* In #pragma omp task untied omp_get_thread_num () can change
3358 during the execution of the task region. */
3359 if (untied_task)
3360 continue;
3361 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3363 else if (DECL_NAME (decl) == num_thr_id)
3364 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3365 else
3366 continue;
3368 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3369 || gimple_call_num_args (call) != 0)
3370 continue;
3372 if (flag_exceptions && !TREE_NOTHROW (decl))
3373 continue;
3375 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3376 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3377 TREE_TYPE (TREE_TYPE (built_in))))
3378 continue;
3380 gimple_call_set_fndecl (call, built_in);
3385 /* Expand the OpenMP parallel or task directive starting at REGION. */
3387 static void
3388 expand_omp_taskreg (struct omp_region *region)
3390 basic_block entry_bb, exit_bb, new_bb;
3391 struct function *child_cfun;
3392 tree child_fn, block, t;
3393 tree save_current;
3394 gimple_stmt_iterator gsi;
3395 gimple entry_stmt, stmt;
3396 edge e;
3397 VEC(tree,gc) *ws_args;
3399 entry_stmt = last_stmt (region->entry);
3400 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3401 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3402 /* If this function has been already instrumented, make sure
3403 the child function isn't instrumented again. */
3404 child_cfun->after_tree_profile = cfun->after_tree_profile;
3406 entry_bb = region->entry;
3407 exit_bb = region->exit;
3409 if (is_combined_parallel (region))
3410 ws_args = region->ws_args;
3411 else
3412 ws_args = NULL;
3414 if (child_cfun->cfg)
3416 /* Due to inlining, it may happen that we have already outlined
3417 the region, in which case all we need to do is make the
3418 sub-graph unreachable and emit the parallel call. */
3419 edge entry_succ_e, exit_succ_e;
3420 gimple_stmt_iterator gsi;
3422 entry_succ_e = single_succ_edge (entry_bb);
3424 gsi = gsi_last_bb (entry_bb);
3425 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3426 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3427 gsi_remove (&gsi, true);
3429 new_bb = entry_bb;
3430 if (exit_bb)
3432 exit_succ_e = single_succ_edge (exit_bb);
3433 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3435 remove_edge_and_dominated_blocks (entry_succ_e);
3437 else
3439 unsigned srcidx, dstidx, num;
3441 /* If the parallel region needs data sent from the parent
3442 function, then the very first statement (except possible
3443 tree profile counter updates) of the parallel body
3444 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3445 &.OMP_DATA_O is passed as an argument to the child function,
3446 we need to replace it with the argument as seen by the child
3447 function.
3449 In most cases, this will end up being the identity assignment
3450 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3451 a function call that has been inlined, the original PARM_DECL
3452 .OMP_DATA_I may have been converted into a different local
3453 variable. In which case, we need to keep the assignment. */
3454 if (gimple_omp_taskreg_data_arg (entry_stmt))
3456 basic_block entry_succ_bb = single_succ (entry_bb);
3457 gimple_stmt_iterator gsi;
3458 tree arg, narg;
3459 gimple parcopy_stmt = NULL;
3461 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3463 gimple stmt;
3465 gcc_assert (!gsi_end_p (gsi));
3466 stmt = gsi_stmt (gsi);
3467 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3468 continue;
3470 if (gimple_num_ops (stmt) == 2)
3472 tree arg = gimple_assign_rhs1 (stmt);
3474 /* We're ignore the subcode because we're
3475 effectively doing a STRIP_NOPS. */
3477 if (TREE_CODE (arg) == ADDR_EXPR
3478 && TREE_OPERAND (arg, 0)
3479 == gimple_omp_taskreg_data_arg (entry_stmt))
3481 parcopy_stmt = stmt;
3482 break;
3487 gcc_assert (parcopy_stmt != NULL);
3488 arg = DECL_ARGUMENTS (child_fn);
3490 if (!gimple_in_ssa_p (cfun))
3492 if (gimple_assign_lhs (parcopy_stmt) == arg)
3493 gsi_remove (&gsi, true);
3494 else
3496 /* ?? Is setting the subcode really necessary ?? */
3497 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3498 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3501 else
3503 /* If we are in ssa form, we must load the value from the default
3504 definition of the argument. That should not be defined now,
3505 since the argument is not used uninitialized. */
3506 gcc_assert (gimple_default_def (cfun, arg) == NULL);
3507 narg = make_ssa_name (arg, gimple_build_nop ());
3508 set_default_def (arg, narg);
3509 /* ?? Is setting the subcode really necessary ?? */
3510 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3511 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3512 update_stmt (parcopy_stmt);
3516 /* Declare local variables needed in CHILD_CFUN. */
3517 block = DECL_INITIAL (child_fn);
3518 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
3519 /* The gimplifier could record temporaries in parallel/task block
3520 rather than in containing function's local_decls chain,
3521 which would mean cgraph missed finalizing them. Do it now. */
3522 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
3523 if (TREE_CODE (t) == VAR_DECL
3524 && TREE_STATIC (t)
3525 && !DECL_EXTERNAL (t))
3526 varpool_finalize_decl (t);
3527 DECL_SAVED_TREE (child_fn) = NULL;
3528 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3529 gimple_set_body (child_fn, NULL);
3530 TREE_USED (block) = 1;
3532 /* Reset DECL_CONTEXT on function arguments. */
3533 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
3534 DECL_CONTEXT (t) = child_fn;
3536 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3537 so that it can be moved to the child function. */
3538 gsi = gsi_last_bb (entry_bb);
3539 stmt = gsi_stmt (gsi);
3540 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3541 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3542 gsi_remove (&gsi, true);
3543 e = split_block (entry_bb, stmt);
3544 entry_bb = e->dest;
3545 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3547 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3548 if (exit_bb)
3550 gsi = gsi_last_bb (exit_bb);
3551 gcc_assert (!gsi_end_p (gsi)
3552 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3553 stmt = gimple_build_return (NULL);
3554 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3555 gsi_remove (&gsi, true);
3558 /* Move the parallel region into CHILD_CFUN. */
3560 if (gimple_in_ssa_p (cfun))
3562 init_tree_ssa (child_cfun);
3563 init_ssa_operands (child_cfun);
3564 child_cfun->gimple_df->in_ssa_p = true;
3565 block = NULL_TREE;
3567 else
3568 block = gimple_block (entry_stmt);
3570 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3571 if (exit_bb)
3572 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3574 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3575 num = VEC_length (tree, child_cfun->local_decls);
3576 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3578 t = VEC_index (tree, child_cfun->local_decls, srcidx);
3579 if (DECL_CONTEXT (t) == cfun->decl)
3580 continue;
3581 if (srcidx != dstidx)
3582 VEC_replace (tree, child_cfun->local_decls, dstidx, t);
3583 dstidx++;
3585 if (dstidx != num)
3586 VEC_truncate (tree, child_cfun->local_decls, dstidx);
3588 /* Inform the callgraph about the new function. */
3589 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
3590 = cfun->curr_properties & ~PROP_loops;
3591 cgraph_add_new_function (child_fn, true);
3593 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3594 fixed in a following pass. */
3595 push_cfun (child_cfun);
3596 save_current = current_function_decl;
3597 current_function_decl = child_fn;
3598 if (optimize)
3599 optimize_omp_library_calls (entry_stmt);
3600 rebuild_cgraph_edges ();
3602 /* Some EH regions might become dead, see PR34608. If
3603 pass_cleanup_cfg isn't the first pass to happen with the
3604 new child, these dead EH edges might cause problems.
3605 Clean them up now. */
3606 if (flag_exceptions)
3608 basic_block bb;
3609 bool changed = false;
3611 FOR_EACH_BB (bb)
3612 changed |= gimple_purge_dead_eh_edges (bb);
3613 if (changed)
3614 cleanup_tree_cfg ();
3616 if (gimple_in_ssa_p (cfun))
3617 update_ssa (TODO_update_ssa);
3618 current_function_decl = save_current;
3619 pop_cfun ();
3622 /* Emit a library call to launch the children threads. */
3623 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
3624 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3625 else
3626 expand_task_call (new_bb, entry_stmt);
3627 if (gimple_in_ssa_p (cfun))
3628 update_ssa (TODO_update_ssa_only_virtuals);
3632 /* A subroutine of expand_omp_for. Generate code for a parallel
3633 loop with any schedule. Given parameters:
3635 for (V = N1; V cond N2; V += STEP) BODY;
3637 where COND is "<" or ">", we generate pseudocode
3639 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3640 if (more) goto L0; else goto L3;
3642 V = istart0;
3643 iend = iend0;
3645 BODY;
3646 V += STEP;
3647 if (V cond iend) goto L1; else goto L2;
3649 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3652 If this is a combined omp parallel loop, instead of the call to
3653 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3655 For collapsed loops, given parameters:
3656 collapse(3)
3657 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3658 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3659 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3660 BODY;
3662 we generate pseudocode
3664 if (cond3 is <)
3665 adj = STEP3 - 1;
3666 else
3667 adj = STEP3 + 1;
3668 count3 = (adj + N32 - N31) / STEP3;
3669 if (cond2 is <)
3670 adj = STEP2 - 1;
3671 else
3672 adj = STEP2 + 1;
3673 count2 = (adj + N22 - N21) / STEP2;
3674 if (cond1 is <)
3675 adj = STEP1 - 1;
3676 else
3677 adj = STEP1 + 1;
3678 count1 = (adj + N12 - N11) / STEP1;
3679 count = count1 * count2 * count3;
3680 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3681 if (more) goto L0; else goto L3;
3683 V = istart0;
3684 T = V;
3685 V3 = N31 + (T % count3) * STEP3;
3686 T = T / count3;
3687 V2 = N21 + (T % count2) * STEP2;
3688 T = T / count2;
3689 V1 = N11 + T * STEP1;
3690 iend = iend0;
3692 BODY;
3693 V += 1;
3694 if (V < iend) goto L10; else goto L2;
3695 L10:
3696 V3 += STEP3;
3697 if (V3 cond3 N32) goto L1; else goto L11;
3698 L11:
3699 V3 = N31;
3700 V2 += STEP2;
3701 if (V2 cond2 N22) goto L1; else goto L12;
3702 L12:
3703 V2 = N21;
3704 V1 += STEP1;
3705 goto L1;
3707 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3712 static void
3713 expand_omp_for_generic (struct omp_region *region,
3714 struct omp_for_data *fd,
3715 enum built_in_function start_fn,
3716 enum built_in_function next_fn)
3718 tree type, istart0, iend0, iend;
3719 tree t, vmain, vback, bias = NULL_TREE;
3720 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3721 basic_block l2_bb = NULL, l3_bb = NULL;
3722 gimple_stmt_iterator gsi;
3723 gimple stmt;
3724 bool in_combined_parallel = is_combined_parallel (region);
3725 bool broken_loop = region->cont == NULL;
3726 edge e, ne;
3727 tree *counts = NULL;
3728 int i;
3730 gcc_assert (!broken_loop || !in_combined_parallel);
3731 gcc_assert (fd->iter_type == long_integer_type_node
3732 || !in_combined_parallel);
3734 type = TREE_TYPE (fd->loop.v);
3735 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3736 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3737 TREE_ADDRESSABLE (istart0) = 1;
3738 TREE_ADDRESSABLE (iend0) = 1;
3739 if (gimple_referenced_vars (cfun))
3741 add_referenced_var (istart0);
3742 add_referenced_var (iend0);
3745 /* See if we need to bias by LLONG_MIN. */
3746 if (fd->iter_type == long_long_unsigned_type_node
3747 && TREE_CODE (type) == INTEGER_TYPE
3748 && !TYPE_UNSIGNED (type))
3750 tree n1, n2;
3752 if (fd->loop.cond_code == LT_EXPR)
3754 n1 = fd->loop.n1;
3755 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3757 else
3759 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3760 n2 = fd->loop.n1;
3762 if (TREE_CODE (n1) != INTEGER_CST
3763 || TREE_CODE (n2) != INTEGER_CST
3764 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3765 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3768 entry_bb = region->entry;
3769 cont_bb = region->cont;
3770 collapse_bb = NULL;
3771 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3772 gcc_assert (broken_loop
3773 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3774 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3775 l1_bb = single_succ (l0_bb);
3776 if (!broken_loop)
3778 l2_bb = create_empty_bb (cont_bb);
3779 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3780 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3782 else
3783 l2_bb = NULL;
3784 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3785 exit_bb = region->exit;
3787 gsi = gsi_last_bb (entry_bb);
3789 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
3790 if (fd->collapse > 1)
3792 /* collapsed loops need work for expansion in SSA form. */
3793 gcc_assert (!gimple_in_ssa_p (cfun));
3794 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3795 for (i = 0; i < fd->collapse; i++)
3797 tree itype = TREE_TYPE (fd->loops[i].v);
3799 if (POINTER_TYPE_P (itype))
3800 itype = signed_type_for (itype);
3801 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3802 ? -1 : 1));
3803 t = fold_build2 (PLUS_EXPR, itype,
3804 fold_convert (itype, fd->loops[i].step), t);
3805 t = fold_build2 (PLUS_EXPR, itype, t,
3806 fold_convert (itype, fd->loops[i].n2));
3807 t = fold_build2 (MINUS_EXPR, itype, t,
3808 fold_convert (itype, fd->loops[i].n1));
3809 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3810 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3811 fold_build1 (NEGATE_EXPR, itype, t),
3812 fold_build1 (NEGATE_EXPR, itype,
3813 fold_convert (itype,
3814 fd->loops[i].step)));
3815 else
3816 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3817 fold_convert (itype, fd->loops[i].step));
3818 t = fold_convert (type, t);
3819 if (TREE_CODE (t) == INTEGER_CST)
3820 counts[i] = t;
3821 else
3823 counts[i] = make_rename_temp (type, ".count");
3824 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3825 true, GSI_SAME_STMT);
3826 stmt = gimple_build_assign (counts[i], t);
3827 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3829 if (SSA_VAR_P (fd->loop.n2))
3831 if (i == 0)
3832 t = counts[0];
3833 else
3835 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3836 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3837 true, GSI_SAME_STMT);
3839 stmt = gimple_build_assign (fd->loop.n2, t);
3840 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3844 if (in_combined_parallel)
3846 /* In a combined parallel loop, emit a call to
3847 GOMP_loop_foo_next. */
3848 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
3849 build_fold_addr_expr (istart0),
3850 build_fold_addr_expr (iend0));
3852 else
3854 tree t0, t1, t2, t3, t4;
3855 /* If this is not a combined parallel loop, emit a call to
3856 GOMP_loop_foo_start in ENTRY_BB. */
3857 t4 = build_fold_addr_expr (iend0);
3858 t3 = build_fold_addr_expr (istart0);
3859 t2 = fold_convert (fd->iter_type, fd->loop.step);
3860 if (POINTER_TYPE_P (type)
3861 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
3863 /* Avoid casting pointers to integer of a different size. */
3864 tree itype = signed_type_for (type);
3865 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
3866 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
3868 else
3870 t1 = fold_convert (fd->iter_type, fd->loop.n2);
3871 t0 = fold_convert (fd->iter_type, fd->loop.n1);
3873 if (bias)
3875 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
3876 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
3878 if (fd->iter_type == long_integer_type_node)
3880 if (fd->chunk_size)
3882 t = fold_convert (fd->iter_type, fd->chunk_size);
3883 t = build_call_expr (builtin_decl_explicit (start_fn),
3884 6, t0, t1, t2, t, t3, t4);
3886 else
3887 t = build_call_expr (builtin_decl_explicit (start_fn),
3888 5, t0, t1, t2, t3, t4);
3890 else
3892 tree t5;
3893 tree c_bool_type;
3894 tree bfn_decl;
3896 /* The GOMP_loop_ull_*start functions have additional boolean
3897 argument, true for < loops and false for > loops.
3898 In Fortran, the C bool type can be different from
3899 boolean_type_node. */
3900 bfn_decl = builtin_decl_explicit (start_fn);
3901 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
3902 t5 = build_int_cst (c_bool_type,
3903 fd->loop.cond_code == LT_EXPR ? 1 : 0);
3904 if (fd->chunk_size)
3906 tree bfn_decl = builtin_decl_explicit (start_fn);
3907 t = fold_convert (fd->iter_type, fd->chunk_size);
3908 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
3910 else
3911 t = build_call_expr (builtin_decl_explicit (start_fn),
3912 6, t5, t0, t1, t2, t3, t4);
3915 if (TREE_TYPE (t) != boolean_type_node)
3916 t = fold_build2 (NE_EXPR, boolean_type_node,
3917 t, build_int_cst (TREE_TYPE (t), 0));
3918 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3919 true, GSI_SAME_STMT);
3920 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
3922 /* Remove the GIMPLE_OMP_FOR statement. */
3923 gsi_remove (&gsi, true);
3925 /* Iteration setup for sequential loop goes in L0_BB. */
3926 gsi = gsi_start_bb (l0_bb);
3927 t = istart0;
3928 if (bias)
3929 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3930 if (POINTER_TYPE_P (type))
3931 t = fold_convert (signed_type_for (type), t);
3932 t = fold_convert (type, t);
3933 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3934 false, GSI_CONTINUE_LINKING);
3935 stmt = gimple_build_assign (fd->loop.v, t);
3936 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3938 t = iend0;
3939 if (bias)
3940 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3941 if (POINTER_TYPE_P (type))
3942 t = fold_convert (signed_type_for (type), t);
3943 t = fold_convert (type, t);
3944 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3945 false, GSI_CONTINUE_LINKING);
3946 if (fd->collapse > 1)
3948 tree tem = make_rename_temp (type, ".tem");
3949 stmt = gimple_build_assign (tem, fd->loop.v);
3950 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3951 for (i = fd->collapse - 1; i >= 0; i--)
3953 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
3954 itype = vtype;
3955 if (POINTER_TYPE_P (vtype))
3956 itype = signed_type_for (vtype);
3957 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
3958 t = fold_convert (itype, t);
3959 t = fold_build2 (MULT_EXPR, itype, t,
3960 fold_convert (itype, fd->loops[i].step));
3961 if (POINTER_TYPE_P (vtype))
3962 t = fold_build_pointer_plus (fd->loops[i].n1, t);
3963 else
3964 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3965 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3966 false, GSI_CONTINUE_LINKING);
3967 stmt = gimple_build_assign (fd->loops[i].v, t);
3968 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3969 if (i != 0)
3971 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3972 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3973 false, GSI_CONTINUE_LINKING);
3974 stmt = gimple_build_assign (tem, t);
3975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3980 if (!broken_loop)
3982 /* Code to control the increment and predicate for the sequential
3983 loop goes in the CONT_BB. */
3984 gsi = gsi_last_bb (cont_bb);
3985 stmt = gsi_stmt (gsi);
3986 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
3987 vmain = gimple_omp_continue_control_use (stmt);
3988 vback = gimple_omp_continue_control_def (stmt);
3990 if (POINTER_TYPE_P (type))
3991 t = fold_build_pointer_plus (vmain, fd->loop.step);
3992 else
3993 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3994 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3995 true, GSI_SAME_STMT);
3996 stmt = gimple_build_assign (vback, t);
3997 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3999 t = build2 (fd->loop.cond_code, boolean_type_node, vback, iend);
4000 stmt = gimple_build_cond_empty (t);
4001 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4003 /* Remove GIMPLE_OMP_CONTINUE. */
4004 gsi_remove (&gsi, true);
4006 if (fd->collapse > 1)
4008 basic_block last_bb, bb;
4010 last_bb = cont_bb;
4011 for (i = fd->collapse - 1; i >= 0; i--)
4013 tree vtype = TREE_TYPE (fd->loops[i].v);
4015 bb = create_empty_bb (last_bb);
4016 gsi = gsi_start_bb (bb);
4018 if (i < fd->collapse - 1)
4020 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4021 e->probability = REG_BR_PROB_BASE / 8;
4023 t = fd->loops[i + 1].n1;
4024 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4025 false, GSI_CONTINUE_LINKING);
4026 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4027 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4029 else
4030 collapse_bb = bb;
4032 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4034 if (POINTER_TYPE_P (vtype))
4035 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4036 else
4037 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
4038 fd->loops[i].step);
4039 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4040 false, GSI_CONTINUE_LINKING);
4041 stmt = gimple_build_assign (fd->loops[i].v, t);
4042 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4044 if (i > 0)
4046 t = fd->loops[i].n2;
4047 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4048 false, GSI_CONTINUE_LINKING);
4049 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
4050 fd->loops[i].v, t);
4051 stmt = gimple_build_cond_empty (t);
4052 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4053 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
4054 e->probability = REG_BR_PROB_BASE * 7 / 8;
4056 else
4057 make_edge (bb, l1_bb, EDGE_FALLTHRU);
4058 last_bb = bb;
4062 /* Emit code to get the next parallel iteration in L2_BB. */
4063 gsi = gsi_start_bb (l2_bb);
4065 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4066 build_fold_addr_expr (istart0),
4067 build_fold_addr_expr (iend0));
4068 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4069 false, GSI_CONTINUE_LINKING);
4070 if (TREE_TYPE (t) != boolean_type_node)
4071 t = fold_build2 (NE_EXPR, boolean_type_node,
4072 t, build_int_cst (TREE_TYPE (t), 0));
4073 stmt = gimple_build_cond_empty (t);
4074 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4077 /* Add the loop cleanup function. */
4078 gsi = gsi_last_bb (exit_bb);
4079 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4080 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4081 else
4082 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4083 stmt = gimple_build_call (t, 0);
4084 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4085 gsi_remove (&gsi, true);
4087 /* Connect the new blocks. */
4088 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4089 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4091 if (!broken_loop)
4093 gimple_seq phis;
4095 e = find_edge (cont_bb, l3_bb);
4096 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4098 phis = phi_nodes (l3_bb);
4099 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4101 gimple phi = gsi_stmt (gsi);
4102 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4103 PHI_ARG_DEF_FROM_EDGE (phi, e));
4105 remove_edge (e);
4107 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4108 if (fd->collapse > 1)
4110 e = find_edge (cont_bb, l1_bb);
4111 remove_edge (e);
4112 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4114 else
4116 e = find_edge (cont_bb, l1_bb);
4117 e->flags = EDGE_TRUE_VALUE;
4119 e->probability = REG_BR_PROB_BASE * 7 / 8;
4120 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4121 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4123 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4124 recompute_dominator (CDI_DOMINATORS, l2_bb));
4125 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4126 recompute_dominator (CDI_DOMINATORS, l3_bb));
4127 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4128 recompute_dominator (CDI_DOMINATORS, l0_bb));
4129 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4130 recompute_dominator (CDI_DOMINATORS, l1_bb));
4135 /* A subroutine of expand_omp_for. Generate code for a parallel
4136 loop with static schedule and no specified chunk size. Given
4137 parameters:
4139 for (V = N1; V cond N2; V += STEP) BODY;
4141 where COND is "<" or ">", we generate pseudocode
4143 if (cond is <)
4144 adj = STEP - 1;
4145 else
4146 adj = STEP + 1;
4147 if ((__typeof (V)) -1 > 0 && cond is >)
4148 n = -(adj + N2 - N1) / -STEP;
4149 else
4150 n = (adj + N2 - N1) / STEP;
4151 q = n / nthreads;
4152 tt = n % nthreads;
4153 if (threadid < tt) goto L3; else goto L4;
4155 tt = 0;
4156 q = q + 1;
4158 s0 = q * threadid + tt;
4159 e0 = s0 + q;
4160 V = s0 * STEP + N1;
4161 if (s0 >= e0) goto L2; else goto L0;
4163 e = e0 * STEP + N1;
4165 BODY;
4166 V += STEP;
4167 if (V cond e) goto L1;
4171 static void
4172 expand_omp_for_static_nochunk (struct omp_region *region,
4173 struct omp_for_data *fd)
4175 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
4176 tree type, itype, vmain, vback;
4177 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4178 basic_block body_bb, cont_bb;
4179 basic_block fin_bb;
4180 gimple_stmt_iterator gsi;
4181 gimple stmt;
4182 edge ep;
4184 itype = type = TREE_TYPE (fd->loop.v);
4185 if (POINTER_TYPE_P (type))
4186 itype = signed_type_for (type);
4188 entry_bb = region->entry;
4189 cont_bb = region->cont;
4190 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4191 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4192 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4193 body_bb = single_succ (seq_start_bb);
4194 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4195 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4196 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4197 exit_bb = region->exit;
4199 /* Iteration space partitioning goes in ENTRY_BB. */
4200 gsi = gsi_last_bb (entry_bb);
4201 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4203 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4204 t = fold_convert (itype, t);
4205 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4206 true, GSI_SAME_STMT);
4208 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4209 t = fold_convert (itype, t);
4210 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4211 true, GSI_SAME_STMT);
4213 fd->loop.n1
4214 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4215 true, NULL_TREE, true, GSI_SAME_STMT);
4216 fd->loop.n2
4217 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4218 true, NULL_TREE, true, GSI_SAME_STMT);
4219 fd->loop.step
4220 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4221 true, NULL_TREE, true, GSI_SAME_STMT);
4223 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4224 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4225 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4226 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4227 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4228 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4229 fold_build1 (NEGATE_EXPR, itype, t),
4230 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4231 else
4232 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4233 t = fold_convert (itype, t);
4234 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4236 q = make_rename_temp (itype, "q");
4237 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4238 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4239 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4241 tt = make_rename_temp (itype, "tt");
4242 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4243 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4244 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
4246 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4247 stmt = gimple_build_cond_empty (t);
4248 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4250 second_bb = split_block (entry_bb, stmt)->dest;
4251 gsi = gsi_last_bb (second_bb);
4252 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4254 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4255 GSI_SAME_STMT);
4256 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4257 build_int_cst (itype, 1));
4258 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4260 third_bb = split_block (second_bb, stmt)->dest;
4261 gsi = gsi_last_bb (third_bb);
4262 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4264 t = build2 (MULT_EXPR, itype, q, threadid);
4265 t = build2 (PLUS_EXPR, itype, t, tt);
4266 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4268 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4269 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4271 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4272 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4274 /* Remove the GIMPLE_OMP_FOR statement. */
4275 gsi_remove (&gsi, true);
4277 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4278 gsi = gsi_start_bb (seq_start_bb);
4280 t = fold_convert (itype, s0);
4281 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4282 if (POINTER_TYPE_P (type))
4283 t = fold_build_pointer_plus (fd->loop.n1, t);
4284 else
4285 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4286 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4287 false, GSI_CONTINUE_LINKING);
4288 stmt = gimple_build_assign (fd->loop.v, t);
4289 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4291 t = fold_convert (itype, e0);
4292 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4293 if (POINTER_TYPE_P (type))
4294 t = fold_build_pointer_plus (fd->loop.n1, t);
4295 else
4296 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4297 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4298 false, GSI_CONTINUE_LINKING);
4300 /* The code controlling the sequential loop replaces the
4301 GIMPLE_OMP_CONTINUE. */
4302 gsi = gsi_last_bb (cont_bb);
4303 stmt = gsi_stmt (gsi);
4304 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4305 vmain = gimple_omp_continue_control_use (stmt);
4306 vback = gimple_omp_continue_control_def (stmt);
4308 if (POINTER_TYPE_P (type))
4309 t = fold_build_pointer_plus (vmain, fd->loop.step);
4310 else
4311 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4312 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4313 true, GSI_SAME_STMT);
4314 stmt = gimple_build_assign (vback, t);
4315 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4317 t = build2 (fd->loop.cond_code, boolean_type_node, vback, e);
4318 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4320 /* Remove the GIMPLE_OMP_CONTINUE statement. */
4321 gsi_remove (&gsi, true);
4323 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4324 gsi = gsi_last_bb (exit_bb);
4325 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4326 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
4327 false, GSI_SAME_STMT);
4328 gsi_remove (&gsi, true);
4330 /* Connect all the blocks. */
4331 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
4332 ep->probability = REG_BR_PROB_BASE / 4 * 3;
4333 ep = find_edge (entry_bb, second_bb);
4334 ep->flags = EDGE_TRUE_VALUE;
4335 ep->probability = REG_BR_PROB_BASE / 4;
4336 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
4337 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
4339 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4340 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4342 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
4343 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
4344 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
4345 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4346 recompute_dominator (CDI_DOMINATORS, body_bb));
4347 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4348 recompute_dominator (CDI_DOMINATORS, fin_bb));
4352 /* A subroutine of expand_omp_for. Generate code for a parallel
4353 loop with static schedule and a specified chunk size. Given
4354 parameters:
4356 for (V = N1; V cond N2; V += STEP) BODY;
4358 where COND is "<" or ">", we generate pseudocode
4360 if (cond is <)
4361 adj = STEP - 1;
4362 else
4363 adj = STEP + 1;
4364 if ((__typeof (V)) -1 > 0 && cond is >)
4365 n = -(adj + N2 - N1) / -STEP;
4366 else
4367 n = (adj + N2 - N1) / STEP;
4368 trip = 0;
4369 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4370 here so that V is defined
4371 if the loop is not entered
4373 s0 = (trip * nthreads + threadid) * CHUNK;
4374 e0 = min(s0 + CHUNK, n);
4375 if (s0 < n) goto L1; else goto L4;
4377 V = s0 * STEP + N1;
4378 e = e0 * STEP + N1;
4380 BODY;
4381 V += STEP;
4382 if (V cond e) goto L2; else goto L3;
4384 trip += 1;
4385 goto L0;
4389 static void
4390 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
4392 tree n, s0, e0, e, t;
4393 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4394 tree type, itype, v_main, v_back, v_extra;
4395 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4396 basic_block trip_update_bb, cont_bb, fin_bb;
4397 gimple_stmt_iterator si;
4398 gimple stmt;
4399 edge se;
4401 itype = type = TREE_TYPE (fd->loop.v);
4402 if (POINTER_TYPE_P (type))
4403 itype = signed_type_for (type);
4405 entry_bb = region->entry;
4406 se = split_block (entry_bb, last_stmt (entry_bb));
4407 entry_bb = se->src;
4408 iter_part_bb = se->dest;
4409 cont_bb = region->cont;
4410 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4411 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4412 == FALLTHRU_EDGE (cont_bb)->dest);
4413 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4414 body_bb = single_succ (seq_start_bb);
4415 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4416 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4417 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4418 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4419 exit_bb = region->exit;
4421 /* Trip and adjustment setup goes in ENTRY_BB. */
4422 si = gsi_last_bb (entry_bb);
4423 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
4425 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4426 t = fold_convert (itype, t);
4427 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4428 true, GSI_SAME_STMT);
4430 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4431 t = fold_convert (itype, t);
4432 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4433 true, GSI_SAME_STMT);
4435 fd->loop.n1
4436 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
4437 true, NULL_TREE, true, GSI_SAME_STMT);
4438 fd->loop.n2
4439 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
4440 true, NULL_TREE, true, GSI_SAME_STMT);
4441 fd->loop.step
4442 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
4443 true, NULL_TREE, true, GSI_SAME_STMT);
4444 fd->chunk_size
4445 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
4446 true, NULL_TREE, true, GSI_SAME_STMT);
4448 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4449 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4450 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4451 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4452 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4453 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4454 fold_build1 (NEGATE_EXPR, itype, t),
4455 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4456 else
4457 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4458 t = fold_convert (itype, t);
4459 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4460 true, GSI_SAME_STMT);
4462 trip_var = create_tmp_reg (itype, ".trip");
4463 if (gimple_in_ssa_p (cfun))
4465 add_referenced_var (trip_var);
4466 trip_init = make_ssa_name (trip_var, NULL);
4467 trip_main = make_ssa_name (trip_var, NULL);
4468 trip_back = make_ssa_name (trip_var, NULL);
4470 else
4472 trip_init = trip_var;
4473 trip_main = trip_var;
4474 trip_back = trip_var;
4477 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
4478 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4480 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4481 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4482 if (POINTER_TYPE_P (type))
4483 t = fold_build_pointer_plus (fd->loop.n1, t);
4484 else
4485 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4486 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4487 true, GSI_SAME_STMT);
4489 /* Remove the GIMPLE_OMP_FOR. */
4490 gsi_remove (&si, true);
4492 /* Iteration space partitioning goes in ITER_PART_BB. */
4493 si = gsi_last_bb (iter_part_bb);
4495 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4496 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4497 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4498 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4499 false, GSI_CONTINUE_LINKING);
4501 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4502 t = fold_build2 (MIN_EXPR, itype, t, n);
4503 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4504 false, GSI_CONTINUE_LINKING);
4506 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4507 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
4509 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4510 si = gsi_start_bb (seq_start_bb);
4512 t = fold_convert (itype, s0);
4513 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4514 if (POINTER_TYPE_P (type))
4515 t = fold_build_pointer_plus (fd->loop.n1, t);
4516 else
4517 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4518 t = force_gimple_operand_gsi (&si, t, false, NULL_TREE,
4519 false, GSI_CONTINUE_LINKING);
4520 stmt = gimple_build_assign (fd->loop.v, t);
4521 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4523 t = fold_convert (itype, e0);
4524 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4525 if (POINTER_TYPE_P (type))
4526 t = fold_build_pointer_plus (fd->loop.n1, t);
4527 else
4528 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4529 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4530 false, GSI_CONTINUE_LINKING);
4532 /* The code controlling the sequential loop goes in CONT_BB,
4533 replacing the GIMPLE_OMP_CONTINUE. */
4534 si = gsi_last_bb (cont_bb);
4535 stmt = gsi_stmt (si);
4536 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4537 v_main = gimple_omp_continue_control_use (stmt);
4538 v_back = gimple_omp_continue_control_def (stmt);
4540 if (POINTER_TYPE_P (type))
4541 t = fold_build_pointer_plus (v_main, fd->loop.step);
4542 else
4543 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4544 stmt = gimple_build_assign (v_back, t);
4545 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4547 t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
4548 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
4550 /* Remove GIMPLE_OMP_CONTINUE. */
4551 gsi_remove (&si, true);
4553 /* Trip update code goes into TRIP_UPDATE_BB. */
4554 si = gsi_start_bb (trip_update_bb);
4556 t = build_int_cst (itype, 1);
4557 t = build2 (PLUS_EXPR, itype, trip_main, t);
4558 stmt = gimple_build_assign (trip_back, t);
4559 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4561 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4562 si = gsi_last_bb (exit_bb);
4563 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
4564 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4565 false, GSI_SAME_STMT);
4566 gsi_remove (&si, true);
4568 /* Connect the new blocks. */
4569 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4570 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4572 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4573 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4575 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4577 if (gimple_in_ssa_p (cfun))
4579 gimple_stmt_iterator psi;
4580 gimple phi;
4581 edge re, ene;
4582 edge_var_map_vector head;
4583 edge_var_map *vm;
4584 size_t i;
4586 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4587 remove arguments of the phi nodes in fin_bb. We need to create
4588 appropriate phi nodes in iter_part_bb instead. */
4589 se = single_pred_edge (fin_bb);
4590 re = single_succ_edge (trip_update_bb);
4591 head = redirect_edge_var_map_vector (re);
4592 ene = single_succ_edge (entry_bb);
4594 psi = gsi_start_phis (fin_bb);
4595 for (i = 0; !gsi_end_p (psi) && VEC_iterate (edge_var_map, head, i, vm);
4596 gsi_next (&psi), ++i)
4598 gimple nphi;
4599 source_location locus;
4601 phi = gsi_stmt (psi);
4602 t = gimple_phi_result (phi);
4603 gcc_assert (t == redirect_edge_var_map_result (vm));
4604 nphi = create_phi_node (t, iter_part_bb);
4605 SSA_NAME_DEF_STMT (t) = nphi;
4607 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4608 locus = gimple_phi_arg_location_from_edge (phi, se);
4610 /* A special case -- fd->loop.v is not yet computed in
4611 iter_part_bb, we need to use v_extra instead. */
4612 if (t == fd->loop.v)
4613 t = v_extra;
4614 add_phi_arg (nphi, t, ene, locus);
4615 locus = redirect_edge_var_map_location (vm);
4616 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
4618 gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
4619 redirect_edge_var_map_clear (re);
4620 while (1)
4622 psi = gsi_start_phis (fin_bb);
4623 if (gsi_end_p (psi))
4624 break;
4625 remove_phi_node (&psi, false);
4628 /* Make phi node for trip. */
4629 phi = create_phi_node (trip_main, iter_part_bb);
4630 SSA_NAME_DEF_STMT (trip_main) = phi;
4631 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
4632 UNKNOWN_LOCATION);
4633 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
4634 UNKNOWN_LOCATION);
4637 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4638 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4639 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4640 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4641 recompute_dominator (CDI_DOMINATORS, fin_bb));
4642 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4643 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4644 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4645 recompute_dominator (CDI_DOMINATORS, body_bb));
4649 /* Expand the OpenMP loop defined by REGION. */
4651 static void
4652 expand_omp_for (struct omp_region *region)
4654 struct omp_for_data fd;
4655 struct omp_for_data_loop *loops;
4657 loops
4658 = (struct omp_for_data_loop *)
4659 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
4660 * sizeof (struct omp_for_data_loop));
4661 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4662 region->sched_kind = fd.sched_kind;
4664 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4665 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4666 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4667 if (region->cont)
4669 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4670 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4671 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4674 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4675 && !fd.have_ordered
4676 && fd.collapse == 1
4677 && region->cont != NULL)
4679 if (fd.chunk_size == NULL)
4680 expand_omp_for_static_nochunk (region, &fd);
4681 else
4682 expand_omp_for_static_chunk (region, &fd);
4684 else
4686 int fn_index, start_ix, next_ix;
4688 if (fd.chunk_size == NULL
4689 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
4690 fd.chunk_size = integer_zero_node;
4691 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4692 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4693 ? 3 : fd.sched_kind;
4694 fn_index += fd.have_ordered * 4;
4695 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
4696 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
4697 if (fd.iter_type == long_long_unsigned_type_node)
4699 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4700 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
4701 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4702 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
4704 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
4705 (enum built_in_function) next_ix);
4708 if (gimple_in_ssa_p (cfun))
4709 update_ssa (TODO_update_ssa_only_virtuals);
4713 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4715 v = GOMP_sections_start (n);
4717 switch (v)
4719 case 0:
4720 goto L2;
4721 case 1:
4722 section 1;
4723 goto L1;
4724 case 2:
4726 case n:
4728 default:
4729 abort ();
4732 v = GOMP_sections_next ();
4733 goto L0;
4735 reduction;
4737 If this is a combined parallel sections, replace the call to
4738 GOMP_sections_start with call to GOMP_sections_next. */
4740 static void
4741 expand_omp_sections (struct omp_region *region)
4743 tree t, u, vin = NULL, vmain, vnext, l2;
4744 VEC (tree,heap) *label_vec;
4745 unsigned len;
4746 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
4747 gimple_stmt_iterator si, switch_si;
4748 gimple sections_stmt, stmt, cont;
4749 edge_iterator ei;
4750 edge e;
4751 struct omp_region *inner;
4752 unsigned i, casei;
4753 bool exit_reachable = region->cont != NULL;
4755 gcc_assert (exit_reachable == (region->exit != NULL));
4756 entry_bb = region->entry;
4757 l0_bb = single_succ (entry_bb);
4758 l1_bb = region->cont;
4759 l2_bb = region->exit;
4760 if (exit_reachable)
4762 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
4763 l2 = gimple_block_label (l2_bb);
4764 else
4766 /* This can happen if there are reductions. */
4767 len = EDGE_COUNT (l0_bb->succs);
4768 gcc_assert (len > 0);
4769 e = EDGE_SUCC (l0_bb, len - 1);
4770 si = gsi_last_bb (e->dest);
4771 l2 = NULL_TREE;
4772 if (gsi_end_p (si)
4773 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4774 l2 = gimple_block_label (e->dest);
4775 else
4776 FOR_EACH_EDGE (e, ei, l0_bb->succs)
4778 si = gsi_last_bb (e->dest);
4779 if (gsi_end_p (si)
4780 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4782 l2 = gimple_block_label (e->dest);
4783 break;
4787 default_bb = create_empty_bb (l1_bb->prev_bb);
4789 else
4791 default_bb = create_empty_bb (l0_bb);
4792 l2 = gimple_block_label (default_bb);
4795 /* We will build a switch() with enough cases for all the
4796 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
4797 and a default case to abort if something goes wrong. */
4798 len = EDGE_COUNT (l0_bb->succs);
4800 /* Use VEC_quick_push on label_vec throughout, since we know the size
4801 in advance. */
4802 label_vec = VEC_alloc (tree, heap, len);
4804 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
4805 GIMPLE_OMP_SECTIONS statement. */
4806 si = gsi_last_bb (entry_bb);
4807 sections_stmt = gsi_stmt (si);
4808 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
4809 vin = gimple_omp_sections_control (sections_stmt);
4810 if (!is_combined_parallel (region))
4812 /* If we are not inside a combined parallel+sections region,
4813 call GOMP_sections_start. */
4814 t = build_int_cst (unsigned_type_node,
4815 exit_reachable ? len - 1 : len);
4816 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
4817 stmt = gimple_build_call (u, 1, t);
4819 else
4821 /* Otherwise, call GOMP_sections_next. */
4822 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4823 stmt = gimple_build_call (u, 0);
4825 gimple_call_set_lhs (stmt, vin);
4826 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4827 gsi_remove (&si, true);
4829 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
4830 L0_BB. */
4831 switch_si = gsi_last_bb (l0_bb);
4832 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
4833 if (exit_reachable)
4835 cont = last_stmt (l1_bb);
4836 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
4837 vmain = gimple_omp_continue_control_use (cont);
4838 vnext = gimple_omp_continue_control_def (cont);
4840 else
4842 vmain = vin;
4843 vnext = NULL_TREE;
4846 i = 0;
4847 if (exit_reachable)
4849 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
4850 VEC_quick_push (tree, label_vec, t);
4851 i++;
4854 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
4855 for (inner = region->inner, casei = 1;
4856 inner;
4857 inner = inner->next, i++, casei++)
4859 basic_block s_entry_bb, s_exit_bb;
4861 /* Skip optional reduction region. */
4862 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
4864 --i;
4865 --casei;
4866 continue;
4869 s_entry_bb = inner->entry;
4870 s_exit_bb = inner->exit;
4872 t = gimple_block_label (s_entry_bb);
4873 u = build_int_cst (unsigned_type_node, casei);
4874 u = build_case_label (u, NULL, t);
4875 VEC_quick_push (tree, label_vec, u);
4877 si = gsi_last_bb (s_entry_bb);
4878 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
4879 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
4880 gsi_remove (&si, true);
4881 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
4883 if (s_exit_bb == NULL)
4884 continue;
4886 si = gsi_last_bb (s_exit_bb);
4887 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4888 gsi_remove (&si, true);
4890 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
4893 /* Error handling code goes in DEFAULT_BB. */
4894 t = gimple_block_label (default_bb);
4895 u = build_case_label (NULL, NULL, t);
4896 make_edge (l0_bb, default_bb, 0);
4898 stmt = gimple_build_switch_vec (vmain, u, label_vec);
4899 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
4900 gsi_remove (&switch_si, true);
4901 VEC_free (tree, heap, label_vec);
4903 si = gsi_start_bb (default_bb);
4904 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
4905 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4907 if (exit_reachable)
4909 tree bfn_decl;
4911 /* Code to get the next section goes in L1_BB. */
4912 si = gsi_last_bb (l1_bb);
4913 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
4915 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4916 stmt = gimple_build_call (bfn_decl, 0);
4917 gimple_call_set_lhs (stmt, vnext);
4918 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4919 gsi_remove (&si, true);
4921 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
4923 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
4924 si = gsi_last_bb (l2_bb);
4925 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
4926 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
4927 else
4928 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
4929 stmt = gimple_build_call (t, 0);
4930 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4931 gsi_remove (&si, true);
4934 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
4938 /* Expand code for an OpenMP single directive. We've already expanded
4939 much of the code, here we simply place the GOMP_barrier call. */
4941 static void
4942 expand_omp_single (struct omp_region *region)
4944 basic_block entry_bb, exit_bb;
4945 gimple_stmt_iterator si;
4946 bool need_barrier = false;
4948 entry_bb = region->entry;
4949 exit_bb = region->exit;
4951 si = gsi_last_bb (entry_bb);
4952 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
4953 be removed. We need to ensure that the thread that entered the single
4954 does not exit before the data is copied out by the other threads. */
4955 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
4956 OMP_CLAUSE_COPYPRIVATE))
4957 need_barrier = true;
4958 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
4959 gsi_remove (&si, true);
4960 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4962 si = gsi_last_bb (exit_bb);
4963 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
4964 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4965 false, GSI_SAME_STMT);
4966 gsi_remove (&si, true);
4967 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4971 /* Generic expansion for OpenMP synchronization directives: master,
4972 ordered and critical. All we need to do here is remove the entry
4973 and exit markers for REGION. */
4975 static void
4976 expand_omp_synch (struct omp_region *region)
4978 basic_block entry_bb, exit_bb;
4979 gimple_stmt_iterator si;
4981 entry_bb = region->entry;
4982 exit_bb = region->exit;
4984 si = gsi_last_bb (entry_bb);
4985 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
4986 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
4987 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
4988 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
4989 gsi_remove (&si, true);
4990 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4992 if (exit_bb)
4994 si = gsi_last_bb (exit_bb);
4995 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4996 gsi_remove (&si, true);
4997 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
5001 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5002 operation as a normal volatile load. */
5004 static bool
5005 expand_omp_atomic_load (basic_block load_bb, tree addr,
5006 tree loaded_val, int index)
5008 enum built_in_function tmpbase;
5009 gimple_stmt_iterator gsi;
5010 basic_block store_bb;
5011 location_t loc;
5012 gimple stmt;
5013 tree decl, call, type, itype;
5015 gsi = gsi_last_bb (load_bb);
5016 stmt = gsi_stmt (gsi);
5017 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5018 loc = gimple_location (stmt);
5020 /* ??? If the target does not implement atomic_load_optab[mode], and mode
5021 is smaller than word size, then expand_atomic_load assumes that the load
5022 is atomic. We could avoid the builtin entirely in this case. */
5024 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
5025 decl = builtin_decl_explicit (tmpbase);
5026 if (decl == NULL_TREE)
5027 return false;
5029 type = TREE_TYPE (loaded_val);
5030 itype = TREE_TYPE (TREE_TYPE (decl));
5032 call = build_call_expr_loc (loc, decl, 2, addr,
5033 build_int_cst (NULL, MEMMODEL_RELAXED));
5034 if (!useless_type_conversion_p (type, itype))
5035 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5036 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5038 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5039 gsi_remove (&gsi, true);
5041 store_bb = single_succ (load_bb);
5042 gsi = gsi_last_bb (store_bb);
5043 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5044 gsi_remove (&gsi, true);
5046 if (gimple_in_ssa_p (cfun))
5047 update_ssa (TODO_update_ssa_no_phi);
5049 return true;
5052 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5053 operation as a normal volatile store. */
5055 static bool
5056 expand_omp_atomic_store (basic_block load_bb, tree addr,
5057 tree loaded_val, tree stored_val, int index)
5059 enum built_in_function tmpbase;
5060 gimple_stmt_iterator gsi;
5061 basic_block store_bb = single_succ (load_bb);
5062 location_t loc;
5063 gimple stmt;
5064 tree decl, call, type, itype;
5065 enum machine_mode imode;
5066 bool exchange;
5068 gsi = gsi_last_bb (load_bb);
5069 stmt = gsi_stmt (gsi);
5070 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5072 /* If the load value is needed, then this isn't a store but an exchange. */
5073 exchange = gimple_omp_atomic_need_value_p (stmt);
5075 gsi = gsi_last_bb (store_bb);
5076 stmt = gsi_stmt (gsi);
5077 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
5078 loc = gimple_location (stmt);
5080 /* ??? If the target does not implement atomic_store_optab[mode], and mode
5081 is smaller than word size, then expand_atomic_store assumes that the store
5082 is atomic. We could avoid the builtin entirely in this case. */
5084 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
5085 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
5086 decl = builtin_decl_explicit (tmpbase);
5087 if (decl == NULL_TREE)
5088 return false;
5090 type = TREE_TYPE (stored_val);
5092 /* Dig out the type of the function's second argument. */
5093 itype = TREE_TYPE (decl);
5094 itype = TYPE_ARG_TYPES (itype);
5095 itype = TREE_CHAIN (itype);
5096 itype = TREE_VALUE (itype);
5097 imode = TYPE_MODE (itype);
5099 if (exchange && !can_atomic_exchange_p (imode, true))
5100 return false;
5102 if (!useless_type_conversion_p (itype, type))
5103 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
5104 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
5105 build_int_cst (NULL, MEMMODEL_RELAXED));
5106 if (exchange)
5108 if (!useless_type_conversion_p (type, itype))
5109 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5110 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5113 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5114 gsi_remove (&gsi, true);
5116 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
5117 gsi = gsi_last_bb (load_bb);
5118 gsi_remove (&gsi, true);
5120 if (gimple_in_ssa_p (cfun))
5121 update_ssa (TODO_update_ssa_no_phi);
5123 return true;
5126 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5127 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
5128 size of the data type, and thus usable to find the index of the builtin
5129 decl. Returns false if the expression is not of the proper form. */
5131 static bool
5132 expand_omp_atomic_fetch_op (basic_block load_bb,
5133 tree addr, tree loaded_val,
5134 tree stored_val, int index)
5136 enum built_in_function oldbase, newbase, tmpbase;
5137 tree decl, itype, call;
5138 tree lhs, rhs;
5139 basic_block store_bb = single_succ (load_bb);
5140 gimple_stmt_iterator gsi;
5141 gimple stmt;
5142 location_t loc;
5143 enum tree_code code;
5144 bool need_old, need_new;
5145 enum machine_mode imode;
5147 /* We expect to find the following sequences:
5149 load_bb:
5150 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
5152 store_bb:
5153 val = tmp OP something; (or: something OP tmp)
5154 GIMPLE_OMP_STORE (val)
5156 ???FIXME: Allow a more flexible sequence.
5157 Perhaps use data flow to pick the statements.
5161 gsi = gsi_after_labels (store_bb);
5162 stmt = gsi_stmt (gsi);
5163 loc = gimple_location (stmt);
5164 if (!is_gimple_assign (stmt))
5165 return false;
5166 gsi_next (&gsi);
5167 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
5168 return false;
5169 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
5170 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
5171 gcc_checking_assert (!need_old || !need_new);
5173 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
5174 return false;
5176 /* Check for one of the supported fetch-op operations. */
5177 code = gimple_assign_rhs_code (stmt);
5178 switch (code)
5180 case PLUS_EXPR:
5181 case POINTER_PLUS_EXPR:
5182 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
5183 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
5184 break;
5185 case MINUS_EXPR:
5186 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
5187 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
5188 break;
5189 case BIT_AND_EXPR:
5190 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
5191 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
5192 break;
5193 case BIT_IOR_EXPR:
5194 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
5195 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
5196 break;
5197 case BIT_XOR_EXPR:
5198 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
5199 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
5200 break;
5201 default:
5202 return false;
5205 /* Make sure the expression is of the proper form. */
5206 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
5207 rhs = gimple_assign_rhs2 (stmt);
5208 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
5209 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
5210 rhs = gimple_assign_rhs1 (stmt);
5211 else
5212 return false;
5214 tmpbase = ((enum built_in_function)
5215 ((need_new ? newbase : oldbase) + index + 1));
5216 decl = builtin_decl_explicit (tmpbase);
5217 if (decl == NULL_TREE)
5218 return false;
5219 itype = TREE_TYPE (TREE_TYPE (decl));
5220 imode = TYPE_MODE (itype);
5222 /* We could test all of the various optabs involved, but the fact of the
5223 matter is that (with the exception of i486 vs i586 and xadd) all targets
5224 that support any atomic operaton optab also implements compare-and-swap.
5225 Let optabs.c take care of expanding any compare-and-swap loop. */
5226 if (!can_compare_and_swap_p (imode, true))
5227 return false;
5229 gsi = gsi_last_bb (load_bb);
5230 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
5232 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
5233 It only requires that the operation happen atomically. Thus we can
5234 use the RELAXED memory model. */
5235 call = build_call_expr_loc (loc, decl, 3, addr,
5236 fold_convert_loc (loc, itype, rhs),
5237 build_int_cst (NULL, MEMMODEL_RELAXED));
5239 if (need_old || need_new)
5241 lhs = need_old ? loaded_val : stored_val;
5242 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
5243 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
5245 else
5246 call = fold_convert_loc (loc, void_type_node, call);
5247 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5248 gsi_remove (&gsi, true);
5250 gsi = gsi_last_bb (store_bb);
5251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5252 gsi_remove (&gsi, true);
5253 gsi = gsi_last_bb (store_bb);
5254 gsi_remove (&gsi, true);
5256 if (gimple_in_ssa_p (cfun))
5257 update_ssa (TODO_update_ssa_no_phi);
5259 return true;
5262 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5264 oldval = *addr;
5265 repeat:
5266 newval = rhs; // with oldval replacing *addr in rhs
5267 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
5268 if (oldval != newval)
5269 goto repeat;
5271 INDEX is log2 of the size of the data type, and thus usable to find the
5272 index of the builtin decl. */
5274 static bool
5275 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
5276 tree addr, tree loaded_val, tree stored_val,
5277 int index)
5279 tree loadedi, storedi, initial, new_storedi, old_vali;
5280 tree type, itype, cmpxchg, iaddr;
5281 gimple_stmt_iterator si;
5282 basic_block loop_header = single_succ (load_bb);
5283 gimple phi, stmt;
5284 edge e;
5285 enum built_in_function fncode;
5287 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
5288 order to use the RELAXED memory model effectively. */
5289 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
5290 + index + 1);
5291 cmpxchg = builtin_decl_explicit (fncode);
5292 if (cmpxchg == NULL_TREE)
5293 return false;
5294 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5295 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
5297 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
5298 return false;
5300 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
5301 si = gsi_last_bb (load_bb);
5302 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5304 /* For floating-point values, we'll need to view-convert them to integers
5305 so that we can perform the atomic compare and swap. Simplify the
5306 following code by always setting up the "i"ntegral variables. */
5307 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
5309 tree iaddr_val;
5311 iaddr = make_rename_temp (build_pointer_type_for_mode (itype, ptr_mode,
5312 true), NULL);
5313 iaddr_val
5314 = force_gimple_operand_gsi (&si,
5315 fold_convert (TREE_TYPE (iaddr), addr),
5316 false, NULL_TREE, true, GSI_SAME_STMT);
5317 stmt = gimple_build_assign (iaddr, iaddr_val);
5318 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5319 loadedi = create_tmp_var (itype, NULL);
5320 if (gimple_in_ssa_p (cfun))
5322 add_referenced_var (iaddr);
5323 add_referenced_var (loadedi);
5324 loadedi = make_ssa_name (loadedi, NULL);
5327 else
5329 iaddr = addr;
5330 loadedi = loaded_val;
5333 initial
5334 = force_gimple_operand_gsi (&si,
5335 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
5336 iaddr,
5337 build_int_cst (TREE_TYPE (iaddr), 0)),
5338 true, NULL_TREE, true, GSI_SAME_STMT);
5340 /* Move the value to the LOADEDI temporary. */
5341 if (gimple_in_ssa_p (cfun))
5343 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
5344 phi = create_phi_node (loadedi, loop_header);
5345 SSA_NAME_DEF_STMT (loadedi) = phi;
5346 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
5347 initial);
5349 else
5350 gsi_insert_before (&si,
5351 gimple_build_assign (loadedi, initial),
5352 GSI_SAME_STMT);
5353 if (loadedi != loaded_val)
5355 gimple_stmt_iterator gsi2;
5356 tree x;
5358 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
5359 gsi2 = gsi_start_bb (loop_header);
5360 if (gimple_in_ssa_p (cfun))
5362 gimple stmt;
5363 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5364 true, GSI_SAME_STMT);
5365 stmt = gimple_build_assign (loaded_val, x);
5366 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
5368 else
5370 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
5371 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5372 true, GSI_SAME_STMT);
5375 gsi_remove (&si, true);
5377 si = gsi_last_bb (store_bb);
5378 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5380 if (iaddr == addr)
5381 storedi = stored_val;
5382 else
5383 storedi =
5384 force_gimple_operand_gsi (&si,
5385 build1 (VIEW_CONVERT_EXPR, itype,
5386 stored_val), true, NULL_TREE, true,
5387 GSI_SAME_STMT);
5389 /* Build the compare&swap statement. */
5390 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
5391 new_storedi = force_gimple_operand_gsi (&si,
5392 fold_convert (TREE_TYPE (loadedi),
5393 new_storedi),
5394 true, NULL_TREE,
5395 true, GSI_SAME_STMT);
5397 if (gimple_in_ssa_p (cfun))
5398 old_vali = loadedi;
5399 else
5401 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
5402 if (gimple_in_ssa_p (cfun))
5403 add_referenced_var (old_vali);
5404 stmt = gimple_build_assign (old_vali, loadedi);
5405 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5407 stmt = gimple_build_assign (loadedi, new_storedi);
5408 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5411 /* Note that we always perform the comparison as an integer, even for
5412 floating point. This allows the atomic operation to properly
5413 succeed even with NaNs and -0.0. */
5414 stmt = gimple_build_cond_empty
5415 (build2 (NE_EXPR, boolean_type_node,
5416 new_storedi, old_vali));
5417 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5419 /* Update cfg. */
5420 e = single_succ_edge (store_bb);
5421 e->flags &= ~EDGE_FALLTHRU;
5422 e->flags |= EDGE_FALSE_VALUE;
5424 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
5426 /* Copy the new value to loadedi (we already did that before the condition
5427 if we are not in SSA). */
5428 if (gimple_in_ssa_p (cfun))
5430 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
5431 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
5434 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
5435 gsi_remove (&si, true);
5437 if (gimple_in_ssa_p (cfun))
5438 update_ssa (TODO_update_ssa_no_phi);
5440 return true;
5443 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5445 GOMP_atomic_start ();
5446 *addr = rhs;
5447 GOMP_atomic_end ();
5449 The result is not globally atomic, but works so long as all parallel
5450 references are within #pragma omp atomic directives. According to
5451 responses received from omp@openmp.org, appears to be within spec.
5452 Which makes sense, since that's how several other compilers handle
5453 this situation as well.
5454 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
5455 expanding. STORED_VAL is the operand of the matching
5456 GIMPLE_OMP_ATOMIC_STORE.
5458 We replace
5459 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
5460 loaded_val = *addr;
5462 and replace
5463 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
5464 *addr = stored_val;
5467 static bool
5468 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
5469 tree addr, tree loaded_val, tree stored_val)
5471 gimple_stmt_iterator si;
5472 gimple stmt;
5473 tree t;
5475 si = gsi_last_bb (load_bb);
5476 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5478 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
5479 t = build_call_expr (t, 0);
5480 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5482 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
5483 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5484 gsi_remove (&si, true);
5486 si = gsi_last_bb (store_bb);
5487 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5489 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
5490 stored_val);
5491 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5493 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
5494 t = build_call_expr (t, 0);
5495 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5496 gsi_remove (&si, true);
5498 if (gimple_in_ssa_p (cfun))
5499 update_ssa (TODO_update_ssa_no_phi);
5500 return true;
5503 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
5504 using expand_omp_atomic_fetch_op. If it failed, we try to
5505 call expand_omp_atomic_pipeline, and if it fails too, the
5506 ultimate fallback is wrapping the operation in a mutex
5507 (expand_omp_atomic_mutex). REGION is the atomic region built
5508 by build_omp_regions_1(). */
5510 static void
5511 expand_omp_atomic (struct omp_region *region)
5513 basic_block load_bb = region->entry, store_bb = region->exit;
5514 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
5515 tree loaded_val = gimple_omp_atomic_load_lhs (load);
5516 tree addr = gimple_omp_atomic_load_rhs (load);
5517 tree stored_val = gimple_omp_atomic_store_val (store);
5518 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5519 HOST_WIDE_INT index;
5521 /* Make sure the type is one of the supported sizes. */
5522 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
5523 index = exact_log2 (index);
5524 if (index >= 0 && index <= 4)
5526 unsigned int align = TYPE_ALIGN_UNIT (type);
5528 /* __sync builtins require strict data alignment. */
5529 if (exact_log2 (align) >= index)
5531 /* Atomic load. */
5532 if (loaded_val == stored_val
5533 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5534 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5535 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5536 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
5537 return;
5539 /* Atomic store. */
5540 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5541 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5542 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5543 && store_bb == single_succ (load_bb)
5544 && first_stmt (store_bb) == store
5545 && expand_omp_atomic_store (load_bb, addr, loaded_val,
5546 stored_val, index))
5547 return;
5549 /* When possible, use specialized atomic update functions. */
5550 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5551 && store_bb == single_succ (load_bb)
5552 && expand_omp_atomic_fetch_op (load_bb, addr,
5553 loaded_val, stored_val, index))
5554 return;
5556 /* If we don't have specialized __sync builtins, try and implement
5557 as a compare and swap loop. */
5558 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5559 loaded_val, stored_val, index))
5560 return;
5564 /* The ultimate fallback is wrapping the operation in a mutex. */
5565 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5569 /* Expand the parallel region tree rooted at REGION. Expansion
5570 proceeds in depth-first order. Innermost regions are expanded
5571 first. This way, parallel regions that require a new function to
5572 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
5573 internal dependencies in their body. */
5575 static void
5576 expand_omp (struct omp_region *region)
5578 while (region)
5580 location_t saved_location;
5582 /* First, determine whether this is a combined parallel+workshare
5583 region. */
5584 if (region->type == GIMPLE_OMP_PARALLEL)
5585 determine_parallel_type (region);
5587 if (region->inner)
5588 expand_omp (region->inner);
5590 saved_location = input_location;
5591 if (gimple_has_location (last_stmt (region->entry)))
5592 input_location = gimple_location (last_stmt (region->entry));
5594 switch (region->type)
5596 case GIMPLE_OMP_PARALLEL:
5597 case GIMPLE_OMP_TASK:
5598 expand_omp_taskreg (region);
5599 break;
5601 case GIMPLE_OMP_FOR:
5602 expand_omp_for (region);
5603 break;
5605 case GIMPLE_OMP_SECTIONS:
5606 expand_omp_sections (region);
5607 break;
5609 case GIMPLE_OMP_SECTION:
5610 /* Individual omp sections are handled together with their
5611 parent GIMPLE_OMP_SECTIONS region. */
5612 break;
5614 case GIMPLE_OMP_SINGLE:
5615 expand_omp_single (region);
5616 break;
5618 case GIMPLE_OMP_MASTER:
5619 case GIMPLE_OMP_ORDERED:
5620 case GIMPLE_OMP_CRITICAL:
5621 expand_omp_synch (region);
5622 break;
5624 case GIMPLE_OMP_ATOMIC_LOAD:
5625 expand_omp_atomic (region);
5626 break;
5628 default:
5629 gcc_unreachable ();
5632 input_location = saved_location;
5633 region = region->next;
5638 /* Helper for build_omp_regions. Scan the dominator tree starting at
5639 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5640 true, the function ends once a single tree is built (otherwise, whole
5641 forest of OMP constructs may be built). */
5643 static void
5644 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5645 bool single_tree)
5647 gimple_stmt_iterator gsi;
5648 gimple stmt;
5649 basic_block son;
5651 gsi = gsi_last_bb (bb);
5652 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
5654 struct omp_region *region;
5655 enum gimple_code code;
5657 stmt = gsi_stmt (gsi);
5658 code = gimple_code (stmt);
5659 if (code == GIMPLE_OMP_RETURN)
5661 /* STMT is the return point out of region PARENT. Mark it
5662 as the exit point and make PARENT the immediately
5663 enclosing region. */
5664 gcc_assert (parent);
5665 region = parent;
5666 region->exit = bb;
5667 parent = parent->outer;
5669 else if (code == GIMPLE_OMP_ATOMIC_STORE)
5671 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
5672 GIMPLE_OMP_RETURN, but matches with
5673 GIMPLE_OMP_ATOMIC_LOAD. */
5674 gcc_assert (parent);
5675 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
5676 region = parent;
5677 region->exit = bb;
5678 parent = parent->outer;
5681 else if (code == GIMPLE_OMP_CONTINUE)
5683 gcc_assert (parent);
5684 parent->cont = bb;
5686 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
5688 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
5689 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
5692 else
5694 /* Otherwise, this directive becomes the parent for a new
5695 region. */
5696 region = new_omp_region (bb, code, parent);
5697 parent = region;
5701 if (single_tree && !parent)
5702 return;
5704 for (son = first_dom_son (CDI_DOMINATORS, bb);
5705 son;
5706 son = next_dom_son (CDI_DOMINATORS, son))
5707 build_omp_regions_1 (son, parent, single_tree);
5710 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5711 root_omp_region. */
5713 static void
5714 build_omp_regions_root (basic_block root)
5716 gcc_assert (root_omp_region == NULL);
5717 build_omp_regions_1 (root, NULL, true);
5718 gcc_assert (root_omp_region != NULL);
5721 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5723 void
5724 omp_expand_local (basic_block head)
5726 build_omp_regions_root (head);
5727 if (dump_file && (dump_flags & TDF_DETAILS))
5729 fprintf (dump_file, "\nOMP region tree\n\n");
5730 dump_omp_region (dump_file, root_omp_region, 0);
5731 fprintf (dump_file, "\n");
5734 remove_exit_barriers (root_omp_region);
5735 expand_omp (root_omp_region);
5737 free_omp_regions ();
5740 /* Scan the CFG and build a tree of OMP regions. Return the root of
5741 the OMP region tree. */
5743 static void
5744 build_omp_regions (void)
5746 gcc_assert (root_omp_region == NULL);
5747 calculate_dominance_info (CDI_DOMINATORS);
5748 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5751 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5753 static unsigned int
5754 execute_expand_omp (void)
5756 build_omp_regions ();
5758 if (!root_omp_region)
5759 return 0;
5761 if (dump_file)
5763 fprintf (dump_file, "\nOMP region tree\n\n");
5764 dump_omp_region (dump_file, root_omp_region, 0);
5765 fprintf (dump_file, "\n");
5768 remove_exit_barriers (root_omp_region);
5770 expand_omp (root_omp_region);
5772 cleanup_tree_cfg ();
5774 free_omp_regions ();
5776 return 0;
5779 /* OMP expansion -- the default pass, run before creation of SSA form. */
5781 static bool
5782 gate_expand_omp (void)
5784 return (flag_openmp != 0 && !seen_error ());
5787 struct gimple_opt_pass pass_expand_omp =
5790 GIMPLE_PASS,
5791 "ompexp", /* name */
5792 gate_expand_omp, /* gate */
5793 execute_expand_omp, /* execute */
5794 NULL, /* sub */
5795 NULL, /* next */
5796 0, /* static_pass_number */
5797 TV_NONE, /* tv_id */
5798 PROP_gimple_any, /* properties_required */
5799 0, /* properties_provided */
5800 0, /* properties_destroyed */
5801 0, /* todo_flags_start */
5802 0 /* todo_flags_finish */
5806 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
5808 /* Lower the OpenMP sections directive in the current statement in GSI_P.
5809 CTX is the enclosing OMP context for the current statement. */
5811 static void
5812 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5814 tree block, control;
5815 gimple_stmt_iterator tgsi;
5816 gimple stmt, new_stmt, bind, t;
5817 gimple_seq ilist, dlist, olist, new_body;
5818 struct gimplify_ctx gctx;
5820 stmt = gsi_stmt (*gsi_p);
5822 push_gimplify_context (&gctx);
5824 dlist = NULL;
5825 ilist = NULL;
5826 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
5827 &ilist, &dlist, ctx);
5829 new_body = gimple_omp_body (stmt);
5830 gimple_omp_set_body (stmt, NULL);
5831 tgsi = gsi_start (new_body);
5832 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
5834 omp_context *sctx;
5835 gimple sec_start;
5837 sec_start = gsi_stmt (tgsi);
5838 sctx = maybe_lookup_ctx (sec_start);
5839 gcc_assert (sctx);
5841 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
5842 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
5843 GSI_CONTINUE_LINKING);
5844 gimple_omp_set_body (sec_start, NULL);
5846 if (gsi_one_before_end_p (tgsi))
5848 gimple_seq l = NULL;
5849 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
5850 &l, ctx);
5851 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
5852 gimple_omp_section_set_last (sec_start);
5855 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
5856 GSI_CONTINUE_LINKING);
5859 block = make_node (BLOCK);
5860 bind = gimple_build_bind (NULL, new_body, block);
5862 olist = NULL;
5863 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
5865 block = make_node (BLOCK);
5866 new_stmt = gimple_build_bind (NULL, NULL, block);
5867 gsi_replace (gsi_p, new_stmt, true);
5869 pop_gimplify_context (new_stmt);
5870 gimple_bind_append_vars (new_stmt, ctx->block_vars);
5871 BLOCK_VARS (block) = gimple_bind_vars (bind);
5872 if (BLOCK_VARS (block))
5873 TREE_USED (block) = 1;
5875 new_body = NULL;
5876 gimple_seq_add_seq (&new_body, ilist);
5877 gimple_seq_add_stmt (&new_body, stmt);
5878 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
5879 gimple_seq_add_stmt (&new_body, bind);
5881 control = create_tmp_var (unsigned_type_node, ".section");
5882 t = gimple_build_omp_continue (control, control);
5883 gimple_omp_sections_set_control (stmt, control);
5884 gimple_seq_add_stmt (&new_body, t);
5886 gimple_seq_add_seq (&new_body, olist);
5887 gimple_seq_add_seq (&new_body, dlist);
5889 new_body = maybe_catch_exception (new_body);
5891 t = gimple_build_omp_return
5892 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
5893 OMP_CLAUSE_NOWAIT));
5894 gimple_seq_add_stmt (&new_body, t);
5896 gimple_bind_set_body (new_stmt, new_body);
5900 /* A subroutine of lower_omp_single. Expand the simple form of
5901 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
5903 if (GOMP_single_start ())
5904 BODY;
5905 [ GOMP_barrier (); ] -> unless 'nowait' is present.
5907 FIXME. It may be better to delay expanding the logic of this until
5908 pass_expand_omp. The expanded logic may make the job more difficult
5909 to a synchronization analysis pass. */
5911 static void
5912 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
5914 location_t loc = gimple_location (single_stmt);
5915 tree tlabel = create_artificial_label (loc);
5916 tree flabel = create_artificial_label (loc);
5917 gimple call, cond;
5918 tree lhs, decl;
5920 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
5921 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
5922 call = gimple_build_call (decl, 0);
5923 gimple_call_set_lhs (call, lhs);
5924 gimple_seq_add_stmt (pre_p, call);
5926 cond = gimple_build_cond (EQ_EXPR, lhs,
5927 fold_convert_loc (loc, TREE_TYPE (lhs),
5928 boolean_true_node),
5929 tlabel, flabel);
5930 gimple_seq_add_stmt (pre_p, cond);
5931 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
5932 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5933 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
5937 /* A subroutine of lower_omp_single. Expand the simple form of
5938 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
5940 #pragma omp single copyprivate (a, b, c)
5942 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
5945 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
5947 BODY;
5948 copyout.a = a;
5949 copyout.b = b;
5950 copyout.c = c;
5951 GOMP_single_copy_end (&copyout);
5953 else
5955 a = copyout_p->a;
5956 b = copyout_p->b;
5957 c = copyout_p->c;
5959 GOMP_barrier ();
5962 FIXME. It may be better to delay expanding the logic of this until
5963 pass_expand_omp. The expanded logic may make the job more difficult
5964 to a synchronization analysis pass. */
5966 static void
5967 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
5969 tree ptr_type, t, l0, l1, l2, bfn_decl;
5970 gimple_seq copyin_seq;
5971 location_t loc = gimple_location (single_stmt);
5973 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
5975 ptr_type = build_pointer_type (ctx->record_type);
5976 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
5978 l0 = create_artificial_label (loc);
5979 l1 = create_artificial_label (loc);
5980 l2 = create_artificial_label (loc);
5982 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
5983 t = build_call_expr_loc (loc, bfn_decl, 0);
5984 t = fold_convert_loc (loc, ptr_type, t);
5985 gimplify_assign (ctx->receiver_decl, t, pre_p);
5987 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
5988 build_int_cst (ptr_type, 0));
5989 t = build3 (COND_EXPR, void_type_node, t,
5990 build_and_jump (&l0), build_and_jump (&l1));
5991 gimplify_and_add (t, pre_p);
5993 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
5995 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5997 copyin_seq = NULL;
5998 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
5999 &copyin_seq, ctx);
6001 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6002 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
6003 t = build_call_expr_loc (loc, bfn_decl, 1, t);
6004 gimplify_and_add (t, pre_p);
6006 t = build_and_jump (&l2);
6007 gimplify_and_add (t, pre_p);
6009 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
6011 gimple_seq_add_seq (pre_p, copyin_seq);
6013 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
6017 /* Expand code for an OpenMP single directive. */
6019 static void
6020 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6022 tree block;
6023 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
6024 gimple_seq bind_body, dlist;
6025 struct gimplify_ctx gctx;
6027 push_gimplify_context (&gctx);
6029 block = make_node (BLOCK);
6030 bind = gimple_build_bind (NULL, NULL, block);
6031 gsi_replace (gsi_p, bind, true);
6032 bind_body = NULL;
6033 dlist = NULL;
6034 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
6035 &bind_body, &dlist, ctx);
6036 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
6038 gimple_seq_add_stmt (&bind_body, single_stmt);
6040 if (ctx->record_type)
6041 lower_omp_single_copy (single_stmt, &bind_body, ctx);
6042 else
6043 lower_omp_single_simple (single_stmt, &bind_body);
6045 gimple_omp_set_body (single_stmt, NULL);
6047 gimple_seq_add_seq (&bind_body, dlist);
6049 bind_body = maybe_catch_exception (bind_body);
6051 t = gimple_build_omp_return
6052 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
6053 OMP_CLAUSE_NOWAIT));
6054 gimple_seq_add_stmt (&bind_body, t);
6055 gimple_bind_set_body (bind, bind_body);
6057 pop_gimplify_context (bind);
6059 gimple_bind_append_vars (bind, ctx->block_vars);
6060 BLOCK_VARS (block) = ctx->block_vars;
6061 if (BLOCK_VARS (block))
6062 TREE_USED (block) = 1;
6066 /* Expand code for an OpenMP master directive. */
6068 static void
6069 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6071 tree block, lab = NULL, x, bfn_decl;
6072 gimple stmt = gsi_stmt (*gsi_p), bind;
6073 location_t loc = gimple_location (stmt);
6074 gimple_seq tseq;
6075 struct gimplify_ctx gctx;
6077 push_gimplify_context (&gctx);
6079 block = make_node (BLOCK);
6080 bind = gimple_build_bind (NULL, NULL, block);
6081 gsi_replace (gsi_p, bind, true);
6082 gimple_bind_add_stmt (bind, stmt);
6084 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6085 x = build_call_expr_loc (loc, bfn_decl, 0);
6086 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
6087 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
6088 tseq = NULL;
6089 gimplify_and_add (x, &tseq);
6090 gimple_bind_add_seq (bind, tseq);
6092 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6093 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6094 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6095 gimple_omp_set_body (stmt, NULL);
6097 gimple_bind_add_stmt (bind, gimple_build_label (lab));
6099 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6101 pop_gimplify_context (bind);
6103 gimple_bind_append_vars (bind, ctx->block_vars);
6104 BLOCK_VARS (block) = ctx->block_vars;
6108 /* Expand code for an OpenMP ordered directive. */
6110 static void
6111 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6113 tree block;
6114 gimple stmt = gsi_stmt (*gsi_p), bind, x;
6115 struct gimplify_ctx gctx;
6117 push_gimplify_context (&gctx);
6119 block = make_node (BLOCK);
6120 bind = gimple_build_bind (NULL, NULL, block);
6121 gsi_replace (gsi_p, bind, true);
6122 gimple_bind_add_stmt (bind, stmt);
6124 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
6126 gimple_bind_add_stmt (bind, x);
6128 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6129 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6130 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6131 gimple_omp_set_body (stmt, NULL);
6133 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
6134 gimple_bind_add_stmt (bind, x);
6136 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6138 pop_gimplify_context (bind);
6140 gimple_bind_append_vars (bind, ctx->block_vars);
6141 BLOCK_VARS (block) = gimple_bind_vars (bind);
6145 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
6146 substitution of a couple of function calls. But in the NAMED case,
6147 requires that languages coordinate a symbol name. It is therefore
6148 best put here in common code. */
6150 static GTY((param1_is (tree), param2_is (tree)))
6151 splay_tree critical_name_mutexes;
6153 static void
6154 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6156 tree block;
6157 tree name, lock, unlock;
6158 gimple stmt = gsi_stmt (*gsi_p), bind;
6159 location_t loc = gimple_location (stmt);
6160 gimple_seq tbody;
6161 struct gimplify_ctx gctx;
6163 name = gimple_omp_critical_name (stmt);
6164 if (name)
6166 tree decl;
6167 splay_tree_node n;
6169 if (!critical_name_mutexes)
6170 critical_name_mutexes
6171 = splay_tree_new_ggc (splay_tree_compare_pointers,
6172 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
6173 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
6175 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
6176 if (n == NULL)
6178 char *new_str;
6180 decl = create_tmp_var_raw (ptr_type_node, NULL);
6182 new_str = ACONCAT ((".gomp_critical_user_",
6183 IDENTIFIER_POINTER (name), NULL));
6184 DECL_NAME (decl) = get_identifier (new_str);
6185 TREE_PUBLIC (decl) = 1;
6186 TREE_STATIC (decl) = 1;
6187 DECL_COMMON (decl) = 1;
6188 DECL_ARTIFICIAL (decl) = 1;
6189 DECL_IGNORED_P (decl) = 1;
6190 varpool_finalize_decl (decl);
6192 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
6193 (splay_tree_value) decl);
6195 else
6196 decl = (tree) n->value;
6198 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
6199 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
6201 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
6202 unlock = build_call_expr_loc (loc, unlock, 1,
6203 build_fold_addr_expr_loc (loc, decl));
6205 else
6207 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
6208 lock = build_call_expr_loc (loc, lock, 0);
6210 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
6211 unlock = build_call_expr_loc (loc, unlock, 0);
6214 push_gimplify_context (&gctx);
6216 block = make_node (BLOCK);
6217 bind = gimple_build_bind (NULL, NULL, block);
6218 gsi_replace (gsi_p, bind, true);
6219 gimple_bind_add_stmt (bind, stmt);
6221 tbody = gimple_bind_body (bind);
6222 gimplify_and_add (lock, &tbody);
6223 gimple_bind_set_body (bind, tbody);
6225 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6226 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6227 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6228 gimple_omp_set_body (stmt, NULL);
6230 tbody = gimple_bind_body (bind);
6231 gimplify_and_add (unlock, &tbody);
6232 gimple_bind_set_body (bind, tbody);
6234 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6236 pop_gimplify_context (bind);
6237 gimple_bind_append_vars (bind, ctx->block_vars);
6238 BLOCK_VARS (block) = gimple_bind_vars (bind);
6242 /* A subroutine of lower_omp_for. Generate code to emit the predicate
6243 for a lastprivate clause. Given a loop control predicate of (V
6244 cond N2), we gate the clause on (!(V cond N2)). The lowered form
6245 is appended to *DLIST, iterator initialization is appended to
6246 *BODY_P. */
6248 static void
6249 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
6250 gimple_seq *dlist, struct omp_context *ctx)
6252 tree clauses, cond, vinit;
6253 enum tree_code cond_code;
6254 gimple_seq stmts;
6256 cond_code = fd->loop.cond_code;
6257 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
6259 /* When possible, use a strict equality expression. This can let VRP
6260 type optimizations deduce the value and remove a copy. */
6261 if (host_integerp (fd->loop.step, 0))
6263 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
6264 if (step == 1 || step == -1)
6265 cond_code = EQ_EXPR;
6268 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
6270 clauses = gimple_omp_for_clauses (fd->for_stmt);
6271 stmts = NULL;
6272 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
6273 if (!gimple_seq_empty_p (stmts))
6275 gimple_seq_add_seq (&stmts, *dlist);
6276 *dlist = stmts;
6278 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
6279 vinit = fd->loop.n1;
6280 if (cond_code == EQ_EXPR
6281 && host_integerp (fd->loop.n2, 0)
6282 && ! integer_zerop (fd->loop.n2))
6283 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
6285 /* Initialize the iterator variable, so that threads that don't execute
6286 any iterations don't execute the lastprivate clauses by accident. */
6287 gimplify_assign (fd->loop.v, vinit, body_p);
6292 /* Lower code for an OpenMP loop directive. */
6294 static void
6295 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6297 tree *rhs_p, block;
6298 struct omp_for_data fd;
6299 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
6300 gimple_seq omp_for_body, body, dlist;
6301 size_t i;
6302 struct gimplify_ctx gctx;
6304 push_gimplify_context (&gctx);
6306 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
6307 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6309 block = make_node (BLOCK);
6310 new_stmt = gimple_build_bind (NULL, NULL, block);
6311 /* Replace at gsi right away, so that 'stmt' is no member
6312 of a sequence anymore as we're going to add to to a different
6313 one below. */
6314 gsi_replace (gsi_p, new_stmt, true);
6316 /* Move declaration of temporaries in the loop body before we make
6317 it go away. */
6318 omp_for_body = gimple_omp_body (stmt);
6319 if (!gimple_seq_empty_p (omp_for_body)
6320 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
6322 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
6323 gimple_bind_append_vars (new_stmt, vars);
6326 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
6327 dlist = NULL;
6328 body = NULL;
6329 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
6330 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
6332 /* Lower the header expressions. At this point, we can assume that
6333 the header is of the form:
6335 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
6337 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
6338 using the .omp_data_s mapping, if needed. */
6339 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
6341 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
6342 if (!is_gimple_min_invariant (*rhs_p))
6343 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6345 rhs_p = gimple_omp_for_final_ptr (stmt, i);
6346 if (!is_gimple_min_invariant (*rhs_p))
6347 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6349 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
6350 if (!is_gimple_min_invariant (*rhs_p))
6351 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6354 /* Once lowered, extract the bounds and clauses. */
6355 extract_omp_for_data (stmt, &fd, NULL);
6357 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
6359 gimple_seq_add_stmt (&body, stmt);
6360 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
6362 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
6363 fd.loop.v));
6365 /* After the loop, add exit clauses. */
6366 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
6367 gimple_seq_add_seq (&body, dlist);
6369 body = maybe_catch_exception (body);
6371 /* Region exit marker goes at the end of the loop body. */
6372 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
6374 pop_gimplify_context (new_stmt);
6376 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6377 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
6378 if (BLOCK_VARS (block))
6379 TREE_USED (block) = 1;
6381 gimple_bind_set_body (new_stmt, body);
6382 gimple_omp_set_body (stmt, NULL);
6383 gimple_omp_for_set_pre_body (stmt, NULL);
6386 /* Callback for walk_stmts. Check if the current statement only contains
6387 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
6389 static tree
6390 check_combined_parallel (gimple_stmt_iterator *gsi_p,
6391 bool *handled_ops_p,
6392 struct walk_stmt_info *wi)
6394 int *info = (int *) wi->info;
6395 gimple stmt = gsi_stmt (*gsi_p);
6397 *handled_ops_p = true;
6398 switch (gimple_code (stmt))
6400 WALK_SUBSTMTS;
6402 case GIMPLE_OMP_FOR:
6403 case GIMPLE_OMP_SECTIONS:
6404 *info = *info == 0 ? 1 : -1;
6405 break;
6406 default:
6407 *info = -1;
6408 break;
6410 return NULL;
6413 struct omp_taskcopy_context
6415 /* This field must be at the beginning, as we do "inheritance": Some
6416 callback functions for tree-inline.c (e.g., omp_copy_decl)
6417 receive a copy_body_data pointer that is up-casted to an
6418 omp_context pointer. */
6419 copy_body_data cb;
6420 omp_context *ctx;
6423 static tree
6424 task_copyfn_copy_decl (tree var, copy_body_data *cb)
6426 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
6428 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
6429 return create_tmp_var (TREE_TYPE (var), NULL);
6431 return var;
6434 static tree
6435 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
6437 tree name, new_fields = NULL, type, f;
6439 type = lang_hooks.types.make_type (RECORD_TYPE);
6440 name = DECL_NAME (TYPE_NAME (orig_type));
6441 name = build_decl (gimple_location (tcctx->ctx->stmt),
6442 TYPE_DECL, name, type);
6443 TYPE_NAME (type) = name;
6445 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
6447 tree new_f = copy_node (f);
6448 DECL_CONTEXT (new_f) = type;
6449 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
6450 TREE_CHAIN (new_f) = new_fields;
6451 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6452 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6453 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
6454 &tcctx->cb, NULL);
6455 new_fields = new_f;
6456 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
6458 TYPE_FIELDS (type) = nreverse (new_fields);
6459 layout_type (type);
6460 return type;
6463 /* Create task copyfn. */
6465 static void
6466 create_task_copyfn (gimple task_stmt, omp_context *ctx)
6468 struct function *child_cfun;
6469 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
6470 tree record_type, srecord_type, bind, list;
6471 bool record_needs_remap = false, srecord_needs_remap = false;
6472 splay_tree_node n;
6473 struct omp_taskcopy_context tcctx;
6474 struct gimplify_ctx gctx;
6475 location_t loc = gimple_location (task_stmt);
6477 child_fn = gimple_omp_task_copy_fn (task_stmt);
6478 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6479 gcc_assert (child_cfun->cfg == NULL);
6480 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
6482 /* Reset DECL_CONTEXT on function arguments. */
6483 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6484 DECL_CONTEXT (t) = child_fn;
6486 /* Populate the function. */
6487 push_gimplify_context (&gctx);
6488 current_function_decl = child_fn;
6490 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6491 TREE_SIDE_EFFECTS (bind) = 1;
6492 list = NULL;
6493 DECL_SAVED_TREE (child_fn) = bind;
6494 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
6496 /* Remap src and dst argument types if needed. */
6497 record_type = ctx->record_type;
6498 srecord_type = ctx->srecord_type;
6499 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6500 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6502 record_needs_remap = true;
6503 break;
6505 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
6506 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6508 srecord_needs_remap = true;
6509 break;
6512 if (record_needs_remap || srecord_needs_remap)
6514 memset (&tcctx, '\0', sizeof (tcctx));
6515 tcctx.cb.src_fn = ctx->cb.src_fn;
6516 tcctx.cb.dst_fn = child_fn;
6517 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
6518 gcc_checking_assert (tcctx.cb.src_node);
6519 tcctx.cb.dst_node = tcctx.cb.src_node;
6520 tcctx.cb.src_cfun = ctx->cb.src_cfun;
6521 tcctx.cb.copy_decl = task_copyfn_copy_decl;
6522 tcctx.cb.eh_lp_nr = 0;
6523 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
6524 tcctx.cb.decl_map = pointer_map_create ();
6525 tcctx.ctx = ctx;
6527 if (record_needs_remap)
6528 record_type = task_copyfn_remap_type (&tcctx, record_type);
6529 if (srecord_needs_remap)
6530 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
6532 else
6533 tcctx.cb.decl_map = NULL;
6535 push_cfun (child_cfun);
6537 arg = DECL_ARGUMENTS (child_fn);
6538 TREE_TYPE (arg) = build_pointer_type (record_type);
6539 sarg = DECL_CHAIN (arg);
6540 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
6542 /* First pass: initialize temporaries used in record_type and srecord_type
6543 sizes and field offsets. */
6544 if (tcctx.cb.decl_map)
6545 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6548 tree *p;
6550 decl = OMP_CLAUSE_DECL (c);
6551 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
6552 if (p == NULL)
6553 continue;
6554 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6555 sf = (tree) n->value;
6556 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6557 src = build_simple_mem_ref_loc (loc, sarg);
6558 src = omp_build_component_ref (src, sf);
6559 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
6560 append_to_statement_list (t, &list);
6563 /* Second pass: copy shared var pointers and copy construct non-VLA
6564 firstprivate vars. */
6565 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6566 switch (OMP_CLAUSE_CODE (c))
6568 case OMP_CLAUSE_SHARED:
6569 decl = OMP_CLAUSE_DECL (c);
6570 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6571 if (n == NULL)
6572 break;
6573 f = (tree) n->value;
6574 if (tcctx.cb.decl_map)
6575 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6576 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6577 sf = (tree) n->value;
6578 if (tcctx.cb.decl_map)
6579 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6580 src = build_simple_mem_ref_loc (loc, sarg);
6581 src = omp_build_component_ref (src, sf);
6582 dst = build_simple_mem_ref_loc (loc, arg);
6583 dst = omp_build_component_ref (dst, f);
6584 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6585 append_to_statement_list (t, &list);
6586 break;
6587 case OMP_CLAUSE_FIRSTPRIVATE:
6588 decl = OMP_CLAUSE_DECL (c);
6589 if (is_variable_sized (decl))
6590 break;
6591 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6592 if (n == NULL)
6593 break;
6594 f = (tree) n->value;
6595 if (tcctx.cb.decl_map)
6596 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6597 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6598 if (n != NULL)
6600 sf = (tree) n->value;
6601 if (tcctx.cb.decl_map)
6602 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6603 src = build_simple_mem_ref_loc (loc, sarg);
6604 src = omp_build_component_ref (src, sf);
6605 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6606 src = build_simple_mem_ref_loc (loc, src);
6608 else
6609 src = decl;
6610 dst = build_simple_mem_ref_loc (loc, arg);
6611 dst = omp_build_component_ref (dst, f);
6612 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6613 append_to_statement_list (t, &list);
6614 break;
6615 case OMP_CLAUSE_PRIVATE:
6616 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6617 break;
6618 decl = OMP_CLAUSE_DECL (c);
6619 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6620 f = (tree) n->value;
6621 if (tcctx.cb.decl_map)
6622 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6623 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6624 if (n != NULL)
6626 sf = (tree) n->value;
6627 if (tcctx.cb.decl_map)
6628 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6629 src = build_simple_mem_ref_loc (loc, sarg);
6630 src = omp_build_component_ref (src, sf);
6631 if (use_pointer_for_field (decl, NULL))
6632 src = build_simple_mem_ref_loc (loc, src);
6634 else
6635 src = decl;
6636 dst = build_simple_mem_ref_loc (loc, arg);
6637 dst = omp_build_component_ref (dst, f);
6638 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6639 append_to_statement_list (t, &list);
6640 break;
6641 default:
6642 break;
6645 /* Last pass: handle VLA firstprivates. */
6646 if (tcctx.cb.decl_map)
6647 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6648 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6650 tree ind, ptr, df;
6652 decl = OMP_CLAUSE_DECL (c);
6653 if (!is_variable_sized (decl))
6654 continue;
6655 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6656 if (n == NULL)
6657 continue;
6658 f = (tree) n->value;
6659 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6660 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6661 ind = DECL_VALUE_EXPR (decl);
6662 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6663 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6664 n = splay_tree_lookup (ctx->sfield_map,
6665 (splay_tree_key) TREE_OPERAND (ind, 0));
6666 sf = (tree) n->value;
6667 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6668 src = build_simple_mem_ref_loc (loc, sarg);
6669 src = omp_build_component_ref (src, sf);
6670 src = build_simple_mem_ref_loc (loc, src);
6671 dst = build_simple_mem_ref_loc (loc, arg);
6672 dst = omp_build_component_ref (dst, f);
6673 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6674 append_to_statement_list (t, &list);
6675 n = splay_tree_lookup (ctx->field_map,
6676 (splay_tree_key) TREE_OPERAND (ind, 0));
6677 df = (tree) n->value;
6678 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6679 ptr = build_simple_mem_ref_loc (loc, arg);
6680 ptr = omp_build_component_ref (ptr, df);
6681 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
6682 build_fold_addr_expr_loc (loc, dst));
6683 append_to_statement_list (t, &list);
6686 t = build1 (RETURN_EXPR, void_type_node, NULL);
6687 append_to_statement_list (t, &list);
6689 if (tcctx.cb.decl_map)
6690 pointer_map_destroy (tcctx.cb.decl_map);
6691 pop_gimplify_context (NULL);
6692 BIND_EXPR_BODY (bind) = list;
6693 pop_cfun ();
6694 current_function_decl = ctx->cb.src_fn;
6697 /* Lower the OpenMP parallel or task directive in the current statement
6698 in GSI_P. CTX holds context information for the directive. */
6700 static void
6701 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6703 tree clauses;
6704 tree child_fn, t;
6705 gimple stmt = gsi_stmt (*gsi_p);
6706 gimple par_bind, bind;
6707 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
6708 struct gimplify_ctx gctx;
6709 location_t loc = gimple_location (stmt);
6711 clauses = gimple_omp_taskreg_clauses (stmt);
6712 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
6713 par_body = gimple_bind_body (par_bind);
6714 child_fn = ctx->cb.dst_fn;
6715 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6716 && !gimple_omp_parallel_combined_p (stmt))
6718 struct walk_stmt_info wi;
6719 int ws_num = 0;
6721 memset (&wi, 0, sizeof (wi));
6722 wi.info = &ws_num;
6723 wi.val_only = true;
6724 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
6725 if (ws_num == 1)
6726 gimple_omp_parallel_set_combined_p (stmt, true);
6728 if (ctx->srecord_type)
6729 create_task_copyfn (stmt, ctx);
6731 push_gimplify_context (&gctx);
6733 par_olist = NULL;
6734 par_ilist = NULL;
6735 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6736 lower_omp (&par_body, ctx);
6737 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
6738 lower_reduction_clauses (clauses, &par_olist, ctx);
6740 /* Declare all the variables created by mapping and the variables
6741 declared in the scope of the parallel body. */
6742 record_vars_into (ctx->block_vars, child_fn);
6743 record_vars_into (gimple_bind_vars (par_bind), child_fn);
6745 if (ctx->record_type)
6747 ctx->sender_decl
6748 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6749 : ctx->record_type, ".omp_data_o");
6750 DECL_NAMELESS (ctx->sender_decl) = 1;
6751 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
6752 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
6755 olist = NULL;
6756 ilist = NULL;
6757 lower_send_clauses (clauses, &ilist, &olist, ctx);
6758 lower_send_shared_vars (&ilist, &olist, ctx);
6760 /* Once all the expansions are done, sequence all the different
6761 fragments inside gimple_omp_body. */
6763 new_body = NULL;
6765 if (ctx->record_type)
6767 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6768 /* fixup_child_record_type might have changed receiver_decl's type. */
6769 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
6770 gimple_seq_add_stmt (&new_body,
6771 gimple_build_assign (ctx->receiver_decl, t));
6774 gimple_seq_add_seq (&new_body, par_ilist);
6775 gimple_seq_add_seq (&new_body, par_body);
6776 gimple_seq_add_seq (&new_body, par_olist);
6777 new_body = maybe_catch_exception (new_body);
6778 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
6779 gimple_omp_set_body (stmt, new_body);
6781 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
6782 gsi_replace (gsi_p, bind, true);
6783 gimple_bind_add_seq (bind, ilist);
6784 gimple_bind_add_stmt (bind, stmt);
6785 gimple_bind_add_seq (bind, olist);
6787 pop_gimplify_context (NULL);
6790 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
6791 regimplified. If DATA is non-NULL, lower_omp_1 is outside
6792 of OpenMP context, but with task_shared_vars set. */
6794 static tree
6795 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
6796 void *data)
6798 tree t = *tp;
6800 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6801 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
6802 return t;
6804 if (task_shared_vars
6805 && DECL_P (t)
6806 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
6807 return t;
6809 /* If a global variable has been privatized, TREE_CONSTANT on
6810 ADDR_EXPR might be wrong. */
6811 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
6812 recompute_tree_invariant_for_addr_expr (t);
6814 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6815 return NULL_TREE;
6818 static void
6819 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6821 gimple stmt = gsi_stmt (*gsi_p);
6822 struct walk_stmt_info wi;
6824 if (gimple_has_location (stmt))
6825 input_location = gimple_location (stmt);
6827 if (task_shared_vars)
6828 memset (&wi, '\0', sizeof (wi));
6830 /* If we have issued syntax errors, avoid doing any heavy lifting.
6831 Just replace the OpenMP directives with a NOP to avoid
6832 confusing RTL expansion. */
6833 if (seen_error () && is_gimple_omp (stmt))
6835 gsi_replace (gsi_p, gimple_build_nop (), true);
6836 return;
6839 switch (gimple_code (stmt))
6841 case GIMPLE_COND:
6842 if ((ctx || task_shared_vars)
6843 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
6844 ctx ? NULL : &wi, NULL)
6845 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
6846 ctx ? NULL : &wi, NULL)))
6847 gimple_regimplify_operands (stmt, gsi_p);
6848 break;
6849 case GIMPLE_CATCH:
6850 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
6851 break;
6852 case GIMPLE_EH_FILTER:
6853 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
6854 break;
6855 case GIMPLE_TRY:
6856 lower_omp (gimple_try_eval_ptr (stmt), ctx);
6857 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
6858 break;
6859 case GIMPLE_BIND:
6860 lower_omp (gimple_bind_body_ptr (stmt), ctx);
6861 break;
6862 case GIMPLE_OMP_PARALLEL:
6863 case GIMPLE_OMP_TASK:
6864 ctx = maybe_lookup_ctx (stmt);
6865 lower_omp_taskreg (gsi_p, ctx);
6866 break;
6867 case GIMPLE_OMP_FOR:
6868 ctx = maybe_lookup_ctx (stmt);
6869 gcc_assert (ctx);
6870 lower_omp_for (gsi_p, ctx);
6871 break;
6872 case GIMPLE_OMP_SECTIONS:
6873 ctx = maybe_lookup_ctx (stmt);
6874 gcc_assert (ctx);
6875 lower_omp_sections (gsi_p, ctx);
6876 break;
6877 case GIMPLE_OMP_SINGLE:
6878 ctx = maybe_lookup_ctx (stmt);
6879 gcc_assert (ctx);
6880 lower_omp_single (gsi_p, ctx);
6881 break;
6882 case GIMPLE_OMP_MASTER:
6883 ctx = maybe_lookup_ctx (stmt);
6884 gcc_assert (ctx);
6885 lower_omp_master (gsi_p, ctx);
6886 break;
6887 case GIMPLE_OMP_ORDERED:
6888 ctx = maybe_lookup_ctx (stmt);
6889 gcc_assert (ctx);
6890 lower_omp_ordered (gsi_p, ctx);
6891 break;
6892 case GIMPLE_OMP_CRITICAL:
6893 ctx = maybe_lookup_ctx (stmt);
6894 gcc_assert (ctx);
6895 lower_omp_critical (gsi_p, ctx);
6896 break;
6897 case GIMPLE_OMP_ATOMIC_LOAD:
6898 if ((ctx || task_shared_vars)
6899 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
6900 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
6901 gimple_regimplify_operands (stmt, gsi_p);
6902 break;
6903 default:
6904 if ((ctx || task_shared_vars)
6905 && walk_gimple_op (stmt, lower_omp_regimplify_p,
6906 ctx ? NULL : &wi))
6907 gimple_regimplify_operands (stmt, gsi_p);
6908 break;
6912 static void
6913 lower_omp (gimple_seq *body, omp_context *ctx)
6915 location_t saved_location = input_location;
6916 gimple_stmt_iterator gsi;
6917 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
6918 lower_omp_1 (&gsi, ctx);
6919 input_location = saved_location;
6922 /* Main entry point. */
6924 static unsigned int
6925 execute_lower_omp (void)
6927 gimple_seq body;
6929 /* This pass always runs, to provide PROP_gimple_lomp.
6930 But there is nothing to do unless -fopenmp is given. */
6931 if (flag_openmp == 0)
6932 return 0;
6934 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
6935 delete_omp_context);
6937 body = gimple_body (current_function_decl);
6938 scan_omp (&body, NULL);
6939 gcc_assert (taskreg_nesting_level == 0);
6941 if (all_contexts->root)
6943 struct gimplify_ctx gctx;
6945 if (task_shared_vars)
6946 push_gimplify_context (&gctx);
6947 lower_omp (&body, NULL);
6948 if (task_shared_vars)
6949 pop_gimplify_context (NULL);
6952 if (all_contexts)
6954 splay_tree_delete (all_contexts);
6955 all_contexts = NULL;
6957 BITMAP_FREE (task_shared_vars);
6958 return 0;
6961 struct gimple_opt_pass pass_lower_omp =
6964 GIMPLE_PASS,
6965 "omplower", /* name */
6966 NULL, /* gate */
6967 execute_lower_omp, /* execute */
6968 NULL, /* sub */
6969 NULL, /* next */
6970 0, /* static_pass_number */
6971 TV_NONE, /* tv_id */
6972 PROP_gimple_any, /* properties_required */
6973 PROP_gimple_lomp, /* properties_provided */
6974 0, /* properties_destroyed */
6975 0, /* todo_flags_start */
6976 0 /* todo_flags_finish */
6980 /* The following is a utility to diagnose OpenMP structured block violations.
6981 It is not part of the "omplower" pass, as that's invoked too late. It
6982 should be invoked by the respective front ends after gimplification. */
6984 static splay_tree all_labels;
6986 /* Check for mismatched contexts and generate an error if needed. Return
6987 true if an error is detected. */
6989 static bool
6990 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
6991 gimple branch_ctx, gimple label_ctx)
6993 if (label_ctx == branch_ctx)
6994 return false;
6998 Previously we kept track of the label's entire context in diagnose_sb_[12]
6999 so we could traverse it and issue a correct "exit" or "enter" error
7000 message upon a structured block violation.
7002 We built the context by building a list with tree_cons'ing, but there is
7003 no easy counterpart in gimple tuples. It seems like far too much work
7004 for issuing exit/enter error messages. If someone really misses the
7005 distinct error message... patches welcome.
7008 #if 0
7009 /* Try to avoid confusing the user by producing and error message
7010 with correct "exit" or "enter" verbiage. We prefer "exit"
7011 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
7012 if (branch_ctx == NULL)
7013 exit_p = false;
7014 else
7016 while (label_ctx)
7018 if (TREE_VALUE (label_ctx) == branch_ctx)
7020 exit_p = false;
7021 break;
7023 label_ctx = TREE_CHAIN (label_ctx);
7027 if (exit_p)
7028 error ("invalid exit from OpenMP structured block");
7029 else
7030 error ("invalid entry to OpenMP structured block");
7031 #endif
7033 /* If it's obvious we have an invalid entry, be specific about the error. */
7034 if (branch_ctx == NULL)
7035 error ("invalid entry to OpenMP structured block");
7036 else
7037 /* Otherwise, be vague and lazy, but efficient. */
7038 error ("invalid branch to/from an OpenMP structured block");
7040 gsi_replace (gsi_p, gimple_build_nop (), false);
7041 return true;
7044 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
7045 where each label is found. */
7047 static tree
7048 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7049 struct walk_stmt_info *wi)
7051 gimple context = (gimple) wi->info;
7052 gimple inner_context;
7053 gimple stmt = gsi_stmt (*gsi_p);
7055 *handled_ops_p = true;
7057 switch (gimple_code (stmt))
7059 WALK_SUBSTMTS;
7061 case GIMPLE_OMP_PARALLEL:
7062 case GIMPLE_OMP_TASK:
7063 case GIMPLE_OMP_SECTIONS:
7064 case GIMPLE_OMP_SINGLE:
7065 case GIMPLE_OMP_SECTION:
7066 case GIMPLE_OMP_MASTER:
7067 case GIMPLE_OMP_ORDERED:
7068 case GIMPLE_OMP_CRITICAL:
7069 /* The minimal context here is just the current OMP construct. */
7070 inner_context = stmt;
7071 wi->info = inner_context;
7072 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7073 wi->info = context;
7074 break;
7076 case GIMPLE_OMP_FOR:
7077 inner_context = stmt;
7078 wi->info = inner_context;
7079 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7080 walk them. */
7081 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
7082 diagnose_sb_1, NULL, wi);
7083 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7084 wi->info = context;
7085 break;
7087 case GIMPLE_LABEL:
7088 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
7089 (splay_tree_value) context);
7090 break;
7092 default:
7093 break;
7096 return NULL_TREE;
7099 /* Pass 2: Check each branch and see if its context differs from that of
7100 the destination label's context. */
7102 static tree
7103 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7104 struct walk_stmt_info *wi)
7106 gimple context = (gimple) wi->info;
7107 splay_tree_node n;
7108 gimple stmt = gsi_stmt (*gsi_p);
7110 *handled_ops_p = true;
7112 switch (gimple_code (stmt))
7114 WALK_SUBSTMTS;
7116 case GIMPLE_OMP_PARALLEL:
7117 case GIMPLE_OMP_TASK:
7118 case GIMPLE_OMP_SECTIONS:
7119 case GIMPLE_OMP_SINGLE:
7120 case GIMPLE_OMP_SECTION:
7121 case GIMPLE_OMP_MASTER:
7122 case GIMPLE_OMP_ORDERED:
7123 case GIMPLE_OMP_CRITICAL:
7124 wi->info = stmt;
7125 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7126 wi->info = context;
7127 break;
7129 case GIMPLE_OMP_FOR:
7130 wi->info = stmt;
7131 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7132 walk them. */
7133 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
7134 diagnose_sb_2, NULL, wi);
7135 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7136 wi->info = context;
7137 break;
7139 case GIMPLE_COND:
7141 tree lab = gimple_cond_true_label (stmt);
7142 if (lab)
7144 n = splay_tree_lookup (all_labels,
7145 (splay_tree_key) lab);
7146 diagnose_sb_0 (gsi_p, context,
7147 n ? (gimple) n->value : NULL);
7149 lab = gimple_cond_false_label (stmt);
7150 if (lab)
7152 n = splay_tree_lookup (all_labels,
7153 (splay_tree_key) lab);
7154 diagnose_sb_0 (gsi_p, context,
7155 n ? (gimple) n->value : NULL);
7158 break;
7160 case GIMPLE_GOTO:
7162 tree lab = gimple_goto_dest (stmt);
7163 if (TREE_CODE (lab) != LABEL_DECL)
7164 break;
7166 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7167 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
7169 break;
7171 case GIMPLE_SWITCH:
7173 unsigned int i;
7174 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
7176 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
7177 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7178 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
7179 break;
7182 break;
7184 case GIMPLE_RETURN:
7185 diagnose_sb_0 (gsi_p, context, NULL);
7186 break;
7188 default:
7189 break;
7192 return NULL_TREE;
7195 static unsigned int
7196 diagnose_omp_structured_block_errors (void)
7198 struct walk_stmt_info wi;
7199 gimple_seq body = gimple_body (current_function_decl);
7201 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
7203 memset (&wi, 0, sizeof (wi));
7204 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
7206 memset (&wi, 0, sizeof (wi));
7207 wi.want_locations = true;
7208 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
7210 gimple_set_body (current_function_decl, body);
7212 splay_tree_delete (all_labels);
7213 all_labels = NULL;
7215 return 0;
7218 static bool
7219 gate_diagnose_omp_blocks (void)
7221 return flag_openmp != 0;
7224 struct gimple_opt_pass pass_diagnose_omp_blocks =
7227 GIMPLE_PASS,
7228 "*diagnose_omp_blocks", /* name */
7229 gate_diagnose_omp_blocks, /* gate */
7230 diagnose_omp_structured_block_errors, /* execute */
7231 NULL, /* sub */
7232 NULL, /* next */
7233 0, /* static_pass_number */
7234 TV_NONE, /* tv_id */
7235 PROP_gimple_any, /* properties_required */
7236 0, /* properties_provided */
7237 0, /* properties_destroyed */
7238 0, /* todo_flags_start */
7239 0, /* todo_flags_finish */
7243 #include "gt-omp-low.h"