Mark ChangeLog
[official-gcc.git] / gcc / omp-low.c
blobfc7c9910168d003b41e5b87cdc914b8f386f44b2
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
6 Copyright (C) 2005-2013 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "gimple.h"
31 #include "tree-iterator.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic-core.h"
35 #include "tree-flow.h"
36 #include "flags.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "tree-pass.h"
40 #include "ggc.h"
41 #include "except.h"
42 #include "splay-tree.h"
43 #include "optabs.h"
44 #include "cfgloop.h"
47 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
48 phases. The first phase scans the function looking for OMP statements
49 and then for variables that must be replaced to satisfy data sharing
50 clauses. The second phase expands code for the constructs, as well as
51 re-gimplifying things when variables have been replaced with complex
52 expressions.
54 Final code generation is done by pass_expand_omp. The flowgraph is
55 scanned for parallel regions which are then moved to a new
56 function, to be invoked by the thread library. */
58 /* Context structure. Used to store information about each parallel
59 directive in the code. */
61 typedef struct omp_context
63 /* This field must be at the beginning, as we do "inheritance": Some
64 callback functions for tree-inline.c (e.g., omp_copy_decl)
65 receive a copy_body_data pointer that is up-casted to an
66 omp_context pointer. */
67 copy_body_data cb;
69 /* The tree of contexts corresponding to the encountered constructs. */
70 struct omp_context *outer;
71 gimple stmt;
73 /* Map variables to fields in a structure that allows communication
74 between sending and receiving threads. */
75 splay_tree field_map;
76 tree record_type;
77 tree sender_decl;
78 tree receiver_decl;
80 /* These are used just by task contexts, if task firstprivate fn is
81 needed. srecord_type is used to communicate from the thread
82 that encountered the task construct to task firstprivate fn,
83 record_type is allocated by GOMP_task, initialized by task firstprivate
84 fn and passed to the task body fn. */
85 splay_tree sfield_map;
86 tree srecord_type;
88 /* A chain of variables to add to the top-level block surrounding the
89 construct. In the case of a parallel, this is in the child function. */
90 tree block_vars;
92 /* What to do with variables with implicitly determined sharing
93 attributes. */
94 enum omp_clause_default_kind default_kind;
96 /* Nesting depth of this context. Used to beautify error messages re
97 invalid gotos. The outermost ctx is depth 1, with depth 0 being
98 reserved for the main body of the function. */
99 int depth;
101 /* True if this parallel directive is nested within another. */
102 bool is_nested;
103 } omp_context;
106 struct omp_for_data_loop
108 tree v, n1, n2, step;
109 enum tree_code cond_code;
112 /* A structure describing the main elements of a parallel loop. */
114 struct omp_for_data
116 struct omp_for_data_loop loop;
117 tree chunk_size;
118 gimple for_stmt;
119 tree pre, iter_type;
120 int collapse;
121 bool have_nowait, have_ordered;
122 enum omp_clause_schedule_kind sched_kind;
123 struct omp_for_data_loop *loops;
127 static splay_tree all_contexts;
128 static int taskreg_nesting_level;
129 struct omp_region *root_omp_region;
130 static bitmap task_shared_vars;
131 static vec<omp_context *> taskreg_contexts;
133 static void scan_omp (gimple_seq *, omp_context *);
134 static tree scan_omp_1_op (tree *, int *, void *);
136 #define WALK_SUBSTMTS \
137 case GIMPLE_BIND: \
138 case GIMPLE_TRY: \
139 case GIMPLE_CATCH: \
140 case GIMPLE_EH_FILTER: \
141 case GIMPLE_TRANSACTION: \
142 /* The sub-statements for these should be walked. */ \
143 *handled_ops_p = false; \
144 break;
146 /* Convenience function for calling scan_omp_1_op on tree operands. */
148 static inline tree
149 scan_omp_op (tree *tp, omp_context *ctx)
151 struct walk_stmt_info wi;
153 memset (&wi, 0, sizeof (wi));
154 wi.info = ctx;
155 wi.want_locations = true;
157 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
160 static void lower_omp (gimple_seq *, omp_context *);
161 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
162 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
164 /* Find an OpenMP clause of type KIND within CLAUSES. */
166 tree
167 find_omp_clause (tree clauses, enum omp_clause_code kind)
169 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
170 if (OMP_CLAUSE_CODE (clauses) == kind)
171 return clauses;
173 return NULL_TREE;
176 /* Return true if CTX is for an omp parallel. */
178 static inline bool
179 is_parallel_ctx (omp_context *ctx)
181 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
185 /* Return true if CTX is for an omp task. */
187 static inline bool
188 is_task_ctx (omp_context *ctx)
190 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
194 /* Return true if CTX is for an omp parallel or omp task. */
196 static inline bool
197 is_taskreg_ctx (omp_context *ctx)
199 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
200 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
204 /* Return true if REGION is a combined parallel+workshare region. */
206 static inline bool
207 is_combined_parallel (struct omp_region *region)
209 return region->is_combined_parallel;
213 /* Extract the header elements of parallel loop FOR_STMT and store
214 them into *FD. */
216 static void
217 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
218 struct omp_for_data_loop *loops)
220 tree t, var, *collapse_iter, *collapse_count;
221 tree count = NULL_TREE, iter_type = long_integer_type_node;
222 struct omp_for_data_loop *loop;
223 int i;
224 struct omp_for_data_loop dummy_loop;
225 location_t loc = gimple_location (for_stmt);
227 fd->for_stmt = for_stmt;
228 fd->pre = NULL;
229 fd->collapse = gimple_omp_for_collapse (for_stmt);
230 if (fd->collapse > 1)
231 fd->loops = loops;
232 else
233 fd->loops = &fd->loop;
235 fd->have_nowait = fd->have_ordered = false;
236 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
237 fd->chunk_size = NULL_TREE;
238 collapse_iter = NULL;
239 collapse_count = NULL;
241 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
242 switch (OMP_CLAUSE_CODE (t))
244 case OMP_CLAUSE_NOWAIT:
245 fd->have_nowait = true;
246 break;
247 case OMP_CLAUSE_ORDERED:
248 fd->have_ordered = true;
249 break;
250 case OMP_CLAUSE_SCHEDULE:
251 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
252 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
253 break;
254 case OMP_CLAUSE_COLLAPSE:
255 if (fd->collapse > 1)
257 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
258 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
260 default:
261 break;
264 /* FIXME: for now map schedule(auto) to schedule(static).
265 There should be analysis to determine whether all iterations
266 are approximately the same amount of work (then schedule(static)
267 is best) or if it varies (then schedule(dynamic,N) is better). */
268 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
270 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
271 gcc_assert (fd->chunk_size == NULL);
273 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
274 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
275 gcc_assert (fd->chunk_size == NULL);
276 else if (fd->chunk_size == NULL)
278 /* We only need to compute a default chunk size for ordered
279 static loops and dynamic loops. */
280 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
281 || fd->have_ordered
282 || fd->collapse > 1)
283 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
284 ? integer_zero_node : integer_one_node;
287 for (i = 0; i < fd->collapse; i++)
289 if (fd->collapse == 1)
290 loop = &fd->loop;
291 else if (loops != NULL)
292 loop = loops + i;
293 else
294 loop = &dummy_loop;
297 loop->v = gimple_omp_for_index (for_stmt, i);
298 gcc_assert (SSA_VAR_P (loop->v));
299 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
300 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
301 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
302 loop->n1 = gimple_omp_for_initial (for_stmt, i);
304 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
305 loop->n2 = gimple_omp_for_final (for_stmt, i);
306 switch (loop->cond_code)
308 case LT_EXPR:
309 case GT_EXPR:
310 break;
311 case LE_EXPR:
312 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
313 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
314 else
315 loop->n2 = fold_build2_loc (loc,
316 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
317 build_int_cst (TREE_TYPE (loop->n2), 1));
318 loop->cond_code = LT_EXPR;
319 break;
320 case GE_EXPR:
321 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
322 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
323 else
324 loop->n2 = fold_build2_loc (loc,
325 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
326 build_int_cst (TREE_TYPE (loop->n2), 1));
327 loop->cond_code = GT_EXPR;
328 break;
329 default:
330 gcc_unreachable ();
333 t = gimple_omp_for_incr (for_stmt, i);
334 gcc_assert (TREE_OPERAND (t, 0) == var);
335 switch (TREE_CODE (t))
337 case PLUS_EXPR:
338 loop->step = TREE_OPERAND (t, 1);
339 break;
340 case POINTER_PLUS_EXPR:
341 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
342 break;
343 case MINUS_EXPR:
344 loop->step = TREE_OPERAND (t, 1);
345 loop->step = fold_build1_loc (loc,
346 NEGATE_EXPR, TREE_TYPE (loop->step),
347 loop->step);
348 break;
349 default:
350 gcc_unreachable ();
353 if (iter_type != long_long_unsigned_type_node)
355 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
356 iter_type = long_long_unsigned_type_node;
357 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
358 && TYPE_PRECISION (TREE_TYPE (loop->v))
359 >= TYPE_PRECISION (iter_type))
361 tree n;
363 if (loop->cond_code == LT_EXPR)
364 n = fold_build2_loc (loc,
365 PLUS_EXPR, TREE_TYPE (loop->v),
366 loop->n2, loop->step);
367 else
368 n = loop->n1;
369 if (TREE_CODE (n) != INTEGER_CST
370 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
371 iter_type = long_long_unsigned_type_node;
373 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
374 > TYPE_PRECISION (iter_type))
376 tree n1, n2;
378 if (loop->cond_code == LT_EXPR)
380 n1 = loop->n1;
381 n2 = fold_build2_loc (loc,
382 PLUS_EXPR, TREE_TYPE (loop->v),
383 loop->n2, loop->step);
385 else
387 n1 = fold_build2_loc (loc,
388 MINUS_EXPR, TREE_TYPE (loop->v),
389 loop->n2, loop->step);
390 n2 = loop->n1;
392 if (TREE_CODE (n1) != INTEGER_CST
393 || TREE_CODE (n2) != INTEGER_CST
394 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
395 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
396 iter_type = long_long_unsigned_type_node;
400 if (collapse_count && *collapse_count == NULL)
402 t = fold_binary (loop->cond_code, boolean_type_node,
403 fold_convert (TREE_TYPE (loop->v), loop->n1),
404 fold_convert (TREE_TYPE (loop->v), loop->n2));
405 if (t && integer_zerop (t))
406 count = build_zero_cst (long_long_unsigned_type_node);
407 else if ((i == 0 || count != NULL_TREE)
408 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
409 && TREE_CONSTANT (loop->n1)
410 && TREE_CONSTANT (loop->n2)
411 && TREE_CODE (loop->step) == INTEGER_CST)
413 tree itype = TREE_TYPE (loop->v);
415 if (POINTER_TYPE_P (itype))
416 itype = signed_type_for (itype);
417 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
418 t = fold_build2_loc (loc,
419 PLUS_EXPR, itype,
420 fold_convert_loc (loc, itype, loop->step), t);
421 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
422 fold_convert_loc (loc, itype, loop->n2));
423 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
424 fold_convert_loc (loc, itype, loop->n1));
425 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
426 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
427 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
428 fold_build1_loc (loc, NEGATE_EXPR, itype,
429 fold_convert_loc (loc, itype,
430 loop->step)));
431 else
432 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
433 fold_convert_loc (loc, itype, loop->step));
434 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
435 if (count != NULL_TREE)
436 count = fold_build2_loc (loc,
437 MULT_EXPR, long_long_unsigned_type_node,
438 count, t);
439 else
440 count = t;
441 if (TREE_CODE (count) != INTEGER_CST)
442 count = NULL_TREE;
444 else if (count && !integer_zerop (count))
445 count = NULL_TREE;
449 if (count)
451 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
452 iter_type = long_long_unsigned_type_node;
453 else
454 iter_type = long_integer_type_node;
456 else if (collapse_iter && *collapse_iter != NULL)
457 iter_type = TREE_TYPE (*collapse_iter);
458 fd->iter_type = iter_type;
459 if (collapse_iter && *collapse_iter == NULL)
460 *collapse_iter = create_tmp_var (iter_type, ".iter");
461 if (collapse_count && *collapse_count == NULL)
463 if (count)
464 *collapse_count = fold_convert_loc (loc, iter_type, count);
465 else
466 *collapse_count = create_tmp_var (iter_type, ".count");
469 if (fd->collapse > 1)
471 fd->loop.v = *collapse_iter;
472 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
473 fd->loop.n2 = *collapse_count;
474 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
475 fd->loop.cond_code = LT_EXPR;
480 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
481 is the immediate dominator of PAR_ENTRY_BB, return true if there
482 are no data dependencies that would prevent expanding the parallel
483 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
485 When expanding a combined parallel+workshare region, the call to
486 the child function may need additional arguments in the case of
487 GIMPLE_OMP_FOR regions. In some cases, these arguments are
488 computed out of variables passed in from the parent to the child
489 via 'struct .omp_data_s'. For instance:
491 #pragma omp parallel for schedule (guided, i * 4)
492 for (j ...)
494 Is lowered into:
496 # BLOCK 2 (PAR_ENTRY_BB)
497 .omp_data_o.i = i;
498 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
500 # BLOCK 3 (WS_ENTRY_BB)
501 .omp_data_i = &.omp_data_o;
502 D.1667 = .omp_data_i->i;
503 D.1598 = D.1667 * 4;
504 #pragma omp for schedule (guided, D.1598)
506 When we outline the parallel region, the call to the child function
507 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
508 that value is computed *after* the call site. So, in principle we
509 cannot do the transformation.
511 To see whether the code in WS_ENTRY_BB blocks the combined
512 parallel+workshare call, we collect all the variables used in the
513 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
514 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
515 call.
517 FIXME. If we had the SSA form built at this point, we could merely
518 hoist the code in block 3 into block 2 and be done with it. But at
519 this point we don't have dataflow information and though we could
520 hack something up here, it is really not worth the aggravation. */
522 static bool
523 workshare_safe_to_combine_p (basic_block ws_entry_bb)
525 struct omp_for_data fd;
526 gimple ws_stmt = last_stmt (ws_entry_bb);
528 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
529 return true;
531 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
533 extract_omp_for_data (ws_stmt, &fd, NULL);
535 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
536 return false;
537 if (fd.iter_type != long_integer_type_node)
538 return false;
540 /* FIXME. We give up too easily here. If any of these arguments
541 are not constants, they will likely involve variables that have
542 been mapped into fields of .omp_data_s for sharing with the child
543 function. With appropriate data flow, it would be possible to
544 see through this. */
545 if (!is_gimple_min_invariant (fd.loop.n1)
546 || !is_gimple_min_invariant (fd.loop.n2)
547 || !is_gimple_min_invariant (fd.loop.step)
548 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
549 return false;
551 return true;
555 /* Collect additional arguments needed to emit a combined
556 parallel+workshare call. WS_STMT is the workshare directive being
557 expanded. */
559 static vec<tree, va_gc> *
560 get_ws_args_for (gimple ws_stmt)
562 tree t;
563 location_t loc = gimple_location (ws_stmt);
564 vec<tree, va_gc> *ws_args;
566 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
568 struct omp_for_data fd;
570 extract_omp_for_data (ws_stmt, &fd, NULL);
572 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
574 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
575 ws_args->quick_push (t);
577 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
578 ws_args->quick_push (t);
580 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
581 ws_args->quick_push (t);
583 if (fd.chunk_size)
585 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
586 ws_args->quick_push (t);
589 return ws_args;
591 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
593 /* Number of sections is equal to the number of edges from the
594 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
595 the exit of the sections region. */
596 basic_block bb = single_succ (gimple_bb (ws_stmt));
597 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
598 vec_alloc (ws_args, 1);
599 ws_args->quick_push (t);
600 return ws_args;
603 gcc_unreachable ();
607 /* Discover whether REGION is a combined parallel+workshare region. */
609 static void
610 determine_parallel_type (struct omp_region *region)
612 basic_block par_entry_bb, par_exit_bb;
613 basic_block ws_entry_bb, ws_exit_bb;
615 if (region == NULL || region->inner == NULL
616 || region->exit == NULL || region->inner->exit == NULL
617 || region->inner->cont == NULL)
618 return;
620 /* We only support parallel+for and parallel+sections. */
621 if (region->type != GIMPLE_OMP_PARALLEL
622 || (region->inner->type != GIMPLE_OMP_FOR
623 && region->inner->type != GIMPLE_OMP_SECTIONS))
624 return;
626 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
627 WS_EXIT_BB -> PAR_EXIT_BB. */
628 par_entry_bb = region->entry;
629 par_exit_bb = region->exit;
630 ws_entry_bb = region->inner->entry;
631 ws_exit_bb = region->inner->exit;
633 if (single_succ (par_entry_bb) == ws_entry_bb
634 && single_succ (ws_exit_bb) == par_exit_bb
635 && workshare_safe_to_combine_p (ws_entry_bb)
636 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
637 || (last_and_only_stmt (ws_entry_bb)
638 && last_and_only_stmt (par_exit_bb))))
640 gimple ws_stmt = last_stmt (ws_entry_bb);
642 if (region->inner->type == GIMPLE_OMP_FOR)
644 /* If this is a combined parallel loop, we need to determine
645 whether or not to use the combined library calls. There
646 are two cases where we do not apply the transformation:
647 static loops and any kind of ordered loop. In the first
648 case, we already open code the loop so there is no need
649 to do anything else. In the latter case, the combined
650 parallel loop call would still need extra synchronization
651 to implement ordered semantics, so there would not be any
652 gain in using the combined call. */
653 tree clauses = gimple_omp_for_clauses (ws_stmt);
654 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
655 if (c == NULL
656 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
657 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
659 region->is_combined_parallel = false;
660 region->inner->is_combined_parallel = false;
661 return;
665 region->is_combined_parallel = true;
666 region->inner->is_combined_parallel = true;
667 region->ws_args = get_ws_args_for (ws_stmt);
672 /* Return true if EXPR is variable sized. */
674 static inline bool
675 is_variable_sized (const_tree expr)
677 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
680 /* Return true if DECL is a reference type. */
682 static inline bool
683 is_reference (tree decl)
685 return lang_hooks.decls.omp_privatize_by_reference (decl);
688 /* Lookup variables in the decl or field splay trees. The "maybe" form
689 allows for the variable form to not have been entered, otherwise we
690 assert that the variable must have been entered. */
692 static inline tree
693 lookup_decl (tree var, omp_context *ctx)
695 tree *n;
696 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
697 return *n;
700 static inline tree
701 maybe_lookup_decl (const_tree var, omp_context *ctx)
703 tree *n;
704 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
705 return n ? *n : NULL_TREE;
708 static inline tree
709 lookup_field (tree var, omp_context *ctx)
711 splay_tree_node n;
712 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
713 return (tree) n->value;
716 static inline tree
717 lookup_sfield (tree var, omp_context *ctx)
719 splay_tree_node n;
720 n = splay_tree_lookup (ctx->sfield_map
721 ? ctx->sfield_map : ctx->field_map,
722 (splay_tree_key) var);
723 return (tree) n->value;
726 static inline tree
727 maybe_lookup_field (tree var, omp_context *ctx)
729 splay_tree_node n;
730 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
731 return n ? (tree) n->value : NULL_TREE;
734 /* Return true if DECL should be copied by pointer. SHARED_CTX is
735 the parallel context if DECL is to be shared. */
737 static bool
738 use_pointer_for_field (tree decl, omp_context *shared_ctx)
740 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
741 return true;
743 /* We can only use copy-in/copy-out semantics for shared variables
744 when we know the value is not accessible from an outer scope. */
745 if (shared_ctx)
747 /* ??? Trivially accessible from anywhere. But why would we even
748 be passing an address in this case? Should we simply assert
749 this to be false, or should we have a cleanup pass that removes
750 these from the list of mappings? */
751 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
752 return true;
754 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
755 without analyzing the expression whether or not its location
756 is accessible to anyone else. In the case of nested parallel
757 regions it certainly may be. */
758 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
759 return true;
761 /* Do not use copy-in/copy-out for variables that have their
762 address taken. */
763 if (TREE_ADDRESSABLE (decl))
764 return true;
766 /* lower_send_shared_vars only uses copy-in, but not copy-out
767 for these. */
768 if (TREE_READONLY (decl)
769 || ((TREE_CODE (decl) == RESULT_DECL
770 || TREE_CODE (decl) == PARM_DECL)
771 && DECL_BY_REFERENCE (decl)))
772 return false;
774 /* Disallow copy-in/out in nested parallel if
775 decl is shared in outer parallel, otherwise
776 each thread could store the shared variable
777 in its own copy-in location, making the
778 variable no longer really shared. */
779 if (shared_ctx->is_nested)
781 omp_context *up;
783 for (up = shared_ctx->outer; up; up = up->outer)
784 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
785 break;
787 if (up)
789 tree c;
791 for (c = gimple_omp_taskreg_clauses (up->stmt);
792 c; c = OMP_CLAUSE_CHAIN (c))
793 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
794 && OMP_CLAUSE_DECL (c) == decl)
795 break;
797 if (c)
798 goto maybe_mark_addressable_and_ret;
802 /* For tasks avoid using copy-in/out. As tasks can be
803 deferred or executed in different thread, when GOMP_task
804 returns, the task hasn't necessarily terminated. */
805 if (is_task_ctx (shared_ctx))
807 tree outer;
808 maybe_mark_addressable_and_ret:
809 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
810 if (is_gimple_reg (outer))
812 /* Taking address of OUTER in lower_send_shared_vars
813 might need regimplification of everything that uses the
814 variable. */
815 if (!task_shared_vars)
816 task_shared_vars = BITMAP_ALLOC (NULL);
817 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
818 TREE_ADDRESSABLE (outer) = 1;
820 return true;
824 return false;
827 /* Create a new VAR_DECL and copy information from VAR to it. */
829 tree
830 copy_var_decl (tree var, tree name, tree type)
832 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
834 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
835 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
836 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
837 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
838 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
839 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
840 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
841 TREE_USED (copy) = 1;
842 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
844 return copy;
847 /* Construct a new automatic decl similar to VAR. */
849 static tree
850 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
852 tree copy = copy_var_decl (var, name, type);
854 DECL_CONTEXT (copy) = current_function_decl;
855 DECL_CHAIN (copy) = ctx->block_vars;
856 ctx->block_vars = copy;
858 return copy;
861 static tree
862 omp_copy_decl_1 (tree var, omp_context *ctx)
864 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
867 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
868 as appropriate. */
869 static tree
870 omp_build_component_ref (tree obj, tree field)
872 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
873 if (TREE_THIS_VOLATILE (field))
874 TREE_THIS_VOLATILE (ret) |= 1;
875 if (TREE_READONLY (field))
876 TREE_READONLY (ret) |= 1;
877 return ret;
880 /* Build tree nodes to access the field for VAR on the receiver side. */
882 static tree
883 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
885 tree x, field = lookup_field (var, ctx);
887 /* If the receiver record type was remapped in the child function,
888 remap the field into the new record type. */
889 x = maybe_lookup_field (field, ctx);
890 if (x != NULL)
891 field = x;
893 x = build_simple_mem_ref (ctx->receiver_decl);
894 x = omp_build_component_ref (x, field);
895 if (by_ref)
896 x = build_simple_mem_ref (x);
898 return x;
901 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
902 of a parallel, this is a component reference; for workshare constructs
903 this is some variable. */
905 static tree
906 build_outer_var_ref (tree var, omp_context *ctx)
908 tree x;
910 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
911 x = var;
912 else if (is_variable_sized (var))
914 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
915 x = build_outer_var_ref (x, ctx);
916 x = build_simple_mem_ref (x);
918 else if (is_taskreg_ctx (ctx))
920 bool by_ref = use_pointer_for_field (var, NULL);
921 x = build_receiver_ref (var, by_ref, ctx);
923 else if (ctx->outer)
924 x = lookup_decl (var, ctx->outer);
925 else if (is_reference (var))
926 /* This can happen with orphaned constructs. If var is reference, it is
927 possible it is shared and as such valid. */
928 x = var;
929 else
930 gcc_unreachable ();
932 if (is_reference (var))
933 x = build_simple_mem_ref (x);
935 return x;
938 /* Build tree nodes to access the field for VAR on the sender side. */
940 static tree
941 build_sender_ref (tree var, omp_context *ctx)
943 tree field = lookup_sfield (var, ctx);
944 return omp_build_component_ref (ctx->sender_decl, field);
947 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
949 static void
950 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
952 tree field, type, sfield = NULL_TREE;
954 gcc_assert ((mask & 1) == 0
955 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
956 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
957 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
959 type = TREE_TYPE (var);
960 if (by_ref)
961 type = build_pointer_type (type);
962 else if ((mask & 3) == 1 && is_reference (var))
963 type = TREE_TYPE (type);
965 field = build_decl (DECL_SOURCE_LOCATION (var),
966 FIELD_DECL, DECL_NAME (var), type);
968 /* Remember what variable this field was created for. This does have a
969 side effect of making dwarf2out ignore this member, so for helpful
970 debugging we clear it later in delete_omp_context. */
971 DECL_ABSTRACT_ORIGIN (field) = var;
972 if (type == TREE_TYPE (var))
974 DECL_ALIGN (field) = DECL_ALIGN (var);
975 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
976 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
978 else
979 DECL_ALIGN (field) = TYPE_ALIGN (type);
981 if ((mask & 3) == 3)
983 insert_field_into_struct (ctx->record_type, field);
984 if (ctx->srecord_type)
986 sfield = build_decl (DECL_SOURCE_LOCATION (var),
987 FIELD_DECL, DECL_NAME (var), type);
988 DECL_ABSTRACT_ORIGIN (sfield) = var;
989 DECL_ALIGN (sfield) = DECL_ALIGN (field);
990 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
991 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
992 insert_field_into_struct (ctx->srecord_type, sfield);
995 else
997 if (ctx->srecord_type == NULL_TREE)
999 tree t;
1001 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1002 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1003 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1005 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1006 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1007 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1008 insert_field_into_struct (ctx->srecord_type, sfield);
1009 splay_tree_insert (ctx->sfield_map,
1010 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1011 (splay_tree_value) sfield);
1014 sfield = field;
1015 insert_field_into_struct ((mask & 1) ? ctx->record_type
1016 : ctx->srecord_type, field);
1019 if (mask & 1)
1020 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1021 (splay_tree_value) field);
1022 if ((mask & 2) && ctx->sfield_map)
1023 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1024 (splay_tree_value) sfield);
1027 static tree
1028 install_var_local (tree var, omp_context *ctx)
1030 tree new_var = omp_copy_decl_1 (var, ctx);
1031 insert_decl_map (&ctx->cb, var, new_var);
1032 return new_var;
1035 /* Adjust the replacement for DECL in CTX for the new context. This means
1036 copying the DECL_VALUE_EXPR, and fixing up the type. */
1038 static void
1039 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1041 tree new_decl, size;
1043 new_decl = lookup_decl (decl, ctx);
1045 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1047 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1048 && DECL_HAS_VALUE_EXPR_P (decl))
1050 tree ve = DECL_VALUE_EXPR (decl);
1051 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1052 SET_DECL_VALUE_EXPR (new_decl, ve);
1053 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1056 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1058 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1059 if (size == error_mark_node)
1060 size = TYPE_SIZE (TREE_TYPE (new_decl));
1061 DECL_SIZE (new_decl) = size;
1063 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1064 if (size == error_mark_node)
1065 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1066 DECL_SIZE_UNIT (new_decl) = size;
1070 /* The callback for remap_decl. Search all containing contexts for a
1071 mapping of the variable; this avoids having to duplicate the splay
1072 tree ahead of time. We know a mapping doesn't already exist in the
1073 given context. Create new mappings to implement default semantics. */
1075 static tree
1076 omp_copy_decl (tree var, copy_body_data *cb)
1078 omp_context *ctx = (omp_context *) cb;
1079 tree new_var;
1081 if (TREE_CODE (var) == LABEL_DECL)
1083 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1084 DECL_CONTEXT (new_var) = current_function_decl;
1085 insert_decl_map (&ctx->cb, var, new_var);
1086 return new_var;
1089 while (!is_taskreg_ctx (ctx))
1091 ctx = ctx->outer;
1092 if (ctx == NULL)
1093 return var;
1094 new_var = maybe_lookup_decl (var, ctx);
1095 if (new_var)
1096 return new_var;
1099 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1100 return var;
1102 return error_mark_node;
1106 /* Return the parallel region associated with STMT. */
1108 /* Debugging dumps for parallel regions. */
1109 void dump_omp_region (FILE *, struct omp_region *, int);
1110 void debug_omp_region (struct omp_region *);
1111 void debug_all_omp_regions (void);
1113 /* Dump the parallel region tree rooted at REGION. */
1115 void
1116 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1118 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1119 gimple_code_name[region->type]);
1121 if (region->inner)
1122 dump_omp_region (file, region->inner, indent + 4);
1124 if (region->cont)
1126 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1127 region->cont->index);
1130 if (region->exit)
1131 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1132 region->exit->index);
1133 else
1134 fprintf (file, "%*s[no exit marker]\n", indent, "");
1136 if (region->next)
1137 dump_omp_region (file, region->next, indent);
1140 DEBUG_FUNCTION void
1141 debug_omp_region (struct omp_region *region)
1143 dump_omp_region (stderr, region, 0);
1146 DEBUG_FUNCTION void
1147 debug_all_omp_regions (void)
1149 dump_omp_region (stderr, root_omp_region, 0);
1153 /* Create a new parallel region starting at STMT inside region PARENT. */
1155 struct omp_region *
1156 new_omp_region (basic_block bb, enum gimple_code type,
1157 struct omp_region *parent)
1159 struct omp_region *region = XCNEW (struct omp_region);
1161 region->outer = parent;
1162 region->entry = bb;
1163 region->type = type;
1165 if (parent)
1167 /* This is a nested region. Add it to the list of inner
1168 regions in PARENT. */
1169 region->next = parent->inner;
1170 parent->inner = region;
1172 else
1174 /* This is a toplevel region. Add it to the list of toplevel
1175 regions in ROOT_OMP_REGION. */
1176 region->next = root_omp_region;
1177 root_omp_region = region;
1180 return region;
1183 /* Release the memory associated with the region tree rooted at REGION. */
1185 static void
1186 free_omp_region_1 (struct omp_region *region)
1188 struct omp_region *i, *n;
1190 for (i = region->inner; i ; i = n)
1192 n = i->next;
1193 free_omp_region_1 (i);
1196 free (region);
1199 /* Release the memory for the entire omp region tree. */
1201 void
1202 free_omp_regions (void)
1204 struct omp_region *r, *n;
1205 for (r = root_omp_region; r ; r = n)
1207 n = r->next;
1208 free_omp_region_1 (r);
1210 root_omp_region = NULL;
1214 /* Create a new context, with OUTER_CTX being the surrounding context. */
1216 static omp_context *
1217 new_omp_context (gimple stmt, omp_context *outer_ctx)
1219 omp_context *ctx = XCNEW (omp_context);
1221 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1222 (splay_tree_value) ctx);
1223 ctx->stmt = stmt;
1225 if (outer_ctx)
1227 ctx->outer = outer_ctx;
1228 ctx->cb = outer_ctx->cb;
1229 ctx->cb.block = NULL;
1230 ctx->depth = outer_ctx->depth + 1;
1232 else
1234 ctx->cb.src_fn = current_function_decl;
1235 ctx->cb.dst_fn = current_function_decl;
1236 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1237 gcc_checking_assert (ctx->cb.src_node);
1238 ctx->cb.dst_node = ctx->cb.src_node;
1239 ctx->cb.src_cfun = cfun;
1240 ctx->cb.copy_decl = omp_copy_decl;
1241 ctx->cb.eh_lp_nr = 0;
1242 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1243 ctx->depth = 1;
1246 ctx->cb.decl_map = pointer_map_create ();
1248 return ctx;
1251 static gimple_seq maybe_catch_exception (gimple_seq);
1253 /* Finalize task copyfn. */
1255 static void
1256 finalize_task_copyfn (gimple task_stmt)
1258 struct function *child_cfun;
1259 tree child_fn;
1260 gimple_seq seq = NULL, new_seq;
1261 gimple bind;
1263 child_fn = gimple_omp_task_copy_fn (task_stmt);
1264 if (child_fn == NULL_TREE)
1265 return;
1267 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1269 /* Inform the callgraph about the new function. */
1270 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
1271 = cfun->curr_properties & ~PROP_loops;
1273 push_cfun (child_cfun);
1274 bind = gimplify_body (child_fn, false);
1275 gimple_seq_add_stmt (&seq, bind);
1276 new_seq = maybe_catch_exception (seq);
1277 if (new_seq != seq)
1279 bind = gimple_build_bind (NULL, new_seq, NULL);
1280 seq = NULL;
1281 gimple_seq_add_stmt (&seq, bind);
1283 gimple_set_body (child_fn, seq);
1284 pop_cfun ();
1286 cgraph_add_new_function (child_fn, false);
1289 /* Destroy a omp_context data structures. Called through the splay tree
1290 value delete callback. */
1292 static void
1293 delete_omp_context (splay_tree_value value)
1295 omp_context *ctx = (omp_context *) value;
1297 pointer_map_destroy (ctx->cb.decl_map);
1299 if (ctx->field_map)
1300 splay_tree_delete (ctx->field_map);
1301 if (ctx->sfield_map)
1302 splay_tree_delete (ctx->sfield_map);
1304 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1305 it produces corrupt debug information. */
1306 if (ctx->record_type)
1308 tree t;
1309 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1310 DECL_ABSTRACT_ORIGIN (t) = NULL;
1312 if (ctx->srecord_type)
1314 tree t;
1315 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1316 DECL_ABSTRACT_ORIGIN (t) = NULL;
1319 if (is_task_ctx (ctx))
1320 finalize_task_copyfn (ctx->stmt);
1322 XDELETE (ctx);
1325 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1326 context. */
1328 static void
1329 fixup_child_record_type (omp_context *ctx)
1331 tree f, type = ctx->record_type;
1333 /* ??? It isn't sufficient to just call remap_type here, because
1334 variably_modified_type_p doesn't work the way we expect for
1335 record types. Testing each field for whether it needs remapping
1336 and creating a new record by hand works, however. */
1337 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1338 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1339 break;
1340 if (f)
1342 tree name, new_fields = NULL;
1344 type = lang_hooks.types.make_type (RECORD_TYPE);
1345 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1346 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1347 TYPE_DECL, name, type);
1348 TYPE_NAME (type) = name;
1350 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1352 tree new_f = copy_node (f);
1353 DECL_CONTEXT (new_f) = type;
1354 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1355 DECL_CHAIN (new_f) = new_fields;
1356 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1357 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1358 &ctx->cb, NULL);
1359 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1360 &ctx->cb, NULL);
1361 new_fields = new_f;
1363 /* Arrange to be able to look up the receiver field
1364 given the sender field. */
1365 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1366 (splay_tree_value) new_f);
1368 TYPE_FIELDS (type) = nreverse (new_fields);
1369 layout_type (type);
1372 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1375 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1376 specified by CLAUSES. */
1378 static void
1379 scan_sharing_clauses (tree clauses, omp_context *ctx)
1381 tree c, decl;
1382 bool scan_array_reductions = false;
1384 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1386 bool by_ref;
1388 switch (OMP_CLAUSE_CODE (c))
1390 case OMP_CLAUSE_PRIVATE:
1391 decl = OMP_CLAUSE_DECL (c);
1392 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1393 goto do_private;
1394 else if (!is_variable_sized (decl))
1395 install_var_local (decl, ctx);
1396 break;
1398 case OMP_CLAUSE_SHARED:
1399 gcc_assert (is_taskreg_ctx (ctx));
1400 decl = OMP_CLAUSE_DECL (c);
1401 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1402 || !is_variable_sized (decl));
1403 /* Global variables don't need to be copied,
1404 the receiver side will use them directly. */
1405 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1406 break;
1407 by_ref = use_pointer_for_field (decl, ctx);
1408 if (! TREE_READONLY (decl)
1409 || TREE_ADDRESSABLE (decl)
1410 || by_ref
1411 || is_reference (decl))
1413 install_var_field (decl, by_ref, 3, ctx);
1414 install_var_local (decl, ctx);
1415 break;
1417 /* We don't need to copy const scalar vars back. */
1418 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1419 goto do_private;
1421 case OMP_CLAUSE_LASTPRIVATE:
1422 /* Let the corresponding firstprivate clause create
1423 the variable. */
1424 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1425 break;
1426 /* FALLTHRU */
1428 case OMP_CLAUSE_FIRSTPRIVATE:
1429 case OMP_CLAUSE_REDUCTION:
1430 decl = OMP_CLAUSE_DECL (c);
1431 do_private:
1432 if (is_variable_sized (decl))
1434 if (is_task_ctx (ctx))
1435 install_var_field (decl, false, 1, ctx);
1436 break;
1438 else if (is_taskreg_ctx (ctx))
1440 bool global
1441 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1442 by_ref = use_pointer_for_field (decl, NULL);
1444 if (is_task_ctx (ctx)
1445 && (global || by_ref || is_reference (decl)))
1447 install_var_field (decl, false, 1, ctx);
1448 if (!global)
1449 install_var_field (decl, by_ref, 2, ctx);
1451 else if (!global)
1452 install_var_field (decl, by_ref, 3, ctx);
1454 install_var_local (decl, ctx);
1455 break;
1457 case OMP_CLAUSE_COPYPRIVATE:
1458 case OMP_CLAUSE_COPYIN:
1459 decl = OMP_CLAUSE_DECL (c);
1460 by_ref = use_pointer_for_field (decl, NULL);
1461 install_var_field (decl, by_ref, 3, ctx);
1462 break;
1464 case OMP_CLAUSE_DEFAULT:
1465 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1466 break;
1468 case OMP_CLAUSE_FINAL:
1469 case OMP_CLAUSE_IF:
1470 case OMP_CLAUSE_NUM_THREADS:
1471 case OMP_CLAUSE_SCHEDULE:
1472 if (ctx->outer)
1473 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1474 break;
1476 case OMP_CLAUSE_NOWAIT:
1477 case OMP_CLAUSE_ORDERED:
1478 case OMP_CLAUSE_COLLAPSE:
1479 case OMP_CLAUSE_UNTIED:
1480 case OMP_CLAUSE_MERGEABLE:
1481 break;
1483 default:
1484 gcc_unreachable ();
1488 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1490 switch (OMP_CLAUSE_CODE (c))
1492 case OMP_CLAUSE_LASTPRIVATE:
1493 /* Let the corresponding firstprivate clause create
1494 the variable. */
1495 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1496 scan_array_reductions = true;
1497 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1498 break;
1499 /* FALLTHRU */
1501 case OMP_CLAUSE_PRIVATE:
1502 case OMP_CLAUSE_FIRSTPRIVATE:
1503 case OMP_CLAUSE_REDUCTION:
1504 decl = OMP_CLAUSE_DECL (c);
1505 if (is_variable_sized (decl))
1506 install_var_local (decl, ctx);
1507 fixup_remapped_decl (decl, ctx,
1508 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1509 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1510 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1511 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1512 scan_array_reductions = true;
1513 break;
1515 case OMP_CLAUSE_SHARED:
1516 decl = OMP_CLAUSE_DECL (c);
1517 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1518 fixup_remapped_decl (decl, ctx, false);
1519 break;
1521 case OMP_CLAUSE_COPYPRIVATE:
1522 case OMP_CLAUSE_COPYIN:
1523 case OMP_CLAUSE_DEFAULT:
1524 case OMP_CLAUSE_IF:
1525 case OMP_CLAUSE_NUM_THREADS:
1526 case OMP_CLAUSE_SCHEDULE:
1527 case OMP_CLAUSE_NOWAIT:
1528 case OMP_CLAUSE_ORDERED:
1529 case OMP_CLAUSE_COLLAPSE:
1530 case OMP_CLAUSE_UNTIED:
1531 case OMP_CLAUSE_FINAL:
1532 case OMP_CLAUSE_MERGEABLE:
1533 break;
1535 default:
1536 gcc_unreachable ();
1540 if (scan_array_reductions)
1541 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1542 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1543 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1545 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1546 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1548 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1549 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1550 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1553 /* Create a new name for omp child function. Returns an identifier. */
1555 static GTY(()) unsigned int tmp_ompfn_id_num;
1557 static tree
1558 create_omp_child_function_name (bool task_copy)
1560 return (clone_function_name (current_function_decl,
1561 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1564 /* Build a decl for the omp child function. It'll not contain a body
1565 yet, just the bare decl. */
1567 static void
1568 create_omp_child_function (omp_context *ctx, bool task_copy)
1570 tree decl, type, name, t;
1572 name = create_omp_child_function_name (task_copy);
1573 if (task_copy)
1574 type = build_function_type_list (void_type_node, ptr_type_node,
1575 ptr_type_node, NULL_TREE);
1576 else
1577 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1579 decl = build_decl (gimple_location (ctx->stmt),
1580 FUNCTION_DECL, name, type);
1582 if (!task_copy)
1583 ctx->cb.dst_fn = decl;
1584 else
1585 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1587 TREE_STATIC (decl) = 1;
1588 TREE_USED (decl) = 1;
1589 DECL_ARTIFICIAL (decl) = 1;
1590 DECL_IGNORED_P (decl) = 0;
1591 TREE_PUBLIC (decl) = 0;
1592 DECL_UNINLINABLE (decl) = 1;
1593 DECL_EXTERNAL (decl) = 0;
1594 DECL_CONTEXT (decl) = NULL_TREE;
1595 DECL_INITIAL (decl) = make_node (BLOCK);
1597 t = build_decl (DECL_SOURCE_LOCATION (decl),
1598 RESULT_DECL, NULL_TREE, void_type_node);
1599 DECL_ARTIFICIAL (t) = 1;
1600 DECL_IGNORED_P (t) = 1;
1601 DECL_CONTEXT (t) = decl;
1602 DECL_RESULT (decl) = t;
1604 t = build_decl (DECL_SOURCE_LOCATION (decl),
1605 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1606 DECL_ARTIFICIAL (t) = 1;
1607 DECL_NAMELESS (t) = 1;
1608 DECL_ARG_TYPE (t) = ptr_type_node;
1609 DECL_CONTEXT (t) = current_function_decl;
1610 TREE_USED (t) = 1;
1611 DECL_ARGUMENTS (decl) = t;
1612 if (!task_copy)
1613 ctx->receiver_decl = t;
1614 else
1616 t = build_decl (DECL_SOURCE_LOCATION (decl),
1617 PARM_DECL, get_identifier (".omp_data_o"),
1618 ptr_type_node);
1619 DECL_ARTIFICIAL (t) = 1;
1620 DECL_NAMELESS (t) = 1;
1621 DECL_ARG_TYPE (t) = ptr_type_node;
1622 DECL_CONTEXT (t) = current_function_decl;
1623 TREE_USED (t) = 1;
1624 TREE_ADDRESSABLE (t) = 1;
1625 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1626 DECL_ARGUMENTS (decl) = t;
1629 /* Allocate memory for the function structure. The call to
1630 allocate_struct_function clobbers CFUN, so we need to restore
1631 it afterward. */
1632 push_struct_function (decl);
1633 cfun->function_end_locus = gimple_location (ctx->stmt);
1634 pop_cfun ();
1638 /* Scan an OpenMP parallel directive. */
1640 static void
1641 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1643 omp_context *ctx;
1644 tree name;
1645 gimple stmt = gsi_stmt (*gsi);
1647 /* Ignore parallel directives with empty bodies, unless there
1648 are copyin clauses. */
1649 if (optimize > 0
1650 && empty_body_p (gimple_omp_body (stmt))
1651 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1652 OMP_CLAUSE_COPYIN) == NULL)
1654 gsi_replace (gsi, gimple_build_nop (), false);
1655 return;
1658 ctx = new_omp_context (stmt, outer_ctx);
1659 taskreg_contexts.safe_push (ctx);
1660 if (taskreg_nesting_level > 1)
1661 ctx->is_nested = true;
1662 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1663 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1664 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1665 name = create_tmp_var_name (".omp_data_s");
1666 name = build_decl (gimple_location (stmt),
1667 TYPE_DECL, name, ctx->record_type);
1668 DECL_ARTIFICIAL (name) = 1;
1669 DECL_NAMELESS (name) = 1;
1670 TYPE_NAME (ctx->record_type) = name;
1671 create_omp_child_function (ctx, false);
1672 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1674 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1675 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1677 if (TYPE_FIELDS (ctx->record_type) == NULL)
1678 ctx->record_type = ctx->receiver_decl = NULL;
1681 /* Scan an OpenMP task directive. */
1683 static void
1684 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1686 omp_context *ctx;
1687 tree name, t;
1688 gimple stmt = gsi_stmt (*gsi);
1690 /* Ignore task directives with empty bodies. */
1691 if (optimize > 0
1692 && empty_body_p (gimple_omp_body (stmt)))
1694 gsi_replace (gsi, gimple_build_nop (), false);
1695 return;
1698 ctx = new_omp_context (stmt, outer_ctx);
1699 taskreg_contexts.safe_push (ctx);
1700 if (taskreg_nesting_level > 1)
1701 ctx->is_nested = true;
1702 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1703 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1704 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1705 name = create_tmp_var_name (".omp_data_s");
1706 name = build_decl (gimple_location (stmt),
1707 TYPE_DECL, name, ctx->record_type);
1708 DECL_ARTIFICIAL (name) = 1;
1709 DECL_NAMELESS (name) = 1;
1710 TYPE_NAME (ctx->record_type) = name;
1711 create_omp_child_function (ctx, false);
1712 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
1714 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
1716 if (ctx->srecord_type)
1718 name = create_tmp_var_name (".omp_data_a");
1719 name = build_decl (gimple_location (stmt),
1720 TYPE_DECL, name, ctx->srecord_type);
1721 DECL_ARTIFICIAL (name) = 1;
1722 DECL_NAMELESS (name) = 1;
1723 TYPE_NAME (ctx->srecord_type) = name;
1724 create_omp_child_function (ctx, true);
1727 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1729 if (TYPE_FIELDS (ctx->record_type) == NULL)
1731 ctx->record_type = ctx->receiver_decl = NULL;
1732 t = build_int_cst (long_integer_type_node, 0);
1733 gimple_omp_task_set_arg_size (stmt, t);
1734 t = build_int_cst (long_integer_type_node, 1);
1735 gimple_omp_task_set_arg_align (stmt, t);
1740 /* If any decls have been made addressable during scan_omp,
1741 adjust their fields if needed, and layout record types
1742 of parallel/task constructs. */
1744 static void
1745 finish_taskreg_scan (omp_context *ctx)
1747 if (ctx->record_type == NULL_TREE)
1748 return;
1750 /* If any task_shared_vars were needed, verify all
1751 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
1752 statements if use_pointer_for_field hasn't changed
1753 because of that. If it did, update field types now. */
1754 if (task_shared_vars)
1756 tree c;
1758 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
1759 c; c = OMP_CLAUSE_CHAIN (c))
1760 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
1762 tree decl = OMP_CLAUSE_DECL (c);
1764 /* Global variables don't need to be copied,
1765 the receiver side will use them directly. */
1766 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1767 continue;
1768 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
1769 || !use_pointer_for_field (decl, ctx))
1770 continue;
1771 tree field = lookup_field (decl, ctx);
1772 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
1773 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
1774 continue;
1775 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
1776 TREE_THIS_VOLATILE (field) = 0;
1777 DECL_USER_ALIGN (field) = 0;
1778 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
1779 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
1780 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
1781 if (ctx->srecord_type)
1783 tree sfield = lookup_sfield (decl, ctx);
1784 TREE_TYPE (sfield) = TREE_TYPE (field);
1785 TREE_THIS_VOLATILE (sfield) = 0;
1786 DECL_USER_ALIGN (sfield) = 0;
1787 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1788 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
1789 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
1794 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1796 layout_type (ctx->record_type);
1797 fixup_child_record_type (ctx);
1799 else
1801 location_t loc = gimple_location (ctx->stmt);
1802 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1803 /* Move VLA fields to the end. */
1804 p = &TYPE_FIELDS (ctx->record_type);
1805 while (*p)
1806 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1807 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1809 *q = *p;
1810 *p = TREE_CHAIN (*p);
1811 TREE_CHAIN (*q) = NULL_TREE;
1812 q = &TREE_CHAIN (*q);
1814 else
1815 p = &DECL_CHAIN (*p);
1816 *p = vla_fields;
1817 layout_type (ctx->record_type);
1818 fixup_child_record_type (ctx);
1819 if (ctx->srecord_type)
1820 layout_type (ctx->srecord_type);
1821 tree t = fold_convert_loc (loc, long_integer_type_node,
1822 TYPE_SIZE_UNIT (ctx->record_type));
1823 gimple_omp_task_set_arg_size (ctx->stmt, t);
1824 t = build_int_cst (long_integer_type_node,
1825 TYPE_ALIGN_UNIT (ctx->record_type));
1826 gimple_omp_task_set_arg_align (ctx->stmt, t);
1831 /* Scan an OpenMP loop directive. */
1833 static void
1834 scan_omp_for (gimple stmt, omp_context *outer_ctx)
1836 omp_context *ctx;
1837 size_t i;
1839 ctx = new_omp_context (stmt, outer_ctx);
1841 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1843 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
1844 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
1846 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1847 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1848 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1849 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
1851 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1854 /* Scan an OpenMP sections directive. */
1856 static void
1857 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1859 omp_context *ctx;
1861 ctx = new_omp_context (stmt, outer_ctx);
1862 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
1863 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1866 /* Scan an OpenMP single directive. */
1868 static void
1869 scan_omp_single (gimple stmt, omp_context *outer_ctx)
1871 omp_context *ctx;
1872 tree name;
1874 ctx = new_omp_context (stmt, outer_ctx);
1875 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1876 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1877 name = create_tmp_var_name (".omp_copy_s");
1878 name = build_decl (gimple_location (stmt),
1879 TYPE_DECL, name, ctx->record_type);
1880 TYPE_NAME (ctx->record_type) = name;
1882 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
1883 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1885 if (TYPE_FIELDS (ctx->record_type) == NULL)
1886 ctx->record_type = NULL;
1887 else
1888 layout_type (ctx->record_type);
1892 /* Check OpenMP nesting restrictions. */
1893 static bool
1894 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
1896 switch (gimple_code (stmt))
1898 case GIMPLE_OMP_FOR:
1899 case GIMPLE_OMP_SECTIONS:
1900 case GIMPLE_OMP_SINGLE:
1901 case GIMPLE_CALL:
1902 for (; ctx != NULL; ctx = ctx->outer)
1903 switch (gimple_code (ctx->stmt))
1905 case GIMPLE_OMP_FOR:
1906 case GIMPLE_OMP_SECTIONS:
1907 case GIMPLE_OMP_SINGLE:
1908 case GIMPLE_OMP_ORDERED:
1909 case GIMPLE_OMP_MASTER:
1910 case GIMPLE_OMP_TASK:
1911 if (is_gimple_call (stmt))
1913 error_at (gimple_location (stmt),
1914 "barrier region may not be closely nested inside "
1915 "of work-sharing, critical, ordered, master or "
1916 "explicit task region");
1917 return false;
1919 error_at (gimple_location (stmt),
1920 "work-sharing region may not be closely nested inside "
1921 "of work-sharing, critical, ordered, master or explicit "
1922 "task region");
1923 return false;
1924 case GIMPLE_OMP_PARALLEL:
1925 return true;
1926 default:
1927 break;
1929 break;
1930 case GIMPLE_OMP_MASTER:
1931 for (; ctx != NULL; ctx = ctx->outer)
1932 switch (gimple_code (ctx->stmt))
1934 case GIMPLE_OMP_FOR:
1935 case GIMPLE_OMP_SECTIONS:
1936 case GIMPLE_OMP_SINGLE:
1937 case GIMPLE_OMP_TASK:
1938 error_at (gimple_location (stmt),
1939 "master region may not be closely nested inside "
1940 "of work-sharing or explicit task region");
1941 return false;
1942 case GIMPLE_OMP_PARALLEL:
1943 return true;
1944 default:
1945 break;
1947 break;
1948 case GIMPLE_OMP_ORDERED:
1949 for (; ctx != NULL; ctx = ctx->outer)
1950 switch (gimple_code (ctx->stmt))
1952 case GIMPLE_OMP_CRITICAL:
1953 case GIMPLE_OMP_TASK:
1954 error_at (gimple_location (stmt),
1955 "ordered region may not be closely nested inside "
1956 "of critical or explicit task region");
1957 return false;
1958 case GIMPLE_OMP_FOR:
1959 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
1960 OMP_CLAUSE_ORDERED) == NULL)
1962 error_at (gimple_location (stmt),
1963 "ordered region must be closely nested inside "
1964 "a loop region with an ordered clause");
1965 return false;
1967 return true;
1968 case GIMPLE_OMP_PARALLEL:
1969 return true;
1970 default:
1971 break;
1973 break;
1974 case GIMPLE_OMP_CRITICAL:
1975 for (; ctx != NULL; ctx = ctx->outer)
1976 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1977 && (gimple_omp_critical_name (stmt)
1978 == gimple_omp_critical_name (ctx->stmt)))
1980 error_at (gimple_location (stmt),
1981 "critical region may not be nested inside a critical "
1982 "region with the same name");
1983 return false;
1985 break;
1986 default:
1987 break;
1989 return true;
1993 /* Helper function scan_omp.
1995 Callback for walk_tree or operators in walk_gimple_stmt used to
1996 scan for OpenMP directives in TP. */
1998 static tree
1999 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2001 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2002 omp_context *ctx = (omp_context *) wi->info;
2003 tree t = *tp;
2005 switch (TREE_CODE (t))
2007 case VAR_DECL:
2008 case PARM_DECL:
2009 case LABEL_DECL:
2010 case RESULT_DECL:
2011 if (ctx)
2012 *tp = remap_decl (t, &ctx->cb);
2013 break;
2015 default:
2016 if (ctx && TYPE_P (t))
2017 *tp = remap_type (t, &ctx->cb);
2018 else if (!DECL_P (t))
2020 *walk_subtrees = 1;
2021 if (ctx)
2023 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2024 if (tem != TREE_TYPE (t))
2026 if (TREE_CODE (t) == INTEGER_CST)
2027 *tp = build_int_cst_wide (tem,
2028 TREE_INT_CST_LOW (t),
2029 TREE_INT_CST_HIGH (t));
2030 else
2031 TREE_TYPE (t) = tem;
2035 break;
2038 return NULL_TREE;
2042 /* Helper function for scan_omp.
2044 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2045 the current statement in GSI. */
2047 static tree
2048 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2049 struct walk_stmt_info *wi)
2051 gimple stmt = gsi_stmt (*gsi);
2052 omp_context *ctx = (omp_context *) wi->info;
2054 if (gimple_has_location (stmt))
2055 input_location = gimple_location (stmt);
2057 /* Check the OpenMP nesting restrictions. */
2058 if (ctx != NULL)
2060 bool remove = false;
2061 if (is_gimple_omp (stmt))
2062 remove = !check_omp_nesting_restrictions (stmt, ctx);
2063 else if (is_gimple_call (stmt))
2065 tree fndecl = gimple_call_fndecl (stmt);
2066 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2067 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
2068 remove = !check_omp_nesting_restrictions (stmt, ctx);
2070 if (remove)
2072 stmt = gimple_build_nop ();
2073 gsi_replace (gsi, stmt, false);
2077 *handled_ops_p = true;
2079 switch (gimple_code (stmt))
2081 case GIMPLE_OMP_PARALLEL:
2082 taskreg_nesting_level++;
2083 scan_omp_parallel (gsi, ctx);
2084 taskreg_nesting_level--;
2085 break;
2087 case GIMPLE_OMP_TASK:
2088 taskreg_nesting_level++;
2089 scan_omp_task (gsi, ctx);
2090 taskreg_nesting_level--;
2091 break;
2093 case GIMPLE_OMP_FOR:
2094 scan_omp_for (stmt, ctx);
2095 break;
2097 case GIMPLE_OMP_SECTIONS:
2098 scan_omp_sections (stmt, ctx);
2099 break;
2101 case GIMPLE_OMP_SINGLE:
2102 scan_omp_single (stmt, ctx);
2103 break;
2105 case GIMPLE_OMP_SECTION:
2106 case GIMPLE_OMP_MASTER:
2107 case GIMPLE_OMP_ORDERED:
2108 case GIMPLE_OMP_CRITICAL:
2109 ctx = new_omp_context (stmt, ctx);
2110 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2111 break;
2113 case GIMPLE_BIND:
2115 tree var;
2117 *handled_ops_p = false;
2118 if (ctx)
2119 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2120 insert_decl_map (&ctx->cb, var, var);
2122 break;
2123 default:
2124 *handled_ops_p = false;
2125 break;
2128 return NULL_TREE;
2132 /* Scan all the statements starting at the current statement. CTX
2133 contains context information about the OpenMP directives and
2134 clauses found during the scan. */
2136 static void
2137 scan_omp (gimple_seq *body_p, omp_context *ctx)
2139 location_t saved_location;
2140 struct walk_stmt_info wi;
2142 memset (&wi, 0, sizeof (wi));
2143 wi.info = ctx;
2144 wi.want_locations = true;
2146 saved_location = input_location;
2147 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2148 input_location = saved_location;
2151 /* Re-gimplification and code generation routines. */
2153 /* Build a call to GOMP_barrier. */
2155 static tree
2156 build_omp_barrier (void)
2158 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
2161 /* If a context was created for STMT when it was scanned, return it. */
2163 static omp_context *
2164 maybe_lookup_ctx (gimple stmt)
2166 splay_tree_node n;
2167 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2168 return n ? (omp_context *) n->value : NULL;
2172 /* Find the mapping for DECL in CTX or the immediately enclosing
2173 context that has a mapping for DECL.
2175 If CTX is a nested parallel directive, we may have to use the decl
2176 mappings created in CTX's parent context. Suppose that we have the
2177 following parallel nesting (variable UIDs showed for clarity):
2179 iD.1562 = 0;
2180 #omp parallel shared(iD.1562) -> outer parallel
2181 iD.1562 = iD.1562 + 1;
2183 #omp parallel shared (iD.1562) -> inner parallel
2184 iD.1562 = iD.1562 - 1;
2186 Each parallel structure will create a distinct .omp_data_s structure
2187 for copying iD.1562 in/out of the directive:
2189 outer parallel .omp_data_s.1.i -> iD.1562
2190 inner parallel .omp_data_s.2.i -> iD.1562
2192 A shared variable mapping will produce a copy-out operation before
2193 the parallel directive and a copy-in operation after it. So, in
2194 this case we would have:
2196 iD.1562 = 0;
2197 .omp_data_o.1.i = iD.1562;
2198 #omp parallel shared(iD.1562) -> outer parallel
2199 .omp_data_i.1 = &.omp_data_o.1
2200 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2202 .omp_data_o.2.i = iD.1562; -> **
2203 #omp parallel shared(iD.1562) -> inner parallel
2204 .omp_data_i.2 = &.omp_data_o.2
2205 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2208 ** This is a problem. The symbol iD.1562 cannot be referenced
2209 inside the body of the outer parallel region. But since we are
2210 emitting this copy operation while expanding the inner parallel
2211 directive, we need to access the CTX structure of the outer
2212 parallel directive to get the correct mapping:
2214 .omp_data_o.2.i = .omp_data_i.1->i
2216 Since there may be other workshare or parallel directives enclosing
2217 the parallel directive, it may be necessary to walk up the context
2218 parent chain. This is not a problem in general because nested
2219 parallelism happens only rarely. */
2221 static tree
2222 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2224 tree t;
2225 omp_context *up;
2227 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2228 t = maybe_lookup_decl (decl, up);
2230 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2232 return t ? t : decl;
2236 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2237 in outer contexts. */
2239 static tree
2240 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2242 tree t = NULL;
2243 omp_context *up;
2245 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2246 t = maybe_lookup_decl (decl, up);
2248 return t ? t : decl;
2252 /* Construct the initialization value for reduction CLAUSE. */
2254 tree
2255 omp_reduction_init (tree clause, tree type)
2257 location_t loc = OMP_CLAUSE_LOCATION (clause);
2258 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2260 case PLUS_EXPR:
2261 case MINUS_EXPR:
2262 case BIT_IOR_EXPR:
2263 case BIT_XOR_EXPR:
2264 case TRUTH_OR_EXPR:
2265 case TRUTH_ORIF_EXPR:
2266 case TRUTH_XOR_EXPR:
2267 case NE_EXPR:
2268 return build_zero_cst (type);
2270 case MULT_EXPR:
2271 case TRUTH_AND_EXPR:
2272 case TRUTH_ANDIF_EXPR:
2273 case EQ_EXPR:
2274 return fold_convert_loc (loc, type, integer_one_node);
2276 case BIT_AND_EXPR:
2277 return fold_convert_loc (loc, type, integer_minus_one_node);
2279 case MAX_EXPR:
2280 if (SCALAR_FLOAT_TYPE_P (type))
2282 REAL_VALUE_TYPE max, min;
2283 if (HONOR_INFINITIES (TYPE_MODE (type)))
2285 real_inf (&max);
2286 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2288 else
2289 real_maxval (&min, 1, TYPE_MODE (type));
2290 return build_real (type, min);
2292 else
2294 gcc_assert (INTEGRAL_TYPE_P (type));
2295 return TYPE_MIN_VALUE (type);
2298 case MIN_EXPR:
2299 if (SCALAR_FLOAT_TYPE_P (type))
2301 REAL_VALUE_TYPE max;
2302 if (HONOR_INFINITIES (TYPE_MODE (type)))
2303 real_inf (&max);
2304 else
2305 real_maxval (&max, 0, TYPE_MODE (type));
2306 return build_real (type, max);
2308 else
2310 gcc_assert (INTEGRAL_TYPE_P (type));
2311 return TYPE_MAX_VALUE (type);
2314 default:
2315 gcc_unreachable ();
2319 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2320 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2321 private variables. Initialization statements go in ILIST, while calls
2322 to destructors go in DLIST. */
2324 static void
2325 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2326 omp_context *ctx)
2328 tree c, dtor, copyin_seq, x, ptr;
2329 bool copyin_by_ref = false;
2330 bool lastprivate_firstprivate = false;
2331 int pass;
2333 copyin_seq = NULL;
2335 /* Do all the fixed sized types in the first pass, and the variable sized
2336 types in the second pass. This makes sure that the scalar arguments to
2337 the variable sized types are processed before we use them in the
2338 variable sized operations. */
2339 for (pass = 0; pass < 2; ++pass)
2341 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2343 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2344 tree var, new_var;
2345 bool by_ref;
2346 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2348 switch (c_kind)
2350 case OMP_CLAUSE_PRIVATE:
2351 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2352 continue;
2353 break;
2354 case OMP_CLAUSE_SHARED:
2355 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2357 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2358 continue;
2360 case OMP_CLAUSE_FIRSTPRIVATE:
2361 case OMP_CLAUSE_COPYIN:
2362 case OMP_CLAUSE_REDUCTION:
2363 break;
2364 case OMP_CLAUSE_LASTPRIVATE:
2365 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2367 lastprivate_firstprivate = true;
2368 if (pass != 0)
2369 continue;
2371 break;
2372 default:
2373 continue;
2376 new_var = var = OMP_CLAUSE_DECL (c);
2377 if (c_kind != OMP_CLAUSE_COPYIN)
2378 new_var = lookup_decl (var, ctx);
2380 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2382 if (pass != 0)
2383 continue;
2385 else if (is_variable_sized (var))
2387 /* For variable sized types, we need to allocate the
2388 actual storage here. Call alloca and store the
2389 result in the pointer decl that we created elsewhere. */
2390 if (pass == 0)
2391 continue;
2393 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2395 gimple stmt;
2396 tree tmp, atmp;
2398 ptr = DECL_VALUE_EXPR (new_var);
2399 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2400 ptr = TREE_OPERAND (ptr, 0);
2401 gcc_assert (DECL_P (ptr));
2402 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2404 /* void *tmp = __builtin_alloca */
2405 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2406 stmt = gimple_build_call (atmp, 1, x);
2407 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2408 gimple_add_tmp_var (tmp);
2409 gimple_call_set_lhs (stmt, tmp);
2411 gimple_seq_add_stmt (ilist, stmt);
2413 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
2414 gimplify_assign (ptr, x, ilist);
2417 else if (is_reference (var))
2419 /* For references that are being privatized for Fortran,
2420 allocate new backing storage for the new pointer
2421 variable. This allows us to avoid changing all the
2422 code that expects a pointer to something that expects
2423 a direct variable. Note that this doesn't apply to
2424 C++, since reference types are disallowed in data
2425 sharing clauses there, except for NRV optimized
2426 return values. */
2427 if (pass == 0)
2428 continue;
2430 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2431 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2433 x = build_receiver_ref (var, false, ctx);
2434 x = build_fold_addr_expr_loc (clause_loc, x);
2436 else if (TREE_CONSTANT (x))
2438 const char *name = NULL;
2439 if (DECL_NAME (var))
2440 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2442 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2443 name);
2444 gimple_add_tmp_var (x);
2445 TREE_ADDRESSABLE (x) = 1;
2446 x = build_fold_addr_expr_loc (clause_loc, x);
2448 else
2450 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2451 x = build_call_expr_loc (clause_loc, atmp, 1, x);
2454 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
2455 gimplify_assign (new_var, x, ilist);
2457 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2459 else if (c_kind == OMP_CLAUSE_REDUCTION
2460 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2462 if (pass == 0)
2463 continue;
2465 else if (pass != 0)
2466 continue;
2468 switch (OMP_CLAUSE_CODE (c))
2470 case OMP_CLAUSE_SHARED:
2471 /* Shared global vars are just accessed directly. */
2472 if (is_global_var (new_var))
2473 break;
2474 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2475 needs to be delayed until after fixup_child_record_type so
2476 that we get the correct type during the dereference. */
2477 by_ref = use_pointer_for_field (var, ctx);
2478 x = build_receiver_ref (var, by_ref, ctx);
2479 SET_DECL_VALUE_EXPR (new_var, x);
2480 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2482 /* ??? If VAR is not passed by reference, and the variable
2483 hasn't been initialized yet, then we'll get a warning for
2484 the store into the omp_data_s structure. Ideally, we'd be
2485 able to notice this and not store anything at all, but
2486 we're generating code too early. Suppress the warning. */
2487 if (!by_ref)
2488 TREE_NO_WARNING (var) = 1;
2489 break;
2491 case OMP_CLAUSE_LASTPRIVATE:
2492 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2493 break;
2494 /* FALLTHRU */
2496 case OMP_CLAUSE_PRIVATE:
2497 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2498 x = build_outer_var_ref (var, ctx);
2499 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2501 if (is_task_ctx (ctx))
2502 x = build_receiver_ref (var, false, ctx);
2503 else
2504 x = build_outer_var_ref (var, ctx);
2506 else
2507 x = NULL;
2508 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2509 if (x)
2510 gimplify_and_add (x, ilist);
2511 /* FALLTHRU */
2513 do_dtor:
2514 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2515 if (x)
2517 gimple_seq tseq = NULL;
2519 dtor = x;
2520 gimplify_stmt (&dtor, &tseq);
2521 gimple_seq_add_seq (dlist, tseq);
2523 break;
2525 case OMP_CLAUSE_FIRSTPRIVATE:
2526 if (is_task_ctx (ctx))
2528 if (is_reference (var) || is_variable_sized (var))
2529 goto do_dtor;
2530 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2531 ctx))
2532 || use_pointer_for_field (var, NULL))
2534 x = build_receiver_ref (var, false, ctx);
2535 SET_DECL_VALUE_EXPR (new_var, x);
2536 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2537 goto do_dtor;
2540 x = build_outer_var_ref (var, ctx);
2541 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2542 gimplify_and_add (x, ilist);
2543 goto do_dtor;
2544 break;
2546 case OMP_CLAUSE_COPYIN:
2547 by_ref = use_pointer_for_field (var, NULL);
2548 x = build_receiver_ref (var, by_ref, ctx);
2549 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2550 append_to_statement_list (x, &copyin_seq);
2551 copyin_by_ref |= by_ref;
2552 break;
2554 case OMP_CLAUSE_REDUCTION:
2555 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2557 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2558 x = build_outer_var_ref (var, ctx);
2560 if (is_reference (var))
2561 x = build_fold_addr_expr_loc (clause_loc, x);
2562 SET_DECL_VALUE_EXPR (placeholder, x);
2563 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2564 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2565 gimple_seq_add_seq (ilist,
2566 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2567 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
2568 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2570 else
2572 x = omp_reduction_init (c, TREE_TYPE (new_var));
2573 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2574 gimplify_assign (new_var, x, ilist);
2576 break;
2578 default:
2579 gcc_unreachable ();
2584 /* The copyin sequence is not to be executed by the main thread, since
2585 that would result in self-copies. Perhaps not visible to scalars,
2586 but it certainly is to C++ operator=. */
2587 if (copyin_seq)
2589 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
2591 x = build2 (NE_EXPR, boolean_type_node, x,
2592 build_int_cst (TREE_TYPE (x), 0));
2593 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2594 gimplify_and_add (x, ilist);
2597 /* If any copyin variable is passed by reference, we must ensure the
2598 master thread doesn't modify it before it is copied over in all
2599 threads. Similarly for variables in both firstprivate and
2600 lastprivate clauses we need to ensure the lastprivate copying
2601 happens after firstprivate copying in all threads. */
2602 if (copyin_by_ref || lastprivate_firstprivate)
2603 gimplify_and_add (build_omp_barrier (), ilist);
2607 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2608 both parallel and workshare constructs. PREDICATE may be NULL if it's
2609 always true. */
2611 static void
2612 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2613 omp_context *ctx)
2615 tree x, c, label = NULL;
2616 bool par_clauses = false;
2618 /* Early exit if there are no lastprivate clauses. */
2619 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
2620 if (clauses == NULL)
2622 /* If this was a workshare clause, see if it had been combined
2623 with its parallel. In that case, look for the clauses on the
2624 parallel statement itself. */
2625 if (is_parallel_ctx (ctx))
2626 return;
2628 ctx = ctx->outer;
2629 if (ctx == NULL || !is_parallel_ctx (ctx))
2630 return;
2632 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2633 OMP_CLAUSE_LASTPRIVATE);
2634 if (clauses == NULL)
2635 return;
2636 par_clauses = true;
2639 if (predicate)
2641 gimple stmt;
2642 tree label_true, arm1, arm2;
2644 label = create_artificial_label (UNKNOWN_LOCATION);
2645 label_true = create_artificial_label (UNKNOWN_LOCATION);
2646 arm1 = TREE_OPERAND (predicate, 0);
2647 arm2 = TREE_OPERAND (predicate, 1);
2648 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2649 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2650 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2651 label_true, label);
2652 gimple_seq_add_stmt (stmt_list, stmt);
2653 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2656 for (c = clauses; c ;)
2658 tree var, new_var;
2659 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2661 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2663 var = OMP_CLAUSE_DECL (c);
2664 new_var = lookup_decl (var, ctx);
2666 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2668 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2669 gimple_seq_add_seq (stmt_list,
2670 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
2672 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
2674 x = build_outer_var_ref (var, ctx);
2675 if (is_reference (var))
2676 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2677 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2678 gimplify_and_add (x, stmt_list);
2680 c = OMP_CLAUSE_CHAIN (c);
2681 if (c == NULL && !par_clauses)
2683 /* If this was a workshare clause, see if it had been combined
2684 with its parallel. In that case, continue looking for the
2685 clauses also on the parallel statement itself. */
2686 if (is_parallel_ctx (ctx))
2687 break;
2689 ctx = ctx->outer;
2690 if (ctx == NULL || !is_parallel_ctx (ctx))
2691 break;
2693 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2694 OMP_CLAUSE_LASTPRIVATE);
2695 par_clauses = true;
2699 if (label)
2700 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
2704 /* Generate code to implement the REDUCTION clauses. */
2706 static void
2707 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
2709 gimple_seq sub_seq = NULL;
2710 gimple stmt;
2711 tree x, c;
2712 int count = 0;
2714 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
2715 update in that case, otherwise use a lock. */
2716 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
2717 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2719 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2721 /* Never use OMP_ATOMIC for array reductions. */
2722 count = -1;
2723 break;
2725 count++;
2728 if (count == 0)
2729 return;
2731 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2733 tree var, ref, new_var;
2734 enum tree_code code;
2735 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2737 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
2738 continue;
2740 var = OMP_CLAUSE_DECL (c);
2741 new_var = lookup_decl (var, ctx);
2742 if (is_reference (var))
2743 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2744 ref = build_outer_var_ref (var, ctx);
2745 code = OMP_CLAUSE_REDUCTION_CODE (c);
2747 /* reduction(-:var) sums up the partial results, so it acts
2748 identically to reduction(+:var). */
2749 if (code == MINUS_EXPR)
2750 code = PLUS_EXPR;
2752 if (count == 1)
2754 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
2756 addr = save_expr (addr);
2757 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
2758 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
2759 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
2760 gimplify_and_add (x, stmt_seqp);
2761 return;
2764 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2766 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2768 if (is_reference (var))
2769 ref = build_fold_addr_expr_loc (clause_loc, ref);
2770 SET_DECL_VALUE_EXPR (placeholder, ref);
2771 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2772 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2773 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
2774 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
2775 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2777 else
2779 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2780 ref = build_outer_var_ref (var, ctx);
2781 gimplify_assign (ref, x, &sub_seq);
2785 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
2787 gimple_seq_add_stmt (stmt_seqp, stmt);
2789 gimple_seq_add_seq (stmt_seqp, sub_seq);
2791 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
2793 gimple_seq_add_stmt (stmt_seqp, stmt);
2797 /* Generate code to implement the COPYPRIVATE clauses. */
2799 static void
2800 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
2801 omp_context *ctx)
2803 tree c;
2805 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2807 tree var, new_var, ref, x;
2808 bool by_ref;
2809 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2811 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2812 continue;
2814 var = OMP_CLAUSE_DECL (c);
2815 by_ref = use_pointer_for_field (var, NULL);
2817 ref = build_sender_ref (var, ctx);
2818 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
2819 if (by_ref)
2821 x = build_fold_addr_expr_loc (clause_loc, new_var);
2822 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
2824 gimplify_assign (ref, x, slist);
2826 ref = build_receiver_ref (var, false, ctx);
2827 if (by_ref)
2829 ref = fold_convert_loc (clause_loc,
2830 build_pointer_type (TREE_TYPE (new_var)),
2831 ref);
2832 ref = build_fold_indirect_ref_loc (clause_loc, ref);
2834 if (is_reference (var))
2836 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
2837 ref = build_simple_mem_ref_loc (clause_loc, ref);
2838 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2840 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
2841 gimplify_and_add (x, rlist);
2846 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2847 and REDUCTION from the sender (aka parent) side. */
2849 static void
2850 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
2851 omp_context *ctx)
2853 tree c;
2855 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2857 tree val, ref, x, var;
2858 bool by_ref, do_in = false, do_out = false;
2859 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2861 switch (OMP_CLAUSE_CODE (c))
2863 case OMP_CLAUSE_PRIVATE:
2864 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2865 break;
2866 continue;
2867 case OMP_CLAUSE_FIRSTPRIVATE:
2868 case OMP_CLAUSE_COPYIN:
2869 case OMP_CLAUSE_LASTPRIVATE:
2870 case OMP_CLAUSE_REDUCTION:
2871 break;
2872 default:
2873 continue;
2876 val = OMP_CLAUSE_DECL (c);
2877 var = lookup_decl_in_outer_ctx (val, ctx);
2879 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2880 && is_global_var (var))
2881 continue;
2882 if (is_variable_sized (val))
2883 continue;
2884 by_ref = use_pointer_for_field (val, NULL);
2886 switch (OMP_CLAUSE_CODE (c))
2888 case OMP_CLAUSE_PRIVATE:
2889 case OMP_CLAUSE_FIRSTPRIVATE:
2890 case OMP_CLAUSE_COPYIN:
2891 do_in = true;
2892 break;
2894 case OMP_CLAUSE_LASTPRIVATE:
2895 if (by_ref || is_reference (val))
2897 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2898 continue;
2899 do_in = true;
2901 else
2903 do_out = true;
2904 if (lang_hooks.decls.omp_private_outer_ref (val))
2905 do_in = true;
2907 break;
2909 case OMP_CLAUSE_REDUCTION:
2910 do_in = true;
2911 do_out = !(by_ref || is_reference (val));
2912 break;
2914 default:
2915 gcc_unreachable ();
2918 if (do_in)
2920 ref = build_sender_ref (val, ctx);
2921 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
2922 gimplify_assign (ref, x, ilist);
2923 if (is_task_ctx (ctx))
2924 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
2927 if (do_out)
2929 ref = build_sender_ref (val, ctx);
2930 gimplify_assign (var, ref, olist);
2935 /* Generate code to implement SHARED from the sender (aka parent)
2936 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
2937 list things that got automatically shared. */
2939 static void
2940 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
2942 tree var, ovar, nvar, f, x, record_type;
2944 if (ctx->record_type == NULL)
2945 return;
2947 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
2948 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
2950 ovar = DECL_ABSTRACT_ORIGIN (f);
2951 nvar = maybe_lookup_decl (ovar, ctx);
2952 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2953 continue;
2955 /* If CTX is a nested parallel directive. Find the immediately
2956 enclosing parallel or workshare construct that contains a
2957 mapping for OVAR. */
2958 var = lookup_decl_in_outer_ctx (ovar, ctx);
2960 if (use_pointer_for_field (ovar, ctx))
2962 x = build_sender_ref (ovar, ctx);
2963 var = build_fold_addr_expr (var);
2964 gimplify_assign (x, var, ilist);
2966 else
2968 x = build_sender_ref (ovar, ctx);
2969 gimplify_assign (x, var, ilist);
2971 if (!TREE_READONLY (var)
2972 /* We don't need to receive a new reference to a result
2973 or parm decl. In fact we may not store to it as we will
2974 invalidate any pending RSO and generate wrong gimple
2975 during inlining. */
2976 && !((TREE_CODE (var) == RESULT_DECL
2977 || TREE_CODE (var) == PARM_DECL)
2978 && DECL_BY_REFERENCE (var)))
2980 x = build_sender_ref (ovar, ctx);
2981 gimplify_assign (var, x, olist);
2988 /* A convenience function to build an empty GIMPLE_COND with just the
2989 condition. */
2991 static gimple
2992 gimple_build_cond_empty (tree cond)
2994 enum tree_code pred_code;
2995 tree lhs, rhs;
2997 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
2998 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
3002 /* Build the function calls to GOMP_parallel_start etc to actually
3003 generate the parallel operation. REGION is the parallel region
3004 being expanded. BB is the block where to insert the code. WS_ARGS
3005 will be set if this is a call to a combined parallel+workshare
3006 construct, it contains the list of additional arguments needed by
3007 the workshare construct. */
3009 static void
3010 expand_parallel_call (struct omp_region *region, basic_block bb,
3011 gimple entry_stmt, vec<tree, va_gc> *ws_args)
3013 tree t, t1, t2, val, cond, c, clauses;
3014 gimple_stmt_iterator gsi;
3015 gimple stmt;
3016 enum built_in_function start_ix;
3017 int start_ix2;
3018 location_t clause_loc;
3019 vec<tree, va_gc> *args;
3021 clauses = gimple_omp_parallel_clauses (entry_stmt);
3023 /* Determine what flavor of GOMP_parallel_start we will be
3024 emitting. */
3025 start_ix = BUILT_IN_GOMP_PARALLEL_START;
3026 if (is_combined_parallel (region))
3028 switch (region->inner->type)
3030 case GIMPLE_OMP_FOR:
3031 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
3032 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
3033 + (region->inner->sched_kind
3034 == OMP_CLAUSE_SCHEDULE_RUNTIME
3035 ? 3 : region->inner->sched_kind));
3036 start_ix = (enum built_in_function)start_ix2;
3037 break;
3038 case GIMPLE_OMP_SECTIONS:
3039 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
3040 break;
3041 default:
3042 gcc_unreachable ();
3046 /* By default, the value of NUM_THREADS is zero (selected at run time)
3047 and there is no conditional. */
3048 cond = NULL_TREE;
3049 val = build_int_cst (unsigned_type_node, 0);
3051 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3052 if (c)
3053 cond = OMP_CLAUSE_IF_EXPR (c);
3055 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
3056 if (c)
3058 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
3059 clause_loc = OMP_CLAUSE_LOCATION (c);
3061 else
3062 clause_loc = gimple_location (entry_stmt);
3064 /* Ensure 'val' is of the correct type. */
3065 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
3067 /* If we found the clause 'if (cond)', build either
3068 (cond != 0) or (cond ? val : 1u). */
3069 if (cond)
3071 gimple_stmt_iterator gsi;
3073 cond = gimple_boolify (cond);
3075 if (integer_zerop (val))
3076 val = fold_build2_loc (clause_loc,
3077 EQ_EXPR, unsigned_type_node, cond,
3078 build_int_cst (TREE_TYPE (cond), 0));
3079 else
3081 basic_block cond_bb, then_bb, else_bb;
3082 edge e, e_then, e_else;
3083 tree tmp_then, tmp_else, tmp_join, tmp_var;
3085 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
3086 if (gimple_in_ssa_p (cfun))
3088 tmp_then = make_ssa_name (tmp_var, NULL);
3089 tmp_else = make_ssa_name (tmp_var, NULL);
3090 tmp_join = make_ssa_name (tmp_var, NULL);
3092 else
3094 tmp_then = tmp_var;
3095 tmp_else = tmp_var;
3096 tmp_join = tmp_var;
3099 e = split_block (bb, NULL);
3100 cond_bb = e->src;
3101 bb = e->dest;
3102 remove_edge (e);
3104 then_bb = create_empty_bb (cond_bb);
3105 else_bb = create_empty_bb (then_bb);
3106 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
3107 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
3109 stmt = gimple_build_cond_empty (cond);
3110 gsi = gsi_start_bb (cond_bb);
3111 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3113 gsi = gsi_start_bb (then_bb);
3114 stmt = gimple_build_assign (tmp_then, val);
3115 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3117 gsi = gsi_start_bb (else_bb);
3118 stmt = gimple_build_assign
3119 (tmp_else, build_int_cst (unsigned_type_node, 1));
3120 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3122 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
3123 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
3124 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3125 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
3127 if (gimple_in_ssa_p (cfun))
3129 gimple phi = create_phi_node (tmp_join, bb);
3130 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3131 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
3134 val = tmp_join;
3137 gsi = gsi_start_bb (bb);
3138 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3139 false, GSI_CONTINUE_LINKING);
3142 gsi = gsi_last_bb (bb);
3143 t = gimple_omp_parallel_data_arg (entry_stmt);
3144 if (t == NULL)
3145 t1 = null_pointer_node;
3146 else
3147 t1 = build_fold_addr_expr (t);
3148 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
3150 vec_alloc (args, 3 + vec_safe_length (ws_args));
3151 args->quick_push (t2);
3152 args->quick_push (t1);
3153 args->quick_push (val);
3154 if (ws_args)
3155 args->splice (*ws_args);
3157 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
3158 builtin_decl_explicit (start_ix), args);
3160 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3161 false, GSI_CONTINUE_LINKING);
3163 t = gimple_omp_parallel_data_arg (entry_stmt);
3164 if (t == NULL)
3165 t = null_pointer_node;
3166 else
3167 t = build_fold_addr_expr (t);
3168 t = build_call_expr_loc (gimple_location (entry_stmt),
3169 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3170 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3171 false, GSI_CONTINUE_LINKING);
3173 t = build_call_expr_loc (gimple_location (entry_stmt),
3174 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3176 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3177 false, GSI_CONTINUE_LINKING);
3181 /* Build the function call to GOMP_task to actually
3182 generate the task operation. BB is the block where to insert the code. */
3184 static void
3185 expand_task_call (basic_block bb, gimple entry_stmt)
3187 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
3188 gimple_stmt_iterator gsi;
3189 location_t loc = gimple_location (entry_stmt);
3191 clauses = gimple_omp_task_clauses (entry_stmt);
3193 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3194 if (c)
3195 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3196 else
3197 cond = boolean_true_node;
3199 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3200 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3201 flags = build_int_cst (unsigned_type_node,
3202 (c ? 1 : 0) + (c2 ? 4 : 0));
3204 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3205 if (c)
3207 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3208 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3209 build_int_cst (unsigned_type_node, 2),
3210 build_int_cst (unsigned_type_node, 0));
3211 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3214 gsi = gsi_last_bb (bb);
3215 t = gimple_omp_task_data_arg (entry_stmt);
3216 if (t == NULL)
3217 t2 = null_pointer_node;
3218 else
3219 t2 = build_fold_addr_expr_loc (loc, t);
3220 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
3221 t = gimple_omp_task_copy_fn (entry_stmt);
3222 if (t == NULL)
3223 t3 = null_pointer_node;
3224 else
3225 t3 = build_fold_addr_expr_loc (loc, t);
3227 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3228 7, t1, t2, t3,
3229 gimple_omp_task_arg_size (entry_stmt),
3230 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3232 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3233 false, GSI_CONTINUE_LINKING);
3237 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3238 catch handler and return it. This prevents programs from violating the
3239 structured block semantics with throws. */
3241 static gimple_seq
3242 maybe_catch_exception (gimple_seq body)
3244 gimple g;
3245 tree decl;
3247 if (!flag_exceptions)
3248 return body;
3250 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3251 decl = lang_hooks.eh_protect_cleanup_actions ();
3252 else
3253 decl = builtin_decl_explicit (BUILT_IN_TRAP);
3255 g = gimple_build_eh_must_not_throw (decl);
3256 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
3257 GIMPLE_TRY_CATCH);
3259 return gimple_seq_alloc_with_stmt (g);
3262 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3264 static tree
3265 vec2chain (vec<tree, va_gc> *v)
3267 tree chain = NULL_TREE, t;
3268 unsigned ix;
3270 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
3272 DECL_CHAIN (t) = chain;
3273 chain = t;
3276 return chain;
3280 /* Remove barriers in REGION->EXIT's block. Note that this is only
3281 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3282 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3283 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3284 removed. */
3286 static void
3287 remove_exit_barrier (struct omp_region *region)
3289 gimple_stmt_iterator gsi;
3290 basic_block exit_bb;
3291 edge_iterator ei;
3292 edge e;
3293 gimple stmt;
3294 int any_addressable_vars = -1;
3296 exit_bb = region->exit;
3298 /* If the parallel region doesn't return, we don't have REGION->EXIT
3299 block at all. */
3300 if (! exit_bb)
3301 return;
3303 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3304 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3305 statements that can appear in between are extremely limited -- no
3306 memory operations at all. Here, we allow nothing at all, so the
3307 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3308 gsi = gsi_last_bb (exit_bb);
3309 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3310 gsi_prev (&gsi);
3311 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3312 return;
3314 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3316 gsi = gsi_last_bb (e->src);
3317 if (gsi_end_p (gsi))
3318 continue;
3319 stmt = gsi_stmt (gsi);
3320 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3321 && !gimple_omp_return_nowait_p (stmt))
3323 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3324 in many cases. If there could be tasks queued, the barrier
3325 might be needed to let the tasks run before some local
3326 variable of the parallel that the task uses as shared
3327 runs out of scope. The task can be spawned either
3328 from within current function (this would be easy to check)
3329 or from some function it calls and gets passed an address
3330 of such a variable. */
3331 if (any_addressable_vars < 0)
3333 gimple parallel_stmt = last_stmt (region->entry);
3334 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3335 tree local_decls, block, decl;
3336 unsigned ix;
3338 any_addressable_vars = 0;
3339 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3340 if (TREE_ADDRESSABLE (decl))
3342 any_addressable_vars = 1;
3343 break;
3345 for (block = gimple_block (stmt);
3346 !any_addressable_vars
3347 && block
3348 && TREE_CODE (block) == BLOCK;
3349 block = BLOCK_SUPERCONTEXT (block))
3351 for (local_decls = BLOCK_VARS (block);
3352 local_decls;
3353 local_decls = DECL_CHAIN (local_decls))
3354 if (TREE_ADDRESSABLE (local_decls))
3356 any_addressable_vars = 1;
3357 break;
3359 if (block == gimple_block (parallel_stmt))
3360 break;
3363 if (!any_addressable_vars)
3364 gimple_omp_return_set_nowait (stmt);
3369 static void
3370 remove_exit_barriers (struct omp_region *region)
3372 if (region->type == GIMPLE_OMP_PARALLEL)
3373 remove_exit_barrier (region);
3375 if (region->inner)
3377 region = region->inner;
3378 remove_exit_barriers (region);
3379 while (region->next)
3381 region = region->next;
3382 remove_exit_barriers (region);
3387 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3388 calls. These can't be declared as const functions, but
3389 within one parallel body they are constant, so they can be
3390 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3391 which are declared const. Similarly for task body, except
3392 that in untied task omp_get_thread_num () can change at any task
3393 scheduling point. */
3395 static void
3396 optimize_omp_library_calls (gimple entry_stmt)
3398 basic_block bb;
3399 gimple_stmt_iterator gsi;
3400 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3401 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3402 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3403 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
3404 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3405 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3406 OMP_CLAUSE_UNTIED) != NULL);
3408 FOR_EACH_BB (bb)
3409 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3411 gimple call = gsi_stmt (gsi);
3412 tree decl;
3414 if (is_gimple_call (call)
3415 && (decl = gimple_call_fndecl (call))
3416 && DECL_EXTERNAL (decl)
3417 && TREE_PUBLIC (decl)
3418 && DECL_INITIAL (decl) == NULL)
3420 tree built_in;
3422 if (DECL_NAME (decl) == thr_num_id)
3424 /* In #pragma omp task untied omp_get_thread_num () can change
3425 during the execution of the task region. */
3426 if (untied_task)
3427 continue;
3428 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3430 else if (DECL_NAME (decl) == num_thr_id)
3431 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3432 else
3433 continue;
3435 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3436 || gimple_call_num_args (call) != 0)
3437 continue;
3439 if (flag_exceptions && !TREE_NOTHROW (decl))
3440 continue;
3442 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3443 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3444 TREE_TYPE (TREE_TYPE (built_in))))
3445 continue;
3447 gimple_call_set_fndecl (call, built_in);
3452 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
3453 regimplified. */
3455 static tree
3456 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
3458 tree t = *tp;
3460 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
3461 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
3462 return t;
3464 if (TREE_CODE (t) == ADDR_EXPR)
3465 recompute_tree_invariant_for_addr_expr (t);
3467 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
3468 return NULL_TREE;
3471 /* Expand the OpenMP parallel or task directive starting at REGION. */
3473 static void
3474 expand_omp_taskreg (struct omp_region *region)
3476 basic_block entry_bb, exit_bb, new_bb;
3477 struct function *child_cfun;
3478 tree child_fn, block, t;
3479 gimple_stmt_iterator gsi;
3480 gimple entry_stmt, stmt;
3481 edge e;
3482 vec<tree, va_gc> *ws_args;
3484 entry_stmt = last_stmt (region->entry);
3485 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3486 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3488 entry_bb = region->entry;
3489 exit_bb = region->exit;
3491 if (is_combined_parallel (region))
3492 ws_args = region->ws_args;
3493 else
3494 ws_args = NULL;
3496 if (child_cfun->cfg)
3498 /* Due to inlining, it may happen that we have already outlined
3499 the region, in which case all we need to do is make the
3500 sub-graph unreachable and emit the parallel call. */
3501 edge entry_succ_e, exit_succ_e;
3502 gimple_stmt_iterator gsi;
3504 entry_succ_e = single_succ_edge (entry_bb);
3506 gsi = gsi_last_bb (entry_bb);
3507 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3508 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3509 gsi_remove (&gsi, true);
3511 new_bb = entry_bb;
3512 if (exit_bb)
3514 exit_succ_e = single_succ_edge (exit_bb);
3515 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3517 remove_edge_and_dominated_blocks (entry_succ_e);
3519 else
3521 unsigned srcidx, dstidx, num;
3523 /* If the parallel region needs data sent from the parent
3524 function, then the very first statement (except possible
3525 tree profile counter updates) of the parallel body
3526 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3527 &.OMP_DATA_O is passed as an argument to the child function,
3528 we need to replace it with the argument as seen by the child
3529 function.
3531 In most cases, this will end up being the identity assignment
3532 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3533 a function call that has been inlined, the original PARM_DECL
3534 .OMP_DATA_I may have been converted into a different local
3535 variable. In which case, we need to keep the assignment. */
3536 if (gimple_omp_taskreg_data_arg (entry_stmt))
3538 basic_block entry_succ_bb = single_succ (entry_bb);
3539 gimple_stmt_iterator gsi;
3540 tree arg, narg;
3541 gimple parcopy_stmt = NULL;
3543 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3545 gimple stmt;
3547 gcc_assert (!gsi_end_p (gsi));
3548 stmt = gsi_stmt (gsi);
3549 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3550 continue;
3552 if (gimple_num_ops (stmt) == 2)
3554 tree arg = gimple_assign_rhs1 (stmt);
3556 /* We're ignore the subcode because we're
3557 effectively doing a STRIP_NOPS. */
3559 if (TREE_CODE (arg) == ADDR_EXPR
3560 && TREE_OPERAND (arg, 0)
3561 == gimple_omp_taskreg_data_arg (entry_stmt))
3563 parcopy_stmt = stmt;
3564 break;
3569 gcc_assert (parcopy_stmt != NULL);
3570 arg = DECL_ARGUMENTS (child_fn);
3572 if (!gimple_in_ssa_p (cfun))
3574 if (gimple_assign_lhs (parcopy_stmt) == arg)
3575 gsi_remove (&gsi, true);
3576 else
3578 /* ?? Is setting the subcode really necessary ?? */
3579 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3580 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3583 else
3585 /* If we are in ssa form, we must load the value from the default
3586 definition of the argument. That should not be defined now,
3587 since the argument is not used uninitialized. */
3588 gcc_assert (ssa_default_def (cfun, arg) == NULL);
3589 narg = make_ssa_name (arg, gimple_build_nop ());
3590 set_ssa_default_def (cfun, arg, narg);
3591 /* ?? Is setting the subcode really necessary ?? */
3592 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3593 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3594 update_stmt (parcopy_stmt);
3598 /* Declare local variables needed in CHILD_CFUN. */
3599 block = DECL_INITIAL (child_fn);
3600 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
3601 /* The gimplifier could record temporaries in parallel/task block
3602 rather than in containing function's local_decls chain,
3603 which would mean cgraph missed finalizing them. Do it now. */
3604 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
3605 if (TREE_CODE (t) == VAR_DECL
3606 && TREE_STATIC (t)
3607 && !DECL_EXTERNAL (t))
3608 varpool_finalize_decl (t);
3609 DECL_SAVED_TREE (child_fn) = NULL;
3610 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3611 gimple_set_body (child_fn, NULL);
3612 TREE_USED (block) = 1;
3614 /* Reset DECL_CONTEXT on function arguments. */
3615 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
3616 DECL_CONTEXT (t) = child_fn;
3618 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3619 so that it can be moved to the child function. */
3620 gsi = gsi_last_bb (entry_bb);
3621 stmt = gsi_stmt (gsi);
3622 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3623 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3624 gsi_remove (&gsi, true);
3625 e = split_block (entry_bb, stmt);
3626 entry_bb = e->dest;
3627 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3629 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3630 if (exit_bb)
3632 gsi = gsi_last_bb (exit_bb);
3633 gcc_assert (!gsi_end_p (gsi)
3634 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3635 stmt = gimple_build_return (NULL);
3636 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3637 gsi_remove (&gsi, true);
3640 /* Move the parallel region into CHILD_CFUN. */
3642 if (gimple_in_ssa_p (cfun))
3644 init_tree_ssa (child_cfun);
3645 init_ssa_operands (child_cfun);
3646 child_cfun->gimple_df->in_ssa_p = true;
3647 block = NULL_TREE;
3649 else
3650 block = gimple_block (entry_stmt);
3652 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3653 if (exit_bb)
3654 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3656 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3657 num = vec_safe_length (child_cfun->local_decls);
3658 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3660 t = (*child_cfun->local_decls)[srcidx];
3661 if (DECL_CONTEXT (t) == cfun->decl)
3662 continue;
3663 if (srcidx != dstidx)
3664 (*child_cfun->local_decls)[dstidx] = t;
3665 dstidx++;
3667 if (dstidx != num)
3668 vec_safe_truncate (child_cfun->local_decls, dstidx);
3670 /* Inform the callgraph about the new function. */
3671 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
3672 = cfun->curr_properties & ~PROP_loops;
3673 cgraph_add_new_function (child_fn, true);
3675 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3676 fixed in a following pass. */
3677 push_cfun (child_cfun);
3678 if (optimize)
3679 optimize_omp_library_calls (entry_stmt);
3680 rebuild_cgraph_edges ();
3682 /* Some EH regions might become dead, see PR34608. If
3683 pass_cleanup_cfg isn't the first pass to happen with the
3684 new child, these dead EH edges might cause problems.
3685 Clean them up now. */
3686 if (flag_exceptions)
3688 basic_block bb;
3689 bool changed = false;
3691 FOR_EACH_BB (bb)
3692 changed |= gimple_purge_dead_eh_edges (bb);
3693 if (changed)
3694 cleanup_tree_cfg ();
3696 if (gimple_in_ssa_p (cfun))
3697 update_ssa (TODO_update_ssa);
3698 pop_cfun ();
3701 /* Emit a library call to launch the children threads. */
3702 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
3703 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3704 else
3705 expand_task_call (new_bb, entry_stmt);
3706 if (gimple_in_ssa_p (cfun))
3707 update_ssa (TODO_update_ssa_only_virtuals);
3711 /* A subroutine of expand_omp_for. Generate code for a parallel
3712 loop with any schedule. Given parameters:
3714 for (V = N1; V cond N2; V += STEP) BODY;
3716 where COND is "<" or ">", we generate pseudocode
3718 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3719 if (more) goto L0; else goto L3;
3721 V = istart0;
3722 iend = iend0;
3724 BODY;
3725 V += STEP;
3726 if (V cond iend) goto L1; else goto L2;
3728 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3731 If this is a combined omp parallel loop, instead of the call to
3732 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3734 For collapsed loops, given parameters:
3735 collapse(3)
3736 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3737 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3738 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3739 BODY;
3741 we generate pseudocode
3743 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
3744 if (cond3 is <)
3745 adj = STEP3 - 1;
3746 else
3747 adj = STEP3 + 1;
3748 count3 = (adj + N32 - N31) / STEP3;
3749 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
3750 if (cond2 is <)
3751 adj = STEP2 - 1;
3752 else
3753 adj = STEP2 + 1;
3754 count2 = (adj + N22 - N21) / STEP2;
3755 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
3756 if (cond1 is <)
3757 adj = STEP1 - 1;
3758 else
3759 adj = STEP1 + 1;
3760 count1 = (adj + N12 - N11) / STEP1;
3761 count = count1 * count2 * count3;
3762 goto Z1;
3764 count = 0;
3766 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3767 if (more) goto L0; else goto L3;
3769 V = istart0;
3770 T = V;
3771 V3 = N31 + (T % count3) * STEP3;
3772 T = T / count3;
3773 V2 = N21 + (T % count2) * STEP2;
3774 T = T / count2;
3775 V1 = N11 + T * STEP1;
3776 iend = iend0;
3778 BODY;
3779 V += 1;
3780 if (V < iend) goto L10; else goto L2;
3781 L10:
3782 V3 += STEP3;
3783 if (V3 cond3 N32) goto L1; else goto L11;
3784 L11:
3785 V3 = N31;
3786 V2 += STEP2;
3787 if (V2 cond2 N22) goto L1; else goto L12;
3788 L12:
3789 V2 = N21;
3790 V1 += STEP1;
3791 goto L1;
3793 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3798 static void
3799 expand_omp_for_generic (struct omp_region *region,
3800 struct omp_for_data *fd,
3801 enum built_in_function start_fn,
3802 enum built_in_function next_fn)
3804 tree type, istart0, iend0, iend;
3805 tree t, vmain, vback, bias = NULL_TREE;
3806 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3807 basic_block l2_bb = NULL, l3_bb = NULL;
3808 gimple_stmt_iterator gsi;
3809 gimple stmt;
3810 bool in_combined_parallel = is_combined_parallel (region);
3811 bool broken_loop = region->cont == NULL;
3812 edge e, ne;
3813 tree *counts = NULL;
3814 int i;
3816 gcc_assert (!broken_loop || !in_combined_parallel);
3817 gcc_assert (fd->iter_type == long_integer_type_node
3818 || !in_combined_parallel);
3820 type = TREE_TYPE (fd->loop.v);
3821 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3822 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3823 TREE_ADDRESSABLE (istart0) = 1;
3824 TREE_ADDRESSABLE (iend0) = 1;
3826 /* See if we need to bias by LLONG_MIN. */
3827 if (fd->iter_type == long_long_unsigned_type_node
3828 && TREE_CODE (type) == INTEGER_TYPE
3829 && !TYPE_UNSIGNED (type))
3831 tree n1, n2;
3833 if (fd->loop.cond_code == LT_EXPR)
3835 n1 = fd->loop.n1;
3836 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3838 else
3840 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3841 n2 = fd->loop.n1;
3843 if (TREE_CODE (n1) != INTEGER_CST
3844 || TREE_CODE (n2) != INTEGER_CST
3845 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3846 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3849 entry_bb = region->entry;
3850 cont_bb = region->cont;
3851 collapse_bb = NULL;
3852 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3853 gcc_assert (broken_loop
3854 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3855 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3856 l1_bb = single_succ (l0_bb);
3857 if (!broken_loop)
3859 l2_bb = create_empty_bb (cont_bb);
3860 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3861 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3863 else
3864 l2_bb = NULL;
3865 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3866 exit_bb = region->exit;
3868 gsi = gsi_last_bb (entry_bb);
3870 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
3871 if (fd->collapse > 1)
3873 basic_block zero_iter_bb = NULL;
3874 int first_zero_iter = -1;
3876 /* collapsed loops need work for expansion in SSA form. */
3877 gcc_assert (!gimple_in_ssa_p (cfun));
3878 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3879 for (i = 0; i < fd->collapse; i++)
3881 tree itype = TREE_TYPE (fd->loops[i].v);
3883 if (SSA_VAR_P (fd->loop.n2)
3884 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
3885 fold_convert (itype, fd->loops[i].n1),
3886 fold_convert (itype, fd->loops[i].n2)))
3887 == NULL_TREE || !integer_onep (t)))
3889 tree n1, n2;
3890 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
3891 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
3892 true, GSI_SAME_STMT);
3893 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
3894 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
3895 true, GSI_SAME_STMT);
3896 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
3897 NULL_TREE, NULL_TREE);
3898 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3899 if (walk_tree (gimple_cond_lhs_ptr (stmt),
3900 expand_omp_regimplify_p, NULL, NULL)
3901 || walk_tree (gimple_cond_rhs_ptr (stmt),
3902 expand_omp_regimplify_p, NULL, NULL))
3904 gsi = gsi_for_stmt (stmt);
3905 gimple_regimplify_operands (stmt, &gsi);
3907 e = split_block (entry_bb, stmt);
3908 if (zero_iter_bb == NULL)
3910 first_zero_iter = i;
3911 zero_iter_bb = create_empty_bb (entry_bb);
3912 if (current_loops)
3913 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3914 gsi = gsi_after_labels (zero_iter_bb);
3915 stmt = gimple_build_assign (fd->loop.n2,
3916 build_zero_cst (type));
3917 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3918 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
3919 entry_bb);
3921 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
3922 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
3923 e->flags = EDGE_TRUE_VALUE;
3924 e->probability = REG_BR_PROB_BASE - ne->probability;
3925 entry_bb = e->dest;
3926 gsi = gsi_last_bb (entry_bb);
3928 if (POINTER_TYPE_P (itype))
3929 itype = signed_type_for (itype);
3930 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3931 ? -1 : 1));
3932 t = fold_build2 (PLUS_EXPR, itype,
3933 fold_convert (itype, fd->loops[i].step), t);
3934 t = fold_build2 (PLUS_EXPR, itype, t,
3935 fold_convert (itype, fd->loops[i].n2));
3936 t = fold_build2 (MINUS_EXPR, itype, t,
3937 fold_convert (itype, fd->loops[i].n1));
3938 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3939 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3940 fold_build1 (NEGATE_EXPR, itype, t),
3941 fold_build1 (NEGATE_EXPR, itype,
3942 fold_convert (itype,
3943 fd->loops[i].step)));
3944 else
3945 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3946 fold_convert (itype, fd->loops[i].step));
3947 t = fold_convert (type, t);
3948 if (TREE_CODE (t) == INTEGER_CST)
3949 counts[i] = t;
3950 else
3952 counts[i] = create_tmp_reg (type, ".count");
3953 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3954 true, GSI_SAME_STMT);
3955 stmt = gimple_build_assign (counts[i], t);
3956 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3958 if (SSA_VAR_P (fd->loop.n2))
3960 if (i == 0)
3961 t = counts[0];
3962 else
3964 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3965 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3966 true, GSI_SAME_STMT);
3968 stmt = gimple_build_assign (fd->loop.n2, t);
3969 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3972 if (zero_iter_bb)
3974 /* Some counts[i] vars might be uninitialized if
3975 some loop has zero iterations. But the body shouldn't
3976 be executed in that case, so just avoid uninit warnings. */
3977 for (i = first_zero_iter; i < fd->collapse; i++)
3978 if (SSA_VAR_P (counts[i]))
3979 TREE_NO_WARNING (counts[i]) = 1;
3980 gsi_prev (&gsi);
3981 e = split_block (entry_bb, gsi_stmt (gsi));
3982 entry_bb = e->dest;
3983 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
3984 gsi = gsi_last_bb (entry_bb);
3985 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
3986 get_immediate_dominator (CDI_DOMINATORS,
3987 zero_iter_bb));
3990 if (in_combined_parallel)
3992 /* In a combined parallel loop, emit a call to
3993 GOMP_loop_foo_next. */
3994 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
3995 build_fold_addr_expr (istart0),
3996 build_fold_addr_expr (iend0));
3998 else
4000 tree t0, t1, t2, t3, t4;
4001 /* If this is not a combined parallel loop, emit a call to
4002 GOMP_loop_foo_start in ENTRY_BB. */
4003 t4 = build_fold_addr_expr (iend0);
4004 t3 = build_fold_addr_expr (istart0);
4005 t2 = fold_convert (fd->iter_type, fd->loop.step);
4006 if (POINTER_TYPE_P (type)
4007 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
4009 /* Avoid casting pointers to integer of a different size. */
4010 tree itype = signed_type_for (type);
4011 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
4012 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
4014 else
4016 t1 = fold_convert (fd->iter_type, fd->loop.n2);
4017 t0 = fold_convert (fd->iter_type, fd->loop.n1);
4019 if (bias)
4021 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
4022 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
4024 if (fd->iter_type == long_integer_type_node)
4026 if (fd->chunk_size)
4028 t = fold_convert (fd->iter_type, fd->chunk_size);
4029 t = build_call_expr (builtin_decl_explicit (start_fn),
4030 6, t0, t1, t2, t, t3, t4);
4032 else
4033 t = build_call_expr (builtin_decl_explicit (start_fn),
4034 5, t0, t1, t2, t3, t4);
4036 else
4038 tree t5;
4039 tree c_bool_type;
4040 tree bfn_decl;
4042 /* The GOMP_loop_ull_*start functions have additional boolean
4043 argument, true for < loops and false for > loops.
4044 In Fortran, the C bool type can be different from
4045 boolean_type_node. */
4046 bfn_decl = builtin_decl_explicit (start_fn);
4047 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
4048 t5 = build_int_cst (c_bool_type,
4049 fd->loop.cond_code == LT_EXPR ? 1 : 0);
4050 if (fd->chunk_size)
4052 tree bfn_decl = builtin_decl_explicit (start_fn);
4053 t = fold_convert (fd->iter_type, fd->chunk_size);
4054 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
4056 else
4057 t = build_call_expr (builtin_decl_explicit (start_fn),
4058 6, t5, t0, t1, t2, t3, t4);
4061 if (TREE_TYPE (t) != boolean_type_node)
4062 t = fold_build2 (NE_EXPR, boolean_type_node,
4063 t, build_int_cst (TREE_TYPE (t), 0));
4064 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4065 true, GSI_SAME_STMT);
4066 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4068 /* Remove the GIMPLE_OMP_FOR statement. */
4069 gsi_remove (&gsi, true);
4071 /* Iteration setup for sequential loop goes in L0_BB. */
4072 gsi = gsi_start_bb (l0_bb);
4073 t = istart0;
4074 if (bias)
4075 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4076 if (POINTER_TYPE_P (type))
4077 t = fold_convert (signed_type_for (type), t);
4078 t = fold_convert (type, t);
4079 t = force_gimple_operand_gsi (&gsi, t,
4080 DECL_P (fd->loop.v)
4081 && TREE_ADDRESSABLE (fd->loop.v),
4082 NULL_TREE, false, GSI_CONTINUE_LINKING);
4083 stmt = gimple_build_assign (fd->loop.v, t);
4084 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4086 t = iend0;
4087 if (bias)
4088 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4089 if (POINTER_TYPE_P (type))
4090 t = fold_convert (signed_type_for (type), t);
4091 t = fold_convert (type, t);
4092 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4093 false, GSI_CONTINUE_LINKING);
4094 if (fd->collapse > 1)
4096 tree tem = create_tmp_reg (type, ".tem");
4097 stmt = gimple_build_assign (tem, fd->loop.v);
4098 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4099 for (i = fd->collapse - 1; i >= 0; i--)
4101 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
4102 itype = vtype;
4103 if (POINTER_TYPE_P (vtype))
4104 itype = signed_type_for (vtype);
4105 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
4106 t = fold_convert (itype, t);
4107 t = fold_build2 (MULT_EXPR, itype, t,
4108 fold_convert (itype, fd->loops[i].step));
4109 if (POINTER_TYPE_P (vtype))
4110 t = fold_build_pointer_plus (fd->loops[i].n1, t);
4111 else
4112 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
4113 t = force_gimple_operand_gsi (&gsi, t,
4114 DECL_P (fd->loops[i].v)
4115 && TREE_ADDRESSABLE (fd->loops[i].v),
4116 NULL_TREE, false,
4117 GSI_CONTINUE_LINKING);
4118 stmt = gimple_build_assign (fd->loops[i].v, t);
4119 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4120 if (i != 0)
4122 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
4123 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4124 false, GSI_CONTINUE_LINKING);
4125 stmt = gimple_build_assign (tem, t);
4126 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4131 if (!broken_loop)
4133 /* Code to control the increment and predicate for the sequential
4134 loop goes in the CONT_BB. */
4135 gsi = gsi_last_bb (cont_bb);
4136 stmt = gsi_stmt (gsi);
4137 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4138 vmain = gimple_omp_continue_control_use (stmt);
4139 vback = gimple_omp_continue_control_def (stmt);
4141 if (POINTER_TYPE_P (type))
4142 t = fold_build_pointer_plus (vmain, fd->loop.step);
4143 else
4144 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4145 t = force_gimple_operand_gsi (&gsi, t,
4146 DECL_P (vback) && TREE_ADDRESSABLE (vback),
4147 NULL_TREE, true, GSI_SAME_STMT);
4148 stmt = gimple_build_assign (vback, t);
4149 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4151 t = build2 (fd->loop.cond_code, boolean_type_node,
4152 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
4153 iend);
4154 stmt = gimple_build_cond_empty (t);
4155 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4157 /* Remove GIMPLE_OMP_CONTINUE. */
4158 gsi_remove (&gsi, true);
4160 if (fd->collapse > 1)
4162 basic_block last_bb, bb;
4164 last_bb = cont_bb;
4165 for (i = fd->collapse - 1; i >= 0; i--)
4167 tree vtype = TREE_TYPE (fd->loops[i].v);
4169 bb = create_empty_bb (last_bb);
4170 gsi = gsi_start_bb (bb);
4172 if (i < fd->collapse - 1)
4174 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4175 e->probability = REG_BR_PROB_BASE / 8;
4177 t = fd->loops[i + 1].n1;
4178 t = force_gimple_operand_gsi (&gsi, t,
4179 DECL_P (fd->loops[i + 1].v)
4180 && TREE_ADDRESSABLE
4181 (fd->loops[i + 1].v),
4182 NULL_TREE, false,
4183 GSI_CONTINUE_LINKING);
4184 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4185 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4187 else
4188 collapse_bb = bb;
4190 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4192 if (POINTER_TYPE_P (vtype))
4193 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4194 else
4195 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
4196 fd->loops[i].step);
4197 t = force_gimple_operand_gsi (&gsi, t,
4198 DECL_P (fd->loops[i].v)
4199 && TREE_ADDRESSABLE (fd->loops[i].v),
4200 NULL_TREE, false,
4201 GSI_CONTINUE_LINKING);
4202 stmt = gimple_build_assign (fd->loops[i].v, t);
4203 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4205 if (i > 0)
4207 t = fd->loops[i].n2;
4208 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4209 false, GSI_CONTINUE_LINKING);
4210 tree v = fd->loops[i].v;
4211 if (DECL_P (v) && TREE_ADDRESSABLE (v))
4212 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
4213 false, GSI_CONTINUE_LINKING);
4214 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
4215 v, t);
4216 stmt = gimple_build_cond_empty (t);
4217 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4218 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
4219 e->probability = REG_BR_PROB_BASE * 7 / 8;
4221 else
4222 make_edge (bb, l1_bb, EDGE_FALLTHRU);
4223 last_bb = bb;
4227 /* Emit code to get the next parallel iteration in L2_BB. */
4228 gsi = gsi_start_bb (l2_bb);
4230 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4231 build_fold_addr_expr (istart0),
4232 build_fold_addr_expr (iend0));
4233 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4234 false, GSI_CONTINUE_LINKING);
4235 if (TREE_TYPE (t) != boolean_type_node)
4236 t = fold_build2 (NE_EXPR, boolean_type_node,
4237 t, build_int_cst (TREE_TYPE (t), 0));
4238 stmt = gimple_build_cond_empty (t);
4239 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4242 /* Add the loop cleanup function. */
4243 gsi = gsi_last_bb (exit_bb);
4244 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4245 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4246 else
4247 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4248 stmt = gimple_build_call (t, 0);
4249 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4250 gsi_remove (&gsi, true);
4252 /* Connect the new blocks. */
4253 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4254 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4256 if (!broken_loop)
4258 gimple_seq phis;
4260 e = find_edge (cont_bb, l3_bb);
4261 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4263 phis = phi_nodes (l3_bb);
4264 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4266 gimple phi = gsi_stmt (gsi);
4267 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4268 PHI_ARG_DEF_FROM_EDGE (phi, e));
4270 remove_edge (e);
4272 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4273 if (fd->collapse > 1)
4275 e = find_edge (cont_bb, l1_bb);
4276 remove_edge (e);
4277 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4279 else
4281 e = find_edge (cont_bb, l1_bb);
4282 e->flags = EDGE_TRUE_VALUE;
4284 e->probability = REG_BR_PROB_BASE * 7 / 8;
4285 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4286 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4288 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4289 recompute_dominator (CDI_DOMINATORS, l2_bb));
4290 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4291 recompute_dominator (CDI_DOMINATORS, l3_bb));
4292 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4293 recompute_dominator (CDI_DOMINATORS, l0_bb));
4294 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4295 recompute_dominator (CDI_DOMINATORS, l1_bb));
4300 /* A subroutine of expand_omp_for. Generate code for a parallel
4301 loop with static schedule and no specified chunk size. Given
4302 parameters:
4304 for (V = N1; V cond N2; V += STEP) BODY;
4306 where COND is "<" or ">", we generate pseudocode
4308 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
4309 if (cond is <)
4310 adj = STEP - 1;
4311 else
4312 adj = STEP + 1;
4313 if ((__typeof (V)) -1 > 0 && cond is >)
4314 n = -(adj + N2 - N1) / -STEP;
4315 else
4316 n = (adj + N2 - N1) / STEP;
4317 q = n / nthreads;
4318 tt = n % nthreads;
4319 if (threadid < tt) goto L3; else goto L4;
4321 tt = 0;
4322 q = q + 1;
4324 s0 = q * threadid + tt;
4325 e0 = s0 + q;
4326 V = s0 * STEP + N1;
4327 if (s0 >= e0) goto L2; else goto L0;
4329 e = e0 * STEP + N1;
4331 BODY;
4332 V += STEP;
4333 if (V cond e) goto L1;
4337 static void
4338 expand_omp_for_static_nochunk (struct omp_region *region,
4339 struct omp_for_data *fd)
4341 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
4342 tree type, itype, vmain, vback;
4343 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4344 basic_block body_bb, cont_bb;
4345 basic_block fin_bb;
4346 gimple_stmt_iterator gsi;
4347 gimple stmt;
4348 edge ep;
4350 itype = type = TREE_TYPE (fd->loop.v);
4351 if (POINTER_TYPE_P (type))
4352 itype = signed_type_for (type);
4354 entry_bb = region->entry;
4355 cont_bb = region->cont;
4356 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4357 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4358 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4359 body_bb = single_succ (seq_start_bb);
4360 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4361 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4362 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4363 exit_bb = region->exit;
4365 /* Iteration space partitioning goes in ENTRY_BB. */
4366 gsi = gsi_last_bb (entry_bb);
4367 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4369 t = fold_binary (fd->loop.cond_code, boolean_type_node,
4370 fold_convert (type, fd->loop.n1),
4371 fold_convert (type, fd->loop.n2));
4372 if (TYPE_UNSIGNED (type)
4373 && (t == NULL_TREE || !integer_onep (t)))
4375 tree n1, n2;
4376 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
4377 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
4378 true, GSI_SAME_STMT);
4379 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
4380 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
4381 true, GSI_SAME_STMT);
4382 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
4383 NULL_TREE, NULL_TREE);
4384 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4385 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4386 expand_omp_regimplify_p, NULL, NULL)
4387 || walk_tree (gimple_cond_rhs_ptr (stmt),
4388 expand_omp_regimplify_p, NULL, NULL))
4390 gsi = gsi_for_stmt (stmt);
4391 gimple_regimplify_operands (stmt, &gsi);
4393 ep = split_block (entry_bb, stmt);
4394 ep->flags = EDGE_TRUE_VALUE;
4395 entry_bb = ep->dest;
4396 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
4397 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
4398 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
4399 if (gimple_in_ssa_p (cfun))
4401 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
4402 for (gsi = gsi_start_phis (fin_bb);
4403 !gsi_end_p (gsi); gsi_next (&gsi))
4405 gimple phi = gsi_stmt (gsi);
4406 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
4407 ep, UNKNOWN_LOCATION);
4410 gsi = gsi_last_bb (entry_bb);
4413 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4414 t = fold_convert (itype, t);
4415 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4416 true, GSI_SAME_STMT);
4418 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4419 t = fold_convert (itype, t);
4420 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4421 true, GSI_SAME_STMT);
4423 fd->loop.n1
4424 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4425 true, NULL_TREE, true, GSI_SAME_STMT);
4426 fd->loop.n2
4427 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4428 true, NULL_TREE, true, GSI_SAME_STMT);
4429 fd->loop.step
4430 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4431 true, NULL_TREE, true, GSI_SAME_STMT);
4433 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4434 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4435 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4436 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4437 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4438 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4439 fold_build1 (NEGATE_EXPR, itype, t),
4440 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4441 else
4442 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4443 t = fold_convert (itype, t);
4444 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4446 q = create_tmp_reg (itype, "q");
4447 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4448 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4449 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4451 tt = create_tmp_reg (itype, "tt");
4452 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4453 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4454 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
4456 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4457 stmt = gimple_build_cond_empty (t);
4458 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4460 second_bb = split_block (entry_bb, stmt)->dest;
4461 gsi = gsi_last_bb (second_bb);
4462 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4464 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4465 GSI_SAME_STMT);
4466 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4467 build_int_cst (itype, 1));
4468 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4470 third_bb = split_block (second_bb, stmt)->dest;
4471 gsi = gsi_last_bb (third_bb);
4472 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4474 t = build2 (MULT_EXPR, itype, q, threadid);
4475 t = build2 (PLUS_EXPR, itype, t, tt);
4476 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4478 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4479 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4481 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4482 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4484 /* Remove the GIMPLE_OMP_FOR statement. */
4485 gsi_remove (&gsi, true);
4487 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4488 gsi = gsi_start_bb (seq_start_bb);
4490 t = fold_convert (itype, s0);
4491 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4492 if (POINTER_TYPE_P (type))
4493 t = fold_build_pointer_plus (fd->loop.n1, t);
4494 else
4495 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4496 t = force_gimple_operand_gsi (&gsi, t,
4497 DECL_P (fd->loop.v)
4498 && TREE_ADDRESSABLE (fd->loop.v),
4499 NULL_TREE, false, GSI_CONTINUE_LINKING);
4500 stmt = gimple_build_assign (fd->loop.v, t);
4501 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4503 t = fold_convert (itype, e0);
4504 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4505 if (POINTER_TYPE_P (type))
4506 t = fold_build_pointer_plus (fd->loop.n1, t);
4507 else
4508 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4509 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4510 false, GSI_CONTINUE_LINKING);
4512 /* The code controlling the sequential loop replaces the
4513 GIMPLE_OMP_CONTINUE. */
4514 gsi = gsi_last_bb (cont_bb);
4515 stmt = gsi_stmt (gsi);
4516 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4517 vmain = gimple_omp_continue_control_use (stmt);
4518 vback = gimple_omp_continue_control_def (stmt);
4520 if (POINTER_TYPE_P (type))
4521 t = fold_build_pointer_plus (vmain, fd->loop.step);
4522 else
4523 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4524 t = force_gimple_operand_gsi (&gsi, t,
4525 DECL_P (vback) && TREE_ADDRESSABLE (vback),
4526 NULL_TREE, true, GSI_SAME_STMT);
4527 stmt = gimple_build_assign (vback, t);
4528 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4530 t = build2 (fd->loop.cond_code, boolean_type_node,
4531 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback, e);
4532 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4534 /* Remove the GIMPLE_OMP_CONTINUE statement. */
4535 gsi_remove (&gsi, true);
4537 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4538 gsi = gsi_last_bb (exit_bb);
4539 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4540 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
4541 false, GSI_SAME_STMT);
4542 gsi_remove (&gsi, true);
4544 /* Connect all the blocks. */
4545 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
4546 ep->probability = REG_BR_PROB_BASE / 4 * 3;
4547 ep = find_edge (entry_bb, second_bb);
4548 ep->flags = EDGE_TRUE_VALUE;
4549 ep->probability = REG_BR_PROB_BASE / 4;
4550 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
4551 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
4553 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4554 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4556 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
4557 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
4558 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
4559 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4560 recompute_dominator (CDI_DOMINATORS, body_bb));
4561 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4562 recompute_dominator (CDI_DOMINATORS, fin_bb));
4566 /* A subroutine of expand_omp_for. Generate code for a parallel
4567 loop with static schedule and a specified chunk size. Given
4568 parameters:
4570 for (V = N1; V cond N2; V += STEP) BODY;
4572 where COND is "<" or ">", we generate pseudocode
4574 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
4575 if (cond is <)
4576 adj = STEP - 1;
4577 else
4578 adj = STEP + 1;
4579 if ((__typeof (V)) -1 > 0 && cond is >)
4580 n = -(adj + N2 - N1) / -STEP;
4581 else
4582 n = (adj + N2 - N1) / STEP;
4583 trip = 0;
4584 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4585 here so that V is defined
4586 if the loop is not entered
4588 s0 = (trip * nthreads + threadid) * CHUNK;
4589 e0 = min(s0 + CHUNK, n);
4590 if (s0 < n) goto L1; else goto L4;
4592 V = s0 * STEP + N1;
4593 e = e0 * STEP + N1;
4595 BODY;
4596 V += STEP;
4597 if (V cond e) goto L2; else goto L3;
4599 trip += 1;
4600 goto L0;
4604 static void
4605 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
4607 tree n, s0, e0, e, t;
4608 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4609 tree type, itype, v_main, v_back, v_extra;
4610 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4611 basic_block trip_update_bb, cont_bb, fin_bb;
4612 gimple_stmt_iterator si;
4613 gimple stmt;
4614 edge se;
4616 itype = type = TREE_TYPE (fd->loop.v);
4617 if (POINTER_TYPE_P (type))
4618 itype = signed_type_for (type);
4620 entry_bb = region->entry;
4621 se = split_block (entry_bb, last_stmt (entry_bb));
4622 entry_bb = se->src;
4623 iter_part_bb = se->dest;
4624 cont_bb = region->cont;
4625 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4626 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4627 == FALLTHRU_EDGE (cont_bb)->dest);
4628 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4629 body_bb = single_succ (seq_start_bb);
4630 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4631 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4632 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4633 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4634 exit_bb = region->exit;
4636 /* Trip and adjustment setup goes in ENTRY_BB. */
4637 si = gsi_last_bb (entry_bb);
4638 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
4640 t = fold_binary (fd->loop.cond_code, boolean_type_node,
4641 fold_convert (type, fd->loop.n1),
4642 fold_convert (type, fd->loop.n2));
4643 if (TYPE_UNSIGNED (type)
4644 && (t == NULL_TREE || !integer_onep (t)))
4646 tree n1, n2;
4647 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
4648 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
4649 true, GSI_SAME_STMT);
4650 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
4651 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
4652 true, GSI_SAME_STMT);
4653 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
4654 NULL_TREE, NULL_TREE);
4655 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4656 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4657 expand_omp_regimplify_p, NULL, NULL)
4658 || walk_tree (gimple_cond_rhs_ptr (stmt),
4659 expand_omp_regimplify_p, NULL, NULL))
4661 si = gsi_for_stmt (stmt);
4662 gimple_regimplify_operands (stmt, &si);
4664 se = split_block (entry_bb, stmt);
4665 se->flags = EDGE_TRUE_VALUE;
4666 entry_bb = se->dest;
4667 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
4668 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
4669 se->probability = REG_BR_PROB_BASE / 2000 - 1;
4670 if (gimple_in_ssa_p (cfun))
4672 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
4673 for (si = gsi_start_phis (fin_bb);
4674 !gsi_end_p (si); gsi_next (&si))
4676 gimple phi = gsi_stmt (si);
4677 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
4678 se, UNKNOWN_LOCATION);
4681 si = gsi_last_bb (entry_bb);
4684 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4685 t = fold_convert (itype, t);
4686 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4687 true, GSI_SAME_STMT);
4689 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4690 t = fold_convert (itype, t);
4691 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4692 true, GSI_SAME_STMT);
4694 fd->loop.n1
4695 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
4696 true, NULL_TREE, true, GSI_SAME_STMT);
4697 fd->loop.n2
4698 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
4699 true, NULL_TREE, true, GSI_SAME_STMT);
4700 fd->loop.step
4701 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
4702 true, NULL_TREE, true, GSI_SAME_STMT);
4703 fd->chunk_size
4704 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
4705 true, NULL_TREE, true, GSI_SAME_STMT);
4707 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4708 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4709 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4710 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4711 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4712 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4713 fold_build1 (NEGATE_EXPR, itype, t),
4714 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4715 else
4716 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4717 t = fold_convert (itype, t);
4718 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4719 true, GSI_SAME_STMT);
4721 trip_var = create_tmp_reg (itype, ".trip");
4722 if (gimple_in_ssa_p (cfun))
4724 trip_init = make_ssa_name (trip_var, NULL);
4725 trip_main = make_ssa_name (trip_var, NULL);
4726 trip_back = make_ssa_name (trip_var, NULL);
4728 else
4730 trip_init = trip_var;
4731 trip_main = trip_var;
4732 trip_back = trip_var;
4735 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
4736 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4738 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4739 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4740 if (POINTER_TYPE_P (type))
4741 t = fold_build_pointer_plus (fd->loop.n1, t);
4742 else
4743 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4744 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4745 true, GSI_SAME_STMT);
4747 /* Remove the GIMPLE_OMP_FOR. */
4748 gsi_remove (&si, true);
4750 /* Iteration space partitioning goes in ITER_PART_BB. */
4751 si = gsi_last_bb (iter_part_bb);
4753 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4754 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4755 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4756 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4757 false, GSI_CONTINUE_LINKING);
4759 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4760 t = fold_build2 (MIN_EXPR, itype, t, n);
4761 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4762 false, GSI_CONTINUE_LINKING);
4764 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4765 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
4767 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4768 si = gsi_start_bb (seq_start_bb);
4770 t = fold_convert (itype, s0);
4771 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4772 if (POINTER_TYPE_P (type))
4773 t = fold_build_pointer_plus (fd->loop.n1, t);
4774 else
4775 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4776 t = force_gimple_operand_gsi (&si, t,
4777 DECL_P (fd->loop.v)
4778 && TREE_ADDRESSABLE (fd->loop.v),
4779 NULL_TREE, false, GSI_CONTINUE_LINKING);
4780 stmt = gimple_build_assign (fd->loop.v, t);
4781 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4783 t = fold_convert (itype, e0);
4784 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4785 if (POINTER_TYPE_P (type))
4786 t = fold_build_pointer_plus (fd->loop.n1, t);
4787 else
4788 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4789 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4790 false, GSI_CONTINUE_LINKING);
4792 /* The code controlling the sequential loop goes in CONT_BB,
4793 replacing the GIMPLE_OMP_CONTINUE. */
4794 si = gsi_last_bb (cont_bb);
4795 stmt = gsi_stmt (si);
4796 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4797 v_main = gimple_omp_continue_control_use (stmt);
4798 v_back = gimple_omp_continue_control_def (stmt);
4800 if (POINTER_TYPE_P (type))
4801 t = fold_build_pointer_plus (v_main, fd->loop.step);
4802 else
4803 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4804 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
4805 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4806 true, GSI_SAME_STMT);
4807 stmt = gimple_build_assign (v_back, t);
4808 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4810 t = build2 (fd->loop.cond_code, boolean_type_node,
4811 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
4812 ? t : v_back, e);
4813 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
4815 /* Remove GIMPLE_OMP_CONTINUE. */
4816 gsi_remove (&si, true);
4818 /* Trip update code goes into TRIP_UPDATE_BB. */
4819 si = gsi_start_bb (trip_update_bb);
4821 t = build_int_cst (itype, 1);
4822 t = build2 (PLUS_EXPR, itype, trip_main, t);
4823 stmt = gimple_build_assign (trip_back, t);
4824 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4826 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4827 si = gsi_last_bb (exit_bb);
4828 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
4829 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4830 false, GSI_SAME_STMT);
4831 gsi_remove (&si, true);
4833 /* Connect the new blocks. */
4834 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4835 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4837 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4838 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4840 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4842 if (gimple_in_ssa_p (cfun))
4844 gimple_stmt_iterator psi;
4845 gimple phi;
4846 edge re, ene;
4847 edge_var_map_vector *head;
4848 edge_var_map *vm;
4849 size_t i;
4851 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4852 remove arguments of the phi nodes in fin_bb. We need to create
4853 appropriate phi nodes in iter_part_bb instead. */
4854 se = single_pred_edge (fin_bb);
4855 re = single_succ_edge (trip_update_bb);
4856 head = redirect_edge_var_map_vector (re);
4857 ene = single_succ_edge (entry_bb);
4859 psi = gsi_start_phis (fin_bb);
4860 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
4861 gsi_next (&psi), ++i)
4863 gimple nphi;
4864 source_location locus;
4866 phi = gsi_stmt (psi);
4867 t = gimple_phi_result (phi);
4868 gcc_assert (t == redirect_edge_var_map_result (vm));
4869 nphi = create_phi_node (t, iter_part_bb);
4871 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4872 locus = gimple_phi_arg_location_from_edge (phi, se);
4874 /* A special case -- fd->loop.v is not yet computed in
4875 iter_part_bb, we need to use v_extra instead. */
4876 if (t == fd->loop.v)
4877 t = v_extra;
4878 add_phi_arg (nphi, t, ene, locus);
4879 locus = redirect_edge_var_map_location (vm);
4880 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
4882 gcc_assert (!gsi_end_p (psi) && i == head->length ());
4883 redirect_edge_var_map_clear (re);
4884 while (1)
4886 psi = gsi_start_phis (fin_bb);
4887 if (gsi_end_p (psi))
4888 break;
4889 remove_phi_node (&psi, false);
4892 /* Make phi node for trip. */
4893 phi = create_phi_node (trip_main, iter_part_bb);
4894 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
4895 UNKNOWN_LOCATION);
4896 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
4897 UNKNOWN_LOCATION);
4900 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4901 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4902 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4903 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4904 recompute_dominator (CDI_DOMINATORS, fin_bb));
4905 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4906 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4907 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4908 recompute_dominator (CDI_DOMINATORS, body_bb));
4912 /* Expand the OpenMP loop defined by REGION. */
4914 static void
4915 expand_omp_for (struct omp_region *region)
4917 struct omp_for_data fd;
4918 struct omp_for_data_loop *loops;
4920 loops
4921 = (struct omp_for_data_loop *)
4922 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
4923 * sizeof (struct omp_for_data_loop));
4924 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4925 region->sched_kind = fd.sched_kind;
4927 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4928 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4929 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4930 if (region->cont)
4932 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4933 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4934 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4937 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4938 && !fd.have_ordered
4939 && fd.collapse == 1
4940 && region->cont != NULL)
4942 if (fd.chunk_size == NULL)
4943 expand_omp_for_static_nochunk (region, &fd);
4944 else
4945 expand_omp_for_static_chunk (region, &fd);
4947 else
4949 int fn_index, start_ix, next_ix;
4951 if (fd.chunk_size == NULL
4952 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
4953 fd.chunk_size = integer_zero_node;
4954 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4955 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4956 ? 3 : fd.sched_kind;
4957 fn_index += fd.have_ordered * 4;
4958 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
4959 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
4960 if (fd.iter_type == long_long_unsigned_type_node)
4962 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4963 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
4964 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4965 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
4967 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
4968 (enum built_in_function) next_ix);
4971 if (gimple_in_ssa_p (cfun))
4972 update_ssa (TODO_update_ssa_only_virtuals);
4976 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4978 v = GOMP_sections_start (n);
4980 switch (v)
4982 case 0:
4983 goto L2;
4984 case 1:
4985 section 1;
4986 goto L1;
4987 case 2:
4989 case n:
4991 default:
4992 abort ();
4995 v = GOMP_sections_next ();
4996 goto L0;
4998 reduction;
5000 If this is a combined parallel sections, replace the call to
5001 GOMP_sections_start with call to GOMP_sections_next. */
5003 static void
5004 expand_omp_sections (struct omp_region *region)
5006 tree t, u, vin = NULL, vmain, vnext, l2;
5007 vec<tree> label_vec;
5008 unsigned len;
5009 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
5010 gimple_stmt_iterator si, switch_si;
5011 gimple sections_stmt, stmt, cont;
5012 edge_iterator ei;
5013 edge e;
5014 struct omp_region *inner;
5015 unsigned i, casei;
5016 bool exit_reachable = region->cont != NULL;
5018 gcc_assert (region->exit != NULL);
5019 entry_bb = region->entry;
5020 l0_bb = single_succ (entry_bb);
5021 l1_bb = region->cont;
5022 l2_bb = region->exit;
5023 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
5024 l2 = gimple_block_label (l2_bb);
5025 else
5027 /* This can happen if there are reductions. */
5028 len = EDGE_COUNT (l0_bb->succs);
5029 gcc_assert (len > 0);
5030 e = EDGE_SUCC (l0_bb, len - 1);
5031 si = gsi_last_bb (e->dest);
5032 l2 = NULL_TREE;
5033 if (gsi_end_p (si)
5034 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
5035 l2 = gimple_block_label (e->dest);
5036 else
5037 FOR_EACH_EDGE (e, ei, l0_bb->succs)
5039 si = gsi_last_bb (e->dest);
5040 if (gsi_end_p (si)
5041 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
5043 l2 = gimple_block_label (e->dest);
5044 break;
5048 if (exit_reachable)
5049 default_bb = create_empty_bb (l1_bb->prev_bb);
5050 else
5051 default_bb = create_empty_bb (l0_bb);
5053 /* We will build a switch() with enough cases for all the
5054 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
5055 and a default case to abort if something goes wrong. */
5056 len = EDGE_COUNT (l0_bb->succs);
5058 /* Use vec::quick_push on label_vec throughout, since we know the size
5059 in advance. */
5060 label_vec.create (len);
5062 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
5063 GIMPLE_OMP_SECTIONS statement. */
5064 si = gsi_last_bb (entry_bb);
5065 sections_stmt = gsi_stmt (si);
5066 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
5067 vin = gimple_omp_sections_control (sections_stmt);
5068 if (!is_combined_parallel (region))
5070 /* If we are not inside a combined parallel+sections region,
5071 call GOMP_sections_start. */
5072 t = build_int_cst (unsigned_type_node, len - 1);
5073 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
5074 stmt = gimple_build_call (u, 1, t);
5076 else
5078 /* Otherwise, call GOMP_sections_next. */
5079 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
5080 stmt = gimple_build_call (u, 0);
5082 gimple_call_set_lhs (stmt, vin);
5083 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5084 gsi_remove (&si, true);
5086 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
5087 L0_BB. */
5088 switch_si = gsi_last_bb (l0_bb);
5089 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
5090 if (exit_reachable)
5092 cont = last_stmt (l1_bb);
5093 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
5094 vmain = gimple_omp_continue_control_use (cont);
5095 vnext = gimple_omp_continue_control_def (cont);
5097 else
5099 vmain = vin;
5100 vnext = NULL_TREE;
5103 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
5104 label_vec.quick_push (t);
5105 i = 1;
5107 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
5108 for (inner = region->inner, casei = 1;
5109 inner;
5110 inner = inner->next, i++, casei++)
5112 basic_block s_entry_bb, s_exit_bb;
5114 /* Skip optional reduction region. */
5115 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
5117 --i;
5118 --casei;
5119 continue;
5122 s_entry_bb = inner->entry;
5123 s_exit_bb = inner->exit;
5125 t = gimple_block_label (s_entry_bb);
5126 u = build_int_cst (unsigned_type_node, casei);
5127 u = build_case_label (u, NULL, t);
5128 label_vec.quick_push (u);
5130 si = gsi_last_bb (s_entry_bb);
5131 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
5132 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
5133 gsi_remove (&si, true);
5134 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
5136 if (s_exit_bb == NULL)
5137 continue;
5139 si = gsi_last_bb (s_exit_bb);
5140 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
5141 gsi_remove (&si, true);
5143 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
5146 /* Error handling code goes in DEFAULT_BB. */
5147 t = gimple_block_label (default_bb);
5148 u = build_case_label (NULL, NULL, t);
5149 make_edge (l0_bb, default_bb, 0);
5151 stmt = gimple_build_switch (vmain, u, label_vec);
5152 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
5153 gsi_remove (&switch_si, true);
5154 label_vec.release ();
5156 si = gsi_start_bb (default_bb);
5157 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
5158 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
5160 if (exit_reachable)
5162 tree bfn_decl;
5164 /* Code to get the next section goes in L1_BB. */
5165 si = gsi_last_bb (l1_bb);
5166 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
5168 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
5169 stmt = gimple_build_call (bfn_decl, 0);
5170 gimple_call_set_lhs (stmt, vnext);
5171 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5172 gsi_remove (&si, true);
5174 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
5177 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
5178 si = gsi_last_bb (l2_bb);
5179 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
5180 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
5181 else
5182 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
5183 stmt = gimple_build_call (t, 0);
5184 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5185 gsi_remove (&si, true);
5187 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
5191 /* Expand code for an OpenMP single directive. We've already expanded
5192 much of the code, here we simply place the GOMP_barrier call. */
5194 static void
5195 expand_omp_single (struct omp_region *region)
5197 basic_block entry_bb, exit_bb;
5198 gimple_stmt_iterator si;
5199 bool need_barrier = false;
5201 entry_bb = region->entry;
5202 exit_bb = region->exit;
5204 si = gsi_last_bb (entry_bb);
5205 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
5206 be removed. We need to ensure that the thread that entered the single
5207 does not exit before the data is copied out by the other threads. */
5208 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
5209 OMP_CLAUSE_COPYPRIVATE))
5210 need_barrier = true;
5211 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
5212 gsi_remove (&si, true);
5213 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5215 si = gsi_last_bb (exit_bb);
5216 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
5217 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
5218 false, GSI_SAME_STMT);
5219 gsi_remove (&si, true);
5220 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
5224 /* Generic expansion for OpenMP synchronization directives: master,
5225 ordered and critical. All we need to do here is remove the entry
5226 and exit markers for REGION. */
5228 static void
5229 expand_omp_synch (struct omp_region *region)
5231 basic_block entry_bb, exit_bb;
5232 gimple_stmt_iterator si;
5234 entry_bb = region->entry;
5235 exit_bb = region->exit;
5237 si = gsi_last_bb (entry_bb);
5238 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
5239 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
5240 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
5241 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
5242 gsi_remove (&si, true);
5243 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5245 if (exit_bb)
5247 si = gsi_last_bb (exit_bb);
5248 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
5249 gsi_remove (&si, true);
5250 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
5254 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5255 operation as a normal volatile load. */
5257 static bool
5258 expand_omp_atomic_load (basic_block load_bb, tree addr,
5259 tree loaded_val, int index)
5261 enum built_in_function tmpbase;
5262 gimple_stmt_iterator gsi;
5263 basic_block store_bb;
5264 location_t loc;
5265 gimple stmt;
5266 tree decl, call, type, itype;
5268 gsi = gsi_last_bb (load_bb);
5269 stmt = gsi_stmt (gsi);
5270 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5271 loc = gimple_location (stmt);
5273 /* ??? If the target does not implement atomic_load_optab[mode], and mode
5274 is smaller than word size, then expand_atomic_load assumes that the load
5275 is atomic. We could avoid the builtin entirely in this case. */
5277 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
5278 decl = builtin_decl_explicit (tmpbase);
5279 if (decl == NULL_TREE)
5280 return false;
5282 type = TREE_TYPE (loaded_val);
5283 itype = TREE_TYPE (TREE_TYPE (decl));
5285 call = build_call_expr_loc (loc, decl, 2, addr,
5286 build_int_cst (NULL, MEMMODEL_RELAXED));
5287 if (!useless_type_conversion_p (type, itype))
5288 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5289 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5291 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5292 gsi_remove (&gsi, true);
5294 store_bb = single_succ (load_bb);
5295 gsi = gsi_last_bb (store_bb);
5296 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5297 gsi_remove (&gsi, true);
5299 if (gimple_in_ssa_p (cfun))
5300 update_ssa (TODO_update_ssa_no_phi);
5302 return true;
5305 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5306 operation as a normal volatile store. */
5308 static bool
5309 expand_omp_atomic_store (basic_block load_bb, tree addr,
5310 tree loaded_val, tree stored_val, int index)
5312 enum built_in_function tmpbase;
5313 gimple_stmt_iterator gsi;
5314 basic_block store_bb = single_succ (load_bb);
5315 location_t loc;
5316 gimple stmt;
5317 tree decl, call, type, itype;
5318 enum machine_mode imode;
5319 bool exchange;
5321 gsi = gsi_last_bb (load_bb);
5322 stmt = gsi_stmt (gsi);
5323 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5325 /* If the load value is needed, then this isn't a store but an exchange. */
5326 exchange = gimple_omp_atomic_need_value_p (stmt);
5328 gsi = gsi_last_bb (store_bb);
5329 stmt = gsi_stmt (gsi);
5330 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
5331 loc = gimple_location (stmt);
5333 /* ??? If the target does not implement atomic_store_optab[mode], and mode
5334 is smaller than word size, then expand_atomic_store assumes that the store
5335 is atomic. We could avoid the builtin entirely in this case. */
5337 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
5338 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
5339 decl = builtin_decl_explicit (tmpbase);
5340 if (decl == NULL_TREE)
5341 return false;
5343 type = TREE_TYPE (stored_val);
5345 /* Dig out the type of the function's second argument. */
5346 itype = TREE_TYPE (decl);
5347 itype = TYPE_ARG_TYPES (itype);
5348 itype = TREE_CHAIN (itype);
5349 itype = TREE_VALUE (itype);
5350 imode = TYPE_MODE (itype);
5352 if (exchange && !can_atomic_exchange_p (imode, true))
5353 return false;
5355 if (!useless_type_conversion_p (itype, type))
5356 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
5357 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
5358 build_int_cst (NULL, MEMMODEL_RELAXED));
5359 if (exchange)
5361 if (!useless_type_conversion_p (type, itype))
5362 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5363 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5366 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5367 gsi_remove (&gsi, true);
5369 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
5370 gsi = gsi_last_bb (load_bb);
5371 gsi_remove (&gsi, true);
5373 if (gimple_in_ssa_p (cfun))
5374 update_ssa (TODO_update_ssa_no_phi);
5376 return true;
5379 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5380 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
5381 size of the data type, and thus usable to find the index of the builtin
5382 decl. Returns false if the expression is not of the proper form. */
5384 static bool
5385 expand_omp_atomic_fetch_op (basic_block load_bb,
5386 tree addr, tree loaded_val,
5387 tree stored_val, int index)
5389 enum built_in_function oldbase, newbase, tmpbase;
5390 tree decl, itype, call;
5391 tree lhs, rhs;
5392 basic_block store_bb = single_succ (load_bb);
5393 gimple_stmt_iterator gsi;
5394 gimple stmt;
5395 location_t loc;
5396 enum tree_code code;
5397 bool need_old, need_new;
5398 enum machine_mode imode;
5400 /* We expect to find the following sequences:
5402 load_bb:
5403 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
5405 store_bb:
5406 val = tmp OP something; (or: something OP tmp)
5407 GIMPLE_OMP_STORE (val)
5409 ???FIXME: Allow a more flexible sequence.
5410 Perhaps use data flow to pick the statements.
5414 gsi = gsi_after_labels (store_bb);
5415 stmt = gsi_stmt (gsi);
5416 loc = gimple_location (stmt);
5417 if (!is_gimple_assign (stmt))
5418 return false;
5419 gsi_next (&gsi);
5420 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
5421 return false;
5422 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
5423 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
5424 gcc_checking_assert (!need_old || !need_new);
5426 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
5427 return false;
5429 /* Check for one of the supported fetch-op operations. */
5430 code = gimple_assign_rhs_code (stmt);
5431 switch (code)
5433 case PLUS_EXPR:
5434 case POINTER_PLUS_EXPR:
5435 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
5436 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
5437 break;
5438 case MINUS_EXPR:
5439 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
5440 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
5441 break;
5442 case BIT_AND_EXPR:
5443 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
5444 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
5445 break;
5446 case BIT_IOR_EXPR:
5447 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
5448 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
5449 break;
5450 case BIT_XOR_EXPR:
5451 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
5452 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
5453 break;
5454 default:
5455 return false;
5458 /* Make sure the expression is of the proper form. */
5459 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
5460 rhs = gimple_assign_rhs2 (stmt);
5461 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
5462 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
5463 rhs = gimple_assign_rhs1 (stmt);
5464 else
5465 return false;
5467 tmpbase = ((enum built_in_function)
5468 ((need_new ? newbase : oldbase) + index + 1));
5469 decl = builtin_decl_explicit (tmpbase);
5470 if (decl == NULL_TREE)
5471 return false;
5472 itype = TREE_TYPE (TREE_TYPE (decl));
5473 imode = TYPE_MODE (itype);
5475 /* We could test all of the various optabs involved, but the fact of the
5476 matter is that (with the exception of i486 vs i586 and xadd) all targets
5477 that support any atomic operaton optab also implements compare-and-swap.
5478 Let optabs.c take care of expanding any compare-and-swap loop. */
5479 if (!can_compare_and_swap_p (imode, true))
5480 return false;
5482 gsi = gsi_last_bb (load_bb);
5483 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
5485 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
5486 It only requires that the operation happen atomically. Thus we can
5487 use the RELAXED memory model. */
5488 call = build_call_expr_loc (loc, decl, 3, addr,
5489 fold_convert_loc (loc, itype, rhs),
5490 build_int_cst (NULL, MEMMODEL_RELAXED));
5492 if (need_old || need_new)
5494 lhs = need_old ? loaded_val : stored_val;
5495 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
5496 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
5498 else
5499 call = fold_convert_loc (loc, void_type_node, call);
5500 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5501 gsi_remove (&gsi, true);
5503 gsi = gsi_last_bb (store_bb);
5504 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5505 gsi_remove (&gsi, true);
5506 gsi = gsi_last_bb (store_bb);
5507 gsi_remove (&gsi, true);
5509 if (gimple_in_ssa_p (cfun))
5510 update_ssa (TODO_update_ssa_no_phi);
5512 return true;
5515 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5517 oldval = *addr;
5518 repeat:
5519 newval = rhs; // with oldval replacing *addr in rhs
5520 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
5521 if (oldval != newval)
5522 goto repeat;
5524 INDEX is log2 of the size of the data type, and thus usable to find the
5525 index of the builtin decl. */
5527 static bool
5528 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
5529 tree addr, tree loaded_val, tree stored_val,
5530 int index)
5532 tree loadedi, storedi, initial, new_storedi, old_vali;
5533 tree type, itype, cmpxchg, iaddr;
5534 gimple_stmt_iterator si;
5535 basic_block loop_header = single_succ (load_bb);
5536 gimple phi, stmt;
5537 edge e;
5538 enum built_in_function fncode;
5540 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
5541 order to use the RELAXED memory model effectively. */
5542 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
5543 + index + 1);
5544 cmpxchg = builtin_decl_explicit (fncode);
5545 if (cmpxchg == NULL_TREE)
5546 return false;
5547 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5548 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
5550 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
5551 return false;
5553 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
5554 si = gsi_last_bb (load_bb);
5555 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5557 /* For floating-point values, we'll need to view-convert them to integers
5558 so that we can perform the atomic compare and swap. Simplify the
5559 following code by always setting up the "i"ntegral variables. */
5560 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
5562 tree iaddr_val;
5564 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
5565 true), NULL);
5566 iaddr_val
5567 = force_gimple_operand_gsi (&si,
5568 fold_convert (TREE_TYPE (iaddr), addr),
5569 false, NULL_TREE, true, GSI_SAME_STMT);
5570 stmt = gimple_build_assign (iaddr, iaddr_val);
5571 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5572 loadedi = create_tmp_var (itype, NULL);
5573 if (gimple_in_ssa_p (cfun))
5574 loadedi = make_ssa_name (loadedi, NULL);
5576 else
5578 iaddr = addr;
5579 loadedi = loaded_val;
5582 initial
5583 = force_gimple_operand_gsi (&si,
5584 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
5585 iaddr,
5586 build_int_cst (TREE_TYPE (iaddr), 0)),
5587 true, NULL_TREE, true, GSI_SAME_STMT);
5589 /* Move the value to the LOADEDI temporary. */
5590 if (gimple_in_ssa_p (cfun))
5592 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
5593 phi = create_phi_node (loadedi, loop_header);
5594 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
5595 initial);
5597 else
5598 gsi_insert_before (&si,
5599 gimple_build_assign (loadedi, initial),
5600 GSI_SAME_STMT);
5601 if (loadedi != loaded_val)
5603 gimple_stmt_iterator gsi2;
5604 tree x;
5606 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
5607 gsi2 = gsi_start_bb (loop_header);
5608 if (gimple_in_ssa_p (cfun))
5610 gimple stmt;
5611 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5612 true, GSI_SAME_STMT);
5613 stmt = gimple_build_assign (loaded_val, x);
5614 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
5616 else
5618 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
5619 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5620 true, GSI_SAME_STMT);
5623 gsi_remove (&si, true);
5625 si = gsi_last_bb (store_bb);
5626 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5628 if (iaddr == addr)
5629 storedi = stored_val;
5630 else
5631 storedi =
5632 force_gimple_operand_gsi (&si,
5633 build1 (VIEW_CONVERT_EXPR, itype,
5634 stored_val), true, NULL_TREE, true,
5635 GSI_SAME_STMT);
5637 /* Build the compare&swap statement. */
5638 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
5639 new_storedi = force_gimple_operand_gsi (&si,
5640 fold_convert (TREE_TYPE (loadedi),
5641 new_storedi),
5642 true, NULL_TREE,
5643 true, GSI_SAME_STMT);
5645 if (gimple_in_ssa_p (cfun))
5646 old_vali = loadedi;
5647 else
5649 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
5650 stmt = gimple_build_assign (old_vali, loadedi);
5651 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5653 stmt = gimple_build_assign (loadedi, new_storedi);
5654 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5657 /* Note that we always perform the comparison as an integer, even for
5658 floating point. This allows the atomic operation to properly
5659 succeed even with NaNs and -0.0. */
5660 stmt = gimple_build_cond_empty
5661 (build2 (NE_EXPR, boolean_type_node,
5662 new_storedi, old_vali));
5663 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5665 /* Update cfg. */
5666 e = single_succ_edge (store_bb);
5667 e->flags &= ~EDGE_FALLTHRU;
5668 e->flags |= EDGE_FALSE_VALUE;
5670 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
5672 /* Copy the new value to loadedi (we already did that before the condition
5673 if we are not in SSA). */
5674 if (gimple_in_ssa_p (cfun))
5676 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
5677 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
5680 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
5681 gsi_remove (&si, true);
5683 if (gimple_in_ssa_p (cfun))
5684 update_ssa (TODO_update_ssa_no_phi);
5686 return true;
5689 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5691 GOMP_atomic_start ();
5692 *addr = rhs;
5693 GOMP_atomic_end ();
5695 The result is not globally atomic, but works so long as all parallel
5696 references are within #pragma omp atomic directives. According to
5697 responses received from omp@openmp.org, appears to be within spec.
5698 Which makes sense, since that's how several other compilers handle
5699 this situation as well.
5700 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
5701 expanding. STORED_VAL is the operand of the matching
5702 GIMPLE_OMP_ATOMIC_STORE.
5704 We replace
5705 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
5706 loaded_val = *addr;
5708 and replace
5709 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
5710 *addr = stored_val;
5713 static bool
5714 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
5715 tree addr, tree loaded_val, tree stored_val)
5717 gimple_stmt_iterator si;
5718 gimple stmt;
5719 tree t;
5721 si = gsi_last_bb (load_bb);
5722 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5724 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
5725 t = build_call_expr (t, 0);
5726 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5728 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
5729 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5730 gsi_remove (&si, true);
5732 si = gsi_last_bb (store_bb);
5733 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5735 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
5736 stored_val);
5737 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5739 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
5740 t = build_call_expr (t, 0);
5741 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5742 gsi_remove (&si, true);
5744 if (gimple_in_ssa_p (cfun))
5745 update_ssa (TODO_update_ssa_no_phi);
5746 return true;
5749 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
5750 using expand_omp_atomic_fetch_op. If it failed, we try to
5751 call expand_omp_atomic_pipeline, and if it fails too, the
5752 ultimate fallback is wrapping the operation in a mutex
5753 (expand_omp_atomic_mutex). REGION is the atomic region built
5754 by build_omp_regions_1(). */
5756 static void
5757 expand_omp_atomic (struct omp_region *region)
5759 basic_block load_bb = region->entry, store_bb = region->exit;
5760 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
5761 tree loaded_val = gimple_omp_atomic_load_lhs (load);
5762 tree addr = gimple_omp_atomic_load_rhs (load);
5763 tree stored_val = gimple_omp_atomic_store_val (store);
5764 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5765 HOST_WIDE_INT index;
5767 /* Make sure the type is one of the supported sizes. */
5768 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
5769 index = exact_log2 (index);
5770 if (index >= 0 && index <= 4)
5772 unsigned int align = TYPE_ALIGN_UNIT (type);
5774 /* __sync builtins require strict data alignment. */
5775 if (exact_log2 (align) >= index)
5777 /* Atomic load. */
5778 if (loaded_val == stored_val
5779 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5780 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5781 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5782 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
5783 return;
5785 /* Atomic store. */
5786 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5787 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5788 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5789 && store_bb == single_succ (load_bb)
5790 && first_stmt (store_bb) == store
5791 && expand_omp_atomic_store (load_bb, addr, loaded_val,
5792 stored_val, index))
5793 return;
5795 /* When possible, use specialized atomic update functions. */
5796 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5797 && store_bb == single_succ (load_bb)
5798 && expand_omp_atomic_fetch_op (load_bb, addr,
5799 loaded_val, stored_val, index))
5800 return;
5802 /* If we don't have specialized __sync builtins, try and implement
5803 as a compare and swap loop. */
5804 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5805 loaded_val, stored_val, index))
5806 return;
5810 /* The ultimate fallback is wrapping the operation in a mutex. */
5811 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5815 /* Expand the parallel region tree rooted at REGION. Expansion
5816 proceeds in depth-first order. Innermost regions are expanded
5817 first. This way, parallel regions that require a new function to
5818 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
5819 internal dependencies in their body. */
5821 static void
5822 expand_omp (struct omp_region *region)
5824 while (region)
5826 location_t saved_location;
5828 /* First, determine whether this is a combined parallel+workshare
5829 region. */
5830 if (region->type == GIMPLE_OMP_PARALLEL)
5831 determine_parallel_type (region);
5833 if (region->inner)
5834 expand_omp (region->inner);
5836 saved_location = input_location;
5837 if (gimple_has_location (last_stmt (region->entry)))
5838 input_location = gimple_location (last_stmt (region->entry));
5840 switch (region->type)
5842 case GIMPLE_OMP_PARALLEL:
5843 case GIMPLE_OMP_TASK:
5844 expand_omp_taskreg (region);
5845 break;
5847 case GIMPLE_OMP_FOR:
5848 expand_omp_for (region);
5849 break;
5851 case GIMPLE_OMP_SECTIONS:
5852 expand_omp_sections (region);
5853 break;
5855 case GIMPLE_OMP_SECTION:
5856 /* Individual omp sections are handled together with their
5857 parent GIMPLE_OMP_SECTIONS region. */
5858 break;
5860 case GIMPLE_OMP_SINGLE:
5861 expand_omp_single (region);
5862 break;
5864 case GIMPLE_OMP_MASTER:
5865 case GIMPLE_OMP_ORDERED:
5866 case GIMPLE_OMP_CRITICAL:
5867 expand_omp_synch (region);
5868 break;
5870 case GIMPLE_OMP_ATOMIC_LOAD:
5871 expand_omp_atomic (region);
5872 break;
5874 default:
5875 gcc_unreachable ();
5878 input_location = saved_location;
5879 region = region->next;
5884 /* Helper for build_omp_regions. Scan the dominator tree starting at
5885 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5886 true, the function ends once a single tree is built (otherwise, whole
5887 forest of OMP constructs may be built). */
5889 static void
5890 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5891 bool single_tree)
5893 gimple_stmt_iterator gsi;
5894 gimple stmt;
5895 basic_block son;
5897 gsi = gsi_last_bb (bb);
5898 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
5900 struct omp_region *region;
5901 enum gimple_code code;
5903 stmt = gsi_stmt (gsi);
5904 code = gimple_code (stmt);
5905 if (code == GIMPLE_OMP_RETURN)
5907 /* STMT is the return point out of region PARENT. Mark it
5908 as the exit point and make PARENT the immediately
5909 enclosing region. */
5910 gcc_assert (parent);
5911 region = parent;
5912 region->exit = bb;
5913 parent = parent->outer;
5915 else if (code == GIMPLE_OMP_ATOMIC_STORE)
5917 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
5918 GIMPLE_OMP_RETURN, but matches with
5919 GIMPLE_OMP_ATOMIC_LOAD. */
5920 gcc_assert (parent);
5921 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
5922 region = parent;
5923 region->exit = bb;
5924 parent = parent->outer;
5927 else if (code == GIMPLE_OMP_CONTINUE)
5929 gcc_assert (parent);
5930 parent->cont = bb;
5932 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
5934 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
5935 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
5938 else
5940 /* Otherwise, this directive becomes the parent for a new
5941 region. */
5942 region = new_omp_region (bb, code, parent);
5943 parent = region;
5947 if (single_tree && !parent)
5948 return;
5950 for (son = first_dom_son (CDI_DOMINATORS, bb);
5951 son;
5952 son = next_dom_son (CDI_DOMINATORS, son))
5953 build_omp_regions_1 (son, parent, single_tree);
5956 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5957 root_omp_region. */
5959 static void
5960 build_omp_regions_root (basic_block root)
5962 gcc_assert (root_omp_region == NULL);
5963 build_omp_regions_1 (root, NULL, true);
5964 gcc_assert (root_omp_region != NULL);
5967 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5969 void
5970 omp_expand_local (basic_block head)
5972 build_omp_regions_root (head);
5973 if (dump_file && (dump_flags & TDF_DETAILS))
5975 fprintf (dump_file, "\nOMP region tree\n\n");
5976 dump_omp_region (dump_file, root_omp_region, 0);
5977 fprintf (dump_file, "\n");
5980 remove_exit_barriers (root_omp_region);
5981 expand_omp (root_omp_region);
5983 free_omp_regions ();
5986 /* Scan the CFG and build a tree of OMP regions. Return the root of
5987 the OMP region tree. */
5989 static void
5990 build_omp_regions (void)
5992 gcc_assert (root_omp_region == NULL);
5993 calculate_dominance_info (CDI_DOMINATORS);
5994 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5997 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5999 static unsigned int
6000 execute_expand_omp (void)
6002 build_omp_regions ();
6004 if (!root_omp_region)
6005 return 0;
6007 if (dump_file)
6009 fprintf (dump_file, "\nOMP region tree\n\n");
6010 dump_omp_region (dump_file, root_omp_region, 0);
6011 fprintf (dump_file, "\n");
6014 remove_exit_barriers (root_omp_region);
6016 expand_omp (root_omp_region);
6018 cleanup_tree_cfg ();
6020 free_omp_regions ();
6022 return 0;
6025 /* OMP expansion -- the default pass, run before creation of SSA form. */
6027 static bool
6028 gate_expand_omp (void)
6030 return (flag_openmp != 0 && !seen_error ());
6033 struct gimple_opt_pass pass_expand_omp =
6036 GIMPLE_PASS,
6037 "ompexp", /* name */
6038 OPTGROUP_NONE, /* optinfo_flags */
6039 gate_expand_omp, /* gate */
6040 execute_expand_omp, /* execute */
6041 NULL, /* sub */
6042 NULL, /* next */
6043 0, /* static_pass_number */
6044 TV_NONE, /* tv_id */
6045 PROP_gimple_any, /* properties_required */
6046 0, /* properties_provided */
6047 0, /* properties_destroyed */
6048 0, /* todo_flags_start */
6049 0 /* todo_flags_finish */
6053 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
6055 /* Lower the OpenMP sections directive in the current statement in GSI_P.
6056 CTX is the enclosing OMP context for the current statement. */
6058 static void
6059 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6061 tree block, control;
6062 gimple_stmt_iterator tgsi;
6063 gimple stmt, new_stmt, bind, t;
6064 gimple_seq ilist, dlist, olist, new_body;
6065 struct gimplify_ctx gctx;
6067 stmt = gsi_stmt (*gsi_p);
6069 push_gimplify_context (&gctx);
6071 dlist = NULL;
6072 ilist = NULL;
6073 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
6074 &ilist, &dlist, ctx);
6076 new_body = gimple_omp_body (stmt);
6077 gimple_omp_set_body (stmt, NULL);
6078 tgsi = gsi_start (new_body);
6079 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
6081 omp_context *sctx;
6082 gimple sec_start;
6084 sec_start = gsi_stmt (tgsi);
6085 sctx = maybe_lookup_ctx (sec_start);
6086 gcc_assert (sctx);
6088 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
6089 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
6090 GSI_CONTINUE_LINKING);
6091 gimple_omp_set_body (sec_start, NULL);
6093 if (gsi_one_before_end_p (tgsi))
6095 gimple_seq l = NULL;
6096 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
6097 &l, ctx);
6098 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
6099 gimple_omp_section_set_last (sec_start);
6102 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
6103 GSI_CONTINUE_LINKING);
6106 block = make_node (BLOCK);
6107 bind = gimple_build_bind (NULL, new_body, block);
6109 olist = NULL;
6110 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
6112 block = make_node (BLOCK);
6113 new_stmt = gimple_build_bind (NULL, NULL, block);
6114 gsi_replace (gsi_p, new_stmt, true);
6116 pop_gimplify_context (new_stmt);
6117 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6118 BLOCK_VARS (block) = gimple_bind_vars (bind);
6119 if (BLOCK_VARS (block))
6120 TREE_USED (block) = 1;
6122 new_body = NULL;
6123 gimple_seq_add_seq (&new_body, ilist);
6124 gimple_seq_add_stmt (&new_body, stmt);
6125 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
6126 gimple_seq_add_stmt (&new_body, bind);
6128 control = create_tmp_var (unsigned_type_node, ".section");
6129 t = gimple_build_omp_continue (control, control);
6130 gimple_omp_sections_set_control (stmt, control);
6131 gimple_seq_add_stmt (&new_body, t);
6133 gimple_seq_add_seq (&new_body, olist);
6134 gimple_seq_add_seq (&new_body, dlist);
6136 new_body = maybe_catch_exception (new_body);
6138 t = gimple_build_omp_return
6139 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
6140 OMP_CLAUSE_NOWAIT));
6141 gimple_seq_add_stmt (&new_body, t);
6143 gimple_bind_set_body (new_stmt, new_body);
6147 /* A subroutine of lower_omp_single. Expand the simple form of
6148 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
6150 if (GOMP_single_start ())
6151 BODY;
6152 [ GOMP_barrier (); ] -> unless 'nowait' is present.
6154 FIXME. It may be better to delay expanding the logic of this until
6155 pass_expand_omp. The expanded logic may make the job more difficult
6156 to a synchronization analysis pass. */
6158 static void
6159 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
6161 location_t loc = gimple_location (single_stmt);
6162 tree tlabel = create_artificial_label (loc);
6163 tree flabel = create_artificial_label (loc);
6164 gimple call, cond;
6165 tree lhs, decl;
6167 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
6168 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
6169 call = gimple_build_call (decl, 0);
6170 gimple_call_set_lhs (call, lhs);
6171 gimple_seq_add_stmt (pre_p, call);
6173 cond = gimple_build_cond (EQ_EXPR, lhs,
6174 fold_convert_loc (loc, TREE_TYPE (lhs),
6175 boolean_true_node),
6176 tlabel, flabel);
6177 gimple_seq_add_stmt (pre_p, cond);
6178 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
6179 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
6180 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
6184 /* A subroutine of lower_omp_single. Expand the simple form of
6185 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
6187 #pragma omp single copyprivate (a, b, c)
6189 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
6192 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
6194 BODY;
6195 copyout.a = a;
6196 copyout.b = b;
6197 copyout.c = c;
6198 GOMP_single_copy_end (&copyout);
6200 else
6202 a = copyout_p->a;
6203 b = copyout_p->b;
6204 c = copyout_p->c;
6206 GOMP_barrier ();
6209 FIXME. It may be better to delay expanding the logic of this until
6210 pass_expand_omp. The expanded logic may make the job more difficult
6211 to a synchronization analysis pass. */
6213 static void
6214 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
6216 tree ptr_type, t, l0, l1, l2, bfn_decl;
6217 gimple_seq copyin_seq;
6218 location_t loc = gimple_location (single_stmt);
6220 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
6222 ptr_type = build_pointer_type (ctx->record_type);
6223 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
6225 l0 = create_artificial_label (loc);
6226 l1 = create_artificial_label (loc);
6227 l2 = create_artificial_label (loc);
6229 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
6230 t = build_call_expr_loc (loc, bfn_decl, 0);
6231 t = fold_convert_loc (loc, ptr_type, t);
6232 gimplify_assign (ctx->receiver_decl, t, pre_p);
6234 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
6235 build_int_cst (ptr_type, 0));
6236 t = build3 (COND_EXPR, void_type_node, t,
6237 build_and_jump (&l0), build_and_jump (&l1));
6238 gimplify_and_add (t, pre_p);
6240 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
6242 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
6244 copyin_seq = NULL;
6245 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
6246 &copyin_seq, ctx);
6248 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6249 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
6250 t = build_call_expr_loc (loc, bfn_decl, 1, t);
6251 gimplify_and_add (t, pre_p);
6253 t = build_and_jump (&l2);
6254 gimplify_and_add (t, pre_p);
6256 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
6258 gimple_seq_add_seq (pre_p, copyin_seq);
6260 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
6264 /* Expand code for an OpenMP single directive. */
6266 static void
6267 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6269 tree block;
6270 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
6271 gimple_seq bind_body, dlist;
6272 struct gimplify_ctx gctx;
6274 push_gimplify_context (&gctx);
6276 block = make_node (BLOCK);
6277 bind = gimple_build_bind (NULL, NULL, block);
6278 gsi_replace (gsi_p, bind, true);
6279 bind_body = NULL;
6280 dlist = NULL;
6281 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
6282 &bind_body, &dlist, ctx);
6283 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
6285 gimple_seq_add_stmt (&bind_body, single_stmt);
6287 if (ctx->record_type)
6288 lower_omp_single_copy (single_stmt, &bind_body, ctx);
6289 else
6290 lower_omp_single_simple (single_stmt, &bind_body);
6292 gimple_omp_set_body (single_stmt, NULL);
6294 gimple_seq_add_seq (&bind_body, dlist);
6296 bind_body = maybe_catch_exception (bind_body);
6298 t = gimple_build_omp_return
6299 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
6300 OMP_CLAUSE_NOWAIT));
6301 gimple_seq_add_stmt (&bind_body, t);
6302 gimple_bind_set_body (bind, bind_body);
6304 pop_gimplify_context (bind);
6306 gimple_bind_append_vars (bind, ctx->block_vars);
6307 BLOCK_VARS (block) = ctx->block_vars;
6308 if (BLOCK_VARS (block))
6309 TREE_USED (block) = 1;
6313 /* Expand code for an OpenMP master directive. */
6315 static void
6316 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6318 tree block, lab = NULL, x, bfn_decl;
6319 gimple stmt = gsi_stmt (*gsi_p), bind;
6320 location_t loc = gimple_location (stmt);
6321 gimple_seq tseq;
6322 struct gimplify_ctx gctx;
6324 push_gimplify_context (&gctx);
6326 block = make_node (BLOCK);
6327 bind = gimple_build_bind (NULL, NULL, block);
6328 gsi_replace (gsi_p, bind, true);
6329 gimple_bind_add_stmt (bind, stmt);
6331 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6332 x = build_call_expr_loc (loc, bfn_decl, 0);
6333 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
6334 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
6335 tseq = NULL;
6336 gimplify_and_add (x, &tseq);
6337 gimple_bind_add_seq (bind, tseq);
6339 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6340 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6341 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6342 gimple_omp_set_body (stmt, NULL);
6344 gimple_bind_add_stmt (bind, gimple_build_label (lab));
6346 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6348 pop_gimplify_context (bind);
6350 gimple_bind_append_vars (bind, ctx->block_vars);
6351 BLOCK_VARS (block) = ctx->block_vars;
6355 /* Expand code for an OpenMP ordered directive. */
6357 static void
6358 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6360 tree block;
6361 gimple stmt = gsi_stmt (*gsi_p), bind, x;
6362 struct gimplify_ctx gctx;
6364 push_gimplify_context (&gctx);
6366 block = make_node (BLOCK);
6367 bind = gimple_build_bind (NULL, NULL, block);
6368 gsi_replace (gsi_p, bind, true);
6369 gimple_bind_add_stmt (bind, stmt);
6371 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
6373 gimple_bind_add_stmt (bind, x);
6375 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6376 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6377 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6378 gimple_omp_set_body (stmt, NULL);
6380 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
6381 gimple_bind_add_stmt (bind, x);
6383 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6385 pop_gimplify_context (bind);
6387 gimple_bind_append_vars (bind, ctx->block_vars);
6388 BLOCK_VARS (block) = gimple_bind_vars (bind);
6392 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
6393 substitution of a couple of function calls. But in the NAMED case,
6394 requires that languages coordinate a symbol name. It is therefore
6395 best put here in common code. */
6397 static GTY((param1_is (tree), param2_is (tree)))
6398 splay_tree critical_name_mutexes;
6400 static void
6401 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6403 tree block;
6404 tree name, lock, unlock;
6405 gimple stmt = gsi_stmt (*gsi_p), bind;
6406 location_t loc = gimple_location (stmt);
6407 gimple_seq tbody;
6408 struct gimplify_ctx gctx;
6410 name = gimple_omp_critical_name (stmt);
6411 if (name)
6413 tree decl;
6414 splay_tree_node n;
6416 if (!critical_name_mutexes)
6417 critical_name_mutexes
6418 = splay_tree_new_ggc (splay_tree_compare_pointers,
6419 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
6420 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
6422 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
6423 if (n == NULL)
6425 char *new_str;
6427 decl = create_tmp_var_raw (ptr_type_node, NULL);
6429 new_str = ACONCAT ((".gomp_critical_user_",
6430 IDENTIFIER_POINTER (name), NULL));
6431 DECL_NAME (decl) = get_identifier (new_str);
6432 TREE_PUBLIC (decl) = 1;
6433 TREE_STATIC (decl) = 1;
6434 DECL_COMMON (decl) = 1;
6435 DECL_ARTIFICIAL (decl) = 1;
6436 DECL_IGNORED_P (decl) = 1;
6437 varpool_finalize_decl (decl);
6439 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
6440 (splay_tree_value) decl);
6442 else
6443 decl = (tree) n->value;
6445 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
6446 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
6448 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
6449 unlock = build_call_expr_loc (loc, unlock, 1,
6450 build_fold_addr_expr_loc (loc, decl));
6452 else
6454 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
6455 lock = build_call_expr_loc (loc, lock, 0);
6457 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
6458 unlock = build_call_expr_loc (loc, unlock, 0);
6461 push_gimplify_context (&gctx);
6463 block = make_node (BLOCK);
6464 bind = gimple_build_bind (NULL, NULL, block);
6465 gsi_replace (gsi_p, bind, true);
6466 gimple_bind_add_stmt (bind, stmt);
6468 tbody = gimple_bind_body (bind);
6469 gimplify_and_add (lock, &tbody);
6470 gimple_bind_set_body (bind, tbody);
6472 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6473 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6474 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6475 gimple_omp_set_body (stmt, NULL);
6477 tbody = gimple_bind_body (bind);
6478 gimplify_and_add (unlock, &tbody);
6479 gimple_bind_set_body (bind, tbody);
6481 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6483 pop_gimplify_context (bind);
6484 gimple_bind_append_vars (bind, ctx->block_vars);
6485 BLOCK_VARS (block) = gimple_bind_vars (bind);
6489 /* A subroutine of lower_omp_for. Generate code to emit the predicate
6490 for a lastprivate clause. Given a loop control predicate of (V
6491 cond N2), we gate the clause on (!(V cond N2)). The lowered form
6492 is appended to *DLIST, iterator initialization is appended to
6493 *BODY_P. */
6495 static void
6496 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
6497 gimple_seq *dlist, struct omp_context *ctx)
6499 tree clauses, cond, vinit;
6500 enum tree_code cond_code;
6501 gimple_seq stmts;
6503 cond_code = fd->loop.cond_code;
6504 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
6506 /* When possible, use a strict equality expression. This can let VRP
6507 type optimizations deduce the value and remove a copy. */
6508 if (host_integerp (fd->loop.step, 0))
6510 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
6511 if (step == 1 || step == -1)
6512 cond_code = EQ_EXPR;
6515 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
6517 clauses = gimple_omp_for_clauses (fd->for_stmt);
6518 stmts = NULL;
6519 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
6520 if (!gimple_seq_empty_p (stmts))
6522 gimple_seq_add_seq (&stmts, *dlist);
6523 *dlist = stmts;
6525 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
6526 vinit = fd->loop.n1;
6527 if (cond_code == EQ_EXPR
6528 && host_integerp (fd->loop.n2, 0)
6529 && ! integer_zerop (fd->loop.n2))
6530 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
6532 /* Initialize the iterator variable, so that threads that don't execute
6533 any iterations don't execute the lastprivate clauses by accident. */
6534 gimplify_assign (fd->loop.v, vinit, body_p);
6539 /* Lower code for an OpenMP loop directive. */
6541 static void
6542 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6544 tree *rhs_p, block;
6545 struct omp_for_data fd;
6546 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
6547 gimple_seq omp_for_body, body, dlist;
6548 size_t i;
6549 struct gimplify_ctx gctx;
6551 push_gimplify_context (&gctx);
6553 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
6554 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6556 block = make_node (BLOCK);
6557 new_stmt = gimple_build_bind (NULL, NULL, block);
6558 /* Replace at gsi right away, so that 'stmt' is no member
6559 of a sequence anymore as we're going to add to to a different
6560 one below. */
6561 gsi_replace (gsi_p, new_stmt, true);
6563 /* Move declaration of temporaries in the loop body before we make
6564 it go away. */
6565 omp_for_body = gimple_omp_body (stmt);
6566 if (!gimple_seq_empty_p (omp_for_body)
6567 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
6569 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
6570 gimple_bind_append_vars (new_stmt, vars);
6573 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
6574 dlist = NULL;
6575 body = NULL;
6576 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
6577 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
6579 /* Lower the header expressions. At this point, we can assume that
6580 the header is of the form:
6582 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
6584 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
6585 using the .omp_data_s mapping, if needed. */
6586 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
6588 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
6589 if (!is_gimple_min_invariant (*rhs_p))
6590 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6592 rhs_p = gimple_omp_for_final_ptr (stmt, i);
6593 if (!is_gimple_min_invariant (*rhs_p))
6594 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6596 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
6597 if (!is_gimple_min_invariant (*rhs_p))
6598 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6601 /* Once lowered, extract the bounds and clauses. */
6602 extract_omp_for_data (stmt, &fd, NULL);
6604 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
6606 gimple_seq_add_stmt (&body, stmt);
6607 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
6609 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
6610 fd.loop.v));
6612 /* After the loop, add exit clauses. */
6613 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
6614 gimple_seq_add_seq (&body, dlist);
6616 body = maybe_catch_exception (body);
6618 /* Region exit marker goes at the end of the loop body. */
6619 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
6621 pop_gimplify_context (new_stmt);
6623 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6624 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
6625 if (BLOCK_VARS (block))
6626 TREE_USED (block) = 1;
6628 gimple_bind_set_body (new_stmt, body);
6629 gimple_omp_set_body (stmt, NULL);
6630 gimple_omp_for_set_pre_body (stmt, NULL);
6633 /* Callback for walk_stmts. Check if the current statement only contains
6634 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
6636 static tree
6637 check_combined_parallel (gimple_stmt_iterator *gsi_p,
6638 bool *handled_ops_p,
6639 struct walk_stmt_info *wi)
6641 int *info = (int *) wi->info;
6642 gimple stmt = gsi_stmt (*gsi_p);
6644 *handled_ops_p = true;
6645 switch (gimple_code (stmt))
6647 WALK_SUBSTMTS;
6649 case GIMPLE_OMP_FOR:
6650 case GIMPLE_OMP_SECTIONS:
6651 *info = *info == 0 ? 1 : -1;
6652 break;
6653 default:
6654 *info = -1;
6655 break;
6657 return NULL;
6660 struct omp_taskcopy_context
6662 /* This field must be at the beginning, as we do "inheritance": Some
6663 callback functions for tree-inline.c (e.g., omp_copy_decl)
6664 receive a copy_body_data pointer that is up-casted to an
6665 omp_context pointer. */
6666 copy_body_data cb;
6667 omp_context *ctx;
6670 static tree
6671 task_copyfn_copy_decl (tree var, copy_body_data *cb)
6673 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
6675 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
6676 return create_tmp_var (TREE_TYPE (var), NULL);
6678 return var;
6681 static tree
6682 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
6684 tree name, new_fields = NULL, type, f;
6686 type = lang_hooks.types.make_type (RECORD_TYPE);
6687 name = DECL_NAME (TYPE_NAME (orig_type));
6688 name = build_decl (gimple_location (tcctx->ctx->stmt),
6689 TYPE_DECL, name, type);
6690 TYPE_NAME (type) = name;
6692 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
6694 tree new_f = copy_node (f);
6695 DECL_CONTEXT (new_f) = type;
6696 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
6697 TREE_CHAIN (new_f) = new_fields;
6698 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6699 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6700 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
6701 &tcctx->cb, NULL);
6702 new_fields = new_f;
6703 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
6705 TYPE_FIELDS (type) = nreverse (new_fields);
6706 layout_type (type);
6707 return type;
6710 /* Create task copyfn. */
6712 static void
6713 create_task_copyfn (gimple task_stmt, omp_context *ctx)
6715 struct function *child_cfun;
6716 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
6717 tree record_type, srecord_type, bind, list;
6718 bool record_needs_remap = false, srecord_needs_remap = false;
6719 splay_tree_node n;
6720 struct omp_taskcopy_context tcctx;
6721 struct gimplify_ctx gctx;
6722 location_t loc = gimple_location (task_stmt);
6724 child_fn = gimple_omp_task_copy_fn (task_stmt);
6725 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6726 gcc_assert (child_cfun->cfg == NULL);
6727 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
6729 /* Reset DECL_CONTEXT on function arguments. */
6730 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6731 DECL_CONTEXT (t) = child_fn;
6733 /* Populate the function. */
6734 push_gimplify_context (&gctx);
6735 push_cfun (child_cfun);
6737 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6738 TREE_SIDE_EFFECTS (bind) = 1;
6739 list = NULL;
6740 DECL_SAVED_TREE (child_fn) = bind;
6741 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
6743 /* Remap src and dst argument types if needed. */
6744 record_type = ctx->record_type;
6745 srecord_type = ctx->srecord_type;
6746 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6747 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6749 record_needs_remap = true;
6750 break;
6752 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
6753 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6755 srecord_needs_remap = true;
6756 break;
6759 if (record_needs_remap || srecord_needs_remap)
6761 memset (&tcctx, '\0', sizeof (tcctx));
6762 tcctx.cb.src_fn = ctx->cb.src_fn;
6763 tcctx.cb.dst_fn = child_fn;
6764 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
6765 gcc_checking_assert (tcctx.cb.src_node);
6766 tcctx.cb.dst_node = tcctx.cb.src_node;
6767 tcctx.cb.src_cfun = ctx->cb.src_cfun;
6768 tcctx.cb.copy_decl = task_copyfn_copy_decl;
6769 tcctx.cb.eh_lp_nr = 0;
6770 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
6771 tcctx.cb.decl_map = pointer_map_create ();
6772 tcctx.ctx = ctx;
6774 if (record_needs_remap)
6775 record_type = task_copyfn_remap_type (&tcctx, record_type);
6776 if (srecord_needs_remap)
6777 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
6779 else
6780 tcctx.cb.decl_map = NULL;
6782 arg = DECL_ARGUMENTS (child_fn);
6783 TREE_TYPE (arg) = build_pointer_type (record_type);
6784 sarg = DECL_CHAIN (arg);
6785 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
6787 /* First pass: initialize temporaries used in record_type and srecord_type
6788 sizes and field offsets. */
6789 if (tcctx.cb.decl_map)
6790 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6791 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6793 tree *p;
6795 decl = OMP_CLAUSE_DECL (c);
6796 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
6797 if (p == NULL)
6798 continue;
6799 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6800 sf = (tree) n->value;
6801 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6802 src = build_simple_mem_ref_loc (loc, sarg);
6803 src = omp_build_component_ref (src, sf);
6804 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
6805 append_to_statement_list (t, &list);
6808 /* Second pass: copy shared var pointers and copy construct non-VLA
6809 firstprivate vars. */
6810 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6811 switch (OMP_CLAUSE_CODE (c))
6813 case OMP_CLAUSE_SHARED:
6814 decl = OMP_CLAUSE_DECL (c);
6815 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6816 if (n == NULL)
6817 break;
6818 f = (tree) n->value;
6819 if (tcctx.cb.decl_map)
6820 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6821 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6822 sf = (tree) n->value;
6823 if (tcctx.cb.decl_map)
6824 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6825 src = build_simple_mem_ref_loc (loc, sarg);
6826 src = omp_build_component_ref (src, sf);
6827 dst = build_simple_mem_ref_loc (loc, arg);
6828 dst = omp_build_component_ref (dst, f);
6829 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6830 append_to_statement_list (t, &list);
6831 break;
6832 case OMP_CLAUSE_FIRSTPRIVATE:
6833 decl = OMP_CLAUSE_DECL (c);
6834 if (is_variable_sized (decl))
6835 break;
6836 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6837 if (n == NULL)
6838 break;
6839 f = (tree) n->value;
6840 if (tcctx.cb.decl_map)
6841 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6842 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6843 if (n != NULL)
6845 sf = (tree) n->value;
6846 if (tcctx.cb.decl_map)
6847 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6848 src = build_simple_mem_ref_loc (loc, sarg);
6849 src = omp_build_component_ref (src, sf);
6850 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6851 src = build_simple_mem_ref_loc (loc, src);
6853 else
6854 src = decl;
6855 dst = build_simple_mem_ref_loc (loc, arg);
6856 dst = omp_build_component_ref (dst, f);
6857 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6858 append_to_statement_list (t, &list);
6859 break;
6860 case OMP_CLAUSE_PRIVATE:
6861 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6862 break;
6863 decl = OMP_CLAUSE_DECL (c);
6864 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6865 f = (tree) n->value;
6866 if (tcctx.cb.decl_map)
6867 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6868 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6869 if (n != NULL)
6871 sf = (tree) n->value;
6872 if (tcctx.cb.decl_map)
6873 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6874 src = build_simple_mem_ref_loc (loc, sarg);
6875 src = omp_build_component_ref (src, sf);
6876 if (use_pointer_for_field (decl, NULL))
6877 src = build_simple_mem_ref_loc (loc, src);
6879 else
6880 src = decl;
6881 dst = build_simple_mem_ref_loc (loc, arg);
6882 dst = omp_build_component_ref (dst, f);
6883 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6884 append_to_statement_list (t, &list);
6885 break;
6886 default:
6887 break;
6890 /* Last pass: handle VLA firstprivates. */
6891 if (tcctx.cb.decl_map)
6892 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6893 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6895 tree ind, ptr, df;
6897 decl = OMP_CLAUSE_DECL (c);
6898 if (!is_variable_sized (decl))
6899 continue;
6900 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6901 if (n == NULL)
6902 continue;
6903 f = (tree) n->value;
6904 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6905 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6906 ind = DECL_VALUE_EXPR (decl);
6907 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6908 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6909 n = splay_tree_lookup (ctx->sfield_map,
6910 (splay_tree_key) TREE_OPERAND (ind, 0));
6911 sf = (tree) n->value;
6912 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6913 src = build_simple_mem_ref_loc (loc, sarg);
6914 src = omp_build_component_ref (src, sf);
6915 src = build_simple_mem_ref_loc (loc, src);
6916 dst = build_simple_mem_ref_loc (loc, arg);
6917 dst = omp_build_component_ref (dst, f);
6918 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6919 append_to_statement_list (t, &list);
6920 n = splay_tree_lookup (ctx->field_map,
6921 (splay_tree_key) TREE_OPERAND (ind, 0));
6922 df = (tree) n->value;
6923 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6924 ptr = build_simple_mem_ref_loc (loc, arg);
6925 ptr = omp_build_component_ref (ptr, df);
6926 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
6927 build_fold_addr_expr_loc (loc, dst));
6928 append_to_statement_list (t, &list);
6931 t = build1 (RETURN_EXPR, void_type_node, NULL);
6932 append_to_statement_list (t, &list);
6934 if (tcctx.cb.decl_map)
6935 pointer_map_destroy (tcctx.cb.decl_map);
6936 pop_gimplify_context (NULL);
6937 BIND_EXPR_BODY (bind) = list;
6938 pop_cfun ();
6941 /* Lower the OpenMP parallel or task directive in the current statement
6942 in GSI_P. CTX holds context information for the directive. */
6944 static void
6945 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6947 tree clauses;
6948 tree child_fn, t;
6949 gimple stmt = gsi_stmt (*gsi_p);
6950 gimple par_bind, bind;
6951 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
6952 struct gimplify_ctx gctx;
6953 location_t loc = gimple_location (stmt);
6955 clauses = gimple_omp_taskreg_clauses (stmt);
6956 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
6957 par_body = gimple_bind_body (par_bind);
6958 child_fn = ctx->cb.dst_fn;
6959 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6960 && !gimple_omp_parallel_combined_p (stmt))
6962 struct walk_stmt_info wi;
6963 int ws_num = 0;
6965 memset (&wi, 0, sizeof (wi));
6966 wi.info = &ws_num;
6967 wi.val_only = true;
6968 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
6969 if (ws_num == 1)
6970 gimple_omp_parallel_set_combined_p (stmt, true);
6972 if (ctx->srecord_type)
6973 create_task_copyfn (stmt, ctx);
6975 push_gimplify_context (&gctx);
6977 par_olist = NULL;
6978 par_ilist = NULL;
6979 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6980 lower_omp (&par_body, ctx);
6981 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
6982 lower_reduction_clauses (clauses, &par_olist, ctx);
6984 /* Declare all the variables created by mapping and the variables
6985 declared in the scope of the parallel body. */
6986 record_vars_into (ctx->block_vars, child_fn);
6987 record_vars_into (gimple_bind_vars (par_bind), child_fn);
6989 if (ctx->record_type)
6991 ctx->sender_decl
6992 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6993 : ctx->record_type, ".omp_data_o");
6994 DECL_NAMELESS (ctx->sender_decl) = 1;
6995 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
6996 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
6999 olist = NULL;
7000 ilist = NULL;
7001 lower_send_clauses (clauses, &ilist, &olist, ctx);
7002 lower_send_shared_vars (&ilist, &olist, ctx);
7004 /* Once all the expansions are done, sequence all the different
7005 fragments inside gimple_omp_body. */
7007 new_body = NULL;
7009 if (ctx->record_type)
7011 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
7012 /* fixup_child_record_type might have changed receiver_decl's type. */
7013 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
7014 gimple_seq_add_stmt (&new_body,
7015 gimple_build_assign (ctx->receiver_decl, t));
7018 gimple_seq_add_seq (&new_body, par_ilist);
7019 gimple_seq_add_seq (&new_body, par_body);
7020 gimple_seq_add_seq (&new_body, par_olist);
7021 new_body = maybe_catch_exception (new_body);
7022 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
7023 gimple_omp_set_body (stmt, new_body);
7025 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
7026 gsi_replace (gsi_p, bind, true);
7027 gimple_bind_add_seq (bind, ilist);
7028 gimple_bind_add_stmt (bind, stmt);
7029 gimple_bind_add_seq (bind, olist);
7031 pop_gimplify_context (NULL);
7034 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
7035 regimplified. If DATA is non-NULL, lower_omp_1 is outside
7036 of OpenMP context, but with task_shared_vars set. */
7038 static tree
7039 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
7040 void *data)
7042 tree t = *tp;
7044 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7045 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
7046 return t;
7048 if (task_shared_vars
7049 && DECL_P (t)
7050 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
7051 return t;
7053 /* If a global variable has been privatized, TREE_CONSTANT on
7054 ADDR_EXPR might be wrong. */
7055 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
7056 recompute_tree_invariant_for_addr_expr (t);
7058 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7059 return NULL_TREE;
7062 static void
7063 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7065 gimple stmt = gsi_stmt (*gsi_p);
7066 struct walk_stmt_info wi;
7068 if (gimple_has_location (stmt))
7069 input_location = gimple_location (stmt);
7071 if (task_shared_vars)
7072 memset (&wi, '\0', sizeof (wi));
7074 /* If we have issued syntax errors, avoid doing any heavy lifting.
7075 Just replace the OpenMP directives with a NOP to avoid
7076 confusing RTL expansion. */
7077 if (seen_error () && is_gimple_omp (stmt))
7079 gsi_replace (gsi_p, gimple_build_nop (), true);
7080 return;
7083 switch (gimple_code (stmt))
7085 case GIMPLE_COND:
7086 if ((ctx || task_shared_vars)
7087 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
7088 ctx ? NULL : &wi, NULL)
7089 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
7090 ctx ? NULL : &wi, NULL)))
7091 gimple_regimplify_operands (stmt, gsi_p);
7092 break;
7093 case GIMPLE_CATCH:
7094 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
7095 break;
7096 case GIMPLE_EH_FILTER:
7097 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
7098 break;
7099 case GIMPLE_TRY:
7100 lower_omp (gimple_try_eval_ptr (stmt), ctx);
7101 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
7102 break;
7103 case GIMPLE_TRANSACTION:
7104 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
7105 break;
7106 case GIMPLE_BIND:
7107 lower_omp (gimple_bind_body_ptr (stmt), ctx);
7108 break;
7109 case GIMPLE_OMP_PARALLEL:
7110 case GIMPLE_OMP_TASK:
7111 ctx = maybe_lookup_ctx (stmt);
7112 lower_omp_taskreg (gsi_p, ctx);
7113 break;
7114 case GIMPLE_OMP_FOR:
7115 ctx = maybe_lookup_ctx (stmt);
7116 gcc_assert (ctx);
7117 lower_omp_for (gsi_p, ctx);
7118 break;
7119 case GIMPLE_OMP_SECTIONS:
7120 ctx = maybe_lookup_ctx (stmt);
7121 gcc_assert (ctx);
7122 lower_omp_sections (gsi_p, ctx);
7123 break;
7124 case GIMPLE_OMP_SINGLE:
7125 ctx = maybe_lookup_ctx (stmt);
7126 gcc_assert (ctx);
7127 lower_omp_single (gsi_p, ctx);
7128 break;
7129 case GIMPLE_OMP_MASTER:
7130 ctx = maybe_lookup_ctx (stmt);
7131 gcc_assert (ctx);
7132 lower_omp_master (gsi_p, ctx);
7133 break;
7134 case GIMPLE_OMP_ORDERED:
7135 ctx = maybe_lookup_ctx (stmt);
7136 gcc_assert (ctx);
7137 lower_omp_ordered (gsi_p, ctx);
7138 break;
7139 case GIMPLE_OMP_CRITICAL:
7140 ctx = maybe_lookup_ctx (stmt);
7141 gcc_assert (ctx);
7142 lower_omp_critical (gsi_p, ctx);
7143 break;
7144 case GIMPLE_OMP_ATOMIC_LOAD:
7145 if ((ctx || task_shared_vars)
7146 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
7147 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
7148 gimple_regimplify_operands (stmt, gsi_p);
7149 break;
7150 default:
7151 if ((ctx || task_shared_vars)
7152 && walk_gimple_op (stmt, lower_omp_regimplify_p,
7153 ctx ? NULL : &wi))
7154 gimple_regimplify_operands (stmt, gsi_p);
7155 break;
7159 static void
7160 lower_omp (gimple_seq *body, omp_context *ctx)
7162 location_t saved_location = input_location;
7163 gimple_stmt_iterator gsi;
7164 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
7165 lower_omp_1 (&gsi, ctx);
7166 input_location = saved_location;
7169 /* Main entry point. */
7171 static unsigned int
7172 execute_lower_omp (void)
7174 gimple_seq body;
7175 int i;
7176 omp_context *ctx;
7178 /* This pass always runs, to provide PROP_gimple_lomp.
7179 But there is nothing to do unless -fopenmp is given. */
7180 if (flag_openmp == 0)
7181 return 0;
7183 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
7184 delete_omp_context);
7186 body = gimple_body (current_function_decl);
7187 scan_omp (&body, NULL);
7188 gcc_assert (taskreg_nesting_level == 0);
7189 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
7190 finish_taskreg_scan (ctx);
7191 taskreg_contexts.release ();
7193 if (all_contexts->root)
7195 struct gimplify_ctx gctx;
7197 if (task_shared_vars)
7198 push_gimplify_context (&gctx);
7199 lower_omp (&body, NULL);
7200 if (task_shared_vars)
7201 pop_gimplify_context (NULL);
7204 if (all_contexts)
7206 splay_tree_delete (all_contexts);
7207 all_contexts = NULL;
7209 BITMAP_FREE (task_shared_vars);
7210 return 0;
7213 struct gimple_opt_pass pass_lower_omp =
7216 GIMPLE_PASS,
7217 "omplower", /* name */
7218 OPTGROUP_NONE, /* optinfo_flags */
7219 NULL, /* gate */
7220 execute_lower_omp, /* execute */
7221 NULL, /* sub */
7222 NULL, /* next */
7223 0, /* static_pass_number */
7224 TV_NONE, /* tv_id */
7225 PROP_gimple_any, /* properties_required */
7226 PROP_gimple_lomp, /* properties_provided */
7227 0, /* properties_destroyed */
7228 0, /* todo_flags_start */
7229 0 /* todo_flags_finish */
7233 /* The following is a utility to diagnose OpenMP structured block violations.
7234 It is not part of the "omplower" pass, as that's invoked too late. It
7235 should be invoked by the respective front ends after gimplification. */
7237 static splay_tree all_labels;
7239 /* Check for mismatched contexts and generate an error if needed. Return
7240 true if an error is detected. */
7242 static bool
7243 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
7244 gimple branch_ctx, gimple label_ctx)
7246 if (label_ctx == branch_ctx)
7247 return false;
7251 Previously we kept track of the label's entire context in diagnose_sb_[12]
7252 so we could traverse it and issue a correct "exit" or "enter" error
7253 message upon a structured block violation.
7255 We built the context by building a list with tree_cons'ing, but there is
7256 no easy counterpart in gimple tuples. It seems like far too much work
7257 for issuing exit/enter error messages. If someone really misses the
7258 distinct error message... patches welcome.
7261 #if 0
7262 /* Try to avoid confusing the user by producing and error message
7263 with correct "exit" or "enter" verbiage. We prefer "exit"
7264 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
7265 if (branch_ctx == NULL)
7266 exit_p = false;
7267 else
7269 while (label_ctx)
7271 if (TREE_VALUE (label_ctx) == branch_ctx)
7273 exit_p = false;
7274 break;
7276 label_ctx = TREE_CHAIN (label_ctx);
7280 if (exit_p)
7281 error ("invalid exit from OpenMP structured block");
7282 else
7283 error ("invalid entry to OpenMP structured block");
7284 #endif
7286 /* If it's obvious we have an invalid entry, be specific about the error. */
7287 if (branch_ctx == NULL)
7288 error ("invalid entry to OpenMP structured block");
7289 else
7290 /* Otherwise, be vague and lazy, but efficient. */
7291 error ("invalid branch to/from an OpenMP structured block");
7293 gsi_replace (gsi_p, gimple_build_nop (), false);
7294 return true;
7297 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
7298 where each label is found. */
7300 static tree
7301 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7302 struct walk_stmt_info *wi)
7304 gimple context = (gimple) wi->info;
7305 gimple inner_context;
7306 gimple stmt = gsi_stmt (*gsi_p);
7308 *handled_ops_p = true;
7310 switch (gimple_code (stmt))
7312 WALK_SUBSTMTS;
7314 case GIMPLE_OMP_PARALLEL:
7315 case GIMPLE_OMP_TASK:
7316 case GIMPLE_OMP_SECTIONS:
7317 case GIMPLE_OMP_SINGLE:
7318 case GIMPLE_OMP_SECTION:
7319 case GIMPLE_OMP_MASTER:
7320 case GIMPLE_OMP_ORDERED:
7321 case GIMPLE_OMP_CRITICAL:
7322 /* The minimal context here is just the current OMP construct. */
7323 inner_context = stmt;
7324 wi->info = inner_context;
7325 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7326 wi->info = context;
7327 break;
7329 case GIMPLE_OMP_FOR:
7330 inner_context = stmt;
7331 wi->info = inner_context;
7332 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7333 walk them. */
7334 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
7335 diagnose_sb_1, NULL, wi);
7336 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7337 wi->info = context;
7338 break;
7340 case GIMPLE_LABEL:
7341 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
7342 (splay_tree_value) context);
7343 break;
7345 default:
7346 break;
7349 return NULL_TREE;
7352 /* Pass 2: Check each branch and see if its context differs from that of
7353 the destination label's context. */
7355 static tree
7356 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7357 struct walk_stmt_info *wi)
7359 gimple context = (gimple) wi->info;
7360 splay_tree_node n;
7361 gimple stmt = gsi_stmt (*gsi_p);
7363 *handled_ops_p = true;
7365 switch (gimple_code (stmt))
7367 WALK_SUBSTMTS;
7369 case GIMPLE_OMP_PARALLEL:
7370 case GIMPLE_OMP_TASK:
7371 case GIMPLE_OMP_SECTIONS:
7372 case GIMPLE_OMP_SINGLE:
7373 case GIMPLE_OMP_SECTION:
7374 case GIMPLE_OMP_MASTER:
7375 case GIMPLE_OMP_ORDERED:
7376 case GIMPLE_OMP_CRITICAL:
7377 wi->info = stmt;
7378 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7379 wi->info = context;
7380 break;
7382 case GIMPLE_OMP_FOR:
7383 wi->info = stmt;
7384 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7385 walk them. */
7386 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
7387 diagnose_sb_2, NULL, wi);
7388 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7389 wi->info = context;
7390 break;
7392 case GIMPLE_COND:
7394 tree lab = gimple_cond_true_label (stmt);
7395 if (lab)
7397 n = splay_tree_lookup (all_labels,
7398 (splay_tree_key) lab);
7399 diagnose_sb_0 (gsi_p, context,
7400 n ? (gimple) n->value : NULL);
7402 lab = gimple_cond_false_label (stmt);
7403 if (lab)
7405 n = splay_tree_lookup (all_labels,
7406 (splay_tree_key) lab);
7407 diagnose_sb_0 (gsi_p, context,
7408 n ? (gimple) n->value : NULL);
7411 break;
7413 case GIMPLE_GOTO:
7415 tree lab = gimple_goto_dest (stmt);
7416 if (TREE_CODE (lab) != LABEL_DECL)
7417 break;
7419 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7420 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
7422 break;
7424 case GIMPLE_SWITCH:
7426 unsigned int i;
7427 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
7429 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
7430 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7431 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
7432 break;
7435 break;
7437 case GIMPLE_RETURN:
7438 diagnose_sb_0 (gsi_p, context, NULL);
7439 break;
7441 default:
7442 break;
7445 return NULL_TREE;
7448 static unsigned int
7449 diagnose_omp_structured_block_errors (void)
7451 struct walk_stmt_info wi;
7452 gimple_seq body = gimple_body (current_function_decl);
7454 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
7456 memset (&wi, 0, sizeof (wi));
7457 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
7459 memset (&wi, 0, sizeof (wi));
7460 wi.want_locations = true;
7461 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
7463 gimple_set_body (current_function_decl, body);
7465 splay_tree_delete (all_labels);
7466 all_labels = NULL;
7468 return 0;
7471 static bool
7472 gate_diagnose_omp_blocks (void)
7474 return flag_openmp != 0;
7477 struct gimple_opt_pass pass_diagnose_omp_blocks =
7480 GIMPLE_PASS,
7481 "*diagnose_omp_blocks", /* name */
7482 OPTGROUP_NONE, /* optinfo_flags */
7483 gate_diagnose_omp_blocks, /* gate */
7484 diagnose_omp_structured_block_errors, /* execute */
7485 NULL, /* sub */
7486 NULL, /* next */
7487 0, /* static_pass_number */
7488 TV_NONE, /* tv_id */
7489 PROP_gimple_any, /* properties_required */
7490 0, /* properties_provided */
7491 0, /* properties_destroyed */
7492 0, /* todo_flags_start */
7493 0, /* todo_flags_finish */
7497 #include "gt-omp-low.h"