2013-09-12 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / omp-low.c
blob316ec1ff56c13b4386ed003e1e5f7da038056bcb
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-ssa.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"
45 #include "target.h"
48 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
49 phases. The first phase scans the function looking for OMP statements
50 and then for variables that must be replaced to satisfy data sharing
51 clauses. The second phase expands code for the constructs, as well as
52 re-gimplifying things when variables have been replaced with complex
53 expressions.
55 Final code generation is done by pass_expand_omp. The flowgraph is
56 scanned for parallel regions which are then moved to a new
57 function, to be invoked by the thread library. */
59 /* Context structure. Used to store information about each parallel
60 directive in the code. */
62 typedef struct omp_context
64 /* This field must be at the beginning, as we do "inheritance": Some
65 callback functions for tree-inline.c (e.g., omp_copy_decl)
66 receive a copy_body_data pointer that is up-casted to an
67 omp_context pointer. */
68 copy_body_data cb;
70 /* The tree of contexts corresponding to the encountered constructs. */
71 struct omp_context *outer;
72 gimple stmt;
74 /* Map variables to fields in a structure that allows communication
75 between sending and receiving threads. */
76 splay_tree field_map;
77 tree record_type;
78 tree sender_decl;
79 tree receiver_decl;
81 /* These are used just by task contexts, if task firstprivate fn is
82 needed. srecord_type is used to communicate from the thread
83 that encountered the task construct to task firstprivate fn,
84 record_type is allocated by GOMP_task, initialized by task firstprivate
85 fn and passed to the task body fn. */
86 splay_tree sfield_map;
87 tree srecord_type;
89 /* A chain of variables to add to the top-level block surrounding the
90 construct. In the case of a parallel, this is in the child function. */
91 tree block_vars;
93 /* What to do with variables with implicitly determined sharing
94 attributes. */
95 enum omp_clause_default_kind default_kind;
97 /* Nesting depth of this context. Used to beautify error messages re
98 invalid gotos. The outermost ctx is depth 1, with depth 0 being
99 reserved for the main body of the function. */
100 int depth;
102 /* True if this parallel directive is nested within another. */
103 bool is_nested;
104 } omp_context;
107 struct omp_for_data_loop
109 tree v, n1, n2, step;
110 enum tree_code cond_code;
113 /* A structure describing the main elements of a parallel loop. */
115 struct omp_for_data
117 struct omp_for_data_loop loop;
118 tree chunk_size;
119 gimple for_stmt;
120 tree pre, iter_type;
121 int collapse;
122 bool have_nowait, have_ordered;
123 enum omp_clause_schedule_kind sched_kind;
124 struct omp_for_data_loop *loops;
128 static splay_tree all_contexts;
129 static int taskreg_nesting_level;
130 struct omp_region *root_omp_region;
131 static bitmap task_shared_vars;
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);
226 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
228 fd->for_stmt = for_stmt;
229 fd->pre = NULL;
230 fd->collapse = gimple_omp_for_collapse (for_stmt);
231 if (fd->collapse > 1)
232 fd->loops = loops;
233 else
234 fd->loops = &fd->loop;
236 fd->have_nowait = fd->have_ordered = false;
237 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
238 fd->chunk_size = NULL_TREE;
239 collapse_iter = NULL;
240 collapse_count = NULL;
242 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
243 switch (OMP_CLAUSE_CODE (t))
245 case OMP_CLAUSE_NOWAIT:
246 fd->have_nowait = true;
247 break;
248 case OMP_CLAUSE_ORDERED:
249 fd->have_ordered = true;
250 break;
251 case OMP_CLAUSE_SCHEDULE:
252 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
253 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
254 break;
255 case OMP_CLAUSE_COLLAPSE:
256 if (fd->collapse > 1)
258 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
259 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
261 default:
262 break;
265 /* FIXME: for now map schedule(auto) to schedule(static).
266 There should be analysis to determine whether all iterations
267 are approximately the same amount of work (then schedule(static)
268 is best) or if it varies (then schedule(dynamic,N) is better). */
269 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
271 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
272 gcc_assert (fd->chunk_size == NULL);
274 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
275 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
276 gcc_assert (fd->chunk_size == NULL);
277 else if (fd->chunk_size == NULL)
279 /* We only need to compute a default chunk size for ordered
280 static loops and dynamic loops. */
281 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
282 || fd->have_ordered
283 || fd->collapse > 1)
284 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
285 ? integer_zero_node : integer_one_node;
288 for (i = 0; i < fd->collapse; i++)
290 if (fd->collapse == 1)
291 loop = &fd->loop;
292 else if (loops != NULL)
293 loop = loops + i;
294 else
295 loop = &dummy_loop;
298 loop->v = gimple_omp_for_index (for_stmt, i);
299 gcc_assert (SSA_VAR_P (loop->v));
300 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
301 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
302 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
303 loop->n1 = gimple_omp_for_initial (for_stmt, i);
305 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
306 loop->n2 = gimple_omp_for_final (for_stmt, i);
307 switch (loop->cond_code)
309 case LT_EXPR:
310 case GT_EXPR:
311 break;
312 case LE_EXPR:
313 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
314 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
315 else
316 loop->n2 = fold_build2_loc (loc,
317 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
318 build_int_cst (TREE_TYPE (loop->n2), 1));
319 loop->cond_code = LT_EXPR;
320 break;
321 case GE_EXPR:
322 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
323 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
324 else
325 loop->n2 = fold_build2_loc (loc,
326 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
327 build_int_cst (TREE_TYPE (loop->n2), 1));
328 loop->cond_code = GT_EXPR;
329 break;
330 default:
331 gcc_unreachable ();
334 t = gimple_omp_for_incr (for_stmt, i);
335 gcc_assert (TREE_OPERAND (t, 0) == var);
336 switch (TREE_CODE (t))
338 case PLUS_EXPR:
339 loop->step = TREE_OPERAND (t, 1);
340 break;
341 case POINTER_PLUS_EXPR:
342 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
343 break;
344 case MINUS_EXPR:
345 loop->step = TREE_OPERAND (t, 1);
346 loop->step = fold_build1_loc (loc,
347 NEGATE_EXPR, TREE_TYPE (loop->step),
348 loop->step);
349 break;
350 default:
351 gcc_unreachable ();
354 if (simd)
356 if (fd->collapse == 1)
357 iter_type = TREE_TYPE (loop->v);
358 else if (i == 0
359 || TYPE_PRECISION (iter_type)
360 < TYPE_PRECISION (TREE_TYPE (loop->v)))
361 iter_type
362 = build_nonstandard_integer_type
363 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
365 else if (iter_type != long_long_unsigned_type_node)
367 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
368 iter_type = long_long_unsigned_type_node;
369 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
370 && TYPE_PRECISION (TREE_TYPE (loop->v))
371 >= TYPE_PRECISION (iter_type))
373 tree n;
375 if (loop->cond_code == LT_EXPR)
376 n = fold_build2_loc (loc,
377 PLUS_EXPR, TREE_TYPE (loop->v),
378 loop->n2, loop->step);
379 else
380 n = loop->n1;
381 if (TREE_CODE (n) != INTEGER_CST
382 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
383 iter_type = long_long_unsigned_type_node;
385 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
386 > TYPE_PRECISION (iter_type))
388 tree n1, n2;
390 if (loop->cond_code == LT_EXPR)
392 n1 = loop->n1;
393 n2 = fold_build2_loc (loc,
394 PLUS_EXPR, TREE_TYPE (loop->v),
395 loop->n2, loop->step);
397 else
399 n1 = fold_build2_loc (loc,
400 MINUS_EXPR, TREE_TYPE (loop->v),
401 loop->n2, loop->step);
402 n2 = loop->n1;
404 if (TREE_CODE (n1) != INTEGER_CST
405 || TREE_CODE (n2) != INTEGER_CST
406 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
407 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
408 iter_type = long_long_unsigned_type_node;
412 if (collapse_count && *collapse_count == NULL)
414 t = fold_binary (loop->cond_code, boolean_type_node,
415 fold_convert (TREE_TYPE (loop->v), loop->n1),
416 fold_convert (TREE_TYPE (loop->v), loop->n2));
417 if (t && integer_zerop (t))
418 count = build_zero_cst (long_long_unsigned_type_node);
419 else if ((i == 0 || count != NULL_TREE)
420 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
421 && TREE_CONSTANT (loop->n1)
422 && TREE_CONSTANT (loop->n2)
423 && TREE_CODE (loop->step) == INTEGER_CST)
425 tree itype = TREE_TYPE (loop->v);
427 if (POINTER_TYPE_P (itype))
428 itype = signed_type_for (itype);
429 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
430 t = fold_build2_loc (loc,
431 PLUS_EXPR, itype,
432 fold_convert_loc (loc, itype, loop->step), t);
433 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
434 fold_convert_loc (loc, itype, loop->n2));
435 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
436 fold_convert_loc (loc, itype, loop->n1));
437 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
438 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
439 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
440 fold_build1_loc (loc, NEGATE_EXPR, itype,
441 fold_convert_loc (loc, itype,
442 loop->step)));
443 else
444 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
445 fold_convert_loc (loc, itype, loop->step));
446 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
447 if (count != NULL_TREE)
448 count = fold_build2_loc (loc,
449 MULT_EXPR, long_long_unsigned_type_node,
450 count, t);
451 else
452 count = t;
453 if (TREE_CODE (count) != INTEGER_CST)
454 count = NULL_TREE;
456 else if (count && !integer_zerop (count))
457 count = NULL_TREE;
461 if (count
462 && !simd)
464 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
465 iter_type = long_long_unsigned_type_node;
466 else
467 iter_type = long_integer_type_node;
469 else if (collapse_iter && *collapse_iter != NULL)
470 iter_type = TREE_TYPE (*collapse_iter);
471 fd->iter_type = iter_type;
472 if (collapse_iter && *collapse_iter == NULL)
473 *collapse_iter = create_tmp_var (iter_type, ".iter");
474 if (collapse_count && *collapse_count == NULL)
476 if (count)
477 *collapse_count = fold_convert_loc (loc, iter_type, count);
478 else
479 *collapse_count = create_tmp_var (iter_type, ".count");
482 if (fd->collapse > 1)
484 fd->loop.v = *collapse_iter;
485 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
486 fd->loop.n2 = *collapse_count;
487 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
488 fd->loop.cond_code = LT_EXPR;
493 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
494 is the immediate dominator of PAR_ENTRY_BB, return true if there
495 are no data dependencies that would prevent expanding the parallel
496 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
498 When expanding a combined parallel+workshare region, the call to
499 the child function may need additional arguments in the case of
500 GIMPLE_OMP_FOR regions. In some cases, these arguments are
501 computed out of variables passed in from the parent to the child
502 via 'struct .omp_data_s'. For instance:
504 #pragma omp parallel for schedule (guided, i * 4)
505 for (j ...)
507 Is lowered into:
509 # BLOCK 2 (PAR_ENTRY_BB)
510 .omp_data_o.i = i;
511 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
513 # BLOCK 3 (WS_ENTRY_BB)
514 .omp_data_i = &.omp_data_o;
515 D.1667 = .omp_data_i->i;
516 D.1598 = D.1667 * 4;
517 #pragma omp for schedule (guided, D.1598)
519 When we outline the parallel region, the call to the child function
520 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
521 that value is computed *after* the call site. So, in principle we
522 cannot do the transformation.
524 To see whether the code in WS_ENTRY_BB blocks the combined
525 parallel+workshare call, we collect all the variables used in the
526 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
527 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
528 call.
530 FIXME. If we had the SSA form built at this point, we could merely
531 hoist the code in block 3 into block 2 and be done with it. But at
532 this point we don't have dataflow information and though we could
533 hack something up here, it is really not worth the aggravation. */
535 static bool
536 workshare_safe_to_combine_p (basic_block ws_entry_bb)
538 struct omp_for_data fd;
539 gimple ws_stmt = last_stmt (ws_entry_bb);
541 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
542 return true;
544 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
546 extract_omp_for_data (ws_stmt, &fd, NULL);
548 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
549 return false;
550 if (fd.iter_type != long_integer_type_node)
551 return false;
553 /* FIXME. We give up too easily here. If any of these arguments
554 are not constants, they will likely involve variables that have
555 been mapped into fields of .omp_data_s for sharing with the child
556 function. With appropriate data flow, it would be possible to
557 see through this. */
558 if (!is_gimple_min_invariant (fd.loop.n1)
559 || !is_gimple_min_invariant (fd.loop.n2)
560 || !is_gimple_min_invariant (fd.loop.step)
561 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
562 return false;
564 return true;
568 /* Collect additional arguments needed to emit a combined
569 parallel+workshare call. WS_STMT is the workshare directive being
570 expanded. */
572 static vec<tree, va_gc> *
573 get_ws_args_for (gimple ws_stmt)
575 tree t;
576 location_t loc = gimple_location (ws_stmt);
577 vec<tree, va_gc> *ws_args;
579 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
581 struct omp_for_data fd;
583 extract_omp_for_data (ws_stmt, &fd, NULL);
585 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
587 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
588 ws_args->quick_push (t);
590 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
591 ws_args->quick_push (t);
593 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
594 ws_args->quick_push (t);
596 if (fd.chunk_size)
598 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
599 ws_args->quick_push (t);
602 return ws_args;
604 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
606 /* Number of sections is equal to the number of edges from the
607 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
608 the exit of the sections region. */
609 basic_block bb = single_succ (gimple_bb (ws_stmt));
610 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
611 vec_alloc (ws_args, 1);
612 ws_args->quick_push (t);
613 return ws_args;
616 gcc_unreachable ();
620 /* Discover whether REGION is a combined parallel+workshare region. */
622 static void
623 determine_parallel_type (struct omp_region *region)
625 basic_block par_entry_bb, par_exit_bb;
626 basic_block ws_entry_bb, ws_exit_bb;
628 if (region == NULL || region->inner == NULL
629 || region->exit == NULL || region->inner->exit == NULL
630 || region->inner->cont == NULL)
631 return;
633 /* We only support parallel+for and parallel+sections. */
634 if (region->type != GIMPLE_OMP_PARALLEL
635 || (region->inner->type != GIMPLE_OMP_FOR
636 && region->inner->type != GIMPLE_OMP_SECTIONS))
637 return;
639 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
640 WS_EXIT_BB -> PAR_EXIT_BB. */
641 par_entry_bb = region->entry;
642 par_exit_bb = region->exit;
643 ws_entry_bb = region->inner->entry;
644 ws_exit_bb = region->inner->exit;
646 if (single_succ (par_entry_bb) == ws_entry_bb
647 && single_succ (ws_exit_bb) == par_exit_bb
648 && workshare_safe_to_combine_p (ws_entry_bb)
649 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
650 || (last_and_only_stmt (ws_entry_bb)
651 && last_and_only_stmt (par_exit_bb))))
653 gimple ws_stmt = last_stmt (ws_entry_bb);
655 if (region->inner->type == GIMPLE_OMP_FOR)
657 /* If this is a combined parallel loop, we need to determine
658 whether or not to use the combined library calls. There
659 are two cases where we do not apply the transformation:
660 static loops and any kind of ordered loop. In the first
661 case, we already open code the loop so there is no need
662 to do anything else. In the latter case, the combined
663 parallel loop call would still need extra synchronization
664 to implement ordered semantics, so there would not be any
665 gain in using the combined call. */
666 tree clauses = gimple_omp_for_clauses (ws_stmt);
667 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
668 if (c == NULL
669 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
670 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
672 region->is_combined_parallel = false;
673 region->inner->is_combined_parallel = false;
674 return;
678 region->is_combined_parallel = true;
679 region->inner->is_combined_parallel = true;
680 region->ws_args = get_ws_args_for (ws_stmt);
685 /* Return true if EXPR is variable sized. */
687 static inline bool
688 is_variable_sized (const_tree expr)
690 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
693 /* Return true if DECL is a reference type. */
695 static inline bool
696 is_reference (tree decl)
698 return lang_hooks.decls.omp_privatize_by_reference (decl);
701 /* Lookup variables in the decl or field splay trees. The "maybe" form
702 allows for the variable form to not have been entered, otherwise we
703 assert that the variable must have been entered. */
705 static inline tree
706 lookup_decl (tree var, omp_context *ctx)
708 tree *n;
709 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
710 return *n;
713 static inline tree
714 maybe_lookup_decl (const_tree var, omp_context *ctx)
716 tree *n;
717 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
718 return n ? *n : NULL_TREE;
721 static inline tree
722 lookup_field (tree var, omp_context *ctx)
724 splay_tree_node n;
725 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
726 return (tree) n->value;
729 static inline tree
730 lookup_sfield (tree var, omp_context *ctx)
732 splay_tree_node n;
733 n = splay_tree_lookup (ctx->sfield_map
734 ? ctx->sfield_map : ctx->field_map,
735 (splay_tree_key) var);
736 return (tree) n->value;
739 static inline tree
740 maybe_lookup_field (tree var, omp_context *ctx)
742 splay_tree_node n;
743 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
744 return n ? (tree) n->value : NULL_TREE;
747 /* Return true if DECL should be copied by pointer. SHARED_CTX is
748 the parallel context if DECL is to be shared. */
750 static bool
751 use_pointer_for_field (tree decl, omp_context *shared_ctx)
753 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
754 return true;
756 /* We can only use copy-in/copy-out semantics for shared variables
757 when we know the value is not accessible from an outer scope. */
758 if (shared_ctx)
760 /* ??? Trivially accessible from anywhere. But why would we even
761 be passing an address in this case? Should we simply assert
762 this to be false, or should we have a cleanup pass that removes
763 these from the list of mappings? */
764 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
765 return true;
767 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
768 without analyzing the expression whether or not its location
769 is accessible to anyone else. In the case of nested parallel
770 regions it certainly may be. */
771 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
772 return true;
774 /* Do not use copy-in/copy-out for variables that have their
775 address taken. */
776 if (TREE_ADDRESSABLE (decl))
777 return true;
779 /* lower_send_shared_vars only uses copy-in, but not copy-out
780 for these. */
781 if (TREE_READONLY (decl)
782 || ((TREE_CODE (decl) == RESULT_DECL
783 || TREE_CODE (decl) == PARM_DECL)
784 && DECL_BY_REFERENCE (decl)))
785 return false;
787 /* Disallow copy-in/out in nested parallel if
788 decl is shared in outer parallel, otherwise
789 each thread could store the shared variable
790 in its own copy-in location, making the
791 variable no longer really shared. */
792 if (shared_ctx->is_nested)
794 omp_context *up;
796 for (up = shared_ctx->outer; up; up = up->outer)
797 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
798 break;
800 if (up)
802 tree c;
804 for (c = gimple_omp_taskreg_clauses (up->stmt);
805 c; c = OMP_CLAUSE_CHAIN (c))
806 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
807 && OMP_CLAUSE_DECL (c) == decl)
808 break;
810 if (c)
811 goto maybe_mark_addressable_and_ret;
815 /* For tasks avoid using copy-in/out. As tasks can be
816 deferred or executed in different thread, when GOMP_task
817 returns, the task hasn't necessarily terminated. */
818 if (is_task_ctx (shared_ctx))
820 tree outer;
821 maybe_mark_addressable_and_ret:
822 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
823 if (is_gimple_reg (outer))
825 /* Taking address of OUTER in lower_send_shared_vars
826 might need regimplification of everything that uses the
827 variable. */
828 if (!task_shared_vars)
829 task_shared_vars = BITMAP_ALLOC (NULL);
830 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
831 TREE_ADDRESSABLE (outer) = 1;
833 return true;
837 return false;
840 /* Create a new VAR_DECL and copy information from VAR to it. */
842 tree
843 copy_var_decl (tree var, tree name, tree type)
845 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
847 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
848 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
849 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
850 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
851 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
852 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
853 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
854 TREE_USED (copy) = 1;
855 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
857 return copy;
860 /* Construct a new automatic decl similar to VAR. */
862 static tree
863 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
865 tree copy = copy_var_decl (var, name, type);
867 DECL_CONTEXT (copy) = current_function_decl;
868 DECL_CHAIN (copy) = ctx->block_vars;
869 ctx->block_vars = copy;
871 return copy;
874 static tree
875 omp_copy_decl_1 (tree var, omp_context *ctx)
877 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
880 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
881 as appropriate. */
882 static tree
883 omp_build_component_ref (tree obj, tree field)
885 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
886 if (TREE_THIS_VOLATILE (field))
887 TREE_THIS_VOLATILE (ret) |= 1;
888 if (TREE_READONLY (field))
889 TREE_READONLY (ret) |= 1;
890 return ret;
893 /* Build tree nodes to access the field for VAR on the receiver side. */
895 static tree
896 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
898 tree x, field = lookup_field (var, ctx);
900 /* If the receiver record type was remapped in the child function,
901 remap the field into the new record type. */
902 x = maybe_lookup_field (field, ctx);
903 if (x != NULL)
904 field = x;
906 x = build_simple_mem_ref (ctx->receiver_decl);
907 x = omp_build_component_ref (x, field);
908 if (by_ref)
909 x = build_simple_mem_ref (x);
911 return x;
914 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
915 of a parallel, this is a component reference; for workshare constructs
916 this is some variable. */
918 static tree
919 build_outer_var_ref (tree var, omp_context *ctx)
921 tree x;
923 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
924 x = var;
925 else if (is_variable_sized (var))
927 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
928 x = build_outer_var_ref (x, ctx);
929 x = build_simple_mem_ref (x);
931 else if (is_taskreg_ctx (ctx))
933 bool by_ref = use_pointer_for_field (var, NULL);
934 x = build_receiver_ref (var, by_ref, ctx);
936 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
937 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
939 /* #pragma omp simd isn't a worksharing construct, and can reference even
940 private vars in its linear etc. clauses. */
941 x = NULL_TREE;
942 if (ctx->outer && is_taskreg_ctx (ctx))
943 x = lookup_decl (var, ctx->outer);
944 else if (ctx->outer)
945 x = maybe_lookup_decl (var, ctx->outer);
946 if (x == NULL_TREE)
947 x = var;
949 else if (ctx->outer)
950 x = lookup_decl (var, ctx->outer);
951 else if (is_reference (var))
952 /* This can happen with orphaned constructs. If var is reference, it is
953 possible it is shared and as such valid. */
954 x = var;
955 else
956 gcc_unreachable ();
958 if (is_reference (var))
959 x = build_simple_mem_ref (x);
961 return x;
964 /* Build tree nodes to access the field for VAR on the sender side. */
966 static tree
967 build_sender_ref (tree var, omp_context *ctx)
969 tree field = lookup_sfield (var, ctx);
970 return omp_build_component_ref (ctx->sender_decl, field);
973 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
975 static void
976 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
978 tree field, type, sfield = NULL_TREE;
980 gcc_assert ((mask & 1) == 0
981 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
982 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
983 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
985 type = TREE_TYPE (var);
986 if (by_ref)
987 type = build_pointer_type (type);
988 else if ((mask & 3) == 1 && is_reference (var))
989 type = TREE_TYPE (type);
991 field = build_decl (DECL_SOURCE_LOCATION (var),
992 FIELD_DECL, DECL_NAME (var), type);
994 /* Remember what variable this field was created for. This does have a
995 side effect of making dwarf2out ignore this member, so for helpful
996 debugging we clear it later in delete_omp_context. */
997 DECL_ABSTRACT_ORIGIN (field) = var;
998 if (type == TREE_TYPE (var))
1000 DECL_ALIGN (field) = DECL_ALIGN (var);
1001 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1002 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1004 else
1005 DECL_ALIGN (field) = TYPE_ALIGN (type);
1007 if ((mask & 3) == 3)
1009 insert_field_into_struct (ctx->record_type, field);
1010 if (ctx->srecord_type)
1012 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1013 FIELD_DECL, DECL_NAME (var), type);
1014 DECL_ABSTRACT_ORIGIN (sfield) = var;
1015 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1016 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1017 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1018 insert_field_into_struct (ctx->srecord_type, sfield);
1021 else
1023 if (ctx->srecord_type == NULL_TREE)
1025 tree t;
1027 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1028 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1029 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1031 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1032 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1033 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1034 insert_field_into_struct (ctx->srecord_type, sfield);
1035 splay_tree_insert (ctx->sfield_map,
1036 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1037 (splay_tree_value) sfield);
1040 sfield = field;
1041 insert_field_into_struct ((mask & 1) ? ctx->record_type
1042 : ctx->srecord_type, field);
1045 if (mask & 1)
1046 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1047 (splay_tree_value) field);
1048 if ((mask & 2) && ctx->sfield_map)
1049 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1050 (splay_tree_value) sfield);
1053 static tree
1054 install_var_local (tree var, omp_context *ctx)
1056 tree new_var = omp_copy_decl_1 (var, ctx);
1057 insert_decl_map (&ctx->cb, var, new_var);
1058 return new_var;
1061 /* Adjust the replacement for DECL in CTX for the new context. This means
1062 copying the DECL_VALUE_EXPR, and fixing up the type. */
1064 static void
1065 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1067 tree new_decl, size;
1069 new_decl = lookup_decl (decl, ctx);
1071 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1073 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1074 && DECL_HAS_VALUE_EXPR_P (decl))
1076 tree ve = DECL_VALUE_EXPR (decl);
1077 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1078 SET_DECL_VALUE_EXPR (new_decl, ve);
1079 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1082 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1084 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1085 if (size == error_mark_node)
1086 size = TYPE_SIZE (TREE_TYPE (new_decl));
1087 DECL_SIZE (new_decl) = size;
1089 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1090 if (size == error_mark_node)
1091 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1092 DECL_SIZE_UNIT (new_decl) = size;
1096 /* The callback for remap_decl. Search all containing contexts for a
1097 mapping of the variable; this avoids having to duplicate the splay
1098 tree ahead of time. We know a mapping doesn't already exist in the
1099 given context. Create new mappings to implement default semantics. */
1101 static tree
1102 omp_copy_decl (tree var, copy_body_data *cb)
1104 omp_context *ctx = (omp_context *) cb;
1105 tree new_var;
1107 if (TREE_CODE (var) == LABEL_DECL)
1109 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1110 DECL_CONTEXT (new_var) = current_function_decl;
1111 insert_decl_map (&ctx->cb, var, new_var);
1112 return new_var;
1115 while (!is_taskreg_ctx (ctx))
1117 ctx = ctx->outer;
1118 if (ctx == NULL)
1119 return var;
1120 new_var = maybe_lookup_decl (var, ctx);
1121 if (new_var)
1122 return new_var;
1125 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1126 return var;
1128 return error_mark_node;
1132 /* Return the parallel region associated with STMT. */
1134 /* Debugging dumps for parallel regions. */
1135 void dump_omp_region (FILE *, struct omp_region *, int);
1136 void debug_omp_region (struct omp_region *);
1137 void debug_all_omp_regions (void);
1139 /* Dump the parallel region tree rooted at REGION. */
1141 void
1142 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1144 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1145 gimple_code_name[region->type]);
1147 if (region->inner)
1148 dump_omp_region (file, region->inner, indent + 4);
1150 if (region->cont)
1152 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1153 region->cont->index);
1156 if (region->exit)
1157 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1158 region->exit->index);
1159 else
1160 fprintf (file, "%*s[no exit marker]\n", indent, "");
1162 if (region->next)
1163 dump_omp_region (file, region->next, indent);
1166 DEBUG_FUNCTION void
1167 debug_omp_region (struct omp_region *region)
1169 dump_omp_region (stderr, region, 0);
1172 DEBUG_FUNCTION void
1173 debug_all_omp_regions (void)
1175 dump_omp_region (stderr, root_omp_region, 0);
1179 /* Create a new parallel region starting at STMT inside region PARENT. */
1181 struct omp_region *
1182 new_omp_region (basic_block bb, enum gimple_code type,
1183 struct omp_region *parent)
1185 struct omp_region *region = XCNEW (struct omp_region);
1187 region->outer = parent;
1188 region->entry = bb;
1189 region->type = type;
1191 if (parent)
1193 /* This is a nested region. Add it to the list of inner
1194 regions in PARENT. */
1195 region->next = parent->inner;
1196 parent->inner = region;
1198 else
1200 /* This is a toplevel region. Add it to the list of toplevel
1201 regions in ROOT_OMP_REGION. */
1202 region->next = root_omp_region;
1203 root_omp_region = region;
1206 return region;
1209 /* Release the memory associated with the region tree rooted at REGION. */
1211 static void
1212 free_omp_region_1 (struct omp_region *region)
1214 struct omp_region *i, *n;
1216 for (i = region->inner; i ; i = n)
1218 n = i->next;
1219 free_omp_region_1 (i);
1222 free (region);
1225 /* Release the memory for the entire omp region tree. */
1227 void
1228 free_omp_regions (void)
1230 struct omp_region *r, *n;
1231 for (r = root_omp_region; r ; r = n)
1233 n = r->next;
1234 free_omp_region_1 (r);
1236 root_omp_region = NULL;
1240 /* Create a new context, with OUTER_CTX being the surrounding context. */
1242 static omp_context *
1243 new_omp_context (gimple stmt, omp_context *outer_ctx)
1245 omp_context *ctx = XCNEW (omp_context);
1247 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1248 (splay_tree_value) ctx);
1249 ctx->stmt = stmt;
1251 if (outer_ctx)
1253 ctx->outer = outer_ctx;
1254 ctx->cb = outer_ctx->cb;
1255 ctx->cb.block = NULL;
1256 ctx->depth = outer_ctx->depth + 1;
1258 else
1260 ctx->cb.src_fn = current_function_decl;
1261 ctx->cb.dst_fn = current_function_decl;
1262 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1263 gcc_checking_assert (ctx->cb.src_node);
1264 ctx->cb.dst_node = ctx->cb.src_node;
1265 ctx->cb.src_cfun = cfun;
1266 ctx->cb.copy_decl = omp_copy_decl;
1267 ctx->cb.eh_lp_nr = 0;
1268 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1269 ctx->depth = 1;
1272 ctx->cb.decl_map = pointer_map_create ();
1274 return ctx;
1277 static gimple_seq maybe_catch_exception (gimple_seq);
1279 /* Finalize task copyfn. */
1281 static void
1282 finalize_task_copyfn (gimple task_stmt)
1284 struct function *child_cfun;
1285 tree child_fn;
1286 gimple_seq seq = NULL, new_seq;
1287 gimple bind;
1289 child_fn = gimple_omp_task_copy_fn (task_stmt);
1290 if (child_fn == NULL_TREE)
1291 return;
1293 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1294 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1296 push_cfun (child_cfun);
1297 bind = gimplify_body (child_fn, false);
1298 gimple_seq_add_stmt (&seq, bind);
1299 new_seq = maybe_catch_exception (seq);
1300 if (new_seq != seq)
1302 bind = gimple_build_bind (NULL, new_seq, NULL);
1303 seq = NULL;
1304 gimple_seq_add_stmt (&seq, bind);
1306 gimple_set_body (child_fn, seq);
1307 pop_cfun ();
1309 /* Inform the callgraph about the new function. */
1310 cgraph_add_new_function (child_fn, false);
1313 /* Destroy a omp_context data structures. Called through the splay tree
1314 value delete callback. */
1316 static void
1317 delete_omp_context (splay_tree_value value)
1319 omp_context *ctx = (omp_context *) value;
1321 pointer_map_destroy (ctx->cb.decl_map);
1323 if (ctx->field_map)
1324 splay_tree_delete (ctx->field_map);
1325 if (ctx->sfield_map)
1326 splay_tree_delete (ctx->sfield_map);
1328 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1329 it produces corrupt debug information. */
1330 if (ctx->record_type)
1332 tree t;
1333 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1334 DECL_ABSTRACT_ORIGIN (t) = NULL;
1336 if (ctx->srecord_type)
1338 tree t;
1339 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1340 DECL_ABSTRACT_ORIGIN (t) = NULL;
1343 if (is_task_ctx (ctx))
1344 finalize_task_copyfn (ctx->stmt);
1346 XDELETE (ctx);
1349 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1350 context. */
1352 static void
1353 fixup_child_record_type (omp_context *ctx)
1355 tree f, type = ctx->record_type;
1357 /* ??? It isn't sufficient to just call remap_type here, because
1358 variably_modified_type_p doesn't work the way we expect for
1359 record types. Testing each field for whether it needs remapping
1360 and creating a new record by hand works, however. */
1361 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1362 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1363 break;
1364 if (f)
1366 tree name, new_fields = NULL;
1368 type = lang_hooks.types.make_type (RECORD_TYPE);
1369 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1370 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1371 TYPE_DECL, name, type);
1372 TYPE_NAME (type) = name;
1374 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1376 tree new_f = copy_node (f);
1377 DECL_CONTEXT (new_f) = type;
1378 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1379 DECL_CHAIN (new_f) = new_fields;
1380 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1381 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1382 &ctx->cb, NULL);
1383 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1384 &ctx->cb, NULL);
1385 new_fields = new_f;
1387 /* Arrange to be able to look up the receiver field
1388 given the sender field. */
1389 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1390 (splay_tree_value) new_f);
1392 TYPE_FIELDS (type) = nreverse (new_fields);
1393 layout_type (type);
1396 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1399 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1400 specified by CLAUSES. */
1402 static void
1403 scan_sharing_clauses (tree clauses, omp_context *ctx)
1405 tree c, decl;
1406 bool scan_array_reductions = false;
1408 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1410 bool by_ref;
1412 switch (OMP_CLAUSE_CODE (c))
1414 case OMP_CLAUSE_PRIVATE:
1415 decl = OMP_CLAUSE_DECL (c);
1416 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1417 goto do_private;
1418 else if (!is_variable_sized (decl))
1419 install_var_local (decl, ctx);
1420 break;
1422 case OMP_CLAUSE_SHARED:
1423 gcc_assert (is_taskreg_ctx (ctx));
1424 decl = OMP_CLAUSE_DECL (c);
1425 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1426 || !is_variable_sized (decl));
1427 /* Global variables don't need to be copied,
1428 the receiver side will use them directly. */
1429 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1430 break;
1431 by_ref = use_pointer_for_field (decl, ctx);
1432 if (! TREE_READONLY (decl)
1433 || TREE_ADDRESSABLE (decl)
1434 || by_ref
1435 || is_reference (decl))
1437 install_var_field (decl, by_ref, 3, ctx);
1438 install_var_local (decl, ctx);
1439 break;
1441 /* We don't need to copy const scalar vars back. */
1442 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1443 goto do_private;
1445 case OMP_CLAUSE_LASTPRIVATE:
1446 /* Let the corresponding firstprivate clause create
1447 the variable. */
1448 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1449 break;
1450 /* FALLTHRU */
1452 case OMP_CLAUSE_FIRSTPRIVATE:
1453 case OMP_CLAUSE_REDUCTION:
1454 case OMP_CLAUSE_LINEAR:
1455 decl = OMP_CLAUSE_DECL (c);
1456 do_private:
1457 if (is_variable_sized (decl))
1459 if (is_task_ctx (ctx))
1460 install_var_field (decl, false, 1, ctx);
1461 break;
1463 else if (is_taskreg_ctx (ctx))
1465 bool global
1466 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1467 by_ref = use_pointer_for_field (decl, NULL);
1469 if (is_task_ctx (ctx)
1470 && (global || by_ref || is_reference (decl)))
1472 install_var_field (decl, false, 1, ctx);
1473 if (!global)
1474 install_var_field (decl, by_ref, 2, ctx);
1476 else if (!global)
1477 install_var_field (decl, by_ref, 3, ctx);
1479 install_var_local (decl, ctx);
1480 break;
1482 case OMP_CLAUSE_COPYPRIVATE:
1483 case OMP_CLAUSE_COPYIN:
1484 decl = OMP_CLAUSE_DECL (c);
1485 by_ref = use_pointer_for_field (decl, NULL);
1486 install_var_field (decl, by_ref, 3, ctx);
1487 break;
1489 case OMP_CLAUSE_DEFAULT:
1490 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1491 break;
1493 case OMP_CLAUSE_FINAL:
1494 case OMP_CLAUSE_IF:
1495 case OMP_CLAUSE_NUM_THREADS:
1496 case OMP_CLAUSE_SCHEDULE:
1497 if (ctx->outer)
1498 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1499 break;
1501 case OMP_CLAUSE_NOWAIT:
1502 case OMP_CLAUSE_ORDERED:
1503 case OMP_CLAUSE_COLLAPSE:
1504 case OMP_CLAUSE_UNTIED:
1505 case OMP_CLAUSE_MERGEABLE:
1506 case OMP_CLAUSE_SAFELEN:
1507 break;
1509 default:
1510 gcc_unreachable ();
1514 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1516 switch (OMP_CLAUSE_CODE (c))
1518 case OMP_CLAUSE_LASTPRIVATE:
1519 /* Let the corresponding firstprivate clause create
1520 the variable. */
1521 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1522 scan_array_reductions = true;
1523 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1524 break;
1525 /* FALLTHRU */
1527 case OMP_CLAUSE_PRIVATE:
1528 case OMP_CLAUSE_FIRSTPRIVATE:
1529 case OMP_CLAUSE_REDUCTION:
1530 case OMP_CLAUSE_LINEAR:
1531 decl = OMP_CLAUSE_DECL (c);
1532 if (is_variable_sized (decl))
1533 install_var_local (decl, ctx);
1534 fixup_remapped_decl (decl, ctx,
1535 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1536 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1538 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1539 scan_array_reductions = true;
1540 break;
1542 case OMP_CLAUSE_SHARED:
1543 decl = OMP_CLAUSE_DECL (c);
1544 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1545 fixup_remapped_decl (decl, ctx, false);
1546 break;
1548 case OMP_CLAUSE_COPYPRIVATE:
1549 case OMP_CLAUSE_COPYIN:
1550 case OMP_CLAUSE_DEFAULT:
1551 case OMP_CLAUSE_IF:
1552 case OMP_CLAUSE_NUM_THREADS:
1553 case OMP_CLAUSE_SCHEDULE:
1554 case OMP_CLAUSE_NOWAIT:
1555 case OMP_CLAUSE_ORDERED:
1556 case OMP_CLAUSE_COLLAPSE:
1557 case OMP_CLAUSE_UNTIED:
1558 case OMP_CLAUSE_FINAL:
1559 case OMP_CLAUSE_MERGEABLE:
1560 case OMP_CLAUSE_SAFELEN:
1561 break;
1563 default:
1564 gcc_unreachable ();
1568 if (scan_array_reductions)
1569 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1571 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1573 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1574 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1576 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1577 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1578 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1581 /* Create a new name for omp child function. Returns an identifier. */
1583 static GTY(()) unsigned int tmp_ompfn_id_num;
1585 static tree
1586 create_omp_child_function_name (bool task_copy)
1588 return (clone_function_name (current_function_decl,
1589 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1592 /* Build a decl for the omp child function. It'll not contain a body
1593 yet, just the bare decl. */
1595 static void
1596 create_omp_child_function (omp_context *ctx, bool task_copy)
1598 tree decl, type, name, t;
1600 name = create_omp_child_function_name (task_copy);
1601 if (task_copy)
1602 type = build_function_type_list (void_type_node, ptr_type_node,
1603 ptr_type_node, NULL_TREE);
1604 else
1605 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1607 decl = build_decl (gimple_location (ctx->stmt),
1608 FUNCTION_DECL, name, type);
1610 if (!task_copy)
1611 ctx->cb.dst_fn = decl;
1612 else
1613 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1615 TREE_STATIC (decl) = 1;
1616 TREE_USED (decl) = 1;
1617 DECL_ARTIFICIAL (decl) = 1;
1618 DECL_NAMELESS (decl) = 1;
1619 DECL_IGNORED_P (decl) = 0;
1620 TREE_PUBLIC (decl) = 0;
1621 DECL_UNINLINABLE (decl) = 1;
1622 DECL_EXTERNAL (decl) = 0;
1623 DECL_CONTEXT (decl) = NULL_TREE;
1624 DECL_INITIAL (decl) = make_node (BLOCK);
1626 t = build_decl (DECL_SOURCE_LOCATION (decl),
1627 RESULT_DECL, NULL_TREE, void_type_node);
1628 DECL_ARTIFICIAL (t) = 1;
1629 DECL_IGNORED_P (t) = 1;
1630 DECL_CONTEXT (t) = decl;
1631 DECL_RESULT (decl) = t;
1633 t = build_decl (DECL_SOURCE_LOCATION (decl),
1634 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1635 DECL_ARTIFICIAL (t) = 1;
1636 DECL_NAMELESS (t) = 1;
1637 DECL_ARG_TYPE (t) = ptr_type_node;
1638 DECL_CONTEXT (t) = current_function_decl;
1639 TREE_USED (t) = 1;
1640 DECL_ARGUMENTS (decl) = t;
1641 if (!task_copy)
1642 ctx->receiver_decl = t;
1643 else
1645 t = build_decl (DECL_SOURCE_LOCATION (decl),
1646 PARM_DECL, get_identifier (".omp_data_o"),
1647 ptr_type_node);
1648 DECL_ARTIFICIAL (t) = 1;
1649 DECL_NAMELESS (t) = 1;
1650 DECL_ARG_TYPE (t) = ptr_type_node;
1651 DECL_CONTEXT (t) = current_function_decl;
1652 TREE_USED (t) = 1;
1653 TREE_ADDRESSABLE (t) = 1;
1654 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1655 DECL_ARGUMENTS (decl) = t;
1658 /* Allocate memory for the function structure. The call to
1659 allocate_struct_function clobbers CFUN, so we need to restore
1660 it afterward. */
1661 push_struct_function (decl);
1662 cfun->function_end_locus = gimple_location (ctx->stmt);
1663 pop_cfun ();
1666 /* Scan an OpenMP parallel directive. */
1668 static void
1669 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1671 omp_context *ctx;
1672 tree name;
1673 gimple stmt = gsi_stmt (*gsi);
1675 /* Ignore parallel directives with empty bodies, unless there
1676 are copyin clauses. */
1677 if (optimize > 0
1678 && empty_body_p (gimple_omp_body (stmt))
1679 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1680 OMP_CLAUSE_COPYIN) == NULL)
1682 gsi_replace (gsi, gimple_build_nop (), false);
1683 return;
1686 ctx = new_omp_context (stmt, outer_ctx);
1687 if (taskreg_nesting_level > 1)
1688 ctx->is_nested = true;
1689 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1690 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1691 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1692 name = create_tmp_var_name (".omp_data_s");
1693 name = build_decl (gimple_location (stmt),
1694 TYPE_DECL, name, ctx->record_type);
1695 DECL_ARTIFICIAL (name) = 1;
1696 DECL_NAMELESS (name) = 1;
1697 TYPE_NAME (ctx->record_type) = name;
1698 create_omp_child_function (ctx, false);
1699 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1701 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1702 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1704 if (TYPE_FIELDS (ctx->record_type) == NULL)
1705 ctx->record_type = ctx->receiver_decl = NULL;
1706 else
1708 layout_type (ctx->record_type);
1709 fixup_child_record_type (ctx);
1713 /* Scan an OpenMP task directive. */
1715 static void
1716 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1718 omp_context *ctx;
1719 tree name, t;
1720 gimple stmt = gsi_stmt (*gsi);
1721 location_t loc = gimple_location (stmt);
1723 /* Ignore task directives with empty bodies. */
1724 if (optimize > 0
1725 && empty_body_p (gimple_omp_body (stmt)))
1727 gsi_replace (gsi, gimple_build_nop (), false);
1728 return;
1731 ctx = new_omp_context (stmt, outer_ctx);
1732 if (taskreg_nesting_level > 1)
1733 ctx->is_nested = true;
1734 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1735 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1736 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1737 name = create_tmp_var_name (".omp_data_s");
1738 name = build_decl (gimple_location (stmt),
1739 TYPE_DECL, name, ctx->record_type);
1740 DECL_ARTIFICIAL (name) = 1;
1741 DECL_NAMELESS (name) = 1;
1742 TYPE_NAME (ctx->record_type) = name;
1743 create_omp_child_function (ctx, false);
1744 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
1746 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
1748 if (ctx->srecord_type)
1750 name = create_tmp_var_name (".omp_data_a");
1751 name = build_decl (gimple_location (stmt),
1752 TYPE_DECL, name, ctx->srecord_type);
1753 DECL_ARTIFICIAL (name) = 1;
1754 DECL_NAMELESS (name) = 1;
1755 TYPE_NAME (ctx->srecord_type) = name;
1756 create_omp_child_function (ctx, true);
1759 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1761 if (TYPE_FIELDS (ctx->record_type) == NULL)
1763 ctx->record_type = ctx->receiver_decl = NULL;
1764 t = build_int_cst (long_integer_type_node, 0);
1765 gimple_omp_task_set_arg_size (stmt, t);
1766 t = build_int_cst (long_integer_type_node, 1);
1767 gimple_omp_task_set_arg_align (stmt, t);
1769 else
1771 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1772 /* Move VLA fields to the end. */
1773 p = &TYPE_FIELDS (ctx->record_type);
1774 while (*p)
1775 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1776 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1778 *q = *p;
1779 *p = TREE_CHAIN (*p);
1780 TREE_CHAIN (*q) = NULL_TREE;
1781 q = &TREE_CHAIN (*q);
1783 else
1784 p = &DECL_CHAIN (*p);
1785 *p = vla_fields;
1786 layout_type (ctx->record_type);
1787 fixup_child_record_type (ctx);
1788 if (ctx->srecord_type)
1789 layout_type (ctx->srecord_type);
1790 t = fold_convert_loc (loc, long_integer_type_node,
1791 TYPE_SIZE_UNIT (ctx->record_type));
1792 gimple_omp_task_set_arg_size (stmt, t);
1793 t = build_int_cst (long_integer_type_node,
1794 TYPE_ALIGN_UNIT (ctx->record_type));
1795 gimple_omp_task_set_arg_align (stmt, t);
1800 /* Scan an OpenMP loop directive. */
1802 static void
1803 scan_omp_for (gimple stmt, omp_context *outer_ctx)
1805 omp_context *ctx;
1806 size_t i;
1808 ctx = new_omp_context (stmt, outer_ctx);
1810 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1812 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
1813 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
1815 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1816 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1817 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1818 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
1820 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1823 /* Scan an OpenMP sections directive. */
1825 static void
1826 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1828 omp_context *ctx;
1830 ctx = new_omp_context (stmt, outer_ctx);
1831 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
1832 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1835 /* Scan an OpenMP single directive. */
1837 static void
1838 scan_omp_single (gimple stmt, omp_context *outer_ctx)
1840 omp_context *ctx;
1841 tree name;
1843 ctx = new_omp_context (stmt, outer_ctx);
1844 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1845 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1846 name = create_tmp_var_name (".omp_copy_s");
1847 name = build_decl (gimple_location (stmt),
1848 TYPE_DECL, name, ctx->record_type);
1849 TYPE_NAME (ctx->record_type) = name;
1851 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
1852 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1854 if (TYPE_FIELDS (ctx->record_type) == NULL)
1855 ctx->record_type = NULL;
1856 else
1857 layout_type (ctx->record_type);
1861 /* Check OpenMP nesting restrictions. */
1862 static bool
1863 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
1865 if (ctx != NULL)
1867 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1868 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
1870 error_at (gimple_location (stmt),
1871 "OpenMP constructs may not be nested inside simd region");
1872 return false;
1875 switch (gimple_code (stmt))
1877 case GIMPLE_OMP_FOR:
1878 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
1879 return true;
1880 /* FALLTHRU */
1881 case GIMPLE_OMP_SECTIONS:
1882 case GIMPLE_OMP_SINGLE:
1883 case GIMPLE_CALL:
1884 for (; ctx != NULL; ctx = ctx->outer)
1885 switch (gimple_code (ctx->stmt))
1887 case GIMPLE_OMP_FOR:
1888 case GIMPLE_OMP_SECTIONS:
1889 case GIMPLE_OMP_SINGLE:
1890 case GIMPLE_OMP_ORDERED:
1891 case GIMPLE_OMP_MASTER:
1892 case GIMPLE_OMP_TASK:
1893 if (is_gimple_call (stmt))
1895 error_at (gimple_location (stmt),
1896 "barrier region may not be closely nested inside "
1897 "of work-sharing, critical, ordered, master or "
1898 "explicit task region");
1899 return false;
1901 error_at (gimple_location (stmt),
1902 "work-sharing region may not be closely nested inside "
1903 "of work-sharing, critical, ordered, master or explicit "
1904 "task region");
1905 return false;
1906 case GIMPLE_OMP_PARALLEL:
1907 return true;
1908 default:
1909 break;
1911 break;
1912 case GIMPLE_OMP_MASTER:
1913 for (; ctx != NULL; ctx = ctx->outer)
1914 switch (gimple_code (ctx->stmt))
1916 case GIMPLE_OMP_FOR:
1917 case GIMPLE_OMP_SECTIONS:
1918 case GIMPLE_OMP_SINGLE:
1919 case GIMPLE_OMP_TASK:
1920 error_at (gimple_location (stmt),
1921 "master region may not be closely nested inside "
1922 "of work-sharing or explicit task region");
1923 return false;
1924 case GIMPLE_OMP_PARALLEL:
1925 return true;
1926 default:
1927 break;
1929 break;
1930 case GIMPLE_OMP_ORDERED:
1931 for (; ctx != NULL; ctx = ctx->outer)
1932 switch (gimple_code (ctx->stmt))
1934 case GIMPLE_OMP_CRITICAL:
1935 case GIMPLE_OMP_TASK:
1936 error_at (gimple_location (stmt),
1937 "ordered region may not be closely nested inside "
1938 "of critical or explicit task region");
1939 return false;
1940 case GIMPLE_OMP_FOR:
1941 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
1942 OMP_CLAUSE_ORDERED) == NULL)
1944 error_at (gimple_location (stmt),
1945 "ordered region must be closely nested inside "
1946 "a loop region with an ordered clause");
1947 return false;
1949 return true;
1950 case GIMPLE_OMP_PARALLEL:
1951 return true;
1952 default:
1953 break;
1955 break;
1956 case GIMPLE_OMP_CRITICAL:
1957 for (; ctx != NULL; ctx = ctx->outer)
1958 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1959 && (gimple_omp_critical_name (stmt)
1960 == gimple_omp_critical_name (ctx->stmt)))
1962 error_at (gimple_location (stmt),
1963 "critical region may not be nested inside a critical "
1964 "region with the same name");
1965 return false;
1967 break;
1968 default:
1969 break;
1971 return true;
1975 /* Helper function scan_omp.
1977 Callback for walk_tree or operators in walk_gimple_stmt used to
1978 scan for OpenMP directives in TP. */
1980 static tree
1981 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1983 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1984 omp_context *ctx = (omp_context *) wi->info;
1985 tree t = *tp;
1987 switch (TREE_CODE (t))
1989 case VAR_DECL:
1990 case PARM_DECL:
1991 case LABEL_DECL:
1992 case RESULT_DECL:
1993 if (ctx)
1994 *tp = remap_decl (t, &ctx->cb);
1995 break;
1997 default:
1998 if (ctx && TYPE_P (t))
1999 *tp = remap_type (t, &ctx->cb);
2000 else if (!DECL_P (t))
2002 *walk_subtrees = 1;
2003 if (ctx)
2005 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2006 if (tem != TREE_TYPE (t))
2008 if (TREE_CODE (t) == INTEGER_CST)
2009 *tp = build_int_cst_wide (tem,
2010 TREE_INT_CST_LOW (t),
2011 TREE_INT_CST_HIGH (t));
2012 else
2013 TREE_TYPE (t) = tem;
2017 break;
2020 return NULL_TREE;
2024 /* Helper function for scan_omp.
2026 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2027 the current statement in GSI. */
2029 static tree
2030 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2031 struct walk_stmt_info *wi)
2033 gimple stmt = gsi_stmt (*gsi);
2034 omp_context *ctx = (omp_context *) wi->info;
2036 if (gimple_has_location (stmt))
2037 input_location = gimple_location (stmt);
2039 /* Check the OpenMP nesting restrictions. */
2040 if (ctx != NULL)
2042 bool remove = false;
2043 if (is_gimple_omp (stmt))
2044 remove = !check_omp_nesting_restrictions (stmt, ctx);
2045 else if (is_gimple_call (stmt))
2047 tree fndecl = gimple_call_fndecl (stmt);
2048 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2049 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
2050 remove = !check_omp_nesting_restrictions (stmt, ctx);
2052 if (remove)
2054 stmt = gimple_build_nop ();
2055 gsi_replace (gsi, stmt, false);
2059 *handled_ops_p = true;
2061 switch (gimple_code (stmt))
2063 case GIMPLE_OMP_PARALLEL:
2064 taskreg_nesting_level++;
2065 scan_omp_parallel (gsi, ctx);
2066 taskreg_nesting_level--;
2067 break;
2069 case GIMPLE_OMP_TASK:
2070 taskreg_nesting_level++;
2071 scan_omp_task (gsi, ctx);
2072 taskreg_nesting_level--;
2073 break;
2075 case GIMPLE_OMP_FOR:
2076 scan_omp_for (stmt, ctx);
2077 break;
2079 case GIMPLE_OMP_SECTIONS:
2080 scan_omp_sections (stmt, ctx);
2081 break;
2083 case GIMPLE_OMP_SINGLE:
2084 scan_omp_single (stmt, ctx);
2085 break;
2087 case GIMPLE_OMP_SECTION:
2088 case GIMPLE_OMP_MASTER:
2089 case GIMPLE_OMP_ORDERED:
2090 case GIMPLE_OMP_CRITICAL:
2091 ctx = new_omp_context (stmt, ctx);
2092 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2093 break;
2095 case GIMPLE_BIND:
2097 tree var;
2099 *handled_ops_p = false;
2100 if (ctx)
2101 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2102 insert_decl_map (&ctx->cb, var, var);
2104 break;
2105 default:
2106 *handled_ops_p = false;
2107 break;
2110 return NULL_TREE;
2114 /* Scan all the statements starting at the current statement. CTX
2115 contains context information about the OpenMP directives and
2116 clauses found during the scan. */
2118 static void
2119 scan_omp (gimple_seq *body_p, omp_context *ctx)
2121 location_t saved_location;
2122 struct walk_stmt_info wi;
2124 memset (&wi, 0, sizeof (wi));
2125 wi.info = ctx;
2126 wi.want_locations = true;
2128 saved_location = input_location;
2129 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2130 input_location = saved_location;
2133 /* Re-gimplification and code generation routines. */
2135 /* Build a call to GOMP_barrier. */
2137 static tree
2138 build_omp_barrier (void)
2140 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
2143 /* If a context was created for STMT when it was scanned, return it. */
2145 static omp_context *
2146 maybe_lookup_ctx (gimple stmt)
2148 splay_tree_node n;
2149 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2150 return n ? (omp_context *) n->value : NULL;
2154 /* Find the mapping for DECL in CTX or the immediately enclosing
2155 context that has a mapping for DECL.
2157 If CTX is a nested parallel directive, we may have to use the decl
2158 mappings created in CTX's parent context. Suppose that we have the
2159 following parallel nesting (variable UIDs showed for clarity):
2161 iD.1562 = 0;
2162 #omp parallel shared(iD.1562) -> outer parallel
2163 iD.1562 = iD.1562 + 1;
2165 #omp parallel shared (iD.1562) -> inner parallel
2166 iD.1562 = iD.1562 - 1;
2168 Each parallel structure will create a distinct .omp_data_s structure
2169 for copying iD.1562 in/out of the directive:
2171 outer parallel .omp_data_s.1.i -> iD.1562
2172 inner parallel .omp_data_s.2.i -> iD.1562
2174 A shared variable mapping will produce a copy-out operation before
2175 the parallel directive and a copy-in operation after it. So, in
2176 this case we would have:
2178 iD.1562 = 0;
2179 .omp_data_o.1.i = iD.1562;
2180 #omp parallel shared(iD.1562) -> outer parallel
2181 .omp_data_i.1 = &.omp_data_o.1
2182 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2184 .omp_data_o.2.i = iD.1562; -> **
2185 #omp parallel shared(iD.1562) -> inner parallel
2186 .omp_data_i.2 = &.omp_data_o.2
2187 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2190 ** This is a problem. The symbol iD.1562 cannot be referenced
2191 inside the body of the outer parallel region. But since we are
2192 emitting this copy operation while expanding the inner parallel
2193 directive, we need to access the CTX structure of the outer
2194 parallel directive to get the correct mapping:
2196 .omp_data_o.2.i = .omp_data_i.1->i
2198 Since there may be other workshare or parallel directives enclosing
2199 the parallel directive, it may be necessary to walk up the context
2200 parent chain. This is not a problem in general because nested
2201 parallelism happens only rarely. */
2203 static tree
2204 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2206 tree t;
2207 omp_context *up;
2209 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2210 t = maybe_lookup_decl (decl, up);
2212 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2214 return t ? t : decl;
2218 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2219 in outer contexts. */
2221 static tree
2222 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2224 tree t = NULL;
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 return t ? t : decl;
2234 /* Construct the initialization value for reduction CLAUSE. */
2236 tree
2237 omp_reduction_init (tree clause, tree type)
2239 location_t loc = OMP_CLAUSE_LOCATION (clause);
2240 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2242 case PLUS_EXPR:
2243 case MINUS_EXPR:
2244 case BIT_IOR_EXPR:
2245 case BIT_XOR_EXPR:
2246 case TRUTH_OR_EXPR:
2247 case TRUTH_ORIF_EXPR:
2248 case TRUTH_XOR_EXPR:
2249 case NE_EXPR:
2250 return build_zero_cst (type);
2252 case MULT_EXPR:
2253 case TRUTH_AND_EXPR:
2254 case TRUTH_ANDIF_EXPR:
2255 case EQ_EXPR:
2256 return fold_convert_loc (loc, type, integer_one_node);
2258 case BIT_AND_EXPR:
2259 return fold_convert_loc (loc, type, integer_minus_one_node);
2261 case MAX_EXPR:
2262 if (SCALAR_FLOAT_TYPE_P (type))
2264 REAL_VALUE_TYPE max, min;
2265 if (HONOR_INFINITIES (TYPE_MODE (type)))
2267 real_inf (&max);
2268 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2270 else
2271 real_maxval (&min, 1, TYPE_MODE (type));
2272 return build_real (type, min);
2274 else
2276 gcc_assert (INTEGRAL_TYPE_P (type));
2277 return TYPE_MIN_VALUE (type);
2280 case MIN_EXPR:
2281 if (SCALAR_FLOAT_TYPE_P (type))
2283 REAL_VALUE_TYPE max;
2284 if (HONOR_INFINITIES (TYPE_MODE (type)))
2285 real_inf (&max);
2286 else
2287 real_maxval (&max, 0, TYPE_MODE (type));
2288 return build_real (type, max);
2290 else
2292 gcc_assert (INTEGRAL_TYPE_P (type));
2293 return TYPE_MAX_VALUE (type);
2296 default:
2297 gcc_unreachable ();
2301 /* Return maximum possible vectorization factor for the target. */
2303 static int
2304 omp_max_vf (void)
2306 if (!optimize
2307 || optimize_debug
2308 || (!flag_tree_vectorize
2309 && global_options_set.x_flag_tree_vectorize))
2310 return 1;
2312 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2313 if (vs)
2315 vs = 1 << floor_log2 (vs);
2316 return vs;
2318 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2319 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2320 return GET_MODE_NUNITS (vqimode);
2321 return 1;
2324 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2325 privatization. */
2327 static bool
2328 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2329 tree &idx, tree &lane, tree &ivar, tree &lvar)
2331 if (max_vf == 0)
2333 max_vf = omp_max_vf ();
2334 if (max_vf > 1)
2336 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2337 OMP_CLAUSE_SAFELEN);
2338 if (c
2339 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2340 max_vf = tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c), 0);
2342 if (max_vf > 1)
2344 idx = create_tmp_var (unsigned_type_node, NULL);
2345 lane = create_tmp_var (unsigned_type_node, NULL);
2348 if (max_vf == 1)
2349 return false;
2351 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2352 tree avar = create_tmp_var_raw (atype, NULL);
2353 if (TREE_ADDRESSABLE (new_var))
2354 TREE_ADDRESSABLE (avar) = 1;
2355 DECL_ATTRIBUTES (avar)
2356 = tree_cons (get_identifier ("omp simd array"), NULL,
2357 DECL_ATTRIBUTES (avar));
2358 gimple_add_tmp_var (avar);
2359 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2360 NULL_TREE, NULL_TREE);
2361 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2362 NULL_TREE, NULL_TREE);
2363 SET_DECL_VALUE_EXPR (new_var, lvar);
2364 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2365 return true;
2368 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2369 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2370 private variables. Initialization statements go in ILIST, while calls
2371 to destructors go in DLIST. */
2373 static void
2374 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2375 omp_context *ctx)
2377 tree c, dtor, copyin_seq, x, ptr;
2378 bool copyin_by_ref = false;
2379 bool lastprivate_firstprivate = false;
2380 int pass;
2381 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2382 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
2383 int max_vf = 0;
2384 tree lane = NULL_TREE, idx = NULL_TREE;
2385 tree ivar = NULL_TREE, lvar = NULL_TREE;
2386 gimple_seq llist[2] = { NULL, NULL };
2388 copyin_seq = NULL;
2390 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
2391 with data sharing clauses referencing variable sized vars. That
2392 is unnecessarily hard to support and very unlikely to result in
2393 vectorized code anyway. */
2394 if (is_simd)
2395 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2396 switch (OMP_CLAUSE_CODE (c))
2398 case OMP_CLAUSE_REDUCTION:
2399 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2400 max_vf = 1;
2401 /* FALLTHRU */
2402 case OMP_CLAUSE_PRIVATE:
2403 case OMP_CLAUSE_FIRSTPRIVATE:
2404 case OMP_CLAUSE_LASTPRIVATE:
2405 case OMP_CLAUSE_LINEAR:
2406 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
2407 max_vf = 1;
2408 break;
2409 default:
2410 continue;
2413 /* Do all the fixed sized types in the first pass, and the variable sized
2414 types in the second pass. This makes sure that the scalar arguments to
2415 the variable sized types are processed before we use them in the
2416 variable sized operations. */
2417 for (pass = 0; pass < 2; ++pass)
2419 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2421 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2422 tree var, new_var;
2423 bool by_ref;
2424 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2426 switch (c_kind)
2428 case OMP_CLAUSE_PRIVATE:
2429 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2430 continue;
2431 break;
2432 case OMP_CLAUSE_SHARED:
2433 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2435 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2436 continue;
2438 case OMP_CLAUSE_FIRSTPRIVATE:
2439 case OMP_CLAUSE_COPYIN:
2440 case OMP_CLAUSE_REDUCTION:
2441 break;
2442 case OMP_CLAUSE_LINEAR:
2443 break;
2444 case OMP_CLAUSE_LASTPRIVATE:
2445 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2447 lastprivate_firstprivate = true;
2448 if (pass != 0)
2449 continue;
2451 break;
2452 default:
2453 continue;
2456 new_var = var = OMP_CLAUSE_DECL (c);
2457 if (c_kind != OMP_CLAUSE_COPYIN)
2458 new_var = lookup_decl (var, ctx);
2460 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2462 if (pass != 0)
2463 continue;
2465 else if (is_variable_sized (var))
2467 /* For variable sized types, we need to allocate the
2468 actual storage here. Call alloca and store the
2469 result in the pointer decl that we created elsewhere. */
2470 if (pass == 0)
2471 continue;
2473 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2475 gimple stmt;
2476 tree tmp, atmp;
2478 ptr = DECL_VALUE_EXPR (new_var);
2479 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2480 ptr = TREE_OPERAND (ptr, 0);
2481 gcc_assert (DECL_P (ptr));
2482 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2484 /* void *tmp = __builtin_alloca */
2485 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2486 stmt = gimple_build_call (atmp, 1, x);
2487 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2488 gimple_add_tmp_var (tmp);
2489 gimple_call_set_lhs (stmt, tmp);
2491 gimple_seq_add_stmt (ilist, stmt);
2493 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
2494 gimplify_assign (ptr, x, ilist);
2497 else if (is_reference (var))
2499 /* For references that are being privatized for Fortran,
2500 allocate new backing storage for the new pointer
2501 variable. This allows us to avoid changing all the
2502 code that expects a pointer to something that expects
2503 a direct variable. Note that this doesn't apply to
2504 C++, since reference types are disallowed in data
2505 sharing clauses there, except for NRV optimized
2506 return values. */
2507 if (pass == 0)
2508 continue;
2510 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2511 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2513 x = build_receiver_ref (var, false, ctx);
2514 x = build_fold_addr_expr_loc (clause_loc, x);
2516 else if (TREE_CONSTANT (x))
2518 const char *name = NULL;
2519 if (DECL_NAME (var))
2520 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2522 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2523 name);
2524 gimple_add_tmp_var (x);
2525 TREE_ADDRESSABLE (x) = 1;
2526 x = build_fold_addr_expr_loc (clause_loc, x);
2528 else
2530 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2531 x = build_call_expr_loc (clause_loc, atmp, 1, x);
2534 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
2535 gimplify_assign (new_var, x, ilist);
2537 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2539 else if (c_kind == OMP_CLAUSE_REDUCTION
2540 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2542 if (pass == 0)
2543 continue;
2545 else if (pass != 0)
2546 continue;
2548 switch (OMP_CLAUSE_CODE (c))
2550 case OMP_CLAUSE_SHARED:
2551 /* Shared global vars are just accessed directly. */
2552 if (is_global_var (new_var))
2553 break;
2554 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2555 needs to be delayed until after fixup_child_record_type so
2556 that we get the correct type during the dereference. */
2557 by_ref = use_pointer_for_field (var, ctx);
2558 x = build_receiver_ref (var, by_ref, ctx);
2559 SET_DECL_VALUE_EXPR (new_var, x);
2560 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2562 /* ??? If VAR is not passed by reference, and the variable
2563 hasn't been initialized yet, then we'll get a warning for
2564 the store into the omp_data_s structure. Ideally, we'd be
2565 able to notice this and not store anything at all, but
2566 we're generating code too early. Suppress the warning. */
2567 if (!by_ref)
2568 TREE_NO_WARNING (var) = 1;
2569 break;
2571 case OMP_CLAUSE_LASTPRIVATE:
2572 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2573 break;
2574 /* FALLTHRU */
2576 case OMP_CLAUSE_PRIVATE:
2577 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2578 x = build_outer_var_ref (var, ctx);
2579 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2581 if (is_task_ctx (ctx))
2582 x = build_receiver_ref (var, false, ctx);
2583 else
2584 x = build_outer_var_ref (var, ctx);
2586 else
2587 x = NULL;
2588 do_private:
2589 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2590 if (is_simd)
2592 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
2593 if ((TREE_ADDRESSABLE (new_var) || x || y
2594 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2595 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2596 idx, lane, ivar, lvar))
2598 if (x)
2599 x = lang_hooks.decls.omp_clause_default_ctor
2600 (c, unshare_expr (ivar), x);
2601 if (x)
2602 gimplify_and_add (x, &llist[0]);
2603 if (y)
2605 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
2606 if (y)
2608 gimple_seq tseq = NULL;
2610 dtor = y;
2611 gimplify_stmt (&dtor, &tseq);
2612 gimple_seq_add_seq (&llist[1], tseq);
2615 break;
2618 if (x)
2619 gimplify_and_add (x, ilist);
2620 /* FALLTHRU */
2622 do_dtor:
2623 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2624 if (x)
2626 gimple_seq tseq = NULL;
2628 dtor = x;
2629 gimplify_stmt (&dtor, &tseq);
2630 gimple_seq_add_seq (dlist, tseq);
2632 break;
2634 case OMP_CLAUSE_LINEAR:
2635 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
2636 goto do_firstprivate;
2637 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
2638 x = NULL;
2639 else
2640 x = build_outer_var_ref (var, ctx);
2641 goto do_private;
2643 case OMP_CLAUSE_FIRSTPRIVATE:
2644 if (is_task_ctx (ctx))
2646 if (is_reference (var) || is_variable_sized (var))
2647 goto do_dtor;
2648 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2649 ctx))
2650 || use_pointer_for_field (var, NULL))
2652 x = build_receiver_ref (var, false, ctx);
2653 SET_DECL_VALUE_EXPR (new_var, x);
2654 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2655 goto do_dtor;
2658 do_firstprivate:
2659 x = build_outer_var_ref (var, ctx);
2660 if (is_simd)
2662 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
2663 || TREE_ADDRESSABLE (new_var))
2664 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2665 idx, lane, ivar, lvar))
2667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
2669 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
2670 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
2671 gimplify_and_add (x, ilist);
2672 gimple_stmt_iterator gsi
2673 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
2674 gimple g
2675 = gimple_build_assign (unshare_expr (lvar), iv);
2676 gsi_insert_before_without_update (&gsi, g,
2677 GSI_SAME_STMT);
2678 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
2679 ? sizetype : TREE_TYPE (x);
2680 tree t = fold_convert (stept,
2681 OMP_CLAUSE_LINEAR_STEP (c));
2682 enum tree_code code = PLUS_EXPR;
2683 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
2684 code = POINTER_PLUS_EXPR;
2685 g = gimple_build_assign_with_ops (code, iv, iv, t);
2686 gsi_insert_before_without_update (&gsi, g,
2687 GSI_SAME_STMT);
2688 break;
2690 x = lang_hooks.decls.omp_clause_copy_ctor
2691 (c, unshare_expr (ivar), x);
2692 gimplify_and_add (x, &llist[0]);
2693 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
2694 if (x)
2696 gimple_seq tseq = NULL;
2698 dtor = x;
2699 gimplify_stmt (&dtor, &tseq);
2700 gimple_seq_add_seq (&llist[1], tseq);
2702 break;
2705 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2706 gimplify_and_add (x, ilist);
2707 goto do_dtor;
2709 case OMP_CLAUSE_COPYIN:
2710 by_ref = use_pointer_for_field (var, NULL);
2711 x = build_receiver_ref (var, by_ref, ctx);
2712 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2713 append_to_statement_list (x, &copyin_seq);
2714 copyin_by_ref |= by_ref;
2715 break;
2717 case OMP_CLAUSE_REDUCTION:
2718 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2720 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2721 x = build_outer_var_ref (var, ctx);
2723 /* FIXME: Not handled yet. */
2724 gcc_assert (!is_simd);
2725 if (is_reference (var))
2726 x = build_fold_addr_expr_loc (clause_loc, x);
2727 SET_DECL_VALUE_EXPR (placeholder, x);
2728 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2729 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2730 gimple_seq_add_seq (ilist,
2731 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2732 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
2733 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2735 else
2737 x = omp_reduction_init (c, TREE_TYPE (new_var));
2738 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2739 if (is_simd
2740 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2741 idx, lane, ivar, lvar))
2743 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
2744 tree ref = build_outer_var_ref (var, ctx);
2746 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
2748 /* reduction(-:var) sums up the partial results, so it
2749 acts identically to reduction(+:var). */
2750 if (code == MINUS_EXPR)
2751 code = PLUS_EXPR;
2753 x = build2 (code, TREE_TYPE (ref), ref, ivar);
2754 ref = build_outer_var_ref (var, ctx);
2755 gimplify_assign (ref, x, &llist[1]);
2757 else
2759 gimplify_assign (new_var, x, ilist);
2760 if (is_simd)
2761 gimplify_assign (build_outer_var_ref (var, ctx),
2762 new_var, dlist);
2765 break;
2767 default:
2768 gcc_unreachable ();
2773 if (lane)
2775 tree uid = create_tmp_var (ptr_type_node, "simduid");
2776 gimple g
2777 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
2778 gimple_call_set_lhs (g, lane);
2779 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
2780 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
2781 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
2782 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
2783 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
2784 gimple_omp_for_set_clauses (ctx->stmt, c);
2785 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
2786 build_int_cst (unsigned_type_node, 0),
2787 NULL_TREE);
2788 gimple_seq_add_stmt (ilist, g);
2789 for (int i = 0; i < 2; i++)
2790 if (llist[i])
2792 tree vf = create_tmp_var (unsigned_type_node, NULL);
2793 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
2794 gimple_call_set_lhs (g, vf);
2795 gimple_seq *seq = i == 0 ? ilist : dlist;
2796 gimple_seq_add_stmt (seq, g);
2797 tree t = build_int_cst (unsigned_type_node, 0);
2798 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
2799 gimple_seq_add_stmt (seq, g);
2800 tree body = create_artificial_label (UNKNOWN_LOCATION);
2801 tree header = create_artificial_label (UNKNOWN_LOCATION);
2802 tree end = create_artificial_label (UNKNOWN_LOCATION);
2803 gimple_seq_add_stmt (seq, gimple_build_goto (header));
2804 gimple_seq_add_stmt (seq, gimple_build_label (body));
2805 gimple_seq_add_seq (seq, llist[i]);
2806 t = build_int_cst (unsigned_type_node, 1);
2807 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
2808 gimple_seq_add_stmt (seq, g);
2809 gimple_seq_add_stmt (seq, gimple_build_label (header));
2810 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
2811 gimple_seq_add_stmt (seq, g);
2812 gimple_seq_add_stmt (seq, gimple_build_label (end));
2816 /* The copyin sequence is not to be executed by the main thread, since
2817 that would result in self-copies. Perhaps not visible to scalars,
2818 but it certainly is to C++ operator=. */
2819 if (copyin_seq)
2821 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
2823 x = build2 (NE_EXPR, boolean_type_node, x,
2824 build_int_cst (TREE_TYPE (x), 0));
2825 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2826 gimplify_and_add (x, ilist);
2829 /* If any copyin variable is passed by reference, we must ensure the
2830 master thread doesn't modify it before it is copied over in all
2831 threads. Similarly for variables in both firstprivate and
2832 lastprivate clauses we need to ensure the lastprivate copying
2833 happens after firstprivate copying in all threads. */
2834 if (copyin_by_ref || lastprivate_firstprivate)
2836 /* Don't add any barrier for #pragma omp simd or
2837 #pragma omp distribute. */
2838 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2839 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
2840 gimplify_and_add (build_omp_barrier (), ilist);
2843 /* If max_vf is non-zero, then we can use only a vectorization factor
2844 up to the max_vf we chose. So stick it into the safelen clause. */
2845 if (max_vf)
2847 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2848 OMP_CLAUSE_SAFELEN);
2849 if (c == NULL_TREE
2850 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
2851 max_vf) == 1)
2853 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
2854 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
2855 max_vf);
2856 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
2857 gimple_omp_for_set_clauses (ctx->stmt, c);
2863 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2864 both parallel and workshare constructs. PREDICATE may be NULL if it's
2865 always true. */
2867 static void
2868 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2869 omp_context *ctx)
2871 tree x, c, label = NULL, orig_clauses = clauses;
2872 bool par_clauses = false;
2873 tree simduid = NULL, lastlane = NULL;
2875 /* Early exit if there are no lastprivate or linear clauses. */
2876 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
2877 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
2878 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
2879 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
2880 break;
2881 if (clauses == NULL)
2883 /* If this was a workshare clause, see if it had been combined
2884 with its parallel. In that case, look for the clauses on the
2885 parallel statement itself. */
2886 if (is_parallel_ctx (ctx))
2887 return;
2889 ctx = ctx->outer;
2890 if (ctx == NULL || !is_parallel_ctx (ctx))
2891 return;
2893 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2894 OMP_CLAUSE_LASTPRIVATE);
2895 if (clauses == NULL)
2896 return;
2897 par_clauses = true;
2900 if (predicate)
2902 gimple stmt;
2903 tree label_true, arm1, arm2;
2905 label = create_artificial_label (UNKNOWN_LOCATION);
2906 label_true = create_artificial_label (UNKNOWN_LOCATION);
2907 arm1 = TREE_OPERAND (predicate, 0);
2908 arm2 = TREE_OPERAND (predicate, 1);
2909 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2910 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2911 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2912 label_true, label);
2913 gimple_seq_add_stmt (stmt_list, stmt);
2914 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2917 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2918 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
2920 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
2921 if (simduid)
2922 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
2925 for (c = clauses; c ;)
2927 tree var, new_var;
2928 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2930 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2931 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2932 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
2934 var = OMP_CLAUSE_DECL (c);
2935 new_var = lookup_decl (var, ctx);
2937 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
2939 tree val = DECL_VALUE_EXPR (new_var);
2940 if (TREE_CODE (val) == ARRAY_REF
2941 && VAR_P (TREE_OPERAND (val, 0))
2942 && lookup_attribute ("omp simd array",
2943 DECL_ATTRIBUTES (TREE_OPERAND (val,
2944 0))))
2946 if (lastlane == NULL)
2948 lastlane = create_tmp_var (unsigned_type_node, NULL);
2949 gimple g
2950 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
2951 2, simduid,
2952 TREE_OPERAND (val, 1));
2953 gimple_call_set_lhs (g, lastlane);
2954 gimple_seq_add_stmt (stmt_list, g);
2956 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
2957 TREE_OPERAND (val, 0), lastlane,
2958 NULL_TREE, NULL_TREE);
2962 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2963 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2965 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2966 gimple_seq_add_seq (stmt_list,
2967 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
2968 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
2971 x = build_outer_var_ref (var, ctx);
2972 if (is_reference (var))
2973 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2974 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2975 gimplify_and_add (x, stmt_list);
2977 c = OMP_CLAUSE_CHAIN (c);
2978 if (c == NULL && !par_clauses)
2980 /* If this was a workshare clause, see if it had been combined
2981 with its parallel. In that case, continue looking for the
2982 clauses also on the parallel statement itself. */
2983 if (is_parallel_ctx (ctx))
2984 break;
2986 ctx = ctx->outer;
2987 if (ctx == NULL || !is_parallel_ctx (ctx))
2988 break;
2990 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2991 OMP_CLAUSE_LASTPRIVATE);
2992 par_clauses = true;
2996 if (label)
2997 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3001 /* Generate code to implement the REDUCTION clauses. */
3003 static void
3004 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3006 gimple_seq sub_seq = NULL;
3007 gimple stmt;
3008 tree x, c;
3009 int count = 0;
3011 /* SIMD reductions are handled in lower_rec_input_clauses. */
3012 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3013 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3014 return;
3016 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3017 update in that case, otherwise use a lock. */
3018 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3019 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3021 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3023 /* Never use OMP_ATOMIC for array reductions. */
3024 count = -1;
3025 break;
3027 count++;
3030 if (count == 0)
3031 return;
3033 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3035 tree var, ref, new_var;
3036 enum tree_code code;
3037 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3039 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3040 continue;
3042 var = OMP_CLAUSE_DECL (c);
3043 new_var = lookup_decl (var, ctx);
3044 if (is_reference (var))
3045 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3046 ref = build_outer_var_ref (var, ctx);
3047 code = OMP_CLAUSE_REDUCTION_CODE (c);
3049 /* reduction(-:var) sums up the partial results, so it acts
3050 identically to reduction(+:var). */
3051 if (code == MINUS_EXPR)
3052 code = PLUS_EXPR;
3054 if (count == 1)
3056 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3058 addr = save_expr (addr);
3059 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3060 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3061 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3062 gimplify_and_add (x, stmt_seqp);
3063 return;
3066 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3068 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3070 if (is_reference (var))
3071 ref = build_fold_addr_expr_loc (clause_loc, ref);
3072 SET_DECL_VALUE_EXPR (placeholder, ref);
3073 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3074 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3075 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3076 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3077 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3079 else
3081 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3082 ref = build_outer_var_ref (var, ctx);
3083 gimplify_assign (ref, x, &sub_seq);
3087 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3089 gimple_seq_add_stmt (stmt_seqp, stmt);
3091 gimple_seq_add_seq (stmt_seqp, sub_seq);
3093 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3095 gimple_seq_add_stmt (stmt_seqp, stmt);
3099 /* Generate code to implement the COPYPRIVATE clauses. */
3101 static void
3102 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3103 omp_context *ctx)
3105 tree c;
3107 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3109 tree var, new_var, ref, x;
3110 bool by_ref;
3111 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3113 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3114 continue;
3116 var = OMP_CLAUSE_DECL (c);
3117 by_ref = use_pointer_for_field (var, NULL);
3119 ref = build_sender_ref (var, ctx);
3120 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3121 if (by_ref)
3123 x = build_fold_addr_expr_loc (clause_loc, new_var);
3124 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3126 gimplify_assign (ref, x, slist);
3128 ref = build_receiver_ref (var, false, ctx);
3129 if (by_ref)
3131 ref = fold_convert_loc (clause_loc,
3132 build_pointer_type (TREE_TYPE (new_var)),
3133 ref);
3134 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3136 if (is_reference (var))
3138 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3139 ref = build_simple_mem_ref_loc (clause_loc, ref);
3140 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3142 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3143 gimplify_and_add (x, rlist);
3148 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3149 and REDUCTION from the sender (aka parent) side. */
3151 static void
3152 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3153 omp_context *ctx)
3155 tree c;
3157 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3159 tree val, ref, x, var;
3160 bool by_ref, do_in = false, do_out = false;
3161 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3163 switch (OMP_CLAUSE_CODE (c))
3165 case OMP_CLAUSE_PRIVATE:
3166 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3167 break;
3168 continue;
3169 case OMP_CLAUSE_FIRSTPRIVATE:
3170 case OMP_CLAUSE_COPYIN:
3171 case OMP_CLAUSE_LASTPRIVATE:
3172 case OMP_CLAUSE_REDUCTION:
3173 break;
3174 default:
3175 continue;
3178 val = OMP_CLAUSE_DECL (c);
3179 var = lookup_decl_in_outer_ctx (val, ctx);
3181 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
3182 && is_global_var (var))
3183 continue;
3184 if (is_variable_sized (val))
3185 continue;
3186 by_ref = use_pointer_for_field (val, NULL);
3188 switch (OMP_CLAUSE_CODE (c))
3190 case OMP_CLAUSE_PRIVATE:
3191 case OMP_CLAUSE_FIRSTPRIVATE:
3192 case OMP_CLAUSE_COPYIN:
3193 do_in = true;
3194 break;
3196 case OMP_CLAUSE_LASTPRIVATE:
3197 if (by_ref || is_reference (val))
3199 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3200 continue;
3201 do_in = true;
3203 else
3205 do_out = true;
3206 if (lang_hooks.decls.omp_private_outer_ref (val))
3207 do_in = true;
3209 break;
3211 case OMP_CLAUSE_REDUCTION:
3212 do_in = true;
3213 do_out = !(by_ref || is_reference (val));
3214 break;
3216 default:
3217 gcc_unreachable ();
3220 if (do_in)
3222 ref = build_sender_ref (val, ctx);
3223 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
3224 gimplify_assign (ref, x, ilist);
3225 if (is_task_ctx (ctx))
3226 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
3229 if (do_out)
3231 ref = build_sender_ref (val, ctx);
3232 gimplify_assign (var, ref, olist);
3237 /* Generate code to implement SHARED from the sender (aka parent)
3238 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
3239 list things that got automatically shared. */
3241 static void
3242 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
3244 tree var, ovar, nvar, f, x, record_type;
3246 if (ctx->record_type == NULL)
3247 return;
3249 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
3250 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
3252 ovar = DECL_ABSTRACT_ORIGIN (f);
3253 nvar = maybe_lookup_decl (ovar, ctx);
3254 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
3255 continue;
3257 /* If CTX is a nested parallel directive. Find the immediately
3258 enclosing parallel or workshare construct that contains a
3259 mapping for OVAR. */
3260 var = lookup_decl_in_outer_ctx (ovar, ctx);
3262 if (use_pointer_for_field (ovar, ctx))
3264 x = build_sender_ref (ovar, ctx);
3265 var = build_fold_addr_expr (var);
3266 gimplify_assign (x, var, ilist);
3268 else
3270 x = build_sender_ref (ovar, ctx);
3271 gimplify_assign (x, var, ilist);
3273 if (!TREE_READONLY (var)
3274 /* We don't need to receive a new reference to a result
3275 or parm decl. In fact we may not store to it as we will
3276 invalidate any pending RSO and generate wrong gimple
3277 during inlining. */
3278 && !((TREE_CODE (var) == RESULT_DECL
3279 || TREE_CODE (var) == PARM_DECL)
3280 && DECL_BY_REFERENCE (var)))
3282 x = build_sender_ref (ovar, ctx);
3283 gimplify_assign (var, x, olist);
3290 /* A convenience function to build an empty GIMPLE_COND with just the
3291 condition. */
3293 static gimple
3294 gimple_build_cond_empty (tree cond)
3296 enum tree_code pred_code;
3297 tree lhs, rhs;
3299 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
3300 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
3304 /* Build the function calls to GOMP_parallel_start etc to actually
3305 generate the parallel operation. REGION is the parallel region
3306 being expanded. BB is the block where to insert the code. WS_ARGS
3307 will be set if this is a call to a combined parallel+workshare
3308 construct, it contains the list of additional arguments needed by
3309 the workshare construct. */
3311 static void
3312 expand_parallel_call (struct omp_region *region, basic_block bb,
3313 gimple entry_stmt, vec<tree, va_gc> *ws_args)
3315 tree t, t1, t2, val, cond, c, clauses;
3316 gimple_stmt_iterator gsi;
3317 gimple stmt;
3318 enum built_in_function start_ix;
3319 int start_ix2;
3320 location_t clause_loc;
3321 vec<tree, va_gc> *args;
3323 clauses = gimple_omp_parallel_clauses (entry_stmt);
3325 /* Determine what flavor of GOMP_parallel_start we will be
3326 emitting. */
3327 start_ix = BUILT_IN_GOMP_PARALLEL_START;
3328 if (is_combined_parallel (region))
3330 switch (region->inner->type)
3332 case GIMPLE_OMP_FOR:
3333 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
3334 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
3335 + (region->inner->sched_kind
3336 == OMP_CLAUSE_SCHEDULE_RUNTIME
3337 ? 3 : region->inner->sched_kind));
3338 start_ix = (enum built_in_function)start_ix2;
3339 break;
3340 case GIMPLE_OMP_SECTIONS:
3341 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
3342 break;
3343 default:
3344 gcc_unreachable ();
3348 /* By default, the value of NUM_THREADS is zero (selected at run time)
3349 and there is no conditional. */
3350 cond = NULL_TREE;
3351 val = build_int_cst (unsigned_type_node, 0);
3353 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3354 if (c)
3355 cond = OMP_CLAUSE_IF_EXPR (c);
3357 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
3358 if (c)
3360 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
3361 clause_loc = OMP_CLAUSE_LOCATION (c);
3363 else
3364 clause_loc = gimple_location (entry_stmt);
3366 /* Ensure 'val' is of the correct type. */
3367 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
3369 /* If we found the clause 'if (cond)', build either
3370 (cond != 0) or (cond ? val : 1u). */
3371 if (cond)
3373 gimple_stmt_iterator gsi;
3375 cond = gimple_boolify (cond);
3377 if (integer_zerop (val))
3378 val = fold_build2_loc (clause_loc,
3379 EQ_EXPR, unsigned_type_node, cond,
3380 build_int_cst (TREE_TYPE (cond), 0));
3381 else
3383 basic_block cond_bb, then_bb, else_bb;
3384 edge e, e_then, e_else;
3385 tree tmp_then, tmp_else, tmp_join, tmp_var;
3387 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
3388 if (gimple_in_ssa_p (cfun))
3390 tmp_then = make_ssa_name (tmp_var, NULL);
3391 tmp_else = make_ssa_name (tmp_var, NULL);
3392 tmp_join = make_ssa_name (tmp_var, NULL);
3394 else
3396 tmp_then = tmp_var;
3397 tmp_else = tmp_var;
3398 tmp_join = tmp_var;
3401 e = split_block (bb, NULL);
3402 cond_bb = e->src;
3403 bb = e->dest;
3404 remove_edge (e);
3406 then_bb = create_empty_bb (cond_bb);
3407 else_bb = create_empty_bb (then_bb);
3408 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
3409 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
3411 stmt = gimple_build_cond_empty (cond);
3412 gsi = gsi_start_bb (cond_bb);
3413 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3415 gsi = gsi_start_bb (then_bb);
3416 stmt = gimple_build_assign (tmp_then, val);
3417 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3419 gsi = gsi_start_bb (else_bb);
3420 stmt = gimple_build_assign
3421 (tmp_else, build_int_cst (unsigned_type_node, 1));
3422 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3424 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
3425 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
3426 if (current_loops)
3428 add_bb_to_loop (then_bb, cond_bb->loop_father);
3429 add_bb_to_loop (else_bb, cond_bb->loop_father);
3431 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3432 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
3434 if (gimple_in_ssa_p (cfun))
3436 gimple phi = create_phi_node (tmp_join, bb);
3437 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3438 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
3441 val = tmp_join;
3444 gsi = gsi_start_bb (bb);
3445 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3446 false, GSI_CONTINUE_LINKING);
3449 gsi = gsi_last_bb (bb);
3450 t = gimple_omp_parallel_data_arg (entry_stmt);
3451 if (t == NULL)
3452 t1 = null_pointer_node;
3453 else
3454 t1 = build_fold_addr_expr (t);
3455 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
3457 vec_alloc (args, 3 + vec_safe_length (ws_args));
3458 args->quick_push (t2);
3459 args->quick_push (t1);
3460 args->quick_push (val);
3461 if (ws_args)
3462 args->splice (*ws_args);
3464 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
3465 builtin_decl_explicit (start_ix), args);
3467 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3468 false, GSI_CONTINUE_LINKING);
3470 t = gimple_omp_parallel_data_arg (entry_stmt);
3471 if (t == NULL)
3472 t = null_pointer_node;
3473 else
3474 t = build_fold_addr_expr (t);
3475 t = build_call_expr_loc (gimple_location (entry_stmt),
3476 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3477 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3478 false, GSI_CONTINUE_LINKING);
3480 t = build_call_expr_loc (gimple_location (entry_stmt),
3481 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3483 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3484 false, GSI_CONTINUE_LINKING);
3488 /* Build the function call to GOMP_task to actually
3489 generate the task operation. BB is the block where to insert the code. */
3491 static void
3492 expand_task_call (basic_block bb, gimple entry_stmt)
3494 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
3495 gimple_stmt_iterator gsi;
3496 location_t loc = gimple_location (entry_stmt);
3498 clauses = gimple_omp_task_clauses (entry_stmt);
3500 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3501 if (c)
3502 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3503 else
3504 cond = boolean_true_node;
3506 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3507 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3508 flags = build_int_cst (unsigned_type_node,
3509 (c ? 1 : 0) + (c2 ? 4 : 0));
3511 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3512 if (c)
3514 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3515 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3516 build_int_cst (unsigned_type_node, 2),
3517 build_int_cst (unsigned_type_node, 0));
3518 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3521 gsi = gsi_last_bb (bb);
3522 t = gimple_omp_task_data_arg (entry_stmt);
3523 if (t == NULL)
3524 t2 = null_pointer_node;
3525 else
3526 t2 = build_fold_addr_expr_loc (loc, t);
3527 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
3528 t = gimple_omp_task_copy_fn (entry_stmt);
3529 if (t == NULL)
3530 t3 = null_pointer_node;
3531 else
3532 t3 = build_fold_addr_expr_loc (loc, t);
3534 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3535 7, t1, t2, t3,
3536 gimple_omp_task_arg_size (entry_stmt),
3537 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3539 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3540 false, GSI_CONTINUE_LINKING);
3544 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3545 catch handler and return it. This prevents programs from violating the
3546 structured block semantics with throws. */
3548 static gimple_seq
3549 maybe_catch_exception (gimple_seq body)
3551 gimple g;
3552 tree decl;
3554 if (!flag_exceptions)
3555 return body;
3557 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3558 decl = lang_hooks.eh_protect_cleanup_actions ();
3559 else
3560 decl = builtin_decl_explicit (BUILT_IN_TRAP);
3562 g = gimple_build_eh_must_not_throw (decl);
3563 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
3564 GIMPLE_TRY_CATCH);
3566 return gimple_seq_alloc_with_stmt (g);
3569 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3571 static tree
3572 vec2chain (vec<tree, va_gc> *v)
3574 tree chain = NULL_TREE, t;
3575 unsigned ix;
3577 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
3579 DECL_CHAIN (t) = chain;
3580 chain = t;
3583 return chain;
3587 /* Remove barriers in REGION->EXIT's block. Note that this is only
3588 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3589 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3590 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3591 removed. */
3593 static void
3594 remove_exit_barrier (struct omp_region *region)
3596 gimple_stmt_iterator gsi;
3597 basic_block exit_bb;
3598 edge_iterator ei;
3599 edge e;
3600 gimple stmt;
3601 int any_addressable_vars = -1;
3603 exit_bb = region->exit;
3605 /* If the parallel region doesn't return, we don't have REGION->EXIT
3606 block at all. */
3607 if (! exit_bb)
3608 return;
3610 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3611 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3612 statements that can appear in between are extremely limited -- no
3613 memory operations at all. Here, we allow nothing at all, so the
3614 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3615 gsi = gsi_last_bb (exit_bb);
3616 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3617 gsi_prev (&gsi);
3618 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3619 return;
3621 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3623 gsi = gsi_last_bb (e->src);
3624 if (gsi_end_p (gsi))
3625 continue;
3626 stmt = gsi_stmt (gsi);
3627 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3628 && !gimple_omp_return_nowait_p (stmt))
3630 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3631 in many cases. If there could be tasks queued, the barrier
3632 might be needed to let the tasks run before some local
3633 variable of the parallel that the task uses as shared
3634 runs out of scope. The task can be spawned either
3635 from within current function (this would be easy to check)
3636 or from some function it calls and gets passed an address
3637 of such a variable. */
3638 if (any_addressable_vars < 0)
3640 gimple parallel_stmt = last_stmt (region->entry);
3641 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3642 tree local_decls, block, decl;
3643 unsigned ix;
3645 any_addressable_vars = 0;
3646 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3647 if (TREE_ADDRESSABLE (decl))
3649 any_addressable_vars = 1;
3650 break;
3652 for (block = gimple_block (stmt);
3653 !any_addressable_vars
3654 && block
3655 && TREE_CODE (block) == BLOCK;
3656 block = BLOCK_SUPERCONTEXT (block))
3658 for (local_decls = BLOCK_VARS (block);
3659 local_decls;
3660 local_decls = DECL_CHAIN (local_decls))
3661 if (TREE_ADDRESSABLE (local_decls))
3663 any_addressable_vars = 1;
3664 break;
3666 if (block == gimple_block (parallel_stmt))
3667 break;
3670 if (!any_addressable_vars)
3671 gimple_omp_return_set_nowait (stmt);
3676 static void
3677 remove_exit_barriers (struct omp_region *region)
3679 if (region->type == GIMPLE_OMP_PARALLEL)
3680 remove_exit_barrier (region);
3682 if (region->inner)
3684 region = region->inner;
3685 remove_exit_barriers (region);
3686 while (region->next)
3688 region = region->next;
3689 remove_exit_barriers (region);
3694 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3695 calls. These can't be declared as const functions, but
3696 within one parallel body they are constant, so they can be
3697 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3698 which are declared const. Similarly for task body, except
3699 that in untied task omp_get_thread_num () can change at any task
3700 scheduling point. */
3702 static void
3703 optimize_omp_library_calls (gimple entry_stmt)
3705 basic_block bb;
3706 gimple_stmt_iterator gsi;
3707 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3708 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3709 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3710 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
3711 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3712 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3713 OMP_CLAUSE_UNTIED) != NULL);
3715 FOR_EACH_BB (bb)
3716 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3718 gimple call = gsi_stmt (gsi);
3719 tree decl;
3721 if (is_gimple_call (call)
3722 && (decl = gimple_call_fndecl (call))
3723 && DECL_EXTERNAL (decl)
3724 && TREE_PUBLIC (decl)
3725 && DECL_INITIAL (decl) == NULL)
3727 tree built_in;
3729 if (DECL_NAME (decl) == thr_num_id)
3731 /* In #pragma omp task untied omp_get_thread_num () can change
3732 during the execution of the task region. */
3733 if (untied_task)
3734 continue;
3735 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3737 else if (DECL_NAME (decl) == num_thr_id)
3738 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3739 else
3740 continue;
3742 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3743 || gimple_call_num_args (call) != 0)
3744 continue;
3746 if (flag_exceptions && !TREE_NOTHROW (decl))
3747 continue;
3749 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3750 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3751 TREE_TYPE (TREE_TYPE (built_in))))
3752 continue;
3754 gimple_call_set_fndecl (call, built_in);
3759 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
3760 regimplified. */
3762 static tree
3763 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
3765 tree t = *tp;
3767 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
3768 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
3769 return t;
3771 if (TREE_CODE (t) == ADDR_EXPR)
3772 recompute_tree_invariant_for_addr_expr (t);
3774 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
3775 return NULL_TREE;
3778 /* Prepend TO = FROM assignment before *GSI_P. */
3780 static void
3781 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
3783 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
3784 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
3785 true, GSI_SAME_STMT);
3786 gimple stmt = gimple_build_assign (to, from);
3787 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3788 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
3789 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
3791 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
3792 gimple_regimplify_operands (stmt, &gsi);
3796 /* Expand the OpenMP parallel or task directive starting at REGION. */
3798 static void
3799 expand_omp_taskreg (struct omp_region *region)
3801 basic_block entry_bb, exit_bb, new_bb;
3802 struct function *child_cfun;
3803 tree child_fn, block, t;
3804 gimple_stmt_iterator gsi;
3805 gimple entry_stmt, stmt;
3806 edge e;
3807 vec<tree, va_gc> *ws_args;
3809 entry_stmt = last_stmt (region->entry);
3810 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3811 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3813 entry_bb = region->entry;
3814 exit_bb = region->exit;
3816 if (is_combined_parallel (region))
3817 ws_args = region->ws_args;
3818 else
3819 ws_args = NULL;
3821 if (child_cfun->cfg)
3823 /* Due to inlining, it may happen that we have already outlined
3824 the region, in which case all we need to do is make the
3825 sub-graph unreachable and emit the parallel call. */
3826 edge entry_succ_e, exit_succ_e;
3827 gimple_stmt_iterator gsi;
3829 entry_succ_e = single_succ_edge (entry_bb);
3831 gsi = gsi_last_bb (entry_bb);
3832 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3833 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3834 gsi_remove (&gsi, true);
3836 new_bb = entry_bb;
3837 if (exit_bb)
3839 exit_succ_e = single_succ_edge (exit_bb);
3840 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3842 remove_edge_and_dominated_blocks (entry_succ_e);
3844 else
3846 unsigned srcidx, dstidx, num;
3848 /* If the parallel region needs data sent from the parent
3849 function, then the very first statement (except possible
3850 tree profile counter updates) of the parallel body
3851 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3852 &.OMP_DATA_O is passed as an argument to the child function,
3853 we need to replace it with the argument as seen by the child
3854 function.
3856 In most cases, this will end up being the identity assignment
3857 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3858 a function call that has been inlined, the original PARM_DECL
3859 .OMP_DATA_I may have been converted into a different local
3860 variable. In which case, we need to keep the assignment. */
3861 if (gimple_omp_taskreg_data_arg (entry_stmt))
3863 basic_block entry_succ_bb = single_succ (entry_bb);
3864 gimple_stmt_iterator gsi;
3865 tree arg, narg;
3866 gimple parcopy_stmt = NULL;
3868 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3870 gimple stmt;
3872 gcc_assert (!gsi_end_p (gsi));
3873 stmt = gsi_stmt (gsi);
3874 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3875 continue;
3877 if (gimple_num_ops (stmt) == 2)
3879 tree arg = gimple_assign_rhs1 (stmt);
3881 /* We're ignore the subcode because we're
3882 effectively doing a STRIP_NOPS. */
3884 if (TREE_CODE (arg) == ADDR_EXPR
3885 && TREE_OPERAND (arg, 0)
3886 == gimple_omp_taskreg_data_arg (entry_stmt))
3888 parcopy_stmt = stmt;
3889 break;
3894 gcc_assert (parcopy_stmt != NULL);
3895 arg = DECL_ARGUMENTS (child_fn);
3897 if (!gimple_in_ssa_p (cfun))
3899 if (gimple_assign_lhs (parcopy_stmt) == arg)
3900 gsi_remove (&gsi, true);
3901 else
3903 /* ?? Is setting the subcode really necessary ?? */
3904 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3905 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3908 else
3910 /* If we are in ssa form, we must load the value from the default
3911 definition of the argument. That should not be defined now,
3912 since the argument is not used uninitialized. */
3913 gcc_assert (ssa_default_def (cfun, arg) == NULL);
3914 narg = make_ssa_name (arg, gimple_build_nop ());
3915 set_ssa_default_def (cfun, arg, narg);
3916 /* ?? Is setting the subcode really necessary ?? */
3917 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3918 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3919 update_stmt (parcopy_stmt);
3923 /* Declare local variables needed in CHILD_CFUN. */
3924 block = DECL_INITIAL (child_fn);
3925 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
3926 /* The gimplifier could record temporaries in parallel/task block
3927 rather than in containing function's local_decls chain,
3928 which would mean cgraph missed finalizing them. Do it now. */
3929 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
3930 if (TREE_CODE (t) == VAR_DECL
3931 && TREE_STATIC (t)
3932 && !DECL_EXTERNAL (t))
3933 varpool_finalize_decl (t);
3934 DECL_SAVED_TREE (child_fn) = NULL;
3935 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3936 gimple_set_body (child_fn, NULL);
3937 TREE_USED (block) = 1;
3939 /* Reset DECL_CONTEXT on function arguments. */
3940 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
3941 DECL_CONTEXT (t) = child_fn;
3943 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3944 so that it can be moved to the child function. */
3945 gsi = gsi_last_bb (entry_bb);
3946 stmt = gsi_stmt (gsi);
3947 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3948 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3949 gsi_remove (&gsi, true);
3950 e = split_block (entry_bb, stmt);
3951 entry_bb = e->dest;
3952 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3954 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3955 if (exit_bb)
3957 gsi = gsi_last_bb (exit_bb);
3958 gcc_assert (!gsi_end_p (gsi)
3959 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3960 stmt = gimple_build_return (NULL);
3961 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3962 gsi_remove (&gsi, true);
3965 /* Move the parallel region into CHILD_CFUN. */
3967 if (gimple_in_ssa_p (cfun))
3969 init_tree_ssa (child_cfun);
3970 init_ssa_operands (child_cfun);
3971 child_cfun->gimple_df->in_ssa_p = true;
3972 block = NULL_TREE;
3974 else
3975 block = gimple_block (entry_stmt);
3977 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3978 if (exit_bb)
3979 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3980 /* When the OMP expansion process cannot guarantee an up-to-date
3981 loop tree arrange for the child function to fixup loops. */
3982 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
3983 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
3985 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3986 num = vec_safe_length (child_cfun->local_decls);
3987 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3989 t = (*child_cfun->local_decls)[srcidx];
3990 if (DECL_CONTEXT (t) == cfun->decl)
3991 continue;
3992 if (srcidx != dstidx)
3993 (*child_cfun->local_decls)[dstidx] = t;
3994 dstidx++;
3996 if (dstidx != num)
3997 vec_safe_truncate (child_cfun->local_decls, dstidx);
3999 /* Inform the callgraph about the new function. */
4000 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4001 cgraph_add_new_function (child_fn, true);
4003 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4004 fixed in a following pass. */
4005 push_cfun (child_cfun);
4006 if (optimize)
4007 optimize_omp_library_calls (entry_stmt);
4008 rebuild_cgraph_edges ();
4010 /* Some EH regions might become dead, see PR34608. If
4011 pass_cleanup_cfg isn't the first pass to happen with the
4012 new child, these dead EH edges might cause problems.
4013 Clean them up now. */
4014 if (flag_exceptions)
4016 basic_block bb;
4017 bool changed = false;
4019 FOR_EACH_BB (bb)
4020 changed |= gimple_purge_dead_eh_edges (bb);
4021 if (changed)
4022 cleanup_tree_cfg ();
4024 if (gimple_in_ssa_p (cfun))
4025 update_ssa (TODO_update_ssa);
4026 pop_cfun ();
4029 /* Emit a library call to launch the children threads. */
4030 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4031 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4032 else
4033 expand_task_call (new_bb, entry_stmt);
4034 if (gimple_in_ssa_p (cfun))
4035 update_ssa (TODO_update_ssa_only_virtuals);
4039 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4040 of the combined collapse > 1 loop constructs, generate code like:
4041 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4042 if (cond3 is <)
4043 adj = STEP3 - 1;
4044 else
4045 adj = STEP3 + 1;
4046 count3 = (adj + N32 - N31) / STEP3;
4047 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4048 if (cond2 is <)
4049 adj = STEP2 - 1;
4050 else
4051 adj = STEP2 + 1;
4052 count2 = (adj + N22 - N21) / STEP2;
4053 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4054 if (cond1 is <)
4055 adj = STEP1 - 1;
4056 else
4057 adj = STEP1 + 1;
4058 count1 = (adj + N12 - N11) / STEP1;
4059 count = count1 * count2 * count3;
4060 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4061 count = 0;
4062 and set ZERO_ITER_BB to that bb. */
4064 /* NOTE: It *could* be better to moosh all of the BBs together,
4065 creating one larger BB with all the computation and the unexpected
4066 jump at the end. I.e.
4068 bool zero3, zero2, zero1, zero;
4070 zero3 = N32 c3 N31;
4071 count3 = (N32 - N31) /[cl] STEP3;
4072 zero2 = N22 c2 N21;
4073 count2 = (N22 - N21) /[cl] STEP2;
4074 zero1 = N12 c1 N11;
4075 count1 = (N12 - N11) /[cl] STEP1;
4076 zero = zero3 || zero2 || zero1;
4077 count = count1 * count2 * count3;
4078 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4080 After all, we expect the zero=false, and thus we expect to have to
4081 evaluate all of the comparison expressions, so short-circuiting
4082 oughtn't be a win. Since the condition isn't protecting a
4083 denominator, we're not concerned about divide-by-zero, so we can
4084 fully evaluate count even if a numerator turned out to be wrong.
4086 It seems like putting this all together would create much better
4087 scheduling opportunities, and less pressure on the chip's branch
4088 predictor. */
4090 static void
4091 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4092 basic_block &entry_bb, tree *counts,
4093 basic_block &zero_iter_bb, int &first_zero_iter,
4094 basic_block &l2_dom_bb)
4096 tree t, type = TREE_TYPE (fd->loop.v);
4097 gimple stmt;
4098 edge e, ne;
4099 int i;
4101 /* Collapsed loops need work for expansion into SSA form. */
4102 gcc_assert (!gimple_in_ssa_p (cfun));
4104 for (i = 0; i < fd->collapse; i++)
4106 tree itype = TREE_TYPE (fd->loops[i].v);
4108 if (SSA_VAR_P (fd->loop.n2)
4109 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4110 fold_convert (itype, fd->loops[i].n1),
4111 fold_convert (itype, fd->loops[i].n2)))
4112 == NULL_TREE || !integer_onep (t)))
4114 tree n1, n2;
4115 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4116 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4117 true, GSI_SAME_STMT);
4118 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4119 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4120 true, GSI_SAME_STMT);
4121 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4122 NULL_TREE, NULL_TREE);
4123 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4124 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4125 expand_omp_regimplify_p, NULL, NULL)
4126 || walk_tree (gimple_cond_rhs_ptr (stmt),
4127 expand_omp_regimplify_p, NULL, NULL))
4129 *gsi = gsi_for_stmt (stmt);
4130 gimple_regimplify_operands (stmt, gsi);
4132 e = split_block (entry_bb, stmt);
4133 if (zero_iter_bb == NULL)
4135 first_zero_iter = i;
4136 zero_iter_bb = create_empty_bb (entry_bb);
4137 if (current_loops)
4138 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4139 *gsi = gsi_after_labels (zero_iter_bb);
4140 stmt = gimple_build_assign (fd->loop.n2,
4141 build_zero_cst (type));
4142 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4143 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
4144 entry_bb);
4146 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
4147 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
4148 e->flags = EDGE_TRUE_VALUE;
4149 e->probability = REG_BR_PROB_BASE - ne->probability;
4150 if (l2_dom_bb == NULL)
4151 l2_dom_bb = entry_bb;
4152 entry_bb = e->dest;
4153 *gsi = gsi_last_bb (entry_bb);
4156 if (POINTER_TYPE_P (itype))
4157 itype = signed_type_for (itype);
4158 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
4159 ? -1 : 1));
4160 t = fold_build2 (PLUS_EXPR, itype,
4161 fold_convert (itype, fd->loops[i].step), t);
4162 t = fold_build2 (PLUS_EXPR, itype, t,
4163 fold_convert (itype, fd->loops[i].n2));
4164 t = fold_build2 (MINUS_EXPR, itype, t,
4165 fold_convert (itype, fd->loops[i].n1));
4166 /* ?? We could probably use CEIL_DIV_EXPR instead of
4167 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4168 generate the same code in the end because generically we
4169 don't know that the values involved must be negative for
4170 GT?? */
4171 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
4172 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4173 fold_build1 (NEGATE_EXPR, itype, t),
4174 fold_build1 (NEGATE_EXPR, itype,
4175 fold_convert (itype,
4176 fd->loops[i].step)));
4177 else
4178 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
4179 fold_convert (itype, fd->loops[i].step));
4180 t = fold_convert (type, t);
4181 if (TREE_CODE (t) == INTEGER_CST)
4182 counts[i] = t;
4183 else
4185 counts[i] = create_tmp_reg (type, ".count");
4186 expand_omp_build_assign (gsi, counts[i], t);
4188 if (SSA_VAR_P (fd->loop.n2))
4190 if (i == 0)
4191 t = counts[0];
4192 else
4193 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
4194 expand_omp_build_assign (gsi, fd->loop.n2, t);
4200 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
4201 T = V;
4202 V3 = N31 + (T % count3) * STEP3;
4203 T = T / count3;
4204 V2 = N21 + (T % count2) * STEP2;
4205 T = T / count2;
4206 V1 = N11 + T * STEP1;
4207 if this loop doesn't have an inner loop construct combined with it. */
4209 static void
4210 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4211 tree *counts, tree startvar)
4213 int i;
4214 tree type = TREE_TYPE (fd->loop.v);
4215 tree tem = create_tmp_reg (type, ".tem");
4216 gimple stmt = gimple_build_assign (tem, startvar);
4217 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4219 for (i = fd->collapse - 1; i >= 0; i--)
4221 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
4222 itype = vtype;
4223 if (POINTER_TYPE_P (vtype))
4224 itype = signed_type_for (vtype);
4225 if (i != 0)
4226 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
4227 else
4228 t = tem;
4229 t = fold_convert (itype, t);
4230 t = fold_build2 (MULT_EXPR, itype, t,
4231 fold_convert (itype, fd->loops[i].step));
4232 if (POINTER_TYPE_P (vtype))
4233 t = fold_build_pointer_plus (fd->loops[i].n1, t);
4234 else
4235 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
4236 t = force_gimple_operand_gsi (gsi, t,
4237 DECL_P (fd->loops[i].v)
4238 && TREE_ADDRESSABLE (fd->loops[i].v),
4239 NULL_TREE, false,
4240 GSI_CONTINUE_LINKING);
4241 stmt = gimple_build_assign (fd->loops[i].v, t);
4242 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4243 if (i != 0)
4245 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
4246 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
4247 false, GSI_CONTINUE_LINKING);
4248 stmt = gimple_build_assign (tem, t);
4249 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4255 /* Helper function for expand_omp_for_*. Generate code like:
4256 L10:
4257 V3 += STEP3;
4258 if (V3 cond3 N32) goto BODY_BB; else goto L11;
4259 L11:
4260 V3 = N31;
4261 V2 += STEP2;
4262 if (V2 cond2 N22) goto BODY_BB; else goto L12;
4263 L12:
4264 V2 = N21;
4265 V1 += STEP1;
4266 goto BODY_BB; */
4268 static basic_block
4269 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
4270 basic_block body_bb)
4272 basic_block last_bb, bb, collapse_bb = NULL;
4273 int i;
4274 gimple_stmt_iterator gsi;
4275 edge e;
4276 tree t;
4277 gimple stmt;
4279 last_bb = cont_bb;
4280 for (i = fd->collapse - 1; i >= 0; i--)
4282 tree vtype = TREE_TYPE (fd->loops[i].v);
4284 bb = create_empty_bb (last_bb);
4285 if (current_loops)
4286 add_bb_to_loop (bb, last_bb->loop_father);
4287 gsi = gsi_start_bb (bb);
4289 if (i < fd->collapse - 1)
4291 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4292 e->probability = REG_BR_PROB_BASE / 8;
4294 t = fd->loops[i + 1].n1;
4295 t = force_gimple_operand_gsi (&gsi, t,
4296 DECL_P (fd->loops[i + 1].v)
4297 && TREE_ADDRESSABLE (fd->loops[i
4298 + 1].v),
4299 NULL_TREE, false,
4300 GSI_CONTINUE_LINKING);
4301 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4302 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4304 else
4305 collapse_bb = bb;
4307 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4309 if (POINTER_TYPE_P (vtype))
4310 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4311 else
4312 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
4313 t = force_gimple_operand_gsi (&gsi, t,
4314 DECL_P (fd->loops[i].v)
4315 && TREE_ADDRESSABLE (fd->loops[i].v),
4316 NULL_TREE, false, GSI_CONTINUE_LINKING);
4317 stmt = gimple_build_assign (fd->loops[i].v, t);
4318 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4320 if (i > 0)
4322 t = fd->loops[i].n2;
4323 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4324 false, GSI_CONTINUE_LINKING);
4325 tree v = fd->loops[i].v;
4326 if (DECL_P (v) && TREE_ADDRESSABLE (v))
4327 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
4328 false, GSI_CONTINUE_LINKING);
4329 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
4330 stmt = gimple_build_cond_empty (t);
4331 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4332 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
4333 e->probability = REG_BR_PROB_BASE * 7 / 8;
4335 else
4336 make_edge (bb, body_bb, EDGE_FALLTHRU);
4337 last_bb = bb;
4340 return collapse_bb;
4344 /* A subroutine of expand_omp_for. Generate code for a parallel
4345 loop with any schedule. Given parameters:
4347 for (V = N1; V cond N2; V += STEP) BODY;
4349 where COND is "<" or ">", we generate pseudocode
4351 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
4352 if (more) goto L0; else goto L3;
4354 V = istart0;
4355 iend = iend0;
4357 BODY;
4358 V += STEP;
4359 if (V cond iend) goto L1; else goto L2;
4361 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4364 If this is a combined omp parallel loop, instead of the call to
4365 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
4367 For collapsed loops, given parameters:
4368 collapse(3)
4369 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
4370 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
4371 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
4372 BODY;
4374 we generate pseudocode
4376 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
4377 if (cond3 is <)
4378 adj = STEP3 - 1;
4379 else
4380 adj = STEP3 + 1;
4381 count3 = (adj + N32 - N31) / STEP3;
4382 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
4383 if (cond2 is <)
4384 adj = STEP2 - 1;
4385 else
4386 adj = STEP2 + 1;
4387 count2 = (adj + N22 - N21) / STEP2;
4388 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
4389 if (cond1 is <)
4390 adj = STEP1 - 1;
4391 else
4392 adj = STEP1 + 1;
4393 count1 = (adj + N12 - N11) / STEP1;
4394 count = count1 * count2 * count3;
4395 goto Z1;
4397 count = 0;
4399 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
4400 if (more) goto L0; else goto L3;
4402 V = istart0;
4403 T = V;
4404 V3 = N31 + (T % count3) * STEP3;
4405 T = T / count3;
4406 V2 = N21 + (T % count2) * STEP2;
4407 T = T / count2;
4408 V1 = N11 + T * STEP1;
4409 iend = iend0;
4411 BODY;
4412 V += 1;
4413 if (V < iend) goto L10; else goto L2;
4414 L10:
4415 V3 += STEP3;
4416 if (V3 cond3 N32) goto L1; else goto L11;
4417 L11:
4418 V3 = N31;
4419 V2 += STEP2;
4420 if (V2 cond2 N22) goto L1; else goto L12;
4421 L12:
4422 V2 = N21;
4423 V1 += STEP1;
4424 goto L1;
4426 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4431 static void
4432 expand_omp_for_generic (struct omp_region *region,
4433 struct omp_for_data *fd,
4434 enum built_in_function start_fn,
4435 enum built_in_function next_fn)
4437 tree type, istart0, iend0, iend;
4438 tree t, vmain, vback, bias = NULL_TREE;
4439 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
4440 basic_block l2_bb = NULL, l3_bb = NULL;
4441 gimple_stmt_iterator gsi;
4442 gimple stmt;
4443 bool in_combined_parallel = is_combined_parallel (region);
4444 bool broken_loop = region->cont == NULL;
4445 edge e, ne;
4446 tree *counts = NULL;
4447 int i;
4449 gcc_assert (!broken_loop || !in_combined_parallel);
4450 gcc_assert (fd->iter_type == long_integer_type_node
4451 || !in_combined_parallel);
4453 type = TREE_TYPE (fd->loop.v);
4454 istart0 = create_tmp_var (fd->iter_type, ".istart0");
4455 iend0 = create_tmp_var (fd->iter_type, ".iend0");
4456 TREE_ADDRESSABLE (istart0) = 1;
4457 TREE_ADDRESSABLE (iend0) = 1;
4459 /* See if we need to bias by LLONG_MIN. */
4460 if (fd->iter_type == long_long_unsigned_type_node
4461 && TREE_CODE (type) == INTEGER_TYPE
4462 && !TYPE_UNSIGNED (type))
4464 tree n1, n2;
4466 if (fd->loop.cond_code == LT_EXPR)
4468 n1 = fd->loop.n1;
4469 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
4471 else
4473 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
4474 n2 = fd->loop.n1;
4476 if (TREE_CODE (n1) != INTEGER_CST
4477 || TREE_CODE (n2) != INTEGER_CST
4478 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
4479 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
4482 entry_bb = region->entry;
4483 cont_bb = region->cont;
4484 collapse_bb = NULL;
4485 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4486 gcc_assert (broken_loop
4487 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4488 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4489 l1_bb = single_succ (l0_bb);
4490 if (!broken_loop)
4492 l2_bb = create_empty_bb (cont_bb);
4493 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
4494 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4496 else
4497 l2_bb = NULL;
4498 l3_bb = BRANCH_EDGE (entry_bb)->dest;
4499 exit_bb = region->exit;
4501 gsi = gsi_last_bb (entry_bb);
4503 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4504 if (fd->collapse > 1)
4506 int first_zero_iter = -1;
4507 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
4509 counts = XALLOCAVEC (tree, fd->collapse);
4510 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
4511 zero_iter_bb, first_zero_iter,
4512 l2_dom_bb);
4514 if (zero_iter_bb)
4516 /* Some counts[i] vars might be uninitialized if
4517 some loop has zero iterations. But the body shouldn't
4518 be executed in that case, so just avoid uninit warnings. */
4519 for (i = first_zero_iter; i < fd->collapse; i++)
4520 if (SSA_VAR_P (counts[i]))
4521 TREE_NO_WARNING (counts[i]) = 1;
4522 gsi_prev (&gsi);
4523 e = split_block (entry_bb, gsi_stmt (gsi));
4524 entry_bb = e->dest;
4525 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
4526 gsi = gsi_last_bb (entry_bb);
4527 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
4528 get_immediate_dominator (CDI_DOMINATORS,
4529 zero_iter_bb));
4532 if (in_combined_parallel)
4534 /* In a combined parallel loop, emit a call to
4535 GOMP_loop_foo_next. */
4536 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4537 build_fold_addr_expr (istart0),
4538 build_fold_addr_expr (iend0));
4540 else
4542 tree t0, t1, t2, t3, t4;
4543 /* If this is not a combined parallel loop, emit a call to
4544 GOMP_loop_foo_start in ENTRY_BB. */
4545 t4 = build_fold_addr_expr (iend0);
4546 t3 = build_fold_addr_expr (istart0);
4547 t2 = fold_convert (fd->iter_type, fd->loop.step);
4548 t1 = fd->loop.n2;
4549 t0 = fd->loop.n1;
4550 if (POINTER_TYPE_P (TREE_TYPE (t0))
4551 && TYPE_PRECISION (TREE_TYPE (t0))
4552 != TYPE_PRECISION (fd->iter_type))
4554 /* Avoid casting pointers to integer of a different size. */
4555 tree itype = signed_type_for (type);
4556 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
4557 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
4559 else
4561 t1 = fold_convert (fd->iter_type, t1);
4562 t0 = fold_convert (fd->iter_type, t0);
4564 if (bias)
4566 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
4567 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
4569 if (fd->iter_type == long_integer_type_node)
4571 if (fd->chunk_size)
4573 t = fold_convert (fd->iter_type, fd->chunk_size);
4574 t = build_call_expr (builtin_decl_explicit (start_fn),
4575 6, t0, t1, t2, t, t3, t4);
4577 else
4578 t = build_call_expr (builtin_decl_explicit (start_fn),
4579 5, t0, t1, t2, t3, t4);
4581 else
4583 tree t5;
4584 tree c_bool_type;
4585 tree bfn_decl;
4587 /* The GOMP_loop_ull_*start functions have additional boolean
4588 argument, true for < loops and false for > loops.
4589 In Fortran, the C bool type can be different from
4590 boolean_type_node. */
4591 bfn_decl = builtin_decl_explicit (start_fn);
4592 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
4593 t5 = build_int_cst (c_bool_type,
4594 fd->loop.cond_code == LT_EXPR ? 1 : 0);
4595 if (fd->chunk_size)
4597 tree bfn_decl = builtin_decl_explicit (start_fn);
4598 t = fold_convert (fd->iter_type, fd->chunk_size);
4599 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
4601 else
4602 t = build_call_expr (builtin_decl_explicit (start_fn),
4603 6, t5, t0, t1, t2, t3, t4);
4606 if (TREE_TYPE (t) != boolean_type_node)
4607 t = fold_build2 (NE_EXPR, boolean_type_node,
4608 t, build_int_cst (TREE_TYPE (t), 0));
4609 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4610 true, GSI_SAME_STMT);
4611 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4613 /* Remove the GIMPLE_OMP_FOR statement. */
4614 gsi_remove (&gsi, true);
4616 /* Iteration setup for sequential loop goes in L0_BB. */
4617 tree startvar = fd->loop.v;
4618 tree endvar = NULL_TREE;
4620 gsi = gsi_start_bb (l0_bb);
4621 t = istart0;
4622 if (bias)
4623 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4624 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4625 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4626 t = fold_convert (TREE_TYPE (startvar), t);
4627 t = force_gimple_operand_gsi (&gsi, t,
4628 DECL_P (startvar)
4629 && TREE_ADDRESSABLE (startvar),
4630 NULL_TREE, false, GSI_CONTINUE_LINKING);
4631 stmt = gimple_build_assign (startvar, t);
4632 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4634 t = iend0;
4635 if (bias)
4636 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
4637 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4638 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4639 t = fold_convert (TREE_TYPE (startvar), t);
4640 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4641 false, GSI_CONTINUE_LINKING);
4642 if (endvar)
4644 stmt = gimple_build_assign (endvar, iend);
4645 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4647 if (fd->collapse > 1)
4648 expand_omp_for_init_vars (fd, &gsi, counts, startvar);
4650 if (!broken_loop)
4652 /* Code to control the increment and predicate for the sequential
4653 loop goes in the CONT_BB. */
4654 gsi = gsi_last_bb (cont_bb);
4655 stmt = gsi_stmt (gsi);
4656 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4657 vmain = gimple_omp_continue_control_use (stmt);
4658 vback = gimple_omp_continue_control_def (stmt);
4660 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4661 if (1)
4663 if (POINTER_TYPE_P (type))
4664 t = fold_build_pointer_plus (vmain, fd->loop.step);
4665 else
4666 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4667 t = force_gimple_operand_gsi (&gsi, t,
4668 DECL_P (vback)
4669 && TREE_ADDRESSABLE (vback),
4670 NULL_TREE, true, GSI_SAME_STMT);
4671 stmt = gimple_build_assign (vback, t);
4672 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4674 t = build2 (fd->loop.cond_code, boolean_type_node,
4675 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
4676 iend);
4677 stmt = gimple_build_cond_empty (t);
4678 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4681 /* Remove GIMPLE_OMP_CONTINUE. */
4682 gsi_remove (&gsi, true);
4684 if (fd->collapse > 1)
4685 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
4687 /* Emit code to get the next parallel iteration in L2_BB. */
4688 gsi = gsi_start_bb (l2_bb);
4690 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4691 build_fold_addr_expr (istart0),
4692 build_fold_addr_expr (iend0));
4693 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4694 false, GSI_CONTINUE_LINKING);
4695 if (TREE_TYPE (t) != boolean_type_node)
4696 t = fold_build2 (NE_EXPR, boolean_type_node,
4697 t, build_int_cst (TREE_TYPE (t), 0));
4698 stmt = gimple_build_cond_empty (t);
4699 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4702 /* Add the loop cleanup function. */
4703 gsi = gsi_last_bb (exit_bb);
4704 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4705 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4706 else
4707 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4708 stmt = gimple_build_call (t, 0);
4709 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4710 gsi_remove (&gsi, true);
4712 /* Connect the new blocks. */
4713 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4714 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4716 if (!broken_loop)
4718 gimple_seq phis;
4720 e = find_edge (cont_bb, l3_bb);
4721 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4723 phis = phi_nodes (l3_bb);
4724 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4726 gimple phi = gsi_stmt (gsi);
4727 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4728 PHI_ARG_DEF_FROM_EDGE (phi, e));
4730 remove_edge (e);
4732 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4733 if (current_loops)
4734 add_bb_to_loop (l2_bb, cont_bb->loop_father);
4735 e = find_edge (cont_bb, l1_bb);
4736 /* OMP4 placeholder for gimple_omp_for_combined_p (fd->for_stmt). */
4737 if (0)
4739 else if (fd->collapse > 1)
4741 remove_edge (e);
4742 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4744 else
4745 e->flags = EDGE_TRUE_VALUE;
4746 if (e)
4748 e->probability = REG_BR_PROB_BASE * 7 / 8;
4749 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4751 else
4753 e = find_edge (cont_bb, l2_bb);
4754 e->flags = EDGE_FALLTHRU;
4756 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4758 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4759 recompute_dominator (CDI_DOMINATORS, l2_bb));
4760 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4761 recompute_dominator (CDI_DOMINATORS, l3_bb));
4762 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4763 recompute_dominator (CDI_DOMINATORS, l0_bb));
4764 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4765 recompute_dominator (CDI_DOMINATORS, l1_bb));
4767 struct loop *outer_loop = alloc_loop ();
4768 outer_loop->header = l0_bb;
4769 outer_loop->latch = l2_bb;
4770 add_loop (outer_loop, l0_bb->loop_father);
4772 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4773 if (1)
4775 struct loop *loop = alloc_loop ();
4776 loop->header = l1_bb;
4777 /* The loop may have multiple latches. */
4778 add_loop (loop, outer_loop);
4784 /* A subroutine of expand_omp_for. Generate code for a parallel
4785 loop with static schedule and no specified chunk size. Given
4786 parameters:
4788 for (V = N1; V cond N2; V += STEP) BODY;
4790 where COND is "<" or ">", we generate pseudocode
4792 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
4793 if (cond is <)
4794 adj = STEP - 1;
4795 else
4796 adj = STEP + 1;
4797 if ((__typeof (V)) -1 > 0 && cond is >)
4798 n = -(adj + N2 - N1) / -STEP;
4799 else
4800 n = (adj + N2 - N1) / STEP;
4801 q = n / nthreads;
4802 tt = n % nthreads;
4803 if (threadid < tt) goto L3; else goto L4;
4805 tt = 0;
4806 q = q + 1;
4808 s0 = q * threadid + tt;
4809 e0 = s0 + q;
4810 V = s0 * STEP + N1;
4811 if (s0 >= e0) goto L2; else goto L0;
4813 e = e0 * STEP + N1;
4815 BODY;
4816 V += STEP;
4817 if (V cond e) goto L1;
4821 static void
4822 expand_omp_for_static_nochunk (struct omp_region *region,
4823 struct omp_for_data *fd)
4825 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
4826 tree type, itype, vmain, vback;
4827 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4828 basic_block body_bb, cont_bb;
4829 basic_block fin_bb;
4830 gimple_stmt_iterator gsi;
4831 gimple stmt;
4832 edge ep;
4834 itype = type = TREE_TYPE (fd->loop.v);
4835 if (POINTER_TYPE_P (type))
4836 itype = signed_type_for (type);
4838 entry_bb = region->entry;
4839 cont_bb = region->cont;
4840 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4841 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4842 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4843 body_bb = single_succ (seq_start_bb);
4844 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4845 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4846 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4847 exit_bb = region->exit;
4849 /* Iteration space partitioning goes in ENTRY_BB. */
4850 gsi = gsi_last_bb (entry_bb);
4851 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4853 t = fold_binary (fd->loop.cond_code, boolean_type_node,
4854 fold_convert (type, fd->loop.n1),
4855 fold_convert (type, fd->loop.n2));
4856 if (TYPE_UNSIGNED (type)
4857 && (t == NULL_TREE || !integer_onep (t)))
4859 tree n1, n2;
4860 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
4861 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
4862 true, GSI_SAME_STMT);
4863 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
4864 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
4865 true, GSI_SAME_STMT);
4866 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
4867 NULL_TREE, NULL_TREE);
4868 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4869 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4870 expand_omp_regimplify_p, NULL, NULL)
4871 || walk_tree (gimple_cond_rhs_ptr (stmt),
4872 expand_omp_regimplify_p, NULL, NULL))
4874 gsi = gsi_for_stmt (stmt);
4875 gimple_regimplify_operands (stmt, &gsi);
4877 ep = split_block (entry_bb, stmt);
4878 ep->flags = EDGE_TRUE_VALUE;
4879 entry_bb = ep->dest;
4880 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
4881 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
4882 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
4883 if (gimple_in_ssa_p (cfun))
4885 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
4886 for (gsi = gsi_start_phis (fin_bb);
4887 !gsi_end_p (gsi); gsi_next (&gsi))
4889 gimple phi = gsi_stmt (gsi);
4890 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
4891 ep, UNKNOWN_LOCATION);
4894 gsi = gsi_last_bb (entry_bb);
4897 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4898 t = fold_convert (itype, t);
4899 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4900 true, GSI_SAME_STMT);
4902 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4903 t = fold_convert (itype, t);
4904 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4905 true, GSI_SAME_STMT);
4907 fd->loop.n1
4908 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4909 true, NULL_TREE, true, GSI_SAME_STMT);
4910 fd->loop.n2
4911 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4912 true, NULL_TREE, true, GSI_SAME_STMT);
4913 fd->loop.step
4914 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4915 true, NULL_TREE, true, GSI_SAME_STMT);
4917 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4918 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4919 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4920 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4921 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4922 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4923 fold_build1 (NEGATE_EXPR, itype, t),
4924 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4925 else
4926 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4927 t = fold_convert (itype, t);
4928 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4930 q = create_tmp_reg (itype, "q");
4931 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4932 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4933 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4935 tt = create_tmp_reg (itype, "tt");
4936 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4937 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4938 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
4940 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4941 stmt = gimple_build_cond_empty (t);
4942 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4944 second_bb = split_block (entry_bb, stmt)->dest;
4945 gsi = gsi_last_bb (second_bb);
4946 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4948 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4949 GSI_SAME_STMT);
4950 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4951 build_int_cst (itype, 1));
4952 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4954 third_bb = split_block (second_bb, stmt)->dest;
4955 gsi = gsi_last_bb (third_bb);
4956 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4958 t = build2 (MULT_EXPR, itype, q, threadid);
4959 t = build2 (PLUS_EXPR, itype, t, tt);
4960 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4962 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4963 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4965 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4966 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4968 /* Remove the GIMPLE_OMP_FOR statement. */
4969 gsi_remove (&gsi, true);
4971 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4972 gsi = gsi_start_bb (seq_start_bb);
4974 t = fold_convert (itype, s0);
4975 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4976 if (POINTER_TYPE_P (type))
4977 t = fold_build_pointer_plus (fd->loop.n1, t);
4978 else
4979 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4980 t = force_gimple_operand_gsi (&gsi, t,
4981 DECL_P (fd->loop.v)
4982 && TREE_ADDRESSABLE (fd->loop.v),
4983 NULL_TREE, false, GSI_CONTINUE_LINKING);
4984 stmt = gimple_build_assign (fd->loop.v, t);
4985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4987 t = fold_convert (itype, e0);
4988 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4989 if (POINTER_TYPE_P (type))
4990 t = fold_build_pointer_plus (fd->loop.n1, t);
4991 else
4992 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4993 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4994 false, GSI_CONTINUE_LINKING);
4996 /* The code controlling the sequential loop replaces the
4997 GIMPLE_OMP_CONTINUE. */
4998 gsi = gsi_last_bb (cont_bb);
4999 stmt = gsi_stmt (gsi);
5000 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5001 vmain = gimple_omp_continue_control_use (stmt);
5002 vback = gimple_omp_continue_control_def (stmt);
5004 if (POINTER_TYPE_P (type))
5005 t = fold_build_pointer_plus (vmain, fd->loop.step);
5006 else
5007 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5008 t = force_gimple_operand_gsi (&gsi, t,
5009 DECL_P (vback) && TREE_ADDRESSABLE (vback),
5010 NULL_TREE, true, GSI_SAME_STMT);
5011 stmt = gimple_build_assign (vback, t);
5012 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5014 t = build2 (fd->loop.cond_code, boolean_type_node,
5015 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback, e);
5016 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5018 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5019 gsi_remove (&gsi, true);
5021 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5022 gsi = gsi_last_bb (exit_bb);
5023 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5024 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
5025 false, GSI_SAME_STMT);
5026 gsi_remove (&gsi, true);
5028 /* Connect all the blocks. */
5029 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5030 ep->probability = REG_BR_PROB_BASE / 4 * 3;
5031 ep = find_edge (entry_bb, second_bb);
5032 ep->flags = EDGE_TRUE_VALUE;
5033 ep->probability = REG_BR_PROB_BASE / 4;
5034 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
5035 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
5037 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
5038 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
5040 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
5041 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
5042 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
5043 set_immediate_dominator (CDI_DOMINATORS, body_bb,
5044 recompute_dominator (CDI_DOMINATORS, body_bb));
5045 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5046 recompute_dominator (CDI_DOMINATORS, fin_bb));
5048 struct loop *loop = alloc_loop ();
5049 loop->header = body_bb;
5050 loop->latch = cont_bb;
5051 add_loop (loop, body_bb->loop_father);
5055 /* A subroutine of expand_omp_for. Generate code for a parallel
5056 loop with static schedule and a specified chunk size. Given
5057 parameters:
5059 for (V = N1; V cond N2; V += STEP) BODY;
5061 where COND is "<" or ">", we generate pseudocode
5063 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5064 if (cond is <)
5065 adj = STEP - 1;
5066 else
5067 adj = STEP + 1;
5068 if ((__typeof (V)) -1 > 0 && cond is >)
5069 n = -(adj + N2 - N1) / -STEP;
5070 else
5071 n = (adj + N2 - N1) / STEP;
5072 trip = 0;
5073 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
5074 here so that V is defined
5075 if the loop is not entered
5077 s0 = (trip * nthreads + threadid) * CHUNK;
5078 e0 = min(s0 + CHUNK, n);
5079 if (s0 < n) goto L1; else goto L4;
5081 V = s0 * STEP + N1;
5082 e = e0 * STEP + N1;
5084 BODY;
5085 V += STEP;
5086 if (V cond e) goto L2; else goto L3;
5088 trip += 1;
5089 goto L0;
5093 static void
5094 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
5096 tree n, s0, e0, e, t;
5097 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
5098 tree type, itype, v_main, v_back, v_extra;
5099 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
5100 basic_block trip_update_bb, cont_bb, fin_bb;
5101 gimple_stmt_iterator si;
5102 gimple stmt;
5103 edge se;
5105 itype = type = TREE_TYPE (fd->loop.v);
5106 if (POINTER_TYPE_P (type))
5107 itype = signed_type_for (type);
5109 entry_bb = region->entry;
5110 se = split_block (entry_bb, last_stmt (entry_bb));
5111 entry_bb = se->src;
5112 iter_part_bb = se->dest;
5113 cont_bb = region->cont;
5114 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
5115 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
5116 == FALLTHRU_EDGE (cont_bb)->dest);
5117 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
5118 body_bb = single_succ (seq_start_bb);
5119 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5120 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5121 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
5122 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
5123 exit_bb = region->exit;
5125 /* Trip and adjustment setup goes in ENTRY_BB. */
5126 si = gsi_last_bb (entry_bb);
5127 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
5129 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5130 fold_convert (type, fd->loop.n1),
5131 fold_convert (type, fd->loop.n2));
5132 if (TYPE_UNSIGNED (type)
5133 && (t == NULL_TREE || !integer_onep (t)))
5135 tree n1, n2;
5136 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5137 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
5138 true, GSI_SAME_STMT);
5139 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5140 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
5141 true, GSI_SAME_STMT);
5142 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5143 NULL_TREE, NULL_TREE);
5144 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5145 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5146 expand_omp_regimplify_p, NULL, NULL)
5147 || walk_tree (gimple_cond_rhs_ptr (stmt),
5148 expand_omp_regimplify_p, NULL, NULL))
5150 si = gsi_for_stmt (stmt);
5151 gimple_regimplify_operands (stmt, &si);
5153 se = split_block (entry_bb, stmt);
5154 se->flags = EDGE_TRUE_VALUE;
5155 entry_bb = se->dest;
5156 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5157 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
5158 se->probability = REG_BR_PROB_BASE / 2000 - 1;
5159 if (gimple_in_ssa_p (cfun))
5161 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5162 for (si = gsi_start_phis (fin_bb);
5163 !gsi_end_p (si); gsi_next (&si))
5165 gimple phi = gsi_stmt (si);
5166 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5167 se, UNKNOWN_LOCATION);
5170 si = gsi_last_bb (entry_bb);
5173 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
5174 t = fold_convert (itype, t);
5175 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5176 true, GSI_SAME_STMT);
5178 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
5179 t = fold_convert (itype, t);
5180 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5181 true, GSI_SAME_STMT);
5183 fd->loop.n1
5184 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
5185 true, NULL_TREE, true, GSI_SAME_STMT);
5186 fd->loop.n2
5187 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
5188 true, NULL_TREE, true, GSI_SAME_STMT);
5189 fd->loop.step
5190 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
5191 true, NULL_TREE, true, GSI_SAME_STMT);
5192 fd->chunk_size
5193 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
5194 true, NULL_TREE, true, GSI_SAME_STMT);
5196 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5197 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
5198 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
5199 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
5200 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5201 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5202 fold_build1 (NEGATE_EXPR, itype, t),
5203 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
5204 else
5205 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
5206 t = fold_convert (itype, t);
5207 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5208 true, GSI_SAME_STMT);
5210 trip_var = create_tmp_reg (itype, ".trip");
5211 if (gimple_in_ssa_p (cfun))
5213 trip_init = make_ssa_name (trip_var, NULL);
5214 trip_main = make_ssa_name (trip_var, NULL);
5215 trip_back = make_ssa_name (trip_var, NULL);
5217 else
5219 trip_init = trip_var;
5220 trip_main = trip_var;
5221 trip_back = trip_var;
5224 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
5225 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5227 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
5228 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5229 if (POINTER_TYPE_P (type))
5230 t = fold_build_pointer_plus (fd->loop.n1, t);
5231 else
5232 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
5233 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5234 true, GSI_SAME_STMT);
5236 /* Remove the GIMPLE_OMP_FOR. */
5237 gsi_remove (&si, true);
5239 /* Iteration space partitioning goes in ITER_PART_BB. */
5240 si = gsi_last_bb (iter_part_bb);
5242 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
5243 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
5244 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
5245 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5246 false, GSI_CONTINUE_LINKING);
5248 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
5249 t = fold_build2 (MIN_EXPR, itype, t, n);
5250 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5251 false, GSI_CONTINUE_LINKING);
5253 t = build2 (LT_EXPR, boolean_type_node, s0, n);
5254 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
5256 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5257 si = gsi_start_bb (seq_start_bb);
5259 t = fold_convert (itype, s0);
5260 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5261 if (POINTER_TYPE_P (type))
5262 t = fold_build_pointer_plus (fd->loop.n1, t);
5263 else
5264 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
5265 t = force_gimple_operand_gsi (&si, t,
5266 DECL_P (fd->loop.v)
5267 && TREE_ADDRESSABLE (fd->loop.v),
5268 NULL_TREE, false, GSI_CONTINUE_LINKING);
5269 stmt = gimple_build_assign (fd->loop.v, t);
5270 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
5272 t = fold_convert (itype, e0);
5273 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5274 if (POINTER_TYPE_P (type))
5275 t = fold_build_pointer_plus (fd->loop.n1, t);
5276 else
5277 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
5278 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5279 false, GSI_CONTINUE_LINKING);
5281 /* The code controlling the sequential loop goes in CONT_BB,
5282 replacing the GIMPLE_OMP_CONTINUE. */
5283 si = gsi_last_bb (cont_bb);
5284 stmt = gsi_stmt (si);
5285 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5286 v_main = gimple_omp_continue_control_use (stmt);
5287 v_back = gimple_omp_continue_control_def (stmt);
5289 if (POINTER_TYPE_P (type))
5290 t = fold_build_pointer_plus (v_main, fd->loop.step);
5291 else
5292 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
5293 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
5294 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5295 true, GSI_SAME_STMT);
5296 stmt = gimple_build_assign (v_back, t);
5297 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5299 t = build2 (fd->loop.cond_code, boolean_type_node,
5300 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
5301 ? t : v_back, e);
5302 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
5304 /* Remove GIMPLE_OMP_CONTINUE. */
5305 gsi_remove (&si, true);
5307 /* Trip update code goes into TRIP_UPDATE_BB. */
5308 si = gsi_start_bb (trip_update_bb);
5310 t = build_int_cst (itype, 1);
5311 t = build2 (PLUS_EXPR, itype, trip_main, t);
5312 stmt = gimple_build_assign (trip_back, t);
5313 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
5315 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5316 si = gsi_last_bb (exit_bb);
5317 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
5318 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
5319 false, GSI_SAME_STMT);
5320 gsi_remove (&si, true);
5322 /* Connect the new blocks. */
5323 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
5324 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
5326 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
5327 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
5329 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
5331 if (gimple_in_ssa_p (cfun))
5333 gimple_stmt_iterator psi;
5334 gimple phi;
5335 edge re, ene;
5336 edge_var_map_vector *head;
5337 edge_var_map *vm;
5338 size_t i;
5340 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
5341 remove arguments of the phi nodes in fin_bb. We need to create
5342 appropriate phi nodes in iter_part_bb instead. */
5343 se = single_pred_edge (fin_bb);
5344 re = single_succ_edge (trip_update_bb);
5345 head = redirect_edge_var_map_vector (re);
5346 ene = single_succ_edge (entry_bb);
5348 psi = gsi_start_phis (fin_bb);
5349 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
5350 gsi_next (&psi), ++i)
5352 gimple nphi;
5353 source_location locus;
5355 phi = gsi_stmt (psi);
5356 t = gimple_phi_result (phi);
5357 gcc_assert (t == redirect_edge_var_map_result (vm));
5358 nphi = create_phi_node (t, iter_part_bb);
5360 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
5361 locus = gimple_phi_arg_location_from_edge (phi, se);
5363 /* A special case -- fd->loop.v is not yet computed in
5364 iter_part_bb, we need to use v_extra instead. */
5365 if (t == fd->loop.v)
5366 t = v_extra;
5367 add_phi_arg (nphi, t, ene, locus);
5368 locus = redirect_edge_var_map_location (vm);
5369 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
5371 gcc_assert (!gsi_end_p (psi) && i == head->length ());
5372 redirect_edge_var_map_clear (re);
5373 while (1)
5375 psi = gsi_start_phis (fin_bb);
5376 if (gsi_end_p (psi))
5377 break;
5378 remove_phi_node (&psi, false);
5381 /* Make phi node for trip. */
5382 phi = create_phi_node (trip_main, iter_part_bb);
5383 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
5384 UNKNOWN_LOCATION);
5385 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
5386 UNKNOWN_LOCATION);
5389 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
5390 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
5391 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
5392 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5393 recompute_dominator (CDI_DOMINATORS, fin_bb));
5394 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
5395 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
5396 set_immediate_dominator (CDI_DOMINATORS, body_bb,
5397 recompute_dominator (CDI_DOMINATORS, body_bb));
5399 struct loop *trip_loop = alloc_loop ();
5400 trip_loop->header = iter_part_bb;
5401 trip_loop->latch = trip_update_bb;
5402 add_loop (trip_loop, iter_part_bb->loop_father);
5404 struct loop *loop = alloc_loop ();
5405 loop->header = body_bb;
5406 loop->latch = cont_bb;
5407 add_loop (loop, trip_loop);
5410 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
5411 loop. Given parameters:
5413 for (V = N1; V cond N2; V += STEP) BODY;
5415 where COND is "<" or ">", we generate pseudocode
5417 V = N1;
5418 goto L1;
5420 BODY;
5421 V += STEP;
5423 if (V cond N2) goto L0; else goto L2;
5426 For collapsed loops, given parameters:
5427 collapse(3)
5428 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5429 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5430 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5431 BODY;
5433 we generate pseudocode
5435 if (cond3 is <)
5436 adj = STEP3 - 1;
5437 else
5438 adj = STEP3 + 1;
5439 count3 = (adj + N32 - N31) / STEP3;
5440 if (cond2 is <)
5441 adj = STEP2 - 1;
5442 else
5443 adj = STEP2 + 1;
5444 count2 = (adj + N22 - N21) / STEP2;
5445 if (cond1 is <)
5446 adj = STEP1 - 1;
5447 else
5448 adj = STEP1 + 1;
5449 count1 = (adj + N12 - N11) / STEP1;
5450 count = count1 * count2 * count3;
5451 V = 0;
5452 V1 = N11;
5453 V2 = N21;
5454 V3 = N31;
5455 goto L1;
5457 BODY;
5458 V += 1;
5459 V3 += STEP3;
5460 V2 += (V3 cond3 N32) ? 0 : STEP2;
5461 V3 = (V3 cond3 N32) ? V3 : N31;
5462 V1 += (V2 cond2 N22) ? 0 : STEP1;
5463 V2 = (V2 cond2 N22) ? V2 : N21;
5465 if (V < count) goto L0; else goto L2;
5470 static void
5471 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
5473 tree type, t;
5474 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
5475 gimple_stmt_iterator gsi;
5476 gimple stmt;
5477 bool broken_loop = region->cont == NULL;
5478 edge e, ne;
5479 tree *counts = NULL;
5480 int i;
5481 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5482 OMP_CLAUSE_SAFELEN);
5483 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5484 OMP_CLAUSE__SIMDUID_);
5485 tree n2;
5487 type = TREE_TYPE (fd->loop.v);
5488 entry_bb = region->entry;
5489 cont_bb = region->cont;
5490 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5491 gcc_assert (broken_loop
5492 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5493 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
5494 if (!broken_loop)
5496 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
5497 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5498 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
5499 l2_bb = BRANCH_EDGE (entry_bb)->dest;
5501 else
5503 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
5504 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
5505 l2_bb = single_succ (l1_bb);
5507 exit_bb = region->exit;
5508 l2_dom_bb = NULL;
5510 gsi = gsi_last_bb (entry_bb);
5512 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5513 /* Not needed in SSA form right now. */
5514 gcc_assert (!gimple_in_ssa_p (cfun));
5515 if (fd->collapse > 1)
5517 int first_zero_iter = -1;
5518 basic_block zero_iter_bb = l2_bb;
5520 counts = XALLOCAVEC (tree, fd->collapse);
5521 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5522 zero_iter_bb, first_zero_iter,
5523 l2_dom_bb);
5525 if (l2_dom_bb == NULL)
5526 l2_dom_bb = l1_bb;
5528 n2 = fd->loop.n2;
5529 if (0)
5530 /* Place holder for gimple_omp_for_combined_into_p() in
5531 the upcoming gomp-4_0-branch merge. */;
5532 else
5534 expand_omp_build_assign (&gsi, fd->loop.v,
5535 fold_convert (type, fd->loop.n1));
5536 if (fd->collapse > 1)
5537 for (i = 0; i < fd->collapse; i++)
5539 tree itype = TREE_TYPE (fd->loops[i].v);
5540 if (POINTER_TYPE_P (itype))
5541 itype = signed_type_for (itype);
5542 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
5543 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5547 /* Remove the GIMPLE_OMP_FOR statement. */
5548 gsi_remove (&gsi, true);
5550 if (!broken_loop)
5552 /* Code to control the increment goes in the CONT_BB. */
5553 gsi = gsi_last_bb (cont_bb);
5554 stmt = gsi_stmt (gsi);
5555 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5557 if (POINTER_TYPE_P (type))
5558 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
5559 else
5560 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
5561 expand_omp_build_assign (&gsi, fd->loop.v, t);
5563 if (fd->collapse > 1)
5565 i = fd->collapse - 1;
5566 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
5568 t = fold_convert (sizetype, fd->loops[i].step);
5569 t = fold_build_pointer_plus (fd->loops[i].v, t);
5571 else
5573 t = fold_convert (TREE_TYPE (fd->loops[i].v),
5574 fd->loops[i].step);
5575 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
5576 fd->loops[i].v, t);
5578 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5580 for (i = fd->collapse - 1; i > 0; i--)
5582 tree itype = TREE_TYPE (fd->loops[i].v);
5583 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
5584 if (POINTER_TYPE_P (itype2))
5585 itype2 = signed_type_for (itype2);
5586 t = build3 (COND_EXPR, itype2,
5587 build2 (fd->loops[i].cond_code, boolean_type_node,
5588 fd->loops[i].v,
5589 fold_convert (itype, fd->loops[i].n2)),
5590 build_int_cst (itype2, 0),
5591 fold_convert (itype2, fd->loops[i - 1].step));
5592 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
5593 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
5594 else
5595 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
5596 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
5598 t = build3 (COND_EXPR, itype,
5599 build2 (fd->loops[i].cond_code, boolean_type_node,
5600 fd->loops[i].v,
5601 fold_convert (itype, fd->loops[i].n2)),
5602 fd->loops[i].v,
5603 fold_convert (itype, fd->loops[i].n1));
5604 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5608 /* Remove GIMPLE_OMP_CONTINUE. */
5609 gsi_remove (&gsi, true);
5612 /* Emit the condition in L1_BB. */
5613 gsi = gsi_start_bb (l1_bb);
5615 t = fold_convert (type, n2);
5616 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5617 false, GSI_CONTINUE_LINKING);
5618 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
5619 stmt = gimple_build_cond_empty (t);
5620 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5621 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
5622 NULL, NULL)
5623 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
5624 NULL, NULL))
5626 gsi = gsi_for_stmt (stmt);
5627 gimple_regimplify_operands (stmt, &gsi);
5630 /* Remove GIMPLE_OMP_RETURN. */
5631 gsi = gsi_last_bb (exit_bb);
5632 gsi_remove (&gsi, true);
5634 /* Connect the new blocks. */
5635 remove_edge (FALLTHRU_EDGE (entry_bb));
5637 if (!broken_loop)
5639 remove_edge (BRANCH_EDGE (entry_bb));
5640 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
5642 e = BRANCH_EDGE (l1_bb);
5643 ne = FALLTHRU_EDGE (l1_bb);
5644 e->flags = EDGE_TRUE_VALUE;
5646 else
5648 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5650 ne = single_succ_edge (l1_bb);
5651 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
5654 ne->flags = EDGE_FALSE_VALUE;
5655 e->probability = REG_BR_PROB_BASE * 7 / 8;
5656 ne->probability = REG_BR_PROB_BASE / 8;
5658 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
5659 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
5660 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
5662 if (!broken_loop)
5664 struct loop *loop = alloc_loop ();
5665 loop->header = l1_bb;
5666 loop->latch = e->dest;
5667 add_loop (loop, l1_bb->loop_father);
5668 if (safelen == NULL_TREE)
5669 loop->safelen = INT_MAX;
5670 else
5672 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
5673 if (!host_integerp (safelen, 1)
5674 || (unsigned HOST_WIDE_INT) tree_low_cst (safelen, 1)
5675 > INT_MAX)
5676 loop->safelen = INT_MAX;
5677 else
5678 loop->safelen = tree_low_cst (safelen, 1);
5679 if (loop->safelen == 1)
5680 loop->safelen = 0;
5682 if (simduid)
5684 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5685 cfun->has_simduid_loops = true;
5687 /* If not -fno-tree-vectorize, hint that we want to vectorize
5688 the loop. */
5689 if ((flag_tree_vectorize
5690 || !global_options_set.x_flag_tree_vectorize)
5691 && loop->safelen > 1)
5693 loop->force_vect = true;
5694 cfun->has_force_vect_loops = true;
5700 /* Expand the OpenMP loop defined by REGION. */
5702 static void
5703 expand_omp_for (struct omp_region *region)
5705 struct omp_for_data fd;
5706 struct omp_for_data_loop *loops;
5708 loops
5709 = (struct omp_for_data_loop *)
5710 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
5711 * sizeof (struct omp_for_data_loop));
5712 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
5713 region->sched_kind = fd.sched_kind;
5715 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
5716 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
5717 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
5718 if (region->cont)
5720 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
5721 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
5722 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
5724 else
5725 /* If there isn't a continue then this is a degerate case where
5726 the introduction of abnormal edges during lowering will prevent
5727 original loops from being detected. Fix that up. */
5728 loops_state_set (LOOPS_NEED_FIXUP);
5730 if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
5731 expand_omp_simd (region, &fd);
5732 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
5733 && !fd.have_ordered
5734 && fd.collapse == 1
5735 && region->cont != NULL)
5737 if (fd.chunk_size == NULL)
5738 expand_omp_for_static_nochunk (region, &fd);
5739 else
5740 expand_omp_for_static_chunk (region, &fd);
5742 else
5744 int fn_index, start_ix, next_ix;
5746 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
5747 == GF_OMP_FOR_KIND_FOR);
5748 if (fd.chunk_size == NULL
5749 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
5750 fd.chunk_size = integer_zero_node;
5751 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
5752 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
5753 ? 3 : fd.sched_kind;
5754 fn_index += fd.have_ordered * 4;
5755 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
5756 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
5757 if (fd.iter_type == long_long_unsigned_type_node)
5759 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
5760 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
5761 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
5762 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
5764 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
5765 (enum built_in_function) next_ix);
5768 if (gimple_in_ssa_p (cfun))
5769 update_ssa (TODO_update_ssa_only_virtuals);
5773 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
5775 v = GOMP_sections_start (n);
5777 switch (v)
5779 case 0:
5780 goto L2;
5781 case 1:
5782 section 1;
5783 goto L1;
5784 case 2:
5786 case n:
5788 default:
5789 abort ();
5792 v = GOMP_sections_next ();
5793 goto L0;
5795 reduction;
5797 If this is a combined parallel sections, replace the call to
5798 GOMP_sections_start with call to GOMP_sections_next. */
5800 static void
5801 expand_omp_sections (struct omp_region *region)
5803 tree t, u, vin = NULL, vmain, vnext, l2;
5804 vec<tree> label_vec;
5805 unsigned len;
5806 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
5807 gimple_stmt_iterator si, switch_si;
5808 gimple sections_stmt, stmt, cont;
5809 edge_iterator ei;
5810 edge e;
5811 struct omp_region *inner;
5812 unsigned i, casei;
5813 bool exit_reachable = region->cont != NULL;
5815 gcc_assert (region->exit != NULL);
5816 entry_bb = region->entry;
5817 l0_bb = single_succ (entry_bb);
5818 l1_bb = region->cont;
5819 l2_bb = region->exit;
5820 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
5821 l2 = gimple_block_label (l2_bb);
5822 else
5824 /* This can happen if there are reductions. */
5825 len = EDGE_COUNT (l0_bb->succs);
5826 gcc_assert (len > 0);
5827 e = EDGE_SUCC (l0_bb, len - 1);
5828 si = gsi_last_bb (e->dest);
5829 l2 = NULL_TREE;
5830 if (gsi_end_p (si)
5831 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
5832 l2 = gimple_block_label (e->dest);
5833 else
5834 FOR_EACH_EDGE (e, ei, l0_bb->succs)
5836 si = gsi_last_bb (e->dest);
5837 if (gsi_end_p (si)
5838 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
5840 l2 = gimple_block_label (e->dest);
5841 break;
5845 if (exit_reachable)
5846 default_bb = create_empty_bb (l1_bb->prev_bb);
5847 else
5848 default_bb = create_empty_bb (l0_bb);
5850 /* We will build a switch() with enough cases for all the
5851 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
5852 and a default case to abort if something goes wrong. */
5853 len = EDGE_COUNT (l0_bb->succs);
5855 /* Use vec::quick_push on label_vec throughout, since we know the size
5856 in advance. */
5857 label_vec.create (len);
5859 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
5860 GIMPLE_OMP_SECTIONS statement. */
5861 si = gsi_last_bb (entry_bb);
5862 sections_stmt = gsi_stmt (si);
5863 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
5864 vin = gimple_omp_sections_control (sections_stmt);
5865 if (!is_combined_parallel (region))
5867 /* If we are not inside a combined parallel+sections region,
5868 call GOMP_sections_start. */
5869 t = build_int_cst (unsigned_type_node,
5870 exit_reachable ? len - 1 : len);
5871 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
5872 stmt = gimple_build_call (u, 1, t);
5874 else
5876 /* Otherwise, call GOMP_sections_next. */
5877 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
5878 stmt = gimple_build_call (u, 0);
5880 gimple_call_set_lhs (stmt, vin);
5881 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5882 gsi_remove (&si, true);
5884 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
5885 L0_BB. */
5886 switch_si = gsi_last_bb (l0_bb);
5887 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
5888 if (exit_reachable)
5890 cont = last_stmt (l1_bb);
5891 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
5892 vmain = gimple_omp_continue_control_use (cont);
5893 vnext = gimple_omp_continue_control_def (cont);
5895 else
5897 vmain = vin;
5898 vnext = NULL_TREE;
5901 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
5902 label_vec.quick_push (t);
5903 i = 1;
5905 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
5906 for (inner = region->inner, casei = 1;
5907 inner;
5908 inner = inner->next, i++, casei++)
5910 basic_block s_entry_bb, s_exit_bb;
5912 /* Skip optional reduction region. */
5913 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
5915 --i;
5916 --casei;
5917 continue;
5920 s_entry_bb = inner->entry;
5921 s_exit_bb = inner->exit;
5923 t = gimple_block_label (s_entry_bb);
5924 u = build_int_cst (unsigned_type_node, casei);
5925 u = build_case_label (u, NULL, t);
5926 label_vec.quick_push (u);
5928 si = gsi_last_bb (s_entry_bb);
5929 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
5930 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
5931 gsi_remove (&si, true);
5932 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
5934 if (s_exit_bb == NULL)
5935 continue;
5937 si = gsi_last_bb (s_exit_bb);
5938 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
5939 gsi_remove (&si, true);
5941 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
5944 /* Error handling code goes in DEFAULT_BB. */
5945 t = gimple_block_label (default_bb);
5946 u = build_case_label (NULL, NULL, t);
5947 make_edge (l0_bb, default_bb, 0);
5948 if (current_loops)
5949 add_bb_to_loop (default_bb, current_loops->tree_root);
5951 stmt = gimple_build_switch (vmain, u, label_vec);
5952 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
5953 gsi_remove (&switch_si, true);
5954 label_vec.release ();
5956 si = gsi_start_bb (default_bb);
5957 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
5958 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
5960 if (exit_reachable)
5962 tree bfn_decl;
5964 /* Code to get the next section goes in L1_BB. */
5965 si = gsi_last_bb (l1_bb);
5966 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
5968 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
5969 stmt = gimple_build_call (bfn_decl, 0);
5970 gimple_call_set_lhs (stmt, vnext);
5971 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5972 gsi_remove (&si, true);
5974 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
5977 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
5978 si = gsi_last_bb (l2_bb);
5979 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
5980 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
5981 else
5982 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
5983 stmt = gimple_build_call (t, 0);
5984 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5985 gsi_remove (&si, true);
5987 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
5991 /* Expand code for an OpenMP single directive. We've already expanded
5992 much of the code, here we simply place the GOMP_barrier call. */
5994 static void
5995 expand_omp_single (struct omp_region *region)
5997 basic_block entry_bb, exit_bb;
5998 gimple_stmt_iterator si;
5999 bool need_barrier = false;
6001 entry_bb = region->entry;
6002 exit_bb = region->exit;
6004 si = gsi_last_bb (entry_bb);
6005 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
6006 be removed. We need to ensure that the thread that entered the single
6007 does not exit before the data is copied out by the other threads. */
6008 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
6009 OMP_CLAUSE_COPYPRIVATE))
6010 need_barrier = true;
6011 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
6012 gsi_remove (&si, true);
6013 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6015 si = gsi_last_bb (exit_bb);
6016 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
6017 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
6018 false, GSI_SAME_STMT);
6019 gsi_remove (&si, true);
6020 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
6024 /* Generic expansion for OpenMP synchronization directives: master,
6025 ordered and critical. All we need to do here is remove the entry
6026 and exit markers for REGION. */
6028 static void
6029 expand_omp_synch (struct omp_region *region)
6031 basic_block entry_bb, exit_bb;
6032 gimple_stmt_iterator si;
6034 entry_bb = region->entry;
6035 exit_bb = region->exit;
6037 si = gsi_last_bb (entry_bb);
6038 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
6039 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
6040 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
6041 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
6042 gsi_remove (&si, true);
6043 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6045 if (exit_bb)
6047 si = gsi_last_bb (exit_bb);
6048 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
6049 gsi_remove (&si, true);
6050 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
6054 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6055 operation as a normal volatile load. */
6057 static bool
6058 expand_omp_atomic_load (basic_block load_bb, tree addr,
6059 tree loaded_val, int index)
6061 enum built_in_function tmpbase;
6062 gimple_stmt_iterator gsi;
6063 basic_block store_bb;
6064 location_t loc;
6065 gimple stmt;
6066 tree decl, call, type, itype;
6068 gsi = gsi_last_bb (load_bb);
6069 stmt = gsi_stmt (gsi);
6070 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
6071 loc = gimple_location (stmt);
6073 /* ??? If the target does not implement atomic_load_optab[mode], and mode
6074 is smaller than word size, then expand_atomic_load assumes that the load
6075 is atomic. We could avoid the builtin entirely in this case. */
6077 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
6078 decl = builtin_decl_explicit (tmpbase);
6079 if (decl == NULL_TREE)
6080 return false;
6082 type = TREE_TYPE (loaded_val);
6083 itype = TREE_TYPE (TREE_TYPE (decl));
6085 call = build_call_expr_loc (loc, decl, 2, addr,
6086 build_int_cst (NULL, MEMMODEL_RELAXED));
6087 if (!useless_type_conversion_p (type, itype))
6088 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
6089 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
6091 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6092 gsi_remove (&gsi, true);
6094 store_bb = single_succ (load_bb);
6095 gsi = gsi_last_bb (store_bb);
6096 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
6097 gsi_remove (&gsi, true);
6099 if (gimple_in_ssa_p (cfun))
6100 update_ssa (TODO_update_ssa_no_phi);
6102 return true;
6105 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6106 operation as a normal volatile store. */
6108 static bool
6109 expand_omp_atomic_store (basic_block load_bb, tree addr,
6110 tree loaded_val, tree stored_val, int index)
6112 enum built_in_function tmpbase;
6113 gimple_stmt_iterator gsi;
6114 basic_block store_bb = single_succ (load_bb);
6115 location_t loc;
6116 gimple stmt;
6117 tree decl, call, type, itype;
6118 enum machine_mode imode;
6119 bool exchange;
6121 gsi = gsi_last_bb (load_bb);
6122 stmt = gsi_stmt (gsi);
6123 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
6125 /* If the load value is needed, then this isn't a store but an exchange. */
6126 exchange = gimple_omp_atomic_need_value_p (stmt);
6128 gsi = gsi_last_bb (store_bb);
6129 stmt = gsi_stmt (gsi);
6130 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
6131 loc = gimple_location (stmt);
6133 /* ??? If the target does not implement atomic_store_optab[mode], and mode
6134 is smaller than word size, then expand_atomic_store assumes that the store
6135 is atomic. We could avoid the builtin entirely in this case. */
6137 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
6138 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
6139 decl = builtin_decl_explicit (tmpbase);
6140 if (decl == NULL_TREE)
6141 return false;
6143 type = TREE_TYPE (stored_val);
6145 /* Dig out the type of the function's second argument. */
6146 itype = TREE_TYPE (decl);
6147 itype = TYPE_ARG_TYPES (itype);
6148 itype = TREE_CHAIN (itype);
6149 itype = TREE_VALUE (itype);
6150 imode = TYPE_MODE (itype);
6152 if (exchange && !can_atomic_exchange_p (imode, true))
6153 return false;
6155 if (!useless_type_conversion_p (itype, type))
6156 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
6157 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
6158 build_int_cst (NULL, MEMMODEL_RELAXED));
6159 if (exchange)
6161 if (!useless_type_conversion_p (type, itype))
6162 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
6163 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
6166 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6167 gsi_remove (&gsi, true);
6169 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
6170 gsi = gsi_last_bb (load_bb);
6171 gsi_remove (&gsi, true);
6173 if (gimple_in_ssa_p (cfun))
6174 update_ssa (TODO_update_ssa_no_phi);
6176 return true;
6179 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6180 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
6181 size of the data type, and thus usable to find the index of the builtin
6182 decl. Returns false if the expression is not of the proper form. */
6184 static bool
6185 expand_omp_atomic_fetch_op (basic_block load_bb,
6186 tree addr, tree loaded_val,
6187 tree stored_val, int index)
6189 enum built_in_function oldbase, newbase, tmpbase;
6190 tree decl, itype, call;
6191 tree lhs, rhs;
6192 basic_block store_bb = single_succ (load_bb);
6193 gimple_stmt_iterator gsi;
6194 gimple stmt;
6195 location_t loc;
6196 enum tree_code code;
6197 bool need_old, need_new;
6198 enum machine_mode imode;
6200 /* We expect to find the following sequences:
6202 load_bb:
6203 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
6205 store_bb:
6206 val = tmp OP something; (or: something OP tmp)
6207 GIMPLE_OMP_STORE (val)
6209 ???FIXME: Allow a more flexible sequence.
6210 Perhaps use data flow to pick the statements.
6214 gsi = gsi_after_labels (store_bb);
6215 stmt = gsi_stmt (gsi);
6216 loc = gimple_location (stmt);
6217 if (!is_gimple_assign (stmt))
6218 return false;
6219 gsi_next (&gsi);
6220 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
6221 return false;
6222 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
6223 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
6224 gcc_checking_assert (!need_old || !need_new);
6226 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
6227 return false;
6229 /* Check for one of the supported fetch-op operations. */
6230 code = gimple_assign_rhs_code (stmt);
6231 switch (code)
6233 case PLUS_EXPR:
6234 case POINTER_PLUS_EXPR:
6235 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
6236 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
6237 break;
6238 case MINUS_EXPR:
6239 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
6240 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
6241 break;
6242 case BIT_AND_EXPR:
6243 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
6244 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
6245 break;
6246 case BIT_IOR_EXPR:
6247 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
6248 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
6249 break;
6250 case BIT_XOR_EXPR:
6251 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
6252 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
6253 break;
6254 default:
6255 return false;
6258 /* Make sure the expression is of the proper form. */
6259 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
6260 rhs = gimple_assign_rhs2 (stmt);
6261 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
6262 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
6263 rhs = gimple_assign_rhs1 (stmt);
6264 else
6265 return false;
6267 tmpbase = ((enum built_in_function)
6268 ((need_new ? newbase : oldbase) + index + 1));
6269 decl = builtin_decl_explicit (tmpbase);
6270 if (decl == NULL_TREE)
6271 return false;
6272 itype = TREE_TYPE (TREE_TYPE (decl));
6273 imode = TYPE_MODE (itype);
6275 /* We could test all of the various optabs involved, but the fact of the
6276 matter is that (with the exception of i486 vs i586 and xadd) all targets
6277 that support any atomic operaton optab also implements compare-and-swap.
6278 Let optabs.c take care of expanding any compare-and-swap loop. */
6279 if (!can_compare_and_swap_p (imode, true))
6280 return false;
6282 gsi = gsi_last_bb (load_bb);
6283 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
6285 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
6286 It only requires that the operation happen atomically. Thus we can
6287 use the RELAXED memory model. */
6288 call = build_call_expr_loc (loc, decl, 3, addr,
6289 fold_convert_loc (loc, itype, rhs),
6290 build_int_cst (NULL, MEMMODEL_RELAXED));
6292 if (need_old || need_new)
6294 lhs = need_old ? loaded_val : stored_val;
6295 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
6296 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
6298 else
6299 call = fold_convert_loc (loc, void_type_node, call);
6300 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6301 gsi_remove (&gsi, true);
6303 gsi = gsi_last_bb (store_bb);
6304 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
6305 gsi_remove (&gsi, true);
6306 gsi = gsi_last_bb (store_bb);
6307 gsi_remove (&gsi, true);
6309 if (gimple_in_ssa_p (cfun))
6310 update_ssa (TODO_update_ssa_no_phi);
6312 return true;
6315 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6317 oldval = *addr;
6318 repeat:
6319 newval = rhs; // with oldval replacing *addr in rhs
6320 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
6321 if (oldval != newval)
6322 goto repeat;
6324 INDEX is log2 of the size of the data type, and thus usable to find the
6325 index of the builtin decl. */
6327 static bool
6328 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
6329 tree addr, tree loaded_val, tree stored_val,
6330 int index)
6332 tree loadedi, storedi, initial, new_storedi, old_vali;
6333 tree type, itype, cmpxchg, iaddr;
6334 gimple_stmt_iterator si;
6335 basic_block loop_header = single_succ (load_bb);
6336 gimple phi, stmt;
6337 edge e;
6338 enum built_in_function fncode;
6340 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
6341 order to use the RELAXED memory model effectively. */
6342 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
6343 + index + 1);
6344 cmpxchg = builtin_decl_explicit (fncode);
6345 if (cmpxchg == NULL_TREE)
6346 return false;
6347 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
6348 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
6350 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
6351 return false;
6353 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
6354 si = gsi_last_bb (load_bb);
6355 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
6357 /* For floating-point values, we'll need to view-convert them to integers
6358 so that we can perform the atomic compare and swap. Simplify the
6359 following code by always setting up the "i"ntegral variables. */
6360 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
6362 tree iaddr_val;
6364 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
6365 true), NULL);
6366 iaddr_val
6367 = force_gimple_operand_gsi (&si,
6368 fold_convert (TREE_TYPE (iaddr), addr),
6369 false, NULL_TREE, true, GSI_SAME_STMT);
6370 stmt = gimple_build_assign (iaddr, iaddr_val);
6371 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6372 loadedi = create_tmp_var (itype, NULL);
6373 if (gimple_in_ssa_p (cfun))
6374 loadedi = make_ssa_name (loadedi, NULL);
6376 else
6378 iaddr = addr;
6379 loadedi = loaded_val;
6382 initial
6383 = force_gimple_operand_gsi (&si,
6384 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
6385 iaddr,
6386 build_int_cst (TREE_TYPE (iaddr), 0)),
6387 true, NULL_TREE, true, GSI_SAME_STMT);
6389 /* Move the value to the LOADEDI temporary. */
6390 if (gimple_in_ssa_p (cfun))
6392 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
6393 phi = create_phi_node (loadedi, loop_header);
6394 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
6395 initial);
6397 else
6398 gsi_insert_before (&si,
6399 gimple_build_assign (loadedi, initial),
6400 GSI_SAME_STMT);
6401 if (loadedi != loaded_val)
6403 gimple_stmt_iterator gsi2;
6404 tree x;
6406 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
6407 gsi2 = gsi_start_bb (loop_header);
6408 if (gimple_in_ssa_p (cfun))
6410 gimple stmt;
6411 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
6412 true, GSI_SAME_STMT);
6413 stmt = gimple_build_assign (loaded_val, x);
6414 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
6416 else
6418 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
6419 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
6420 true, GSI_SAME_STMT);
6423 gsi_remove (&si, true);
6425 si = gsi_last_bb (store_bb);
6426 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
6428 if (iaddr == addr)
6429 storedi = stored_val;
6430 else
6431 storedi =
6432 force_gimple_operand_gsi (&si,
6433 build1 (VIEW_CONVERT_EXPR, itype,
6434 stored_val), true, NULL_TREE, true,
6435 GSI_SAME_STMT);
6437 /* Build the compare&swap statement. */
6438 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
6439 new_storedi = force_gimple_operand_gsi (&si,
6440 fold_convert (TREE_TYPE (loadedi),
6441 new_storedi),
6442 true, NULL_TREE,
6443 true, GSI_SAME_STMT);
6445 if (gimple_in_ssa_p (cfun))
6446 old_vali = loadedi;
6447 else
6449 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
6450 stmt = gimple_build_assign (old_vali, loadedi);
6451 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6453 stmt = gimple_build_assign (loadedi, new_storedi);
6454 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6457 /* Note that we always perform the comparison as an integer, even for
6458 floating point. This allows the atomic operation to properly
6459 succeed even with NaNs and -0.0. */
6460 stmt = gimple_build_cond_empty
6461 (build2 (NE_EXPR, boolean_type_node,
6462 new_storedi, old_vali));
6463 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6465 /* Update cfg. */
6466 e = single_succ_edge (store_bb);
6467 e->flags &= ~EDGE_FALLTHRU;
6468 e->flags |= EDGE_FALSE_VALUE;
6470 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
6472 /* Copy the new value to loadedi (we already did that before the condition
6473 if we are not in SSA). */
6474 if (gimple_in_ssa_p (cfun))
6476 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
6477 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
6480 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
6481 gsi_remove (&si, true);
6483 struct loop *loop = alloc_loop ();
6484 loop->header = loop_header;
6485 loop->latch = store_bb;
6486 add_loop (loop, loop_header->loop_father);
6488 if (gimple_in_ssa_p (cfun))
6489 update_ssa (TODO_update_ssa_no_phi);
6491 return true;
6494 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6496 GOMP_atomic_start ();
6497 *addr = rhs;
6498 GOMP_atomic_end ();
6500 The result is not globally atomic, but works so long as all parallel
6501 references are within #pragma omp atomic directives. According to
6502 responses received from omp@openmp.org, appears to be within spec.
6503 Which makes sense, since that's how several other compilers handle
6504 this situation as well.
6505 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
6506 expanding. STORED_VAL is the operand of the matching
6507 GIMPLE_OMP_ATOMIC_STORE.
6509 We replace
6510 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
6511 loaded_val = *addr;
6513 and replace
6514 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
6515 *addr = stored_val;
6518 static bool
6519 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
6520 tree addr, tree loaded_val, tree stored_val)
6522 gimple_stmt_iterator si;
6523 gimple stmt;
6524 tree t;
6526 si = gsi_last_bb (load_bb);
6527 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
6529 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
6530 t = build_call_expr (t, 0);
6531 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
6533 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
6534 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6535 gsi_remove (&si, true);
6537 si = gsi_last_bb (store_bb);
6538 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
6540 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
6541 stored_val);
6542 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6544 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
6545 t = build_call_expr (t, 0);
6546 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
6547 gsi_remove (&si, true);
6549 if (gimple_in_ssa_p (cfun))
6550 update_ssa (TODO_update_ssa_no_phi);
6551 return true;
6554 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
6555 using expand_omp_atomic_fetch_op. If it failed, we try to
6556 call expand_omp_atomic_pipeline, and if it fails too, the
6557 ultimate fallback is wrapping the operation in a mutex
6558 (expand_omp_atomic_mutex). REGION is the atomic region built
6559 by build_omp_regions_1(). */
6561 static void
6562 expand_omp_atomic (struct omp_region *region)
6564 basic_block load_bb = region->entry, store_bb = region->exit;
6565 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
6566 tree loaded_val = gimple_omp_atomic_load_lhs (load);
6567 tree addr = gimple_omp_atomic_load_rhs (load);
6568 tree stored_val = gimple_omp_atomic_store_val (store);
6569 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
6570 HOST_WIDE_INT index;
6572 /* Make sure the type is one of the supported sizes. */
6573 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
6574 index = exact_log2 (index);
6575 if (index >= 0 && index <= 4)
6577 unsigned int align = TYPE_ALIGN_UNIT (type);
6579 /* __sync builtins require strict data alignment. */
6580 if (exact_log2 (align) >= index)
6582 /* Atomic load. */
6583 if (loaded_val == stored_val
6584 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
6585 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
6586 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
6587 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
6588 return;
6590 /* Atomic store. */
6591 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
6592 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
6593 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
6594 && store_bb == single_succ (load_bb)
6595 && first_stmt (store_bb) == store
6596 && expand_omp_atomic_store (load_bb, addr, loaded_val,
6597 stored_val, index))
6598 return;
6600 /* When possible, use specialized atomic update functions. */
6601 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
6602 && store_bb == single_succ (load_bb)
6603 && expand_omp_atomic_fetch_op (load_bb, addr,
6604 loaded_val, stored_val, index))
6605 return;
6607 /* If we don't have specialized __sync builtins, try and implement
6608 as a compare and swap loop. */
6609 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
6610 loaded_val, stored_val, index))
6611 return;
6615 /* The ultimate fallback is wrapping the operation in a mutex. */
6616 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
6620 /* Expand the parallel region tree rooted at REGION. Expansion
6621 proceeds in depth-first order. Innermost regions are expanded
6622 first. This way, parallel regions that require a new function to
6623 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
6624 internal dependencies in their body. */
6626 static void
6627 expand_omp (struct omp_region *region)
6629 while (region)
6631 location_t saved_location;
6633 /* First, determine whether this is a combined parallel+workshare
6634 region. */
6635 if (region->type == GIMPLE_OMP_PARALLEL)
6636 determine_parallel_type (region);
6638 if (region->inner)
6639 expand_omp (region->inner);
6641 saved_location = input_location;
6642 if (gimple_has_location (last_stmt (region->entry)))
6643 input_location = gimple_location (last_stmt (region->entry));
6645 switch (region->type)
6647 case GIMPLE_OMP_PARALLEL:
6648 case GIMPLE_OMP_TASK:
6649 expand_omp_taskreg (region);
6650 break;
6652 case GIMPLE_OMP_FOR:
6653 expand_omp_for (region);
6654 break;
6656 case GIMPLE_OMP_SECTIONS:
6657 expand_omp_sections (region);
6658 break;
6660 case GIMPLE_OMP_SECTION:
6661 /* Individual omp sections are handled together with their
6662 parent GIMPLE_OMP_SECTIONS region. */
6663 break;
6665 case GIMPLE_OMP_SINGLE:
6666 expand_omp_single (region);
6667 break;
6669 case GIMPLE_OMP_MASTER:
6670 case GIMPLE_OMP_ORDERED:
6671 case GIMPLE_OMP_CRITICAL:
6672 expand_omp_synch (region);
6673 break;
6675 case GIMPLE_OMP_ATOMIC_LOAD:
6676 expand_omp_atomic (region);
6677 break;
6679 default:
6680 gcc_unreachable ();
6683 input_location = saved_location;
6684 region = region->next;
6689 /* Helper for build_omp_regions. Scan the dominator tree starting at
6690 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
6691 true, the function ends once a single tree is built (otherwise, whole
6692 forest of OMP constructs may be built). */
6694 static void
6695 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
6696 bool single_tree)
6698 gimple_stmt_iterator gsi;
6699 gimple stmt;
6700 basic_block son;
6702 gsi = gsi_last_bb (bb);
6703 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
6705 struct omp_region *region;
6706 enum gimple_code code;
6708 stmt = gsi_stmt (gsi);
6709 code = gimple_code (stmt);
6710 if (code == GIMPLE_OMP_RETURN)
6712 /* STMT is the return point out of region PARENT. Mark it
6713 as the exit point and make PARENT the immediately
6714 enclosing region. */
6715 gcc_assert (parent);
6716 region = parent;
6717 region->exit = bb;
6718 parent = parent->outer;
6720 else if (code == GIMPLE_OMP_ATOMIC_STORE)
6722 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
6723 GIMPLE_OMP_RETURN, but matches with
6724 GIMPLE_OMP_ATOMIC_LOAD. */
6725 gcc_assert (parent);
6726 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
6727 region = parent;
6728 region->exit = bb;
6729 parent = parent->outer;
6732 else if (code == GIMPLE_OMP_CONTINUE)
6734 gcc_assert (parent);
6735 parent->cont = bb;
6737 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
6739 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
6740 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
6743 else
6745 /* Otherwise, this directive becomes the parent for a new
6746 region. */
6747 region = new_omp_region (bb, code, parent);
6748 parent = region;
6752 if (single_tree && !parent)
6753 return;
6755 for (son = first_dom_son (CDI_DOMINATORS, bb);
6756 son;
6757 son = next_dom_son (CDI_DOMINATORS, son))
6758 build_omp_regions_1 (son, parent, single_tree);
6761 /* Builds the tree of OMP regions rooted at ROOT, storing it to
6762 root_omp_region. */
6764 static void
6765 build_omp_regions_root (basic_block root)
6767 gcc_assert (root_omp_region == NULL);
6768 build_omp_regions_1 (root, NULL, true);
6769 gcc_assert (root_omp_region != NULL);
6772 /* Expands omp construct (and its subconstructs) starting in HEAD. */
6774 void
6775 omp_expand_local (basic_block head)
6777 build_omp_regions_root (head);
6778 if (dump_file && (dump_flags & TDF_DETAILS))
6780 fprintf (dump_file, "\nOMP region tree\n\n");
6781 dump_omp_region (dump_file, root_omp_region, 0);
6782 fprintf (dump_file, "\n");
6785 remove_exit_barriers (root_omp_region);
6786 expand_omp (root_omp_region);
6788 free_omp_regions ();
6791 /* Scan the CFG and build a tree of OMP regions. Return the root of
6792 the OMP region tree. */
6794 static void
6795 build_omp_regions (void)
6797 gcc_assert (root_omp_region == NULL);
6798 calculate_dominance_info (CDI_DOMINATORS);
6799 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
6802 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
6804 static unsigned int
6805 execute_expand_omp (void)
6807 build_omp_regions ();
6809 if (!root_omp_region)
6810 return 0;
6812 if (dump_file)
6814 fprintf (dump_file, "\nOMP region tree\n\n");
6815 dump_omp_region (dump_file, root_omp_region, 0);
6816 fprintf (dump_file, "\n");
6819 remove_exit_barriers (root_omp_region);
6821 expand_omp (root_omp_region);
6823 cleanup_tree_cfg ();
6825 free_omp_regions ();
6827 return 0;
6830 /* OMP expansion -- the default pass, run before creation of SSA form. */
6832 static bool
6833 gate_expand_omp (void)
6835 return (flag_openmp != 0 && !seen_error ());
6838 namespace {
6840 const pass_data pass_data_expand_omp =
6842 GIMPLE_PASS, /* type */
6843 "ompexp", /* name */
6844 OPTGROUP_NONE, /* optinfo_flags */
6845 true, /* has_gate */
6846 true, /* has_execute */
6847 TV_NONE, /* tv_id */
6848 PROP_gimple_any, /* properties_required */
6849 0, /* properties_provided */
6850 0, /* properties_destroyed */
6851 0, /* todo_flags_start */
6852 0, /* todo_flags_finish */
6855 class pass_expand_omp : public gimple_opt_pass
6857 public:
6858 pass_expand_omp(gcc::context *ctxt)
6859 : gimple_opt_pass(pass_data_expand_omp, ctxt)
6862 /* opt_pass methods: */
6863 bool gate () { return gate_expand_omp (); }
6864 unsigned int execute () { return execute_expand_omp (); }
6866 }; // class pass_expand_omp
6868 } // anon namespace
6870 gimple_opt_pass *
6871 make_pass_expand_omp (gcc::context *ctxt)
6873 return new pass_expand_omp (ctxt);
6876 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
6878 /* Lower the OpenMP sections directive in the current statement in GSI_P.
6879 CTX is the enclosing OMP context for the current statement. */
6881 static void
6882 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6884 tree block, control;
6885 gimple_stmt_iterator tgsi;
6886 gimple stmt, new_stmt, bind, t;
6887 gimple_seq ilist, dlist, olist, new_body;
6888 struct gimplify_ctx gctx;
6890 stmt = gsi_stmt (*gsi_p);
6892 push_gimplify_context (&gctx);
6894 dlist = NULL;
6895 ilist = NULL;
6896 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
6897 &ilist, &dlist, ctx);
6899 new_body = gimple_omp_body (stmt);
6900 gimple_omp_set_body (stmt, NULL);
6901 tgsi = gsi_start (new_body);
6902 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
6904 omp_context *sctx;
6905 gimple sec_start;
6907 sec_start = gsi_stmt (tgsi);
6908 sctx = maybe_lookup_ctx (sec_start);
6909 gcc_assert (sctx);
6911 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
6912 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
6913 GSI_CONTINUE_LINKING);
6914 gimple_omp_set_body (sec_start, NULL);
6916 if (gsi_one_before_end_p (tgsi))
6918 gimple_seq l = NULL;
6919 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
6920 &l, ctx);
6921 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
6922 gimple_omp_section_set_last (sec_start);
6925 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
6926 GSI_CONTINUE_LINKING);
6929 block = make_node (BLOCK);
6930 bind = gimple_build_bind (NULL, new_body, block);
6932 olist = NULL;
6933 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
6935 block = make_node (BLOCK);
6936 new_stmt = gimple_build_bind (NULL, NULL, block);
6937 gsi_replace (gsi_p, new_stmt, true);
6939 pop_gimplify_context (new_stmt);
6940 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6941 BLOCK_VARS (block) = gimple_bind_vars (bind);
6942 if (BLOCK_VARS (block))
6943 TREE_USED (block) = 1;
6945 new_body = NULL;
6946 gimple_seq_add_seq (&new_body, ilist);
6947 gimple_seq_add_stmt (&new_body, stmt);
6948 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
6949 gimple_seq_add_stmt (&new_body, bind);
6951 control = create_tmp_var (unsigned_type_node, ".section");
6952 t = gimple_build_omp_continue (control, control);
6953 gimple_omp_sections_set_control (stmt, control);
6954 gimple_seq_add_stmt (&new_body, t);
6956 gimple_seq_add_seq (&new_body, olist);
6957 gimple_seq_add_seq (&new_body, dlist);
6959 new_body = maybe_catch_exception (new_body);
6961 t = gimple_build_omp_return
6962 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
6963 OMP_CLAUSE_NOWAIT));
6964 gimple_seq_add_stmt (&new_body, t);
6966 gimple_bind_set_body (new_stmt, new_body);
6970 /* A subroutine of lower_omp_single. Expand the simple form of
6971 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
6973 if (GOMP_single_start ())
6974 BODY;
6975 [ GOMP_barrier (); ] -> unless 'nowait' is present.
6977 FIXME. It may be better to delay expanding the logic of this until
6978 pass_expand_omp. The expanded logic may make the job more difficult
6979 to a synchronization analysis pass. */
6981 static void
6982 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
6984 location_t loc = gimple_location (single_stmt);
6985 tree tlabel = create_artificial_label (loc);
6986 tree flabel = create_artificial_label (loc);
6987 gimple call, cond;
6988 tree lhs, decl;
6990 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
6991 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
6992 call = gimple_build_call (decl, 0);
6993 gimple_call_set_lhs (call, lhs);
6994 gimple_seq_add_stmt (pre_p, call);
6996 cond = gimple_build_cond (EQ_EXPR, lhs,
6997 fold_convert_loc (loc, TREE_TYPE (lhs),
6998 boolean_true_node),
6999 tlabel, flabel);
7000 gimple_seq_add_stmt (pre_p, cond);
7001 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
7002 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
7003 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
7007 /* A subroutine of lower_omp_single. Expand the simple form of
7008 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
7010 #pragma omp single copyprivate (a, b, c)
7012 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
7015 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
7017 BODY;
7018 copyout.a = a;
7019 copyout.b = b;
7020 copyout.c = c;
7021 GOMP_single_copy_end (&copyout);
7023 else
7025 a = copyout_p->a;
7026 b = copyout_p->b;
7027 c = copyout_p->c;
7029 GOMP_barrier ();
7032 FIXME. It may be better to delay expanding the logic of this until
7033 pass_expand_omp. The expanded logic may make the job more difficult
7034 to a synchronization analysis pass. */
7036 static void
7037 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
7039 tree ptr_type, t, l0, l1, l2, bfn_decl;
7040 gimple_seq copyin_seq;
7041 location_t loc = gimple_location (single_stmt);
7043 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
7045 ptr_type = build_pointer_type (ctx->record_type);
7046 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
7048 l0 = create_artificial_label (loc);
7049 l1 = create_artificial_label (loc);
7050 l2 = create_artificial_label (loc);
7052 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
7053 t = build_call_expr_loc (loc, bfn_decl, 0);
7054 t = fold_convert_loc (loc, ptr_type, t);
7055 gimplify_assign (ctx->receiver_decl, t, pre_p);
7057 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
7058 build_int_cst (ptr_type, 0));
7059 t = build3 (COND_EXPR, void_type_node, t,
7060 build_and_jump (&l0), build_and_jump (&l1));
7061 gimplify_and_add (t, pre_p);
7063 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
7065 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
7067 copyin_seq = NULL;
7068 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
7069 &copyin_seq, ctx);
7071 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
7072 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
7073 t = build_call_expr_loc (loc, bfn_decl, 1, t);
7074 gimplify_and_add (t, pre_p);
7076 t = build_and_jump (&l2);
7077 gimplify_and_add (t, pre_p);
7079 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
7081 gimple_seq_add_seq (pre_p, copyin_seq);
7083 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
7087 /* Expand code for an OpenMP single directive. */
7089 static void
7090 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7092 tree block;
7093 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
7094 gimple_seq bind_body, dlist;
7095 struct gimplify_ctx gctx;
7097 push_gimplify_context (&gctx);
7099 block = make_node (BLOCK);
7100 bind = gimple_build_bind (NULL, NULL, block);
7101 gsi_replace (gsi_p, bind, true);
7102 bind_body = NULL;
7103 dlist = NULL;
7104 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
7105 &bind_body, &dlist, ctx);
7106 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
7108 gimple_seq_add_stmt (&bind_body, single_stmt);
7110 if (ctx->record_type)
7111 lower_omp_single_copy (single_stmt, &bind_body, ctx);
7112 else
7113 lower_omp_single_simple (single_stmt, &bind_body);
7115 gimple_omp_set_body (single_stmt, NULL);
7117 gimple_seq_add_seq (&bind_body, dlist);
7119 bind_body = maybe_catch_exception (bind_body);
7121 t = gimple_build_omp_return
7122 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
7123 OMP_CLAUSE_NOWAIT));
7124 gimple_seq_add_stmt (&bind_body, t);
7125 gimple_bind_set_body (bind, bind_body);
7127 pop_gimplify_context (bind);
7129 gimple_bind_append_vars (bind, ctx->block_vars);
7130 BLOCK_VARS (block) = ctx->block_vars;
7131 if (BLOCK_VARS (block))
7132 TREE_USED (block) = 1;
7136 /* Expand code for an OpenMP master directive. */
7138 static void
7139 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7141 tree block, lab = NULL, x, bfn_decl;
7142 gimple stmt = gsi_stmt (*gsi_p), bind;
7143 location_t loc = gimple_location (stmt);
7144 gimple_seq tseq;
7145 struct gimplify_ctx gctx;
7147 push_gimplify_context (&gctx);
7149 block = make_node (BLOCK);
7150 bind = gimple_build_bind (NULL, NULL, block);
7151 gsi_replace (gsi_p, bind, true);
7152 gimple_bind_add_stmt (bind, stmt);
7154 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7155 x = build_call_expr_loc (loc, bfn_decl, 0);
7156 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
7157 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
7158 tseq = NULL;
7159 gimplify_and_add (x, &tseq);
7160 gimple_bind_add_seq (bind, tseq);
7162 lower_omp (gimple_omp_body_ptr (stmt), ctx);
7163 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7164 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7165 gimple_omp_set_body (stmt, NULL);
7167 gimple_bind_add_stmt (bind, gimple_build_label (lab));
7169 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
7171 pop_gimplify_context (bind);
7173 gimple_bind_append_vars (bind, ctx->block_vars);
7174 BLOCK_VARS (block) = ctx->block_vars;
7178 /* Expand code for an OpenMP ordered directive. */
7180 static void
7181 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7183 tree block;
7184 gimple stmt = gsi_stmt (*gsi_p), bind, x;
7185 struct gimplify_ctx gctx;
7187 push_gimplify_context (&gctx);
7189 block = make_node (BLOCK);
7190 bind = gimple_build_bind (NULL, NULL, block);
7191 gsi_replace (gsi_p, bind, true);
7192 gimple_bind_add_stmt (bind, stmt);
7194 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
7196 gimple_bind_add_stmt (bind, x);
7198 lower_omp (gimple_omp_body_ptr (stmt), ctx);
7199 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7200 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7201 gimple_omp_set_body (stmt, NULL);
7203 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
7204 gimple_bind_add_stmt (bind, x);
7206 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
7208 pop_gimplify_context (bind);
7210 gimple_bind_append_vars (bind, ctx->block_vars);
7211 BLOCK_VARS (block) = gimple_bind_vars (bind);
7215 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
7216 substitution of a couple of function calls. But in the NAMED case,
7217 requires that languages coordinate a symbol name. It is therefore
7218 best put here in common code. */
7220 static GTY((param1_is (tree), param2_is (tree)))
7221 splay_tree critical_name_mutexes;
7223 static void
7224 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7226 tree block;
7227 tree name, lock, unlock;
7228 gimple stmt = gsi_stmt (*gsi_p), bind;
7229 location_t loc = gimple_location (stmt);
7230 gimple_seq tbody;
7231 struct gimplify_ctx gctx;
7233 name = gimple_omp_critical_name (stmt);
7234 if (name)
7236 tree decl;
7237 splay_tree_node n;
7239 if (!critical_name_mutexes)
7240 critical_name_mutexes
7241 = splay_tree_new_ggc (splay_tree_compare_pointers,
7242 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
7243 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
7245 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
7246 if (n == NULL)
7248 char *new_str;
7250 decl = create_tmp_var_raw (ptr_type_node, NULL);
7252 new_str = ACONCAT ((".gomp_critical_user_",
7253 IDENTIFIER_POINTER (name), NULL));
7254 DECL_NAME (decl) = get_identifier (new_str);
7255 TREE_PUBLIC (decl) = 1;
7256 TREE_STATIC (decl) = 1;
7257 DECL_COMMON (decl) = 1;
7258 DECL_ARTIFICIAL (decl) = 1;
7259 DECL_IGNORED_P (decl) = 1;
7260 varpool_finalize_decl (decl);
7262 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
7263 (splay_tree_value) decl);
7265 else
7266 decl = (tree) n->value;
7268 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
7269 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
7271 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
7272 unlock = build_call_expr_loc (loc, unlock, 1,
7273 build_fold_addr_expr_loc (loc, decl));
7275 else
7277 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
7278 lock = build_call_expr_loc (loc, lock, 0);
7280 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
7281 unlock = build_call_expr_loc (loc, unlock, 0);
7284 push_gimplify_context (&gctx);
7286 block = make_node (BLOCK);
7287 bind = gimple_build_bind (NULL, NULL, block);
7288 gsi_replace (gsi_p, bind, true);
7289 gimple_bind_add_stmt (bind, stmt);
7291 tbody = gimple_bind_body (bind);
7292 gimplify_and_add (lock, &tbody);
7293 gimple_bind_set_body (bind, tbody);
7295 lower_omp (gimple_omp_body_ptr (stmt), ctx);
7296 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7297 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7298 gimple_omp_set_body (stmt, NULL);
7300 tbody = gimple_bind_body (bind);
7301 gimplify_and_add (unlock, &tbody);
7302 gimple_bind_set_body (bind, tbody);
7304 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
7306 pop_gimplify_context (bind);
7307 gimple_bind_append_vars (bind, ctx->block_vars);
7308 BLOCK_VARS (block) = gimple_bind_vars (bind);
7312 /* A subroutine of lower_omp_for. Generate code to emit the predicate
7313 for a lastprivate clause. Given a loop control predicate of (V
7314 cond N2), we gate the clause on (!(V cond N2)). The lowered form
7315 is appended to *DLIST, iterator initialization is appended to
7316 *BODY_P. */
7318 static void
7319 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
7320 gimple_seq *dlist, struct omp_context *ctx)
7322 tree clauses, cond, vinit;
7323 enum tree_code cond_code;
7324 gimple_seq stmts;
7326 cond_code = fd->loop.cond_code;
7327 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
7329 /* When possible, use a strict equality expression. This can let VRP
7330 type optimizations deduce the value and remove a copy. */
7331 if (host_integerp (fd->loop.step, 0))
7333 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
7334 if (step == 1 || step == -1)
7335 cond_code = EQ_EXPR;
7338 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
7340 clauses = gimple_omp_for_clauses (fd->for_stmt);
7341 stmts = NULL;
7342 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
7343 if (!gimple_seq_empty_p (stmts))
7345 gimple_seq_add_seq (&stmts, *dlist);
7346 *dlist = stmts;
7348 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
7349 vinit = fd->loop.n1;
7350 if (cond_code == EQ_EXPR
7351 && host_integerp (fd->loop.n2, 0)
7352 && ! integer_zerop (fd->loop.n2))
7353 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
7354 else
7355 vinit = unshare_expr (vinit);
7357 /* Initialize the iterator variable, so that threads that don't execute
7358 any iterations don't execute the lastprivate clauses by accident. */
7359 gimplify_assign (fd->loop.v, vinit, body_p);
7364 /* Lower code for an OpenMP loop directive. */
7366 static void
7367 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7369 tree *rhs_p, block;
7370 struct omp_for_data fd;
7371 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
7372 gimple_seq omp_for_body, body, dlist;
7373 size_t i;
7374 struct gimplify_ctx gctx;
7376 push_gimplify_context (&gctx);
7378 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
7380 block = make_node (BLOCK);
7381 new_stmt = gimple_build_bind (NULL, NULL, block);
7382 /* Replace at gsi right away, so that 'stmt' is no member
7383 of a sequence anymore as we're going to add to to a different
7384 one below. */
7385 gsi_replace (gsi_p, new_stmt, true);
7387 /* Move declaration of temporaries in the loop body before we make
7388 it go away. */
7389 omp_for_body = gimple_omp_body (stmt);
7390 if (!gimple_seq_empty_p (omp_for_body)
7391 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
7393 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
7394 gimple_bind_append_vars (new_stmt, vars);
7397 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
7398 dlist = NULL;
7399 body = NULL;
7400 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
7401 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
7403 lower_omp (gimple_omp_body_ptr (stmt), ctx);
7405 /* Lower the header expressions. At this point, we can assume that
7406 the header is of the form:
7408 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
7410 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
7411 using the .omp_data_s mapping, if needed. */
7412 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
7414 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
7415 if (!is_gimple_min_invariant (*rhs_p))
7416 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
7418 rhs_p = gimple_omp_for_final_ptr (stmt, i);
7419 if (!is_gimple_min_invariant (*rhs_p))
7420 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
7422 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
7423 if (!is_gimple_min_invariant (*rhs_p))
7424 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
7427 /* Once lowered, extract the bounds and clauses. */
7428 extract_omp_for_data (stmt, &fd, NULL);
7430 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
7432 gimple_seq_add_stmt (&body, stmt);
7433 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
7435 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
7436 fd.loop.v));
7438 /* After the loop, add exit clauses. */
7439 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
7440 gimple_seq_add_seq (&body, dlist);
7442 body = maybe_catch_exception (body);
7444 /* Region exit marker goes at the end of the loop body. */
7445 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
7447 pop_gimplify_context (new_stmt);
7449 gimple_bind_append_vars (new_stmt, ctx->block_vars);
7450 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
7451 if (BLOCK_VARS (block))
7452 TREE_USED (block) = 1;
7454 gimple_bind_set_body (new_stmt, body);
7455 gimple_omp_set_body (stmt, NULL);
7456 gimple_omp_for_set_pre_body (stmt, NULL);
7459 /* Callback for walk_stmts. Check if the current statement only contains
7460 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
7462 static tree
7463 check_combined_parallel (gimple_stmt_iterator *gsi_p,
7464 bool *handled_ops_p,
7465 struct walk_stmt_info *wi)
7467 int *info = (int *) wi->info;
7468 gimple stmt = gsi_stmt (*gsi_p);
7470 *handled_ops_p = true;
7471 switch (gimple_code (stmt))
7473 WALK_SUBSTMTS;
7475 case GIMPLE_OMP_FOR:
7476 case GIMPLE_OMP_SECTIONS:
7477 *info = *info == 0 ? 1 : -1;
7478 break;
7479 default:
7480 *info = -1;
7481 break;
7483 return NULL;
7486 struct omp_taskcopy_context
7488 /* This field must be at the beginning, as we do "inheritance": Some
7489 callback functions for tree-inline.c (e.g., omp_copy_decl)
7490 receive a copy_body_data pointer that is up-casted to an
7491 omp_context pointer. */
7492 copy_body_data cb;
7493 omp_context *ctx;
7496 static tree
7497 task_copyfn_copy_decl (tree var, copy_body_data *cb)
7499 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
7501 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
7502 return create_tmp_var (TREE_TYPE (var), NULL);
7504 return var;
7507 static tree
7508 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
7510 tree name, new_fields = NULL, type, f;
7512 type = lang_hooks.types.make_type (RECORD_TYPE);
7513 name = DECL_NAME (TYPE_NAME (orig_type));
7514 name = build_decl (gimple_location (tcctx->ctx->stmt),
7515 TYPE_DECL, name, type);
7516 TYPE_NAME (type) = name;
7518 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
7520 tree new_f = copy_node (f);
7521 DECL_CONTEXT (new_f) = type;
7522 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
7523 TREE_CHAIN (new_f) = new_fields;
7524 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
7525 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
7526 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
7527 &tcctx->cb, NULL);
7528 new_fields = new_f;
7529 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
7531 TYPE_FIELDS (type) = nreverse (new_fields);
7532 layout_type (type);
7533 return type;
7536 /* Create task copyfn. */
7538 static void
7539 create_task_copyfn (gimple task_stmt, omp_context *ctx)
7541 struct function *child_cfun;
7542 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
7543 tree record_type, srecord_type, bind, list;
7544 bool record_needs_remap = false, srecord_needs_remap = false;
7545 splay_tree_node n;
7546 struct omp_taskcopy_context tcctx;
7547 struct gimplify_ctx gctx;
7548 location_t loc = gimple_location (task_stmt);
7550 child_fn = gimple_omp_task_copy_fn (task_stmt);
7551 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7552 gcc_assert (child_cfun->cfg == NULL);
7553 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
7555 /* Reset DECL_CONTEXT on function arguments. */
7556 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7557 DECL_CONTEXT (t) = child_fn;
7559 /* Populate the function. */
7560 push_gimplify_context (&gctx);
7561 push_cfun (child_cfun);
7563 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
7564 TREE_SIDE_EFFECTS (bind) = 1;
7565 list = NULL;
7566 DECL_SAVED_TREE (child_fn) = bind;
7567 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
7569 /* Remap src and dst argument types if needed. */
7570 record_type = ctx->record_type;
7571 srecord_type = ctx->srecord_type;
7572 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
7573 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
7575 record_needs_remap = true;
7576 break;
7578 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
7579 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
7581 srecord_needs_remap = true;
7582 break;
7585 if (record_needs_remap || srecord_needs_remap)
7587 memset (&tcctx, '\0', sizeof (tcctx));
7588 tcctx.cb.src_fn = ctx->cb.src_fn;
7589 tcctx.cb.dst_fn = child_fn;
7590 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
7591 gcc_checking_assert (tcctx.cb.src_node);
7592 tcctx.cb.dst_node = tcctx.cb.src_node;
7593 tcctx.cb.src_cfun = ctx->cb.src_cfun;
7594 tcctx.cb.copy_decl = task_copyfn_copy_decl;
7595 tcctx.cb.eh_lp_nr = 0;
7596 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
7597 tcctx.cb.decl_map = pointer_map_create ();
7598 tcctx.ctx = ctx;
7600 if (record_needs_remap)
7601 record_type = task_copyfn_remap_type (&tcctx, record_type);
7602 if (srecord_needs_remap)
7603 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
7605 else
7606 tcctx.cb.decl_map = NULL;
7608 arg = DECL_ARGUMENTS (child_fn);
7609 TREE_TYPE (arg) = build_pointer_type (record_type);
7610 sarg = DECL_CHAIN (arg);
7611 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
7613 /* First pass: initialize temporaries used in record_type and srecord_type
7614 sizes and field offsets. */
7615 if (tcctx.cb.decl_map)
7616 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
7617 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
7619 tree *p;
7621 decl = OMP_CLAUSE_DECL (c);
7622 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
7623 if (p == NULL)
7624 continue;
7625 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7626 sf = (tree) n->value;
7627 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
7628 src = build_simple_mem_ref_loc (loc, sarg);
7629 src = omp_build_component_ref (src, sf);
7630 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
7631 append_to_statement_list (t, &list);
7634 /* Second pass: copy shared var pointers and copy construct non-VLA
7635 firstprivate vars. */
7636 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
7637 switch (OMP_CLAUSE_CODE (c))
7639 case OMP_CLAUSE_SHARED:
7640 decl = OMP_CLAUSE_DECL (c);
7641 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7642 if (n == NULL)
7643 break;
7644 f = (tree) n->value;
7645 if (tcctx.cb.decl_map)
7646 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7647 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7648 sf = (tree) n->value;
7649 if (tcctx.cb.decl_map)
7650 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
7651 src = build_simple_mem_ref_loc (loc, sarg);
7652 src = omp_build_component_ref (src, sf);
7653 dst = build_simple_mem_ref_loc (loc, arg);
7654 dst = omp_build_component_ref (dst, f);
7655 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
7656 append_to_statement_list (t, &list);
7657 break;
7658 case OMP_CLAUSE_FIRSTPRIVATE:
7659 decl = OMP_CLAUSE_DECL (c);
7660 if (is_variable_sized (decl))
7661 break;
7662 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7663 if (n == NULL)
7664 break;
7665 f = (tree) n->value;
7666 if (tcctx.cb.decl_map)
7667 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7668 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7669 if (n != NULL)
7671 sf = (tree) n->value;
7672 if (tcctx.cb.decl_map)
7673 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
7674 src = build_simple_mem_ref_loc (loc, sarg);
7675 src = omp_build_component_ref (src, sf);
7676 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
7677 src = build_simple_mem_ref_loc (loc, src);
7679 else
7680 src = decl;
7681 dst = build_simple_mem_ref_loc (loc, arg);
7682 dst = omp_build_component_ref (dst, f);
7683 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
7684 append_to_statement_list (t, &list);
7685 break;
7686 case OMP_CLAUSE_PRIVATE:
7687 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
7688 break;
7689 decl = OMP_CLAUSE_DECL (c);
7690 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7691 f = (tree) n->value;
7692 if (tcctx.cb.decl_map)
7693 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7694 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7695 if (n != NULL)
7697 sf = (tree) n->value;
7698 if (tcctx.cb.decl_map)
7699 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
7700 src = build_simple_mem_ref_loc (loc, sarg);
7701 src = omp_build_component_ref (src, sf);
7702 if (use_pointer_for_field (decl, NULL))
7703 src = build_simple_mem_ref_loc (loc, src);
7705 else
7706 src = decl;
7707 dst = build_simple_mem_ref_loc (loc, arg);
7708 dst = omp_build_component_ref (dst, f);
7709 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
7710 append_to_statement_list (t, &list);
7711 break;
7712 default:
7713 break;
7716 /* Last pass: handle VLA firstprivates. */
7717 if (tcctx.cb.decl_map)
7718 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
7719 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
7721 tree ind, ptr, df;
7723 decl = OMP_CLAUSE_DECL (c);
7724 if (!is_variable_sized (decl))
7725 continue;
7726 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7727 if (n == NULL)
7728 continue;
7729 f = (tree) n->value;
7730 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7731 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
7732 ind = DECL_VALUE_EXPR (decl);
7733 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
7734 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
7735 n = splay_tree_lookup (ctx->sfield_map,
7736 (splay_tree_key) TREE_OPERAND (ind, 0));
7737 sf = (tree) n->value;
7738 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
7739 src = build_simple_mem_ref_loc (loc, sarg);
7740 src = omp_build_component_ref (src, sf);
7741 src = build_simple_mem_ref_loc (loc, src);
7742 dst = build_simple_mem_ref_loc (loc, arg);
7743 dst = omp_build_component_ref (dst, f);
7744 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
7745 append_to_statement_list (t, &list);
7746 n = splay_tree_lookup (ctx->field_map,
7747 (splay_tree_key) TREE_OPERAND (ind, 0));
7748 df = (tree) n->value;
7749 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
7750 ptr = build_simple_mem_ref_loc (loc, arg);
7751 ptr = omp_build_component_ref (ptr, df);
7752 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
7753 build_fold_addr_expr_loc (loc, dst));
7754 append_to_statement_list (t, &list);
7757 t = build1 (RETURN_EXPR, void_type_node, NULL);
7758 append_to_statement_list (t, &list);
7760 if (tcctx.cb.decl_map)
7761 pointer_map_destroy (tcctx.cb.decl_map);
7762 pop_gimplify_context (NULL);
7763 BIND_EXPR_BODY (bind) = list;
7764 pop_cfun ();
7767 /* Lower the OpenMP parallel or task directive in the current statement
7768 in GSI_P. CTX holds context information for the directive. */
7770 static void
7771 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7773 tree clauses;
7774 tree child_fn, t;
7775 gimple stmt = gsi_stmt (*gsi_p);
7776 gimple par_bind, bind;
7777 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
7778 struct gimplify_ctx gctx;
7779 location_t loc = gimple_location (stmt);
7781 clauses = gimple_omp_taskreg_clauses (stmt);
7782 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
7783 par_body = gimple_bind_body (par_bind);
7784 child_fn = ctx->cb.dst_fn;
7785 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7786 && !gimple_omp_parallel_combined_p (stmt))
7788 struct walk_stmt_info wi;
7789 int ws_num = 0;
7791 memset (&wi, 0, sizeof (wi));
7792 wi.info = &ws_num;
7793 wi.val_only = true;
7794 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
7795 if (ws_num == 1)
7796 gimple_omp_parallel_set_combined_p (stmt, true);
7798 if (ctx->srecord_type)
7799 create_task_copyfn (stmt, ctx);
7801 push_gimplify_context (&gctx);
7803 par_olist = NULL;
7804 par_ilist = NULL;
7805 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
7806 lower_omp (&par_body, ctx);
7807 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
7808 lower_reduction_clauses (clauses, &par_olist, ctx);
7810 /* Declare all the variables created by mapping and the variables
7811 declared in the scope of the parallel body. */
7812 record_vars_into (ctx->block_vars, child_fn);
7813 record_vars_into (gimple_bind_vars (par_bind), child_fn);
7815 if (ctx->record_type)
7817 ctx->sender_decl
7818 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
7819 : ctx->record_type, ".omp_data_o");
7820 DECL_NAMELESS (ctx->sender_decl) = 1;
7821 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
7822 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
7825 olist = NULL;
7826 ilist = NULL;
7827 lower_send_clauses (clauses, &ilist, &olist, ctx);
7828 lower_send_shared_vars (&ilist, &olist, ctx);
7830 /* Once all the expansions are done, sequence all the different
7831 fragments inside gimple_omp_body. */
7833 new_body = NULL;
7835 if (ctx->record_type)
7837 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
7838 /* fixup_child_record_type might have changed receiver_decl's type. */
7839 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
7840 gimple_seq_add_stmt (&new_body,
7841 gimple_build_assign (ctx->receiver_decl, t));
7844 gimple_seq_add_seq (&new_body, par_ilist);
7845 gimple_seq_add_seq (&new_body, par_body);
7846 gimple_seq_add_seq (&new_body, par_olist);
7847 new_body = maybe_catch_exception (new_body);
7848 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
7849 gimple_omp_set_body (stmt, new_body);
7851 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
7852 gsi_replace (gsi_p, bind, true);
7853 gimple_bind_add_seq (bind, ilist);
7854 gimple_bind_add_stmt (bind, stmt);
7855 gimple_bind_add_seq (bind, olist);
7857 pop_gimplify_context (NULL);
7860 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
7861 regimplified. If DATA is non-NULL, lower_omp_1 is outside
7862 of OpenMP context, but with task_shared_vars set. */
7864 static tree
7865 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
7866 void *data)
7868 tree t = *tp;
7870 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7871 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
7872 return t;
7874 if (task_shared_vars
7875 && DECL_P (t)
7876 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
7877 return t;
7879 /* If a global variable has been privatized, TREE_CONSTANT on
7880 ADDR_EXPR might be wrong. */
7881 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
7882 recompute_tree_invariant_for_addr_expr (t);
7884 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7885 return NULL_TREE;
7888 static void
7889 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
7891 gimple stmt = gsi_stmt (*gsi_p);
7892 struct walk_stmt_info wi;
7894 if (gimple_has_location (stmt))
7895 input_location = gimple_location (stmt);
7897 if (task_shared_vars)
7898 memset (&wi, '\0', sizeof (wi));
7900 /* If we have issued syntax errors, avoid doing any heavy lifting.
7901 Just replace the OpenMP directives with a NOP to avoid
7902 confusing RTL expansion. */
7903 if (seen_error () && is_gimple_omp (stmt))
7905 gsi_replace (gsi_p, gimple_build_nop (), true);
7906 return;
7909 switch (gimple_code (stmt))
7911 case GIMPLE_COND:
7912 if ((ctx || task_shared_vars)
7913 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
7914 ctx ? NULL : &wi, NULL)
7915 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
7916 ctx ? NULL : &wi, NULL)))
7917 gimple_regimplify_operands (stmt, gsi_p);
7918 break;
7919 case GIMPLE_CATCH:
7920 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
7921 break;
7922 case GIMPLE_EH_FILTER:
7923 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
7924 break;
7925 case GIMPLE_TRY:
7926 lower_omp (gimple_try_eval_ptr (stmt), ctx);
7927 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
7928 break;
7929 case GIMPLE_TRANSACTION:
7930 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
7931 break;
7932 case GIMPLE_BIND:
7933 lower_omp (gimple_bind_body_ptr (stmt), ctx);
7934 break;
7935 case GIMPLE_OMP_PARALLEL:
7936 case GIMPLE_OMP_TASK:
7937 ctx = maybe_lookup_ctx (stmt);
7938 lower_omp_taskreg (gsi_p, ctx);
7939 break;
7940 case GIMPLE_OMP_FOR:
7941 ctx = maybe_lookup_ctx (stmt);
7942 gcc_assert (ctx);
7943 lower_omp_for (gsi_p, ctx);
7944 break;
7945 case GIMPLE_OMP_SECTIONS:
7946 ctx = maybe_lookup_ctx (stmt);
7947 gcc_assert (ctx);
7948 lower_omp_sections (gsi_p, ctx);
7949 break;
7950 case GIMPLE_OMP_SINGLE:
7951 ctx = maybe_lookup_ctx (stmt);
7952 gcc_assert (ctx);
7953 lower_omp_single (gsi_p, ctx);
7954 break;
7955 case GIMPLE_OMP_MASTER:
7956 ctx = maybe_lookup_ctx (stmt);
7957 gcc_assert (ctx);
7958 lower_omp_master (gsi_p, ctx);
7959 break;
7960 case GIMPLE_OMP_ORDERED:
7961 ctx = maybe_lookup_ctx (stmt);
7962 gcc_assert (ctx);
7963 lower_omp_ordered (gsi_p, ctx);
7964 break;
7965 case GIMPLE_OMP_CRITICAL:
7966 ctx = maybe_lookup_ctx (stmt);
7967 gcc_assert (ctx);
7968 lower_omp_critical (gsi_p, ctx);
7969 break;
7970 case GIMPLE_OMP_ATOMIC_LOAD:
7971 if ((ctx || task_shared_vars)
7972 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
7973 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
7974 gimple_regimplify_operands (stmt, gsi_p);
7975 break;
7976 default:
7977 if ((ctx || task_shared_vars)
7978 && walk_gimple_op (stmt, lower_omp_regimplify_p,
7979 ctx ? NULL : &wi))
7980 gimple_regimplify_operands (stmt, gsi_p);
7981 break;
7985 static void
7986 lower_omp (gimple_seq *body, omp_context *ctx)
7988 location_t saved_location = input_location;
7989 gimple_stmt_iterator gsi;
7990 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
7991 lower_omp_1 (&gsi, ctx);
7992 input_location = saved_location;
7995 /* Main entry point. */
7997 static unsigned int
7998 execute_lower_omp (void)
8000 gimple_seq body;
8002 /* This pass always runs, to provide PROP_gimple_lomp.
8003 But there is nothing to do unless -fopenmp is given. */
8004 if (flag_openmp == 0)
8005 return 0;
8007 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
8008 delete_omp_context);
8010 body = gimple_body (current_function_decl);
8011 scan_omp (&body, NULL);
8012 gcc_assert (taskreg_nesting_level == 0);
8014 if (all_contexts->root)
8016 struct gimplify_ctx gctx;
8018 if (task_shared_vars)
8019 push_gimplify_context (&gctx);
8020 lower_omp (&body, NULL);
8021 if (task_shared_vars)
8022 pop_gimplify_context (NULL);
8025 if (all_contexts)
8027 splay_tree_delete (all_contexts);
8028 all_contexts = NULL;
8030 BITMAP_FREE (task_shared_vars);
8031 return 0;
8034 namespace {
8036 const pass_data pass_data_lower_omp =
8038 GIMPLE_PASS, /* type */
8039 "omplower", /* name */
8040 OPTGROUP_NONE, /* optinfo_flags */
8041 false, /* has_gate */
8042 true, /* has_execute */
8043 TV_NONE, /* tv_id */
8044 PROP_gimple_any, /* properties_required */
8045 PROP_gimple_lomp, /* properties_provided */
8046 0, /* properties_destroyed */
8047 0, /* todo_flags_start */
8048 0, /* todo_flags_finish */
8051 class pass_lower_omp : public gimple_opt_pass
8053 public:
8054 pass_lower_omp(gcc::context *ctxt)
8055 : gimple_opt_pass(pass_data_lower_omp, ctxt)
8058 /* opt_pass methods: */
8059 unsigned int execute () { return execute_lower_omp (); }
8061 }; // class pass_lower_omp
8063 } // anon namespace
8065 gimple_opt_pass *
8066 make_pass_lower_omp (gcc::context *ctxt)
8068 return new pass_lower_omp (ctxt);
8071 /* The following is a utility to diagnose OpenMP structured block violations.
8072 It is not part of the "omplower" pass, as that's invoked too late. It
8073 should be invoked by the respective front ends after gimplification. */
8075 static splay_tree all_labels;
8077 /* Check for mismatched contexts and generate an error if needed. Return
8078 true if an error is detected. */
8080 static bool
8081 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
8082 gimple branch_ctx, gimple label_ctx)
8084 if (label_ctx == branch_ctx)
8085 return false;
8089 Previously we kept track of the label's entire context in diagnose_sb_[12]
8090 so we could traverse it and issue a correct "exit" or "enter" error
8091 message upon a structured block violation.
8093 We built the context by building a list with tree_cons'ing, but there is
8094 no easy counterpart in gimple tuples. It seems like far too much work
8095 for issuing exit/enter error messages. If someone really misses the
8096 distinct error message... patches welcome.
8099 #if 0
8100 /* Try to avoid confusing the user by producing and error message
8101 with correct "exit" or "enter" verbiage. We prefer "exit"
8102 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
8103 if (branch_ctx == NULL)
8104 exit_p = false;
8105 else
8107 while (label_ctx)
8109 if (TREE_VALUE (label_ctx) == branch_ctx)
8111 exit_p = false;
8112 break;
8114 label_ctx = TREE_CHAIN (label_ctx);
8118 if (exit_p)
8119 error ("invalid exit from OpenMP structured block");
8120 else
8121 error ("invalid entry to OpenMP structured block");
8122 #endif
8124 /* If it's obvious we have an invalid entry, be specific about the error. */
8125 if (branch_ctx == NULL)
8126 error ("invalid entry to OpenMP structured block");
8127 else
8128 /* Otherwise, be vague and lazy, but efficient. */
8129 error ("invalid branch to/from an OpenMP structured block");
8131 gsi_replace (gsi_p, gimple_build_nop (), false);
8132 return true;
8135 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
8136 where each label is found. */
8138 static tree
8139 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
8140 struct walk_stmt_info *wi)
8142 gimple context = (gimple) wi->info;
8143 gimple inner_context;
8144 gimple stmt = gsi_stmt (*gsi_p);
8146 *handled_ops_p = true;
8148 switch (gimple_code (stmt))
8150 WALK_SUBSTMTS;
8152 case GIMPLE_OMP_PARALLEL:
8153 case GIMPLE_OMP_TASK:
8154 case GIMPLE_OMP_SECTIONS:
8155 case GIMPLE_OMP_SINGLE:
8156 case GIMPLE_OMP_SECTION:
8157 case GIMPLE_OMP_MASTER:
8158 case GIMPLE_OMP_ORDERED:
8159 case GIMPLE_OMP_CRITICAL:
8160 /* The minimal context here is just the current OMP construct. */
8161 inner_context = stmt;
8162 wi->info = inner_context;
8163 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
8164 wi->info = context;
8165 break;
8167 case GIMPLE_OMP_FOR:
8168 inner_context = stmt;
8169 wi->info = inner_context;
8170 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8171 walk them. */
8172 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
8173 diagnose_sb_1, NULL, wi);
8174 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
8175 wi->info = context;
8176 break;
8178 case GIMPLE_LABEL:
8179 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
8180 (splay_tree_value) context);
8181 break;
8183 default:
8184 break;
8187 return NULL_TREE;
8190 /* Pass 2: Check each branch and see if its context differs from that of
8191 the destination label's context. */
8193 static tree
8194 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
8195 struct walk_stmt_info *wi)
8197 gimple context = (gimple) wi->info;
8198 splay_tree_node n;
8199 gimple stmt = gsi_stmt (*gsi_p);
8201 *handled_ops_p = true;
8203 switch (gimple_code (stmt))
8205 WALK_SUBSTMTS;
8207 case GIMPLE_OMP_PARALLEL:
8208 case GIMPLE_OMP_TASK:
8209 case GIMPLE_OMP_SECTIONS:
8210 case GIMPLE_OMP_SINGLE:
8211 case GIMPLE_OMP_SECTION:
8212 case GIMPLE_OMP_MASTER:
8213 case GIMPLE_OMP_ORDERED:
8214 case GIMPLE_OMP_CRITICAL:
8215 wi->info = stmt;
8216 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
8217 wi->info = context;
8218 break;
8220 case GIMPLE_OMP_FOR:
8221 wi->info = stmt;
8222 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8223 walk them. */
8224 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
8225 diagnose_sb_2, NULL, wi);
8226 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
8227 wi->info = context;
8228 break;
8230 case GIMPLE_COND:
8232 tree lab = gimple_cond_true_label (stmt);
8233 if (lab)
8235 n = splay_tree_lookup (all_labels,
8236 (splay_tree_key) lab);
8237 diagnose_sb_0 (gsi_p, context,
8238 n ? (gimple) n->value : NULL);
8240 lab = gimple_cond_false_label (stmt);
8241 if (lab)
8243 n = splay_tree_lookup (all_labels,
8244 (splay_tree_key) lab);
8245 diagnose_sb_0 (gsi_p, context,
8246 n ? (gimple) n->value : NULL);
8249 break;
8251 case GIMPLE_GOTO:
8253 tree lab = gimple_goto_dest (stmt);
8254 if (TREE_CODE (lab) != LABEL_DECL)
8255 break;
8257 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
8258 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
8260 break;
8262 case GIMPLE_SWITCH:
8264 unsigned int i;
8265 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
8267 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
8268 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
8269 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
8270 break;
8273 break;
8275 case GIMPLE_RETURN:
8276 diagnose_sb_0 (gsi_p, context, NULL);
8277 break;
8279 default:
8280 break;
8283 return NULL_TREE;
8286 static unsigned int
8287 diagnose_omp_structured_block_errors (void)
8289 struct walk_stmt_info wi;
8290 gimple_seq body = gimple_body (current_function_decl);
8292 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
8294 memset (&wi, 0, sizeof (wi));
8295 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
8297 memset (&wi, 0, sizeof (wi));
8298 wi.want_locations = true;
8299 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
8301 gimple_set_body (current_function_decl, body);
8303 splay_tree_delete (all_labels);
8304 all_labels = NULL;
8306 return 0;
8309 static bool
8310 gate_diagnose_omp_blocks (void)
8312 return flag_openmp != 0;
8315 namespace {
8317 const pass_data pass_data_diagnose_omp_blocks =
8319 GIMPLE_PASS, /* type */
8320 "*diagnose_omp_blocks", /* name */
8321 OPTGROUP_NONE, /* optinfo_flags */
8322 true, /* has_gate */
8323 true, /* has_execute */
8324 TV_NONE, /* tv_id */
8325 PROP_gimple_any, /* properties_required */
8326 0, /* properties_provided */
8327 0, /* properties_destroyed */
8328 0, /* todo_flags_start */
8329 0, /* todo_flags_finish */
8332 class pass_diagnose_omp_blocks : public gimple_opt_pass
8334 public:
8335 pass_diagnose_omp_blocks(gcc::context *ctxt)
8336 : gimple_opt_pass(pass_data_diagnose_omp_blocks, ctxt)
8339 /* opt_pass methods: */
8340 bool gate () { return gate_diagnose_omp_blocks (); }
8341 unsigned int execute () {
8342 return diagnose_omp_structured_block_errors ();
8345 }; // class pass_diagnose_omp_blocks
8347 } // anon namespace
8349 gimple_opt_pass *
8350 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
8352 return new pass_diagnose_omp_blocks (ctxt);
8355 #include "gt-omp-low.h"