2013-10-11 Marc Glisse <marc.glisse@inria.fr>
[official-gcc.git] / gcc / omp-low.c
blob26f0c35e28596e93051f1f3f6cd8df7b248236e5
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 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
94 barriers should jump to during omplower pass. */
95 tree cancel_label;
97 /* What to do with variables with implicitly determined sharing
98 attributes. */
99 enum omp_clause_default_kind default_kind;
101 /* Nesting depth of this context. Used to beautify error messages re
102 invalid gotos. The outermost ctx is depth 1, with depth 0 being
103 reserved for the main body of the function. */
104 int depth;
106 /* True if this parallel directive is nested within another. */
107 bool is_nested;
109 /* True if this construct can be cancelled. */
110 bool cancellable;
111 } omp_context;
114 struct omp_for_data_loop
116 tree v, n1, n2, step;
117 enum tree_code cond_code;
120 /* A structure describing the main elements of a parallel loop. */
122 struct omp_for_data
124 struct omp_for_data_loop loop;
125 tree chunk_size;
126 gimple for_stmt;
127 tree pre, iter_type;
128 int collapse;
129 bool have_nowait, have_ordered;
130 enum omp_clause_schedule_kind sched_kind;
131 struct omp_for_data_loop *loops;
135 static splay_tree all_contexts;
136 static int taskreg_nesting_level;
137 static int target_nesting_level;
138 struct omp_region *root_omp_region;
139 static bitmap task_shared_vars;
141 static void scan_omp (gimple_seq *, omp_context *);
142 static tree scan_omp_1_op (tree *, int *, void *);
144 #define WALK_SUBSTMTS \
145 case GIMPLE_BIND: \
146 case GIMPLE_TRY: \
147 case GIMPLE_CATCH: \
148 case GIMPLE_EH_FILTER: \
149 case GIMPLE_TRANSACTION: \
150 /* The sub-statements for these should be walked. */ \
151 *handled_ops_p = false; \
152 break;
154 /* Convenience function for calling scan_omp_1_op on tree operands. */
156 static inline tree
157 scan_omp_op (tree *tp, omp_context *ctx)
159 struct walk_stmt_info wi;
161 memset (&wi, 0, sizeof (wi));
162 wi.info = ctx;
163 wi.want_locations = true;
165 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
168 static void lower_omp (gimple_seq *, omp_context *);
169 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
170 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
172 /* Find an OpenMP clause of type KIND within CLAUSES. */
174 tree
175 find_omp_clause (tree clauses, enum omp_clause_code kind)
177 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
178 if (OMP_CLAUSE_CODE (clauses) == kind)
179 return clauses;
181 return NULL_TREE;
184 /* Return true if CTX is for an omp parallel. */
186 static inline bool
187 is_parallel_ctx (omp_context *ctx)
189 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
193 /* Return true if CTX is for an omp task. */
195 static inline bool
196 is_task_ctx (omp_context *ctx)
198 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
202 /* Return true if CTX is for an omp parallel or omp task. */
204 static inline bool
205 is_taskreg_ctx (omp_context *ctx)
207 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
208 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
212 /* Return true if REGION is a combined parallel+workshare region. */
214 static inline bool
215 is_combined_parallel (struct omp_region *region)
217 return region->is_combined_parallel;
221 /* Extract the header elements of parallel loop FOR_STMT and store
222 them into *FD. */
224 static void
225 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
226 struct omp_for_data_loop *loops)
228 tree t, var, *collapse_iter, *collapse_count;
229 tree count = NULL_TREE, iter_type = long_integer_type_node;
230 struct omp_for_data_loop *loop;
231 int i;
232 struct omp_for_data_loop dummy_loop;
233 location_t loc = gimple_location (for_stmt);
234 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
235 bool distribute = gimple_omp_for_kind (for_stmt)
236 == GF_OMP_FOR_KIND_DISTRIBUTE;
238 fd->for_stmt = for_stmt;
239 fd->pre = NULL;
240 fd->collapse = gimple_omp_for_collapse (for_stmt);
241 if (fd->collapse > 1)
242 fd->loops = loops;
243 else
244 fd->loops = &fd->loop;
246 fd->have_nowait = distribute || simd;
247 fd->have_ordered = false;
248 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
249 fd->chunk_size = NULL_TREE;
250 collapse_iter = NULL;
251 collapse_count = NULL;
253 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
254 switch (OMP_CLAUSE_CODE (t))
256 case OMP_CLAUSE_NOWAIT:
257 fd->have_nowait = true;
258 break;
259 case OMP_CLAUSE_ORDERED:
260 fd->have_ordered = true;
261 break;
262 case OMP_CLAUSE_SCHEDULE:
263 gcc_assert (!distribute);
264 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
265 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
266 break;
267 case OMP_CLAUSE_DIST_SCHEDULE:
268 gcc_assert (distribute);
269 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
270 break;
271 case OMP_CLAUSE_COLLAPSE:
272 if (fd->collapse > 1)
274 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
275 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
277 default:
278 break;
281 /* FIXME: for now map schedule(auto) to schedule(static).
282 There should be analysis to determine whether all iterations
283 are approximately the same amount of work (then schedule(static)
284 is best) or if it varies (then schedule(dynamic,N) is better). */
285 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
287 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
288 gcc_assert (fd->chunk_size == NULL);
290 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
291 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
292 gcc_assert (fd->chunk_size == NULL);
293 else if (fd->chunk_size == NULL)
295 /* We only need to compute a default chunk size for ordered
296 static loops and dynamic loops. */
297 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
298 || fd->have_ordered)
299 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
300 ? integer_zero_node : integer_one_node;
303 for (i = 0; i < fd->collapse; i++)
305 if (fd->collapse == 1)
306 loop = &fd->loop;
307 else if (loops != NULL)
308 loop = loops + i;
309 else
310 loop = &dummy_loop;
312 loop->v = gimple_omp_for_index (for_stmt, i);
313 gcc_assert (SSA_VAR_P (loop->v));
314 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
315 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
316 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
317 loop->n1 = gimple_omp_for_initial (for_stmt, i);
319 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
320 loop->n2 = gimple_omp_for_final (for_stmt, i);
321 switch (loop->cond_code)
323 case LT_EXPR:
324 case GT_EXPR:
325 break;
326 case LE_EXPR:
327 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
328 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
329 else
330 loop->n2 = fold_build2_loc (loc,
331 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
332 build_int_cst (TREE_TYPE (loop->n2), 1));
333 loop->cond_code = LT_EXPR;
334 break;
335 case GE_EXPR:
336 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
337 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
338 else
339 loop->n2 = fold_build2_loc (loc,
340 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
341 build_int_cst (TREE_TYPE (loop->n2), 1));
342 loop->cond_code = GT_EXPR;
343 break;
344 default:
345 gcc_unreachable ();
348 t = gimple_omp_for_incr (for_stmt, i);
349 gcc_assert (TREE_OPERAND (t, 0) == var);
350 switch (TREE_CODE (t))
352 case PLUS_EXPR:
353 loop->step = TREE_OPERAND (t, 1);
354 break;
355 case POINTER_PLUS_EXPR:
356 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
357 break;
358 case MINUS_EXPR:
359 loop->step = TREE_OPERAND (t, 1);
360 loop->step = fold_build1_loc (loc,
361 NEGATE_EXPR, TREE_TYPE (loop->step),
362 loop->step);
363 break;
364 default:
365 gcc_unreachable ();
368 if (simd
369 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
370 && !fd->have_ordered))
372 if (fd->collapse == 1)
373 iter_type = TREE_TYPE (loop->v);
374 else if (i == 0
375 || TYPE_PRECISION (iter_type)
376 < TYPE_PRECISION (TREE_TYPE (loop->v)))
377 iter_type
378 = build_nonstandard_integer_type
379 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
381 else if (iter_type != long_long_unsigned_type_node)
383 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
384 iter_type = long_long_unsigned_type_node;
385 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
386 && TYPE_PRECISION (TREE_TYPE (loop->v))
387 >= TYPE_PRECISION (iter_type))
389 tree n;
391 if (loop->cond_code == LT_EXPR)
392 n = fold_build2_loc (loc,
393 PLUS_EXPR, TREE_TYPE (loop->v),
394 loop->n2, loop->step);
395 else
396 n = loop->n1;
397 if (TREE_CODE (n) != INTEGER_CST
398 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
399 iter_type = long_long_unsigned_type_node;
401 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
402 > TYPE_PRECISION (iter_type))
404 tree n1, n2;
406 if (loop->cond_code == LT_EXPR)
408 n1 = loop->n1;
409 n2 = fold_build2_loc (loc,
410 PLUS_EXPR, TREE_TYPE (loop->v),
411 loop->n2, loop->step);
413 else
415 n1 = fold_build2_loc (loc,
416 MINUS_EXPR, TREE_TYPE (loop->v),
417 loop->n2, loop->step);
418 n2 = loop->n1;
420 if (TREE_CODE (n1) != INTEGER_CST
421 || TREE_CODE (n2) != INTEGER_CST
422 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
423 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
424 iter_type = long_long_unsigned_type_node;
428 if (collapse_count && *collapse_count == NULL)
430 t = fold_binary (loop->cond_code, boolean_type_node,
431 fold_convert (TREE_TYPE (loop->v), loop->n1),
432 fold_convert (TREE_TYPE (loop->v), loop->n2));
433 if (t && integer_zerop (t))
434 count = build_zero_cst (long_long_unsigned_type_node);
435 else if ((i == 0 || count != NULL_TREE)
436 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
437 && TREE_CONSTANT (loop->n1)
438 && TREE_CONSTANT (loop->n2)
439 && TREE_CODE (loop->step) == INTEGER_CST)
441 tree itype = TREE_TYPE (loop->v);
443 if (POINTER_TYPE_P (itype))
444 itype = signed_type_for (itype);
445 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
446 t = fold_build2_loc (loc,
447 PLUS_EXPR, itype,
448 fold_convert_loc (loc, itype, loop->step), t);
449 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
450 fold_convert_loc (loc, itype, loop->n2));
451 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
452 fold_convert_loc (loc, itype, loop->n1));
453 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
454 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
455 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
456 fold_build1_loc (loc, NEGATE_EXPR, itype,
457 fold_convert_loc (loc, itype,
458 loop->step)));
459 else
460 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
461 fold_convert_loc (loc, itype, loop->step));
462 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
463 if (count != NULL_TREE)
464 count = fold_build2_loc (loc,
465 MULT_EXPR, long_long_unsigned_type_node,
466 count, t);
467 else
468 count = t;
469 if (TREE_CODE (count) != INTEGER_CST)
470 count = NULL_TREE;
472 else if (count && !integer_zerop (count))
473 count = NULL_TREE;
477 if (count
478 && !simd
479 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
480 || fd->have_ordered))
482 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
483 iter_type = long_long_unsigned_type_node;
484 else
485 iter_type = long_integer_type_node;
487 else if (collapse_iter && *collapse_iter != NULL)
488 iter_type = TREE_TYPE (*collapse_iter);
489 fd->iter_type = iter_type;
490 if (collapse_iter && *collapse_iter == NULL)
491 *collapse_iter = create_tmp_var (iter_type, ".iter");
492 if (collapse_count && *collapse_count == NULL)
494 if (count)
495 *collapse_count = fold_convert_loc (loc, iter_type, count);
496 else
497 *collapse_count = create_tmp_var (iter_type, ".count");
500 if (fd->collapse > 1)
502 fd->loop.v = *collapse_iter;
503 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
504 fd->loop.n2 = *collapse_count;
505 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
506 fd->loop.cond_code = LT_EXPR;
511 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
512 is the immediate dominator of PAR_ENTRY_BB, return true if there
513 are no data dependencies that would prevent expanding the parallel
514 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
516 When expanding a combined parallel+workshare region, the call to
517 the child function may need additional arguments in the case of
518 GIMPLE_OMP_FOR regions. In some cases, these arguments are
519 computed out of variables passed in from the parent to the child
520 via 'struct .omp_data_s'. For instance:
522 #pragma omp parallel for schedule (guided, i * 4)
523 for (j ...)
525 Is lowered into:
527 # BLOCK 2 (PAR_ENTRY_BB)
528 .omp_data_o.i = i;
529 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
531 # BLOCK 3 (WS_ENTRY_BB)
532 .omp_data_i = &.omp_data_o;
533 D.1667 = .omp_data_i->i;
534 D.1598 = D.1667 * 4;
535 #pragma omp for schedule (guided, D.1598)
537 When we outline the parallel region, the call to the child function
538 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
539 that value is computed *after* the call site. So, in principle we
540 cannot do the transformation.
542 To see whether the code in WS_ENTRY_BB blocks the combined
543 parallel+workshare call, we collect all the variables used in the
544 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
545 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
546 call.
548 FIXME. If we had the SSA form built at this point, we could merely
549 hoist the code in block 3 into block 2 and be done with it. But at
550 this point we don't have dataflow information and though we could
551 hack something up here, it is really not worth the aggravation. */
553 static bool
554 workshare_safe_to_combine_p (basic_block ws_entry_bb)
556 struct omp_for_data fd;
557 gimple ws_stmt = last_stmt (ws_entry_bb);
559 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
560 return true;
562 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
564 extract_omp_for_data (ws_stmt, &fd, NULL);
566 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
567 return false;
568 if (fd.iter_type != long_integer_type_node)
569 return false;
571 /* FIXME. We give up too easily here. If any of these arguments
572 are not constants, they will likely involve variables that have
573 been mapped into fields of .omp_data_s for sharing with the child
574 function. With appropriate data flow, it would be possible to
575 see through this. */
576 if (!is_gimple_min_invariant (fd.loop.n1)
577 || !is_gimple_min_invariant (fd.loop.n2)
578 || !is_gimple_min_invariant (fd.loop.step)
579 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
580 return false;
582 return true;
586 /* Collect additional arguments needed to emit a combined
587 parallel+workshare call. WS_STMT is the workshare directive being
588 expanded. */
590 static vec<tree, va_gc> *
591 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
593 tree t;
594 location_t loc = gimple_location (ws_stmt);
595 vec<tree, va_gc> *ws_args;
597 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
599 struct omp_for_data fd;
600 tree n1, n2;
602 extract_omp_for_data (ws_stmt, &fd, NULL);
603 n1 = fd.loop.n1;
604 n2 = fd.loop.n2;
606 if (gimple_omp_for_combined_into_p (ws_stmt))
608 tree innerc
609 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
610 OMP_CLAUSE__LOOPTEMP_);
611 gcc_assert (innerc);
612 n1 = OMP_CLAUSE_DECL (innerc);
613 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
614 OMP_CLAUSE__LOOPTEMP_);
615 gcc_assert (innerc);
616 n2 = OMP_CLAUSE_DECL (innerc);
619 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
621 t = fold_convert_loc (loc, long_integer_type_node, n1);
622 ws_args->quick_push (t);
624 t = fold_convert_loc (loc, long_integer_type_node, n2);
625 ws_args->quick_push (t);
627 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
628 ws_args->quick_push (t);
630 if (fd.chunk_size)
632 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
633 ws_args->quick_push (t);
636 return ws_args;
638 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
640 /* Number of sections is equal to the number of edges from the
641 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
642 the exit of the sections region. */
643 basic_block bb = single_succ (gimple_bb (ws_stmt));
644 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
645 vec_alloc (ws_args, 1);
646 ws_args->quick_push (t);
647 return ws_args;
650 gcc_unreachable ();
654 /* Discover whether REGION is a combined parallel+workshare region. */
656 static void
657 determine_parallel_type (struct omp_region *region)
659 basic_block par_entry_bb, par_exit_bb;
660 basic_block ws_entry_bb, ws_exit_bb;
662 if (region == NULL || region->inner == NULL
663 || region->exit == NULL || region->inner->exit == NULL
664 || region->inner->cont == NULL)
665 return;
667 /* We only support parallel+for and parallel+sections. */
668 if (region->type != GIMPLE_OMP_PARALLEL
669 || (region->inner->type != GIMPLE_OMP_FOR
670 && region->inner->type != GIMPLE_OMP_SECTIONS))
671 return;
673 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
674 WS_EXIT_BB -> PAR_EXIT_BB. */
675 par_entry_bb = region->entry;
676 par_exit_bb = region->exit;
677 ws_entry_bb = region->inner->entry;
678 ws_exit_bb = region->inner->exit;
680 if (single_succ (par_entry_bb) == ws_entry_bb
681 && single_succ (ws_exit_bb) == par_exit_bb
682 && workshare_safe_to_combine_p (ws_entry_bb)
683 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
684 || (last_and_only_stmt (ws_entry_bb)
685 && last_and_only_stmt (par_exit_bb))))
687 gimple par_stmt = last_stmt (par_entry_bb);
688 gimple ws_stmt = last_stmt (ws_entry_bb);
690 if (region->inner->type == GIMPLE_OMP_FOR)
692 /* If this is a combined parallel loop, we need to determine
693 whether or not to use the combined library calls. There
694 are two cases where we do not apply the transformation:
695 static loops and any kind of ordered loop. In the first
696 case, we already open code the loop so there is no need
697 to do anything else. In the latter case, the combined
698 parallel loop call would still need extra synchronization
699 to implement ordered semantics, so there would not be any
700 gain in using the combined call. */
701 tree clauses = gimple_omp_for_clauses (ws_stmt);
702 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
703 if (c == NULL
704 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
705 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
707 region->is_combined_parallel = false;
708 region->inner->is_combined_parallel = false;
709 return;
713 region->is_combined_parallel = true;
714 region->inner->is_combined_parallel = true;
715 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
720 /* Return true if EXPR is variable sized. */
722 static inline bool
723 is_variable_sized (const_tree expr)
725 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
728 /* Return true if DECL is a reference type. */
730 static inline bool
731 is_reference (tree decl)
733 return lang_hooks.decls.omp_privatize_by_reference (decl);
736 /* Lookup variables in the decl or field splay trees. The "maybe" form
737 allows for the variable form to not have been entered, otherwise we
738 assert that the variable must have been entered. */
740 static inline tree
741 lookup_decl (tree var, omp_context *ctx)
743 tree *n;
744 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
745 return *n;
748 static inline tree
749 maybe_lookup_decl (const_tree var, omp_context *ctx)
751 tree *n;
752 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
753 return n ? *n : NULL_TREE;
756 static inline tree
757 lookup_field (tree var, omp_context *ctx)
759 splay_tree_node n;
760 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
761 return (tree) n->value;
764 static inline tree
765 lookup_sfield (tree var, omp_context *ctx)
767 splay_tree_node n;
768 n = splay_tree_lookup (ctx->sfield_map
769 ? ctx->sfield_map : ctx->field_map,
770 (splay_tree_key) var);
771 return (tree) n->value;
774 static inline tree
775 maybe_lookup_field (tree var, omp_context *ctx)
777 splay_tree_node n;
778 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
779 return n ? (tree) n->value : NULL_TREE;
782 /* Return true if DECL should be copied by pointer. SHARED_CTX is
783 the parallel context if DECL is to be shared. */
785 static bool
786 use_pointer_for_field (tree decl, omp_context *shared_ctx)
788 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
789 return true;
791 /* We can only use copy-in/copy-out semantics for shared variables
792 when we know the value is not accessible from an outer scope. */
793 if (shared_ctx)
795 /* ??? Trivially accessible from anywhere. But why would we even
796 be passing an address in this case? Should we simply assert
797 this to be false, or should we have a cleanup pass that removes
798 these from the list of mappings? */
799 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
800 return true;
802 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
803 without analyzing the expression whether or not its location
804 is accessible to anyone else. In the case of nested parallel
805 regions it certainly may be. */
806 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
807 return true;
809 /* Do not use copy-in/copy-out for variables that have their
810 address taken. */
811 if (TREE_ADDRESSABLE (decl))
812 return true;
814 /* lower_send_shared_vars only uses copy-in, but not copy-out
815 for these. */
816 if (TREE_READONLY (decl)
817 || ((TREE_CODE (decl) == RESULT_DECL
818 || TREE_CODE (decl) == PARM_DECL)
819 && DECL_BY_REFERENCE (decl)))
820 return false;
822 /* Disallow copy-in/out in nested parallel if
823 decl is shared in outer parallel, otherwise
824 each thread could store the shared variable
825 in its own copy-in location, making the
826 variable no longer really shared. */
827 if (shared_ctx->is_nested)
829 omp_context *up;
831 for (up = shared_ctx->outer; up; up = up->outer)
832 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
833 break;
835 if (up)
837 tree c;
839 for (c = gimple_omp_taskreg_clauses (up->stmt);
840 c; c = OMP_CLAUSE_CHAIN (c))
841 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
842 && OMP_CLAUSE_DECL (c) == decl)
843 break;
845 if (c)
846 goto maybe_mark_addressable_and_ret;
850 /* For tasks avoid using copy-in/out. As tasks can be
851 deferred or executed in different thread, when GOMP_task
852 returns, the task hasn't necessarily terminated. */
853 if (is_task_ctx (shared_ctx))
855 tree outer;
856 maybe_mark_addressable_and_ret:
857 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
858 if (is_gimple_reg (outer))
860 /* Taking address of OUTER in lower_send_shared_vars
861 might need regimplification of everything that uses the
862 variable. */
863 if (!task_shared_vars)
864 task_shared_vars = BITMAP_ALLOC (NULL);
865 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
866 TREE_ADDRESSABLE (outer) = 1;
868 return true;
872 return false;
875 /* Create a new VAR_DECL and copy information from VAR to it. */
877 tree
878 copy_var_decl (tree var, tree name, tree type)
880 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
882 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
883 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
884 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
885 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
886 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
887 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
888 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
889 TREE_USED (copy) = 1;
890 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
891 DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
893 return copy;
896 /* Construct a new automatic decl similar to VAR. */
898 static tree
899 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
901 tree copy = copy_var_decl (var, name, type);
903 DECL_CONTEXT (copy) = current_function_decl;
904 DECL_CHAIN (copy) = ctx->block_vars;
905 ctx->block_vars = copy;
907 return copy;
910 static tree
911 omp_copy_decl_1 (tree var, omp_context *ctx)
913 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
916 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
917 as appropriate. */
918 static tree
919 omp_build_component_ref (tree obj, tree field)
921 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
922 if (TREE_THIS_VOLATILE (field))
923 TREE_THIS_VOLATILE (ret) |= 1;
924 if (TREE_READONLY (field))
925 TREE_READONLY (ret) |= 1;
926 return ret;
929 /* Build tree nodes to access the field for VAR on the receiver side. */
931 static tree
932 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
934 tree x, field = lookup_field (var, ctx);
936 /* If the receiver record type was remapped in the child function,
937 remap the field into the new record type. */
938 x = maybe_lookup_field (field, ctx);
939 if (x != NULL)
940 field = x;
942 x = build_simple_mem_ref (ctx->receiver_decl);
943 x = omp_build_component_ref (x, field);
944 if (by_ref)
945 x = build_simple_mem_ref (x);
947 return x;
950 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
951 of a parallel, this is a component reference; for workshare constructs
952 this is some variable. */
954 static tree
955 build_outer_var_ref (tree var, omp_context *ctx)
957 tree x;
959 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
960 x = var;
961 else if (is_variable_sized (var))
963 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
964 x = build_outer_var_ref (x, ctx);
965 x = build_simple_mem_ref (x);
967 else if (is_taskreg_ctx (ctx))
969 bool by_ref = use_pointer_for_field (var, NULL);
970 x = build_receiver_ref (var, by_ref, ctx);
972 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
973 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
975 /* #pragma omp simd isn't a worksharing construct, and can reference even
976 private vars in its linear etc. clauses. */
977 x = NULL_TREE;
978 if (ctx->outer && is_taskreg_ctx (ctx))
979 x = lookup_decl (var, ctx->outer);
980 else if (ctx->outer)
981 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
982 if (x == NULL_TREE)
983 x = var;
985 else if (ctx->outer)
986 x = lookup_decl (var, ctx->outer);
987 else if (is_reference (var))
988 /* This can happen with orphaned constructs. If var is reference, it is
989 possible it is shared and as such valid. */
990 x = var;
991 else
992 gcc_unreachable ();
994 if (is_reference (var))
995 x = build_simple_mem_ref (x);
997 return x;
1000 /* Build tree nodes to access the field for VAR on the sender side. */
1002 static tree
1003 build_sender_ref (tree var, omp_context *ctx)
1005 tree field = lookup_sfield (var, ctx);
1006 return omp_build_component_ref (ctx->sender_decl, field);
1009 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1011 static void
1012 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1014 tree field, type, sfield = NULL_TREE;
1016 gcc_assert ((mask & 1) == 0
1017 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1018 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1019 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1021 type = TREE_TYPE (var);
1022 if (mask & 4)
1024 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1025 type = build_pointer_type (build_pointer_type (type));
1027 else if (by_ref)
1028 type = build_pointer_type (type);
1029 else if ((mask & 3) == 1 && is_reference (var))
1030 type = TREE_TYPE (type);
1032 field = build_decl (DECL_SOURCE_LOCATION (var),
1033 FIELD_DECL, DECL_NAME (var), type);
1035 /* Remember what variable this field was created for. This does have a
1036 side effect of making dwarf2out ignore this member, so for helpful
1037 debugging we clear it later in delete_omp_context. */
1038 DECL_ABSTRACT_ORIGIN (field) = var;
1039 if (type == TREE_TYPE (var))
1041 DECL_ALIGN (field) = DECL_ALIGN (var);
1042 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1043 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1045 else
1046 DECL_ALIGN (field) = TYPE_ALIGN (type);
1048 if ((mask & 3) == 3)
1050 insert_field_into_struct (ctx->record_type, field);
1051 if (ctx->srecord_type)
1053 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1054 FIELD_DECL, DECL_NAME (var), type);
1055 DECL_ABSTRACT_ORIGIN (sfield) = var;
1056 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1057 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1058 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1059 insert_field_into_struct (ctx->srecord_type, sfield);
1062 else
1064 if (ctx->srecord_type == NULL_TREE)
1066 tree t;
1068 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1069 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1070 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1072 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1073 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1074 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1075 insert_field_into_struct (ctx->srecord_type, sfield);
1076 splay_tree_insert (ctx->sfield_map,
1077 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1078 (splay_tree_value) sfield);
1081 sfield = field;
1082 insert_field_into_struct ((mask & 1) ? ctx->record_type
1083 : ctx->srecord_type, field);
1086 if (mask & 1)
1087 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1088 (splay_tree_value) field);
1089 if ((mask & 2) && ctx->sfield_map)
1090 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1091 (splay_tree_value) sfield);
1094 static tree
1095 install_var_local (tree var, omp_context *ctx)
1097 tree new_var = omp_copy_decl_1 (var, ctx);
1098 insert_decl_map (&ctx->cb, var, new_var);
1099 return new_var;
1102 /* Adjust the replacement for DECL in CTX for the new context. This means
1103 copying the DECL_VALUE_EXPR, and fixing up the type. */
1105 static void
1106 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1108 tree new_decl, size;
1110 new_decl = lookup_decl (decl, ctx);
1112 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1114 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1115 && DECL_HAS_VALUE_EXPR_P (decl))
1117 tree ve = DECL_VALUE_EXPR (decl);
1118 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1119 SET_DECL_VALUE_EXPR (new_decl, ve);
1120 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1123 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1125 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1126 if (size == error_mark_node)
1127 size = TYPE_SIZE (TREE_TYPE (new_decl));
1128 DECL_SIZE (new_decl) = size;
1130 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1131 if (size == error_mark_node)
1132 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1133 DECL_SIZE_UNIT (new_decl) = size;
1137 /* The callback for remap_decl. Search all containing contexts for a
1138 mapping of the variable; this avoids having to duplicate the splay
1139 tree ahead of time. We know a mapping doesn't already exist in the
1140 given context. Create new mappings to implement default semantics. */
1142 static tree
1143 omp_copy_decl (tree var, copy_body_data *cb)
1145 omp_context *ctx = (omp_context *) cb;
1146 tree new_var;
1148 if (TREE_CODE (var) == LABEL_DECL)
1150 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1151 DECL_CONTEXT (new_var) = current_function_decl;
1152 insert_decl_map (&ctx->cb, var, new_var);
1153 return new_var;
1156 while (!is_taskreg_ctx (ctx))
1158 ctx = ctx->outer;
1159 if (ctx == NULL)
1160 return var;
1161 new_var = maybe_lookup_decl (var, ctx);
1162 if (new_var)
1163 return new_var;
1166 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1167 return var;
1169 return error_mark_node;
1173 /* Return the parallel region associated with STMT. */
1175 /* Debugging dumps for parallel regions. */
1176 void dump_omp_region (FILE *, struct omp_region *, int);
1177 void debug_omp_region (struct omp_region *);
1178 void debug_all_omp_regions (void);
1180 /* Dump the parallel region tree rooted at REGION. */
1182 void
1183 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1185 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1186 gimple_code_name[region->type]);
1188 if (region->inner)
1189 dump_omp_region (file, region->inner, indent + 4);
1191 if (region->cont)
1193 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1194 region->cont->index);
1197 if (region->exit)
1198 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1199 region->exit->index);
1200 else
1201 fprintf (file, "%*s[no exit marker]\n", indent, "");
1203 if (region->next)
1204 dump_omp_region (file, region->next, indent);
1207 DEBUG_FUNCTION void
1208 debug_omp_region (struct omp_region *region)
1210 dump_omp_region (stderr, region, 0);
1213 DEBUG_FUNCTION void
1214 debug_all_omp_regions (void)
1216 dump_omp_region (stderr, root_omp_region, 0);
1220 /* Create a new parallel region starting at STMT inside region PARENT. */
1222 struct omp_region *
1223 new_omp_region (basic_block bb, enum gimple_code type,
1224 struct omp_region *parent)
1226 struct omp_region *region = XCNEW (struct omp_region);
1228 region->outer = parent;
1229 region->entry = bb;
1230 region->type = type;
1232 if (parent)
1234 /* This is a nested region. Add it to the list of inner
1235 regions in PARENT. */
1236 region->next = parent->inner;
1237 parent->inner = region;
1239 else
1241 /* This is a toplevel region. Add it to the list of toplevel
1242 regions in ROOT_OMP_REGION. */
1243 region->next = root_omp_region;
1244 root_omp_region = region;
1247 return region;
1250 /* Release the memory associated with the region tree rooted at REGION. */
1252 static void
1253 free_omp_region_1 (struct omp_region *region)
1255 struct omp_region *i, *n;
1257 for (i = region->inner; i ; i = n)
1259 n = i->next;
1260 free_omp_region_1 (i);
1263 free (region);
1266 /* Release the memory for the entire omp region tree. */
1268 void
1269 free_omp_regions (void)
1271 struct omp_region *r, *n;
1272 for (r = root_omp_region; r ; r = n)
1274 n = r->next;
1275 free_omp_region_1 (r);
1277 root_omp_region = NULL;
1281 /* Create a new context, with OUTER_CTX being the surrounding context. */
1283 static omp_context *
1284 new_omp_context (gimple stmt, omp_context *outer_ctx)
1286 omp_context *ctx = XCNEW (omp_context);
1288 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1289 (splay_tree_value) ctx);
1290 ctx->stmt = stmt;
1292 if (outer_ctx)
1294 ctx->outer = outer_ctx;
1295 ctx->cb = outer_ctx->cb;
1296 ctx->cb.block = NULL;
1297 ctx->depth = outer_ctx->depth + 1;
1299 else
1301 ctx->cb.src_fn = current_function_decl;
1302 ctx->cb.dst_fn = current_function_decl;
1303 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1304 gcc_checking_assert (ctx->cb.src_node);
1305 ctx->cb.dst_node = ctx->cb.src_node;
1306 ctx->cb.src_cfun = cfun;
1307 ctx->cb.copy_decl = omp_copy_decl;
1308 ctx->cb.eh_lp_nr = 0;
1309 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1310 ctx->depth = 1;
1313 ctx->cb.decl_map = pointer_map_create ();
1315 return ctx;
1318 static gimple_seq maybe_catch_exception (gimple_seq);
1320 /* Finalize task copyfn. */
1322 static void
1323 finalize_task_copyfn (gimple task_stmt)
1325 struct function *child_cfun;
1326 tree child_fn;
1327 gimple_seq seq = NULL, new_seq;
1328 gimple bind;
1330 child_fn = gimple_omp_task_copy_fn (task_stmt);
1331 if (child_fn == NULL_TREE)
1332 return;
1334 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1335 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1337 push_cfun (child_cfun);
1338 bind = gimplify_body (child_fn, false);
1339 gimple_seq_add_stmt (&seq, bind);
1340 new_seq = maybe_catch_exception (seq);
1341 if (new_seq != seq)
1343 bind = gimple_build_bind (NULL, new_seq, NULL);
1344 seq = NULL;
1345 gimple_seq_add_stmt (&seq, bind);
1347 gimple_set_body (child_fn, seq);
1348 pop_cfun ();
1350 /* Inform the callgraph about the new function. */
1351 cgraph_add_new_function (child_fn, false);
1354 /* Destroy a omp_context data structures. Called through the splay tree
1355 value delete callback. */
1357 static void
1358 delete_omp_context (splay_tree_value value)
1360 omp_context *ctx = (omp_context *) value;
1362 pointer_map_destroy (ctx->cb.decl_map);
1364 if (ctx->field_map)
1365 splay_tree_delete (ctx->field_map);
1366 if (ctx->sfield_map)
1367 splay_tree_delete (ctx->sfield_map);
1369 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1370 it produces corrupt debug information. */
1371 if (ctx->record_type)
1373 tree t;
1374 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1375 DECL_ABSTRACT_ORIGIN (t) = NULL;
1377 if (ctx->srecord_type)
1379 tree t;
1380 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1381 DECL_ABSTRACT_ORIGIN (t) = NULL;
1384 if (is_task_ctx (ctx))
1385 finalize_task_copyfn (ctx->stmt);
1387 XDELETE (ctx);
1390 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1391 context. */
1393 static void
1394 fixup_child_record_type (omp_context *ctx)
1396 tree f, type = ctx->record_type;
1398 /* ??? It isn't sufficient to just call remap_type here, because
1399 variably_modified_type_p doesn't work the way we expect for
1400 record types. Testing each field for whether it needs remapping
1401 and creating a new record by hand works, however. */
1402 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1403 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1404 break;
1405 if (f)
1407 tree name, new_fields = NULL;
1409 type = lang_hooks.types.make_type (RECORD_TYPE);
1410 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1411 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1412 TYPE_DECL, name, type);
1413 TYPE_NAME (type) = name;
1415 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1417 tree new_f = copy_node (f);
1418 DECL_CONTEXT (new_f) = type;
1419 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1420 DECL_CHAIN (new_f) = new_fields;
1421 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1422 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1423 &ctx->cb, NULL);
1424 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1425 &ctx->cb, NULL);
1426 new_fields = new_f;
1428 /* Arrange to be able to look up the receiver field
1429 given the sender field. */
1430 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1431 (splay_tree_value) new_f);
1433 TYPE_FIELDS (type) = nreverse (new_fields);
1434 layout_type (type);
1437 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1440 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1441 specified by CLAUSES. */
1443 static void
1444 scan_sharing_clauses (tree clauses, omp_context *ctx)
1446 tree c, decl;
1447 bool scan_array_reductions = false;
1449 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1451 bool by_ref;
1453 switch (OMP_CLAUSE_CODE (c))
1455 case OMP_CLAUSE_PRIVATE:
1456 decl = OMP_CLAUSE_DECL (c);
1457 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1458 goto do_private;
1459 else if (!is_variable_sized (decl))
1460 install_var_local (decl, ctx);
1461 break;
1463 case OMP_CLAUSE_SHARED:
1464 /* Ignore shared directives in teams construct. */
1465 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1466 break;
1467 gcc_assert (is_taskreg_ctx (ctx));
1468 decl = OMP_CLAUSE_DECL (c);
1469 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1470 || !is_variable_sized (decl));
1471 /* Global variables don't need to be copied,
1472 the receiver side will use them directly. */
1473 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1474 break;
1475 by_ref = use_pointer_for_field (decl, ctx);
1476 if (! TREE_READONLY (decl)
1477 || TREE_ADDRESSABLE (decl)
1478 || by_ref
1479 || is_reference (decl))
1481 install_var_field (decl, by_ref, 3, ctx);
1482 install_var_local (decl, ctx);
1483 break;
1485 /* We don't need to copy const scalar vars back. */
1486 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1487 goto do_private;
1489 case OMP_CLAUSE_LASTPRIVATE:
1490 /* Let the corresponding firstprivate clause create
1491 the variable. */
1492 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1493 break;
1494 /* FALLTHRU */
1496 case OMP_CLAUSE_FIRSTPRIVATE:
1497 case OMP_CLAUSE_REDUCTION:
1498 case OMP_CLAUSE_LINEAR:
1499 decl = OMP_CLAUSE_DECL (c);
1500 do_private:
1501 if (is_variable_sized (decl))
1503 if (is_task_ctx (ctx))
1504 install_var_field (decl, false, 1, ctx);
1505 break;
1507 else if (is_taskreg_ctx (ctx))
1509 bool global
1510 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1511 by_ref = use_pointer_for_field (decl, NULL);
1513 if (is_task_ctx (ctx)
1514 && (global || by_ref || is_reference (decl)))
1516 install_var_field (decl, false, 1, ctx);
1517 if (!global)
1518 install_var_field (decl, by_ref, 2, ctx);
1520 else if (!global)
1521 install_var_field (decl, by_ref, 3, ctx);
1523 install_var_local (decl, ctx);
1524 break;
1526 case OMP_CLAUSE__LOOPTEMP_:
1527 gcc_assert (is_parallel_ctx (ctx));
1528 decl = OMP_CLAUSE_DECL (c);
1529 install_var_field (decl, false, 3, ctx);
1530 install_var_local (decl, ctx);
1531 break;
1533 case OMP_CLAUSE_COPYPRIVATE:
1534 case OMP_CLAUSE_COPYIN:
1535 decl = OMP_CLAUSE_DECL (c);
1536 by_ref = use_pointer_for_field (decl, NULL);
1537 install_var_field (decl, by_ref, 3, ctx);
1538 break;
1540 case OMP_CLAUSE_DEFAULT:
1541 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1542 break;
1544 case OMP_CLAUSE_FINAL:
1545 case OMP_CLAUSE_IF:
1546 case OMP_CLAUSE_NUM_THREADS:
1547 case OMP_CLAUSE_NUM_TEAMS:
1548 case OMP_CLAUSE_THREAD_LIMIT:
1549 case OMP_CLAUSE_DEVICE:
1550 case OMP_CLAUSE_SCHEDULE:
1551 case OMP_CLAUSE_DIST_SCHEDULE:
1552 case OMP_CLAUSE_DEPEND:
1553 if (ctx->outer)
1554 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1555 break;
1557 case OMP_CLAUSE_TO:
1558 case OMP_CLAUSE_FROM:
1559 case OMP_CLAUSE_MAP:
1560 if (ctx->outer)
1561 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1562 decl = OMP_CLAUSE_DECL (c);
1563 /* Global variables with "omp declare target" attribute
1564 don't need to be copied, the receiver side will use them
1565 directly. */
1566 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1567 && DECL_P (decl)
1568 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1569 && lookup_attribute ("omp declare target",
1570 DECL_ATTRIBUTES (decl)))
1571 break;
1572 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1573 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1575 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1576 #pragma omp target data, there is nothing to map for
1577 those. */
1578 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1579 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1580 break;
1582 if (DECL_P (decl))
1584 if (DECL_SIZE (decl)
1585 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1587 tree decl2 = DECL_VALUE_EXPR (decl);
1588 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1589 decl2 = TREE_OPERAND (decl2, 0);
1590 gcc_assert (DECL_P (decl2));
1591 install_var_field (decl2, true, 3, ctx);
1592 install_var_local (decl2, ctx);
1593 install_var_local (decl, ctx);
1595 else
1597 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1598 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1599 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1600 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1601 install_var_field (decl, true, 7, ctx);
1602 else
1603 install_var_field (decl, true, 3, ctx);
1604 if (gimple_omp_target_kind (ctx->stmt)
1605 == GF_OMP_TARGET_KIND_REGION)
1606 install_var_local (decl, ctx);
1609 else
1611 tree base = get_base_address (decl);
1612 tree nc = OMP_CLAUSE_CHAIN (c);
1613 if (DECL_P (base)
1614 && nc != NULL_TREE
1615 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1616 && OMP_CLAUSE_DECL (nc) == base
1617 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1618 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1620 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1621 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1623 else
1625 gcc_assert (!splay_tree_lookup (ctx->field_map,
1626 (splay_tree_key) decl));
1627 tree field
1628 = build_decl (OMP_CLAUSE_LOCATION (c),
1629 FIELD_DECL, NULL_TREE, ptr_type_node);
1630 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1631 insert_field_into_struct (ctx->record_type, field);
1632 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1633 (splay_tree_value) field);
1636 break;
1638 case OMP_CLAUSE_NOWAIT:
1639 case OMP_CLAUSE_ORDERED:
1640 case OMP_CLAUSE_COLLAPSE:
1641 case OMP_CLAUSE_UNTIED:
1642 case OMP_CLAUSE_MERGEABLE:
1643 case OMP_CLAUSE_PROC_BIND:
1644 case OMP_CLAUSE_SAFELEN:
1645 break;
1647 case OMP_CLAUSE_ALIGNED:
1648 decl = OMP_CLAUSE_DECL (c);
1649 if (is_global_var (decl)
1650 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1651 install_var_local (decl, ctx);
1652 break;
1654 default:
1655 gcc_unreachable ();
1659 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1661 switch (OMP_CLAUSE_CODE (c))
1663 case OMP_CLAUSE_LASTPRIVATE:
1664 /* Let the corresponding firstprivate clause create
1665 the variable. */
1666 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1667 scan_array_reductions = true;
1668 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1669 break;
1670 /* FALLTHRU */
1672 case OMP_CLAUSE_PRIVATE:
1673 case OMP_CLAUSE_FIRSTPRIVATE:
1674 case OMP_CLAUSE_REDUCTION:
1675 case OMP_CLAUSE_LINEAR:
1676 decl = OMP_CLAUSE_DECL (c);
1677 if (is_variable_sized (decl))
1678 install_var_local (decl, ctx);
1679 fixup_remapped_decl (decl, ctx,
1680 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1681 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1682 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1683 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1684 scan_array_reductions = true;
1685 break;
1687 case OMP_CLAUSE_SHARED:
1688 /* Ignore shared directives in teams construct. */
1689 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1690 break;
1691 decl = OMP_CLAUSE_DECL (c);
1692 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1693 fixup_remapped_decl (decl, ctx, false);
1694 break;
1696 case OMP_CLAUSE_MAP:
1697 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1698 break;
1699 decl = OMP_CLAUSE_DECL (c);
1700 if (DECL_P (decl)
1701 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1702 && lookup_attribute ("omp declare target",
1703 DECL_ATTRIBUTES (decl)))
1704 break;
1705 if (DECL_P (decl))
1707 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1708 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1709 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1711 tree new_decl = lookup_decl (decl, ctx);
1712 TREE_TYPE (new_decl)
1713 = remap_type (TREE_TYPE (decl), &ctx->cb);
1715 else if (DECL_SIZE (decl)
1716 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1718 tree decl2 = DECL_VALUE_EXPR (decl);
1719 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1720 decl2 = TREE_OPERAND (decl2, 0);
1721 gcc_assert (DECL_P (decl2));
1722 fixup_remapped_decl (decl2, ctx, false);
1723 fixup_remapped_decl (decl, ctx, true);
1725 else
1726 fixup_remapped_decl (decl, ctx, false);
1728 break;
1730 case OMP_CLAUSE_COPYPRIVATE:
1731 case OMP_CLAUSE_COPYIN:
1732 case OMP_CLAUSE_DEFAULT:
1733 case OMP_CLAUSE_IF:
1734 case OMP_CLAUSE_NUM_THREADS:
1735 case OMP_CLAUSE_NUM_TEAMS:
1736 case OMP_CLAUSE_THREAD_LIMIT:
1737 case OMP_CLAUSE_DEVICE:
1738 case OMP_CLAUSE_SCHEDULE:
1739 case OMP_CLAUSE_DIST_SCHEDULE:
1740 case OMP_CLAUSE_NOWAIT:
1741 case OMP_CLAUSE_ORDERED:
1742 case OMP_CLAUSE_COLLAPSE:
1743 case OMP_CLAUSE_UNTIED:
1744 case OMP_CLAUSE_FINAL:
1745 case OMP_CLAUSE_MERGEABLE:
1746 case OMP_CLAUSE_PROC_BIND:
1747 case OMP_CLAUSE_SAFELEN:
1748 case OMP_CLAUSE_ALIGNED:
1749 case OMP_CLAUSE_DEPEND:
1750 case OMP_CLAUSE__LOOPTEMP_:
1751 case OMP_CLAUSE_TO:
1752 case OMP_CLAUSE_FROM:
1753 break;
1755 default:
1756 gcc_unreachable ();
1760 if (scan_array_reductions)
1761 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1763 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1765 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1766 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1768 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1769 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1770 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1773 /* Create a new name for omp child function. Returns an identifier. */
1775 static GTY(()) unsigned int tmp_ompfn_id_num;
1777 static tree
1778 create_omp_child_function_name (bool task_copy)
1780 return (clone_function_name (current_function_decl,
1781 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1784 /* Build a decl for the omp child function. It'll not contain a body
1785 yet, just the bare decl. */
1787 static void
1788 create_omp_child_function (omp_context *ctx, bool task_copy)
1790 tree decl, type, name, t;
1792 name = create_omp_child_function_name (task_copy);
1793 if (task_copy)
1794 type = build_function_type_list (void_type_node, ptr_type_node,
1795 ptr_type_node, NULL_TREE);
1796 else
1797 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1799 decl = build_decl (gimple_location (ctx->stmt),
1800 FUNCTION_DECL, name, type);
1802 if (!task_copy)
1803 ctx->cb.dst_fn = decl;
1804 else
1805 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1807 TREE_STATIC (decl) = 1;
1808 TREE_USED (decl) = 1;
1809 DECL_ARTIFICIAL (decl) = 1;
1810 DECL_NAMELESS (decl) = 1;
1811 DECL_IGNORED_P (decl) = 0;
1812 TREE_PUBLIC (decl) = 0;
1813 DECL_UNINLINABLE (decl) = 1;
1814 DECL_EXTERNAL (decl) = 0;
1815 DECL_CONTEXT (decl) = NULL_TREE;
1816 DECL_INITIAL (decl) = make_node (BLOCK);
1817 bool target_p = false;
1818 if (lookup_attribute ("omp declare target",
1819 DECL_ATTRIBUTES (current_function_decl)))
1820 target_p = true;
1821 else
1823 omp_context *octx;
1824 for (octx = ctx; octx; octx = octx->outer)
1825 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1826 && gimple_omp_target_kind (octx->stmt)
1827 == GF_OMP_TARGET_KIND_REGION)
1829 target_p = true;
1830 break;
1833 if (target_p)
1834 DECL_ATTRIBUTES (decl)
1835 = tree_cons (get_identifier ("omp declare target"),
1836 NULL_TREE, DECL_ATTRIBUTES (decl));
1838 t = build_decl (DECL_SOURCE_LOCATION (decl),
1839 RESULT_DECL, NULL_TREE, void_type_node);
1840 DECL_ARTIFICIAL (t) = 1;
1841 DECL_IGNORED_P (t) = 1;
1842 DECL_CONTEXT (t) = decl;
1843 DECL_RESULT (decl) = t;
1845 t = build_decl (DECL_SOURCE_LOCATION (decl),
1846 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1847 DECL_ARTIFICIAL (t) = 1;
1848 DECL_NAMELESS (t) = 1;
1849 DECL_ARG_TYPE (t) = ptr_type_node;
1850 DECL_CONTEXT (t) = current_function_decl;
1851 TREE_USED (t) = 1;
1852 DECL_ARGUMENTS (decl) = t;
1853 if (!task_copy)
1854 ctx->receiver_decl = t;
1855 else
1857 t = build_decl (DECL_SOURCE_LOCATION (decl),
1858 PARM_DECL, get_identifier (".omp_data_o"),
1859 ptr_type_node);
1860 DECL_ARTIFICIAL (t) = 1;
1861 DECL_NAMELESS (t) = 1;
1862 DECL_ARG_TYPE (t) = ptr_type_node;
1863 DECL_CONTEXT (t) = current_function_decl;
1864 TREE_USED (t) = 1;
1865 TREE_ADDRESSABLE (t) = 1;
1866 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1867 DECL_ARGUMENTS (decl) = t;
1870 /* Allocate memory for the function structure. The call to
1871 allocate_struct_function clobbers CFUN, so we need to restore
1872 it afterward. */
1873 push_struct_function (decl);
1874 cfun->function_end_locus = gimple_location (ctx->stmt);
1875 pop_cfun ();
1878 /* Callback for walk_gimple_seq. Check if combined parallel
1879 contains gimple_omp_for_combined_into_p OMP_FOR. */
1881 static tree
1882 find_combined_for (gimple_stmt_iterator *gsi_p,
1883 bool *handled_ops_p,
1884 struct walk_stmt_info *wi)
1886 gimple stmt = gsi_stmt (*gsi_p);
1888 *handled_ops_p = true;
1889 switch (gimple_code (stmt))
1891 WALK_SUBSTMTS;
1893 case GIMPLE_OMP_FOR:
1894 if (gimple_omp_for_combined_into_p (stmt)
1895 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1897 wi->info = stmt;
1898 return integer_zero_node;
1900 break;
1901 default:
1902 break;
1904 return NULL;
1907 /* Scan an OpenMP parallel directive. */
1909 static void
1910 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1912 omp_context *ctx;
1913 tree name;
1914 gimple stmt = gsi_stmt (*gsi);
1916 /* Ignore parallel directives with empty bodies, unless there
1917 are copyin clauses. */
1918 if (optimize > 0
1919 && empty_body_p (gimple_omp_body (stmt))
1920 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1921 OMP_CLAUSE_COPYIN) == NULL)
1923 gsi_replace (gsi, gimple_build_nop (), false);
1924 return;
1927 if (gimple_omp_parallel_combined_p (stmt))
1929 gimple for_stmt;
1930 struct walk_stmt_info wi;
1932 memset (&wi, 0, sizeof (wi));
1933 wi.val_only = true;
1934 walk_gimple_seq (gimple_omp_body (stmt),
1935 find_combined_for, NULL, &wi);
1936 for_stmt = (gimple) wi.info;
1937 if (for_stmt)
1939 struct omp_for_data fd;
1940 extract_omp_for_data (for_stmt, &fd, NULL);
1941 /* We need two temporaries with fd.loop.v type (istart/iend)
1942 and then (fd.collapse - 1) temporaries with the same
1943 type for count2 ... countN-1 vars if not constant. */
1944 size_t count = 2, i;
1945 tree type = fd.iter_type;
1946 if (fd.collapse > 1
1947 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
1948 count += fd.collapse - 1;
1949 for (i = 0; i < count; i++)
1951 tree temp = create_tmp_var (type, NULL);
1952 tree c = build_omp_clause (UNKNOWN_LOCATION,
1953 OMP_CLAUSE__LOOPTEMP_);
1954 OMP_CLAUSE_DECL (c) = temp;
1955 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
1956 gimple_omp_parallel_set_clauses (stmt, c);
1961 ctx = new_omp_context (stmt, outer_ctx);
1962 if (taskreg_nesting_level > 1)
1963 ctx->is_nested = true;
1964 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1965 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1966 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1967 name = create_tmp_var_name (".omp_data_s");
1968 name = build_decl (gimple_location (stmt),
1969 TYPE_DECL, name, ctx->record_type);
1970 DECL_ARTIFICIAL (name) = 1;
1971 DECL_NAMELESS (name) = 1;
1972 TYPE_NAME (ctx->record_type) = name;
1973 create_omp_child_function (ctx, false);
1974 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1976 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1977 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1979 if (TYPE_FIELDS (ctx->record_type) == NULL)
1980 ctx->record_type = ctx->receiver_decl = NULL;
1981 else
1983 layout_type (ctx->record_type);
1984 fixup_child_record_type (ctx);
1988 /* Scan an OpenMP task directive. */
1990 static void
1991 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1993 omp_context *ctx;
1994 tree name, t;
1995 gimple stmt = gsi_stmt (*gsi);
1996 location_t loc = gimple_location (stmt);
1998 /* Ignore task directives with empty bodies. */
1999 if (optimize > 0
2000 && empty_body_p (gimple_omp_body (stmt)))
2002 gsi_replace (gsi, gimple_build_nop (), false);
2003 return;
2006 ctx = new_omp_context (stmt, outer_ctx);
2007 if (taskreg_nesting_level > 1)
2008 ctx->is_nested = true;
2009 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2010 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2011 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2012 name = create_tmp_var_name (".omp_data_s");
2013 name = build_decl (gimple_location (stmt),
2014 TYPE_DECL, name, ctx->record_type);
2015 DECL_ARTIFICIAL (name) = 1;
2016 DECL_NAMELESS (name) = 1;
2017 TYPE_NAME (ctx->record_type) = name;
2018 create_omp_child_function (ctx, false);
2019 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2021 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2023 if (ctx->srecord_type)
2025 name = create_tmp_var_name (".omp_data_a");
2026 name = build_decl (gimple_location (stmt),
2027 TYPE_DECL, name, ctx->srecord_type);
2028 DECL_ARTIFICIAL (name) = 1;
2029 DECL_NAMELESS (name) = 1;
2030 TYPE_NAME (ctx->srecord_type) = name;
2031 create_omp_child_function (ctx, true);
2034 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2036 if (TYPE_FIELDS (ctx->record_type) == NULL)
2038 ctx->record_type = ctx->receiver_decl = NULL;
2039 t = build_int_cst (long_integer_type_node, 0);
2040 gimple_omp_task_set_arg_size (stmt, t);
2041 t = build_int_cst (long_integer_type_node, 1);
2042 gimple_omp_task_set_arg_align (stmt, t);
2044 else
2046 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2047 /* Move VLA fields to the end. */
2048 p = &TYPE_FIELDS (ctx->record_type);
2049 while (*p)
2050 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2051 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2053 *q = *p;
2054 *p = TREE_CHAIN (*p);
2055 TREE_CHAIN (*q) = NULL_TREE;
2056 q = &TREE_CHAIN (*q);
2058 else
2059 p = &DECL_CHAIN (*p);
2060 *p = vla_fields;
2061 layout_type (ctx->record_type);
2062 fixup_child_record_type (ctx);
2063 if (ctx->srecord_type)
2064 layout_type (ctx->srecord_type);
2065 t = fold_convert_loc (loc, long_integer_type_node,
2066 TYPE_SIZE_UNIT (ctx->record_type));
2067 gimple_omp_task_set_arg_size (stmt, t);
2068 t = build_int_cst (long_integer_type_node,
2069 TYPE_ALIGN_UNIT (ctx->record_type));
2070 gimple_omp_task_set_arg_align (stmt, t);
2075 /* Scan an OpenMP loop directive. */
2077 static void
2078 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2080 omp_context *ctx;
2081 size_t i;
2083 ctx = new_omp_context (stmt, outer_ctx);
2085 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2087 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2088 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2090 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2091 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2092 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2093 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2095 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2098 /* Scan an OpenMP sections directive. */
2100 static void
2101 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2103 omp_context *ctx;
2105 ctx = new_omp_context (stmt, outer_ctx);
2106 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2107 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2110 /* Scan an OpenMP single directive. */
2112 static void
2113 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2115 omp_context *ctx;
2116 tree name;
2118 ctx = new_omp_context (stmt, outer_ctx);
2119 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2120 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2121 name = create_tmp_var_name (".omp_copy_s");
2122 name = build_decl (gimple_location (stmt),
2123 TYPE_DECL, name, ctx->record_type);
2124 TYPE_NAME (ctx->record_type) = name;
2126 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2127 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2129 if (TYPE_FIELDS (ctx->record_type) == NULL)
2130 ctx->record_type = NULL;
2131 else
2132 layout_type (ctx->record_type);
2135 /* Scan an OpenMP target{, data, update} directive. */
2137 static void
2138 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2140 omp_context *ctx;
2141 tree name;
2142 int kind = gimple_omp_target_kind (stmt);
2144 ctx = new_omp_context (stmt, outer_ctx);
2145 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2146 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2147 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2148 name = create_tmp_var_name (".omp_data_t");
2149 name = build_decl (gimple_location (stmt),
2150 TYPE_DECL, name, ctx->record_type);
2151 DECL_ARTIFICIAL (name) = 1;
2152 DECL_NAMELESS (name) = 1;
2153 TYPE_NAME (ctx->record_type) = name;
2154 if (kind == GF_OMP_TARGET_KIND_REGION)
2156 create_omp_child_function (ctx, false);
2157 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2160 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2161 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2163 if (TYPE_FIELDS (ctx->record_type) == NULL)
2164 ctx->record_type = ctx->receiver_decl = NULL;
2165 else
2167 TYPE_FIELDS (ctx->record_type)
2168 = nreverse (TYPE_FIELDS (ctx->record_type));
2169 #ifdef ENABLE_CHECKING
2170 tree field;
2171 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2172 for (field = TYPE_FIELDS (ctx->record_type);
2173 field;
2174 field = DECL_CHAIN (field))
2175 gcc_assert (DECL_ALIGN (field) == align);
2176 #endif
2177 layout_type (ctx->record_type);
2178 if (kind == GF_OMP_TARGET_KIND_REGION)
2179 fixup_child_record_type (ctx);
2183 /* Scan an OpenMP teams directive. */
2185 static void
2186 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2188 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2189 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2190 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2193 /* Check OpenMP nesting restrictions. */
2194 static bool
2195 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2197 if (ctx != NULL)
2199 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2200 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
2202 error_at (gimple_location (stmt),
2203 "OpenMP constructs may not be nested inside simd region");
2204 return false;
2206 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2208 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2209 || (gimple_omp_for_kind (stmt)
2210 != GF_OMP_FOR_KIND_DISTRIBUTE))
2211 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2213 error_at (gimple_location (stmt),
2214 "only distribute or parallel constructs are allowed to "
2215 "be closely nested inside teams construct");
2216 return false;
2220 switch (gimple_code (stmt))
2222 case GIMPLE_OMP_FOR:
2223 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
2224 return true;
2225 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2227 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2229 error_at (gimple_location (stmt),
2230 "distribute construct must be closely nested inside "
2231 "teams construct");
2232 return false;
2234 return true;
2236 /* FALLTHRU */
2237 case GIMPLE_CALL:
2238 if (is_gimple_call (stmt)
2239 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2240 == BUILT_IN_GOMP_CANCEL
2241 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2242 == BUILT_IN_GOMP_CANCELLATION_POINT))
2244 const char *bad = NULL;
2245 const char *kind = NULL;
2246 if (ctx == NULL)
2248 error_at (gimple_location (stmt), "orphaned %qs construct",
2249 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2250 == BUILT_IN_GOMP_CANCEL
2251 ? "#pragma omp cancel"
2252 : "#pragma omp cancellation point");
2253 return false;
2255 switch (host_integerp (gimple_call_arg (stmt, 0), 0)
2256 ? tree_low_cst (gimple_call_arg (stmt, 0), 0)
2257 : 0)
2259 case 1:
2260 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2261 bad = "#pragma omp parallel";
2262 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2263 == BUILT_IN_GOMP_CANCEL
2264 && !integer_zerop (gimple_call_arg (stmt, 1)))
2265 ctx->cancellable = true;
2266 kind = "parallel";
2267 break;
2268 case 2:
2269 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2270 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2271 bad = "#pragma omp for";
2272 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2273 == BUILT_IN_GOMP_CANCEL
2274 && !integer_zerop (gimple_call_arg (stmt, 1)))
2276 ctx->cancellable = true;
2277 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2278 OMP_CLAUSE_NOWAIT))
2279 warning_at (gimple_location (stmt), 0,
2280 "%<#pragma omp cancel for%> inside "
2281 "%<nowait%> for construct");
2282 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2283 OMP_CLAUSE_ORDERED))
2284 warning_at (gimple_location (stmt), 0,
2285 "%<#pragma omp cancel for%> inside "
2286 "%<ordered%> for construct");
2288 kind = "for";
2289 break;
2290 case 4:
2291 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2292 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2293 bad = "#pragma omp sections";
2294 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2295 == BUILT_IN_GOMP_CANCEL
2296 && !integer_zerop (gimple_call_arg (stmt, 1)))
2298 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2300 ctx->cancellable = true;
2301 if (find_omp_clause (gimple_omp_sections_clauses
2302 (ctx->stmt),
2303 OMP_CLAUSE_NOWAIT))
2304 warning_at (gimple_location (stmt), 0,
2305 "%<#pragma omp cancel sections%> inside "
2306 "%<nowait%> sections construct");
2308 else
2310 gcc_assert (ctx->outer
2311 && gimple_code (ctx->outer->stmt)
2312 == GIMPLE_OMP_SECTIONS);
2313 ctx->outer->cancellable = true;
2314 if (find_omp_clause (gimple_omp_sections_clauses
2315 (ctx->outer->stmt),
2316 OMP_CLAUSE_NOWAIT))
2317 warning_at (gimple_location (stmt), 0,
2318 "%<#pragma omp cancel sections%> inside "
2319 "%<nowait%> sections construct");
2322 kind = "sections";
2323 break;
2324 case 8:
2325 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2326 bad = "#pragma omp task";
2327 else
2328 ctx->cancellable = true;
2329 kind = "taskgroup";
2330 break;
2331 default:
2332 error_at (gimple_location (stmt), "invalid arguments");
2333 return false;
2335 if (bad)
2337 error_at (gimple_location (stmt),
2338 "%<%s %s%> construct not closely nested inside of %qs",
2339 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2340 == BUILT_IN_GOMP_CANCEL
2341 ? "#pragma omp cancel"
2342 : "#pragma omp cancellation point", kind, bad);
2343 return false;
2346 /* FALLTHRU */
2347 case GIMPLE_OMP_SECTIONS:
2348 case GIMPLE_OMP_SINGLE:
2349 for (; ctx != NULL; ctx = ctx->outer)
2350 switch (gimple_code (ctx->stmt))
2352 case GIMPLE_OMP_FOR:
2353 case GIMPLE_OMP_SECTIONS:
2354 case GIMPLE_OMP_SINGLE:
2355 case GIMPLE_OMP_ORDERED:
2356 case GIMPLE_OMP_MASTER:
2357 case GIMPLE_OMP_TASK:
2358 case GIMPLE_OMP_CRITICAL:
2359 if (is_gimple_call (stmt))
2361 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2362 != BUILT_IN_GOMP_BARRIER)
2363 return true;
2364 error_at (gimple_location (stmt),
2365 "barrier region may not be closely nested inside "
2366 "of work-sharing, critical, ordered, master or "
2367 "explicit task region");
2368 return false;
2370 error_at (gimple_location (stmt),
2371 "work-sharing region may not be closely nested inside "
2372 "of work-sharing, critical, ordered, master or explicit "
2373 "task region");
2374 return false;
2375 case GIMPLE_OMP_PARALLEL:
2376 return true;
2377 default:
2378 break;
2380 break;
2381 case GIMPLE_OMP_MASTER:
2382 for (; ctx != NULL; ctx = ctx->outer)
2383 switch (gimple_code (ctx->stmt))
2385 case GIMPLE_OMP_FOR:
2386 case GIMPLE_OMP_SECTIONS:
2387 case GIMPLE_OMP_SINGLE:
2388 case GIMPLE_OMP_TASK:
2389 error_at (gimple_location (stmt),
2390 "master region may not be closely nested inside "
2391 "of work-sharing or explicit task region");
2392 return false;
2393 case GIMPLE_OMP_PARALLEL:
2394 return true;
2395 default:
2396 break;
2398 break;
2399 case GIMPLE_OMP_ORDERED:
2400 for (; ctx != NULL; ctx = ctx->outer)
2401 switch (gimple_code (ctx->stmt))
2403 case GIMPLE_OMP_CRITICAL:
2404 case GIMPLE_OMP_TASK:
2405 error_at (gimple_location (stmt),
2406 "ordered region may not be closely nested inside "
2407 "of critical or explicit task region");
2408 return false;
2409 case GIMPLE_OMP_FOR:
2410 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2411 OMP_CLAUSE_ORDERED) == NULL)
2413 error_at (gimple_location (stmt),
2414 "ordered region must be closely nested inside "
2415 "a loop region with an ordered clause");
2416 return false;
2418 return true;
2419 case GIMPLE_OMP_PARALLEL:
2420 error_at (gimple_location (stmt),
2421 "ordered region must be closely nested inside "
2422 "a loop region with an ordered clause");
2423 return false;
2424 default:
2425 break;
2427 break;
2428 case GIMPLE_OMP_CRITICAL:
2429 for (; ctx != NULL; ctx = ctx->outer)
2430 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2431 && (gimple_omp_critical_name (stmt)
2432 == gimple_omp_critical_name (ctx->stmt)))
2434 error_at (gimple_location (stmt),
2435 "critical region may not be nested inside a critical "
2436 "region with the same name");
2437 return false;
2439 break;
2440 case GIMPLE_OMP_TEAMS:
2441 if (ctx == NULL
2442 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2443 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2445 error_at (gimple_location (stmt),
2446 "teams construct not closely nested inside of target "
2447 "region");
2448 return false;
2450 break;
2451 default:
2452 break;
2454 return true;
2458 /* Helper function scan_omp.
2460 Callback for walk_tree or operators in walk_gimple_stmt used to
2461 scan for OpenMP directives in TP. */
2463 static tree
2464 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2466 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2467 omp_context *ctx = (omp_context *) wi->info;
2468 tree t = *tp;
2470 switch (TREE_CODE (t))
2472 case VAR_DECL:
2473 case PARM_DECL:
2474 case LABEL_DECL:
2475 case RESULT_DECL:
2476 if (ctx)
2477 *tp = remap_decl (t, &ctx->cb);
2478 break;
2480 default:
2481 if (ctx && TYPE_P (t))
2482 *tp = remap_type (t, &ctx->cb);
2483 else if (!DECL_P (t))
2485 *walk_subtrees = 1;
2486 if (ctx)
2488 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2489 if (tem != TREE_TYPE (t))
2491 if (TREE_CODE (t) == INTEGER_CST)
2492 *tp = build_int_cst_wide (tem,
2493 TREE_INT_CST_LOW (t),
2494 TREE_INT_CST_HIGH (t));
2495 else
2496 TREE_TYPE (t) = tem;
2500 break;
2503 return NULL_TREE;
2507 /* Helper function for scan_omp.
2509 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2510 the current statement in GSI. */
2512 static tree
2513 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2514 struct walk_stmt_info *wi)
2516 gimple stmt = gsi_stmt (*gsi);
2517 omp_context *ctx = (omp_context *) wi->info;
2519 if (gimple_has_location (stmt))
2520 input_location = gimple_location (stmt);
2522 /* Check the OpenMP nesting restrictions. */
2523 bool remove = false;
2524 if (is_gimple_omp (stmt))
2525 remove = !check_omp_nesting_restrictions (stmt, ctx);
2526 else if (is_gimple_call (stmt))
2528 tree fndecl = gimple_call_fndecl (stmt);
2529 if (fndecl
2530 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2531 switch (DECL_FUNCTION_CODE (fndecl))
2533 case BUILT_IN_GOMP_BARRIER:
2534 case BUILT_IN_GOMP_CANCEL:
2535 case BUILT_IN_GOMP_CANCELLATION_POINT:
2536 case BUILT_IN_GOMP_TASKYIELD:
2537 case BUILT_IN_GOMP_TASKWAIT:
2538 case BUILT_IN_GOMP_TASKGROUP_START:
2539 case BUILT_IN_GOMP_TASKGROUP_END:
2540 remove = !check_omp_nesting_restrictions (stmt, ctx);
2541 break;
2542 default:
2543 break;
2546 if (remove)
2548 stmt = gimple_build_nop ();
2549 gsi_replace (gsi, stmt, false);
2552 *handled_ops_p = true;
2554 switch (gimple_code (stmt))
2556 case GIMPLE_OMP_PARALLEL:
2557 taskreg_nesting_level++;
2558 scan_omp_parallel (gsi, ctx);
2559 taskreg_nesting_level--;
2560 break;
2562 case GIMPLE_OMP_TASK:
2563 taskreg_nesting_level++;
2564 scan_omp_task (gsi, ctx);
2565 taskreg_nesting_level--;
2566 break;
2568 case GIMPLE_OMP_FOR:
2569 scan_omp_for (stmt, ctx);
2570 break;
2572 case GIMPLE_OMP_SECTIONS:
2573 scan_omp_sections (stmt, ctx);
2574 break;
2576 case GIMPLE_OMP_SINGLE:
2577 scan_omp_single (stmt, ctx);
2578 break;
2580 case GIMPLE_OMP_SECTION:
2581 case GIMPLE_OMP_MASTER:
2582 case GIMPLE_OMP_TASKGROUP:
2583 case GIMPLE_OMP_ORDERED:
2584 case GIMPLE_OMP_CRITICAL:
2585 ctx = new_omp_context (stmt, ctx);
2586 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2587 break;
2589 case GIMPLE_OMP_TARGET:
2590 scan_omp_target (stmt, ctx);
2591 break;
2593 case GIMPLE_OMP_TEAMS:
2594 scan_omp_teams (stmt, ctx);
2595 break;
2597 case GIMPLE_BIND:
2599 tree var;
2601 *handled_ops_p = false;
2602 if (ctx)
2603 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2604 insert_decl_map (&ctx->cb, var, var);
2606 break;
2607 default:
2608 *handled_ops_p = false;
2609 break;
2612 return NULL_TREE;
2616 /* Scan all the statements starting at the current statement. CTX
2617 contains context information about the OpenMP directives and
2618 clauses found during the scan. */
2620 static void
2621 scan_omp (gimple_seq *body_p, omp_context *ctx)
2623 location_t saved_location;
2624 struct walk_stmt_info wi;
2626 memset (&wi, 0, sizeof (wi));
2627 wi.info = ctx;
2628 wi.want_locations = true;
2630 saved_location = input_location;
2631 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2632 input_location = saved_location;
2635 /* Re-gimplification and code generation routines. */
2637 /* Build a call to GOMP_barrier. */
2639 static gimple
2640 build_omp_barrier (tree lhs)
2642 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2643 : BUILT_IN_GOMP_BARRIER);
2644 gimple g = gimple_build_call (fndecl, 0);
2645 if (lhs)
2646 gimple_call_set_lhs (g, lhs);
2647 return g;
2650 /* If a context was created for STMT when it was scanned, return it. */
2652 static omp_context *
2653 maybe_lookup_ctx (gimple stmt)
2655 splay_tree_node n;
2656 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2657 return n ? (omp_context *) n->value : NULL;
2661 /* Find the mapping for DECL in CTX or the immediately enclosing
2662 context that has a mapping for DECL.
2664 If CTX is a nested parallel directive, we may have to use the decl
2665 mappings created in CTX's parent context. Suppose that we have the
2666 following parallel nesting (variable UIDs showed for clarity):
2668 iD.1562 = 0;
2669 #omp parallel shared(iD.1562) -> outer parallel
2670 iD.1562 = iD.1562 + 1;
2672 #omp parallel shared (iD.1562) -> inner parallel
2673 iD.1562 = iD.1562 - 1;
2675 Each parallel structure will create a distinct .omp_data_s structure
2676 for copying iD.1562 in/out of the directive:
2678 outer parallel .omp_data_s.1.i -> iD.1562
2679 inner parallel .omp_data_s.2.i -> iD.1562
2681 A shared variable mapping will produce a copy-out operation before
2682 the parallel directive and a copy-in operation after it. So, in
2683 this case we would have:
2685 iD.1562 = 0;
2686 .omp_data_o.1.i = iD.1562;
2687 #omp parallel shared(iD.1562) -> outer parallel
2688 .omp_data_i.1 = &.omp_data_o.1
2689 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2691 .omp_data_o.2.i = iD.1562; -> **
2692 #omp parallel shared(iD.1562) -> inner parallel
2693 .omp_data_i.2 = &.omp_data_o.2
2694 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2697 ** This is a problem. The symbol iD.1562 cannot be referenced
2698 inside the body of the outer parallel region. But since we are
2699 emitting this copy operation while expanding the inner parallel
2700 directive, we need to access the CTX structure of the outer
2701 parallel directive to get the correct mapping:
2703 .omp_data_o.2.i = .omp_data_i.1->i
2705 Since there may be other workshare or parallel directives enclosing
2706 the parallel directive, it may be necessary to walk up the context
2707 parent chain. This is not a problem in general because nested
2708 parallelism happens only rarely. */
2710 static tree
2711 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2713 tree t;
2714 omp_context *up;
2716 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2717 t = maybe_lookup_decl (decl, up);
2719 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2721 return t ? t : decl;
2725 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2726 in outer contexts. */
2728 static tree
2729 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2731 tree t = NULL;
2732 omp_context *up;
2734 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2735 t = maybe_lookup_decl (decl, up);
2737 return t ? t : decl;
2741 /* Construct the initialization value for reduction CLAUSE. */
2743 tree
2744 omp_reduction_init (tree clause, tree type)
2746 location_t loc = OMP_CLAUSE_LOCATION (clause);
2747 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2749 case PLUS_EXPR:
2750 case MINUS_EXPR:
2751 case BIT_IOR_EXPR:
2752 case BIT_XOR_EXPR:
2753 case TRUTH_OR_EXPR:
2754 case TRUTH_ORIF_EXPR:
2755 case TRUTH_XOR_EXPR:
2756 case NE_EXPR:
2757 return build_zero_cst (type);
2759 case MULT_EXPR:
2760 case TRUTH_AND_EXPR:
2761 case TRUTH_ANDIF_EXPR:
2762 case EQ_EXPR:
2763 return fold_convert_loc (loc, type, integer_one_node);
2765 case BIT_AND_EXPR:
2766 return fold_convert_loc (loc, type, integer_minus_one_node);
2768 case MAX_EXPR:
2769 if (SCALAR_FLOAT_TYPE_P (type))
2771 REAL_VALUE_TYPE max, min;
2772 if (HONOR_INFINITIES (TYPE_MODE (type)))
2774 real_inf (&max);
2775 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2777 else
2778 real_maxval (&min, 1, TYPE_MODE (type));
2779 return build_real (type, min);
2781 else
2783 gcc_assert (INTEGRAL_TYPE_P (type));
2784 return TYPE_MIN_VALUE (type);
2787 case MIN_EXPR:
2788 if (SCALAR_FLOAT_TYPE_P (type))
2790 REAL_VALUE_TYPE max;
2791 if (HONOR_INFINITIES (TYPE_MODE (type)))
2792 real_inf (&max);
2793 else
2794 real_maxval (&max, 0, TYPE_MODE (type));
2795 return build_real (type, max);
2797 else
2799 gcc_assert (INTEGRAL_TYPE_P (type));
2800 return TYPE_MAX_VALUE (type);
2803 default:
2804 gcc_unreachable ();
2808 /* Return alignment to be assumed for var in CLAUSE, which should be
2809 OMP_CLAUSE_ALIGNED. */
2811 static tree
2812 omp_clause_aligned_alignment (tree clause)
2814 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2815 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2817 /* Otherwise return implementation defined alignment. */
2818 unsigned int al = 1;
2819 enum machine_mode mode, vmode;
2820 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2821 if (vs)
2822 vs = 1 << floor_log2 (vs);
2823 static enum mode_class classes[]
2824 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2825 for (int i = 0; i < 4; i += 2)
2826 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2827 mode != VOIDmode;
2828 mode = GET_MODE_WIDER_MODE (mode))
2830 vmode = targetm.vectorize.preferred_simd_mode (mode);
2831 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2832 continue;
2833 while (vs
2834 && GET_MODE_SIZE (vmode) < vs
2835 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2836 vmode = GET_MODE_2XWIDER_MODE (vmode);
2838 tree type = lang_hooks.types.type_for_mode (mode, 1);
2839 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2840 continue;
2841 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2842 / GET_MODE_SIZE (mode));
2843 if (TYPE_MODE (type) != vmode)
2844 continue;
2845 if (TYPE_ALIGN_UNIT (type) > al)
2846 al = TYPE_ALIGN_UNIT (type);
2848 return build_int_cst (integer_type_node, al);
2851 /* Return maximum possible vectorization factor for the target. */
2853 static int
2854 omp_max_vf (void)
2856 if (!optimize
2857 || optimize_debug
2858 || (!flag_tree_loop_vectorize
2859 && (global_options_set.x_flag_tree_loop_vectorize
2860 || global_options_set.x_flag_tree_vectorize)))
2861 return 1;
2863 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2864 if (vs)
2866 vs = 1 << floor_log2 (vs);
2867 return vs;
2869 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2870 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2871 return GET_MODE_NUNITS (vqimode);
2872 return 1;
2875 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2876 privatization. */
2878 static bool
2879 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2880 tree &idx, tree &lane, tree &ivar, tree &lvar)
2882 if (max_vf == 0)
2884 max_vf = omp_max_vf ();
2885 if (max_vf > 1)
2887 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2888 OMP_CLAUSE_SAFELEN);
2889 if (c
2890 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2891 max_vf = tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c), 0);
2893 if (max_vf > 1)
2895 idx = create_tmp_var (unsigned_type_node, NULL);
2896 lane = create_tmp_var (unsigned_type_node, NULL);
2899 if (max_vf == 1)
2900 return false;
2902 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2903 tree avar = create_tmp_var_raw (atype, NULL);
2904 if (TREE_ADDRESSABLE (new_var))
2905 TREE_ADDRESSABLE (avar) = 1;
2906 DECL_ATTRIBUTES (avar)
2907 = tree_cons (get_identifier ("omp simd array"), NULL,
2908 DECL_ATTRIBUTES (avar));
2909 gimple_add_tmp_var (avar);
2910 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2911 NULL_TREE, NULL_TREE);
2912 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2913 NULL_TREE, NULL_TREE);
2914 if (DECL_P (new_var))
2916 SET_DECL_VALUE_EXPR (new_var, lvar);
2917 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2919 return true;
2922 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2923 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2924 private variables. Initialization statements go in ILIST, while calls
2925 to destructors go in DLIST. */
2927 static void
2928 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2929 omp_context *ctx, struct omp_for_data *fd)
2931 tree c, dtor, copyin_seq, x, ptr;
2932 bool copyin_by_ref = false;
2933 bool lastprivate_firstprivate = false;
2934 bool reduction_omp_orig_ref = false;
2935 int pass;
2936 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2937 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
2938 int max_vf = 0;
2939 tree lane = NULL_TREE, idx = NULL_TREE;
2940 tree ivar = NULL_TREE, lvar = NULL_TREE;
2941 gimple_seq llist[2] = { NULL, NULL };
2943 copyin_seq = NULL;
2945 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
2946 with data sharing clauses referencing variable sized vars. That
2947 is unnecessarily hard to support and very unlikely to result in
2948 vectorized code anyway. */
2949 if (is_simd)
2950 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2951 switch (OMP_CLAUSE_CODE (c))
2953 case OMP_CLAUSE_REDUCTION:
2954 case OMP_CLAUSE_PRIVATE:
2955 case OMP_CLAUSE_FIRSTPRIVATE:
2956 case OMP_CLAUSE_LASTPRIVATE:
2957 case OMP_CLAUSE_LINEAR:
2958 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
2959 max_vf = 1;
2960 break;
2961 default:
2962 continue;
2965 /* Do all the fixed sized types in the first pass, and the variable sized
2966 types in the second pass. This makes sure that the scalar arguments to
2967 the variable sized types are processed before we use them in the
2968 variable sized operations. */
2969 for (pass = 0; pass < 2; ++pass)
2971 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2973 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2974 tree var, new_var;
2975 bool by_ref;
2976 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2978 switch (c_kind)
2980 case OMP_CLAUSE_PRIVATE:
2981 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2982 continue;
2983 break;
2984 case OMP_CLAUSE_SHARED:
2985 /* Ignore shared directives in teams construct. */
2986 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2987 continue;
2988 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2990 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2991 continue;
2993 case OMP_CLAUSE_FIRSTPRIVATE:
2994 case OMP_CLAUSE_COPYIN:
2995 case OMP_CLAUSE_LINEAR:
2996 break;
2997 case OMP_CLAUSE_REDUCTION:
2998 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
2999 reduction_omp_orig_ref = true;
3000 break;
3001 case OMP_CLAUSE__LOOPTEMP_:
3002 /* Handle _looptemp_ clauses only on parallel. */
3003 if (fd)
3004 continue;
3005 break;
3006 case OMP_CLAUSE_LASTPRIVATE:
3007 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3009 lastprivate_firstprivate = true;
3010 if (pass != 0)
3011 continue;
3013 break;
3014 case OMP_CLAUSE_ALIGNED:
3015 if (pass == 0)
3016 continue;
3017 var = OMP_CLAUSE_DECL (c);
3018 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3019 && !is_global_var (var))
3021 new_var = maybe_lookup_decl (var, ctx);
3022 if (new_var == NULL_TREE)
3023 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3024 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3025 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3026 omp_clause_aligned_alignment (c));
3027 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3028 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3029 gimplify_and_add (x, ilist);
3031 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3032 && is_global_var (var))
3034 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3035 new_var = lookup_decl (var, ctx);
3036 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3037 t = build_fold_addr_expr_loc (clause_loc, t);
3038 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3039 t = build_call_expr_loc (clause_loc, t2, 2, t,
3040 omp_clause_aligned_alignment (c));
3041 t = fold_convert_loc (clause_loc, ptype, t);
3042 x = create_tmp_var (ptype, NULL);
3043 t = build2 (MODIFY_EXPR, ptype, x, t);
3044 gimplify_and_add (t, ilist);
3045 t = build_simple_mem_ref_loc (clause_loc, x);
3046 SET_DECL_VALUE_EXPR (new_var, t);
3047 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3049 continue;
3050 default:
3051 continue;
3054 new_var = var = OMP_CLAUSE_DECL (c);
3055 if (c_kind != OMP_CLAUSE_COPYIN)
3056 new_var = lookup_decl (var, ctx);
3058 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3060 if (pass != 0)
3061 continue;
3063 else if (is_variable_sized (var))
3065 /* For variable sized types, we need to allocate the
3066 actual storage here. Call alloca and store the
3067 result in the pointer decl that we created elsewhere. */
3068 if (pass == 0)
3069 continue;
3071 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3073 gimple stmt;
3074 tree tmp, atmp;
3076 ptr = DECL_VALUE_EXPR (new_var);
3077 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3078 ptr = TREE_OPERAND (ptr, 0);
3079 gcc_assert (DECL_P (ptr));
3080 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3082 /* void *tmp = __builtin_alloca */
3083 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3084 stmt = gimple_build_call (atmp, 1, x);
3085 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3086 gimple_add_tmp_var (tmp);
3087 gimple_call_set_lhs (stmt, tmp);
3089 gimple_seq_add_stmt (ilist, stmt);
3091 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3092 gimplify_assign (ptr, x, ilist);
3095 else if (is_reference (var))
3097 /* For references that are being privatized for Fortran,
3098 allocate new backing storage for the new pointer
3099 variable. This allows us to avoid changing all the
3100 code that expects a pointer to something that expects
3101 a direct variable. */
3102 if (pass == 0)
3103 continue;
3105 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3106 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3108 x = build_receiver_ref (var, false, ctx);
3109 x = build_fold_addr_expr_loc (clause_loc, x);
3111 else if (TREE_CONSTANT (x))
3113 const char *name = NULL;
3114 if (DECL_NAME (var))
3115 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3117 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3118 name);
3119 gimple_add_tmp_var (x);
3120 TREE_ADDRESSABLE (x) = 1;
3121 x = build_fold_addr_expr_loc (clause_loc, x);
3123 else
3125 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3126 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3129 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3130 gimplify_assign (new_var, x, ilist);
3132 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3134 else if (c_kind == OMP_CLAUSE_REDUCTION
3135 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3137 if (pass == 0)
3138 continue;
3140 else if (pass != 0)
3141 continue;
3143 switch (OMP_CLAUSE_CODE (c))
3145 case OMP_CLAUSE_SHARED:
3146 /* Ignore shared directives in teams construct. */
3147 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3148 continue;
3149 /* Shared global vars are just accessed directly. */
3150 if (is_global_var (new_var))
3151 break;
3152 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3153 needs to be delayed until after fixup_child_record_type so
3154 that we get the correct type during the dereference. */
3155 by_ref = use_pointer_for_field (var, ctx);
3156 x = build_receiver_ref (var, by_ref, ctx);
3157 SET_DECL_VALUE_EXPR (new_var, x);
3158 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3160 /* ??? If VAR is not passed by reference, and the variable
3161 hasn't been initialized yet, then we'll get a warning for
3162 the store into the omp_data_s structure. Ideally, we'd be
3163 able to notice this and not store anything at all, but
3164 we're generating code too early. Suppress the warning. */
3165 if (!by_ref)
3166 TREE_NO_WARNING (var) = 1;
3167 break;
3169 case OMP_CLAUSE_LASTPRIVATE:
3170 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3171 break;
3172 /* FALLTHRU */
3174 case OMP_CLAUSE_PRIVATE:
3175 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3176 x = build_outer_var_ref (var, ctx);
3177 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3179 if (is_task_ctx (ctx))
3180 x = build_receiver_ref (var, false, ctx);
3181 else
3182 x = build_outer_var_ref (var, ctx);
3184 else
3185 x = NULL;
3186 do_private:
3187 tree nx;
3188 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3189 if (is_simd)
3191 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3192 if ((TREE_ADDRESSABLE (new_var) || nx || y
3193 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3194 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3195 idx, lane, ivar, lvar))
3197 if (nx)
3198 x = lang_hooks.decls.omp_clause_default_ctor
3199 (c, unshare_expr (ivar), x);
3200 if (nx && x)
3201 gimplify_and_add (x, &llist[0]);
3202 if (y)
3204 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3205 if (y)
3207 gimple_seq tseq = NULL;
3209 dtor = y;
3210 gimplify_stmt (&dtor, &tseq);
3211 gimple_seq_add_seq (&llist[1], tseq);
3214 break;
3217 if (nx)
3218 gimplify_and_add (nx, ilist);
3219 /* FALLTHRU */
3221 do_dtor:
3222 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3223 if (x)
3225 gimple_seq tseq = NULL;
3227 dtor = x;
3228 gimplify_stmt (&dtor, &tseq);
3229 gimple_seq_add_seq (dlist, tseq);
3231 break;
3233 case OMP_CLAUSE_LINEAR:
3234 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3235 goto do_firstprivate;
3236 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3237 x = NULL;
3238 else
3239 x = build_outer_var_ref (var, ctx);
3240 goto do_private;
3242 case OMP_CLAUSE_FIRSTPRIVATE:
3243 if (is_task_ctx (ctx))
3245 if (is_reference (var) || is_variable_sized (var))
3246 goto do_dtor;
3247 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3248 ctx))
3249 || use_pointer_for_field (var, NULL))
3251 x = build_receiver_ref (var, false, ctx);
3252 SET_DECL_VALUE_EXPR (new_var, x);
3253 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3254 goto do_dtor;
3257 do_firstprivate:
3258 x = build_outer_var_ref (var, ctx);
3259 if (is_simd)
3261 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3262 && gimple_omp_for_combined_into_p (ctx->stmt))
3264 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3265 ? sizetype : TREE_TYPE (x);
3266 tree t = fold_convert (stept,
3267 OMP_CLAUSE_LINEAR_STEP (c));
3268 tree c = find_omp_clause (clauses,
3269 OMP_CLAUSE__LOOPTEMP_);
3270 gcc_assert (c);
3271 tree l = OMP_CLAUSE_DECL (c);
3272 if (fd->collapse == 1)
3274 tree n1 = fd->loop.n1;
3275 tree step = fd->loop.step;
3276 tree itype = TREE_TYPE (l);
3277 if (POINTER_TYPE_P (itype))
3278 itype = signed_type_for (itype);
3279 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3280 if (TYPE_UNSIGNED (itype)
3281 && fd->loop.cond_code == GT_EXPR)
3282 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3283 fold_build1 (NEGATE_EXPR,
3284 itype, l),
3285 fold_build1 (NEGATE_EXPR,
3286 itype, step));
3287 else
3288 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3290 t = fold_build2 (MULT_EXPR, stept,
3291 fold_convert (stept, l), t);
3292 if (POINTER_TYPE_P (TREE_TYPE (x)))
3293 x = fold_build2 (POINTER_PLUS_EXPR,
3294 TREE_TYPE (x), x, t);
3295 else
3296 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3299 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3300 || TREE_ADDRESSABLE (new_var))
3301 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3302 idx, lane, ivar, lvar))
3304 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3306 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3307 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3308 gimplify_and_add (x, ilist);
3309 gimple_stmt_iterator gsi
3310 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3311 gimple g
3312 = gimple_build_assign (unshare_expr (lvar), iv);
3313 gsi_insert_before_without_update (&gsi, g,
3314 GSI_SAME_STMT);
3315 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3316 ? sizetype : TREE_TYPE (x);
3317 tree t = fold_convert (stept,
3318 OMP_CLAUSE_LINEAR_STEP (c));
3319 enum tree_code code = PLUS_EXPR;
3320 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3321 code = POINTER_PLUS_EXPR;
3322 g = gimple_build_assign_with_ops (code, iv, iv, t);
3323 gsi_insert_before_without_update (&gsi, g,
3324 GSI_SAME_STMT);
3325 break;
3327 x = lang_hooks.decls.omp_clause_copy_ctor
3328 (c, unshare_expr (ivar), x);
3329 gimplify_and_add (x, &llist[0]);
3330 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3331 if (x)
3333 gimple_seq tseq = NULL;
3335 dtor = x;
3336 gimplify_stmt (&dtor, &tseq);
3337 gimple_seq_add_seq (&llist[1], tseq);
3339 break;
3342 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3343 gimplify_and_add (x, ilist);
3344 goto do_dtor;
3346 case OMP_CLAUSE__LOOPTEMP_:
3347 gcc_assert (is_parallel_ctx (ctx));
3348 x = build_outer_var_ref (var, ctx);
3349 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3350 gimplify_and_add (x, ilist);
3351 break;
3353 case OMP_CLAUSE_COPYIN:
3354 by_ref = use_pointer_for_field (var, NULL);
3355 x = build_receiver_ref (var, by_ref, ctx);
3356 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3357 append_to_statement_list (x, &copyin_seq);
3358 copyin_by_ref |= by_ref;
3359 break;
3361 case OMP_CLAUSE_REDUCTION:
3362 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3364 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3365 gimple tseq;
3366 x = build_outer_var_ref (var, ctx);
3368 if (is_reference (var)
3369 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3370 TREE_TYPE (x)))
3371 x = build_fold_addr_expr_loc (clause_loc, x);
3372 SET_DECL_VALUE_EXPR (placeholder, x);
3373 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3374 tree new_vard = new_var;
3375 if (is_reference (var))
3377 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3378 new_vard = TREE_OPERAND (new_var, 0);
3379 gcc_assert (DECL_P (new_vard));
3381 if (is_simd
3382 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3383 idx, lane, ivar, lvar))
3385 if (new_vard == new_var)
3387 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3388 SET_DECL_VALUE_EXPR (new_var, ivar);
3390 else
3392 SET_DECL_VALUE_EXPR (new_vard,
3393 build_fold_addr_expr (ivar));
3394 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3396 x = lang_hooks.decls.omp_clause_default_ctor
3397 (c, unshare_expr (ivar),
3398 build_outer_var_ref (var, ctx));
3399 if (x)
3400 gimplify_and_add (x, &llist[0]);
3401 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3403 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3404 lower_omp (&tseq, ctx);
3405 gimple_seq_add_seq (&llist[0], tseq);
3407 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3408 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3409 lower_omp (&tseq, ctx);
3410 gimple_seq_add_seq (&llist[1], tseq);
3411 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3412 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3413 if (new_vard == new_var)
3414 SET_DECL_VALUE_EXPR (new_var, lvar);
3415 else
3416 SET_DECL_VALUE_EXPR (new_vard,
3417 build_fold_addr_expr (lvar));
3418 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3419 if (x)
3421 tseq = NULL;
3422 dtor = x;
3423 gimplify_stmt (&dtor, &tseq);
3424 gimple_seq_add_seq (&llist[1], tseq);
3426 break;
3428 x = lang_hooks.decls.omp_clause_default_ctor
3429 (c, new_var, unshare_expr (x));
3430 if (x)
3431 gimplify_and_add (x, ilist);
3432 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3434 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3435 lower_omp (&tseq, ctx);
3436 gimple_seq_add_seq (ilist, tseq);
3438 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3439 if (is_simd)
3441 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3442 lower_omp (&tseq, ctx);
3443 gimple_seq_add_seq (dlist, tseq);
3444 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3446 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3447 goto do_dtor;
3449 else
3451 x = omp_reduction_init (c, TREE_TYPE (new_var));
3452 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3453 if (is_simd
3454 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3455 idx, lane, ivar, lvar))
3457 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3458 tree ref = build_outer_var_ref (var, ctx);
3460 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3462 /* reduction(-:var) sums up the partial results, so it
3463 acts identically to reduction(+:var). */
3464 if (code == MINUS_EXPR)
3465 code = PLUS_EXPR;
3467 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3468 ref = build_outer_var_ref (var, ctx);
3469 gimplify_assign (ref, x, &llist[1]);
3471 else
3473 gimplify_assign (new_var, x, ilist);
3474 if (is_simd)
3475 gimplify_assign (build_outer_var_ref (var, ctx),
3476 new_var, dlist);
3479 break;
3481 default:
3482 gcc_unreachable ();
3487 if (lane)
3489 tree uid = create_tmp_var (ptr_type_node, "simduid");
3490 /* Don't want uninit warnings on simduid, it is always uninitialized,
3491 but we use it not for the value, but for the DECL_UID only. */
3492 TREE_NO_WARNING (uid) = 1;
3493 gimple g
3494 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3495 gimple_call_set_lhs (g, lane);
3496 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3497 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3498 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3499 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3500 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3501 gimple_omp_for_set_clauses (ctx->stmt, c);
3502 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3503 build_int_cst (unsigned_type_node, 0),
3504 NULL_TREE);
3505 gimple_seq_add_stmt (ilist, g);
3506 for (int i = 0; i < 2; i++)
3507 if (llist[i])
3509 tree vf = create_tmp_var (unsigned_type_node, NULL);
3510 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3511 gimple_call_set_lhs (g, vf);
3512 gimple_seq *seq = i == 0 ? ilist : dlist;
3513 gimple_seq_add_stmt (seq, g);
3514 tree t = build_int_cst (unsigned_type_node, 0);
3515 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3516 gimple_seq_add_stmt (seq, g);
3517 tree body = create_artificial_label (UNKNOWN_LOCATION);
3518 tree header = create_artificial_label (UNKNOWN_LOCATION);
3519 tree end = create_artificial_label (UNKNOWN_LOCATION);
3520 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3521 gimple_seq_add_stmt (seq, gimple_build_label (body));
3522 gimple_seq_add_seq (seq, llist[i]);
3523 t = build_int_cst (unsigned_type_node, 1);
3524 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3525 gimple_seq_add_stmt (seq, g);
3526 gimple_seq_add_stmt (seq, gimple_build_label (header));
3527 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3528 gimple_seq_add_stmt (seq, g);
3529 gimple_seq_add_stmt (seq, gimple_build_label (end));
3533 /* The copyin sequence is not to be executed by the main thread, since
3534 that would result in self-copies. Perhaps not visible to scalars,
3535 but it certainly is to C++ operator=. */
3536 if (copyin_seq)
3538 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3540 x = build2 (NE_EXPR, boolean_type_node, x,
3541 build_int_cst (TREE_TYPE (x), 0));
3542 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3543 gimplify_and_add (x, ilist);
3546 /* If any copyin variable is passed by reference, we must ensure the
3547 master thread doesn't modify it before it is copied over in all
3548 threads. Similarly for variables in both firstprivate and
3549 lastprivate clauses we need to ensure the lastprivate copying
3550 happens after firstprivate copying in all threads. And similarly
3551 for UDRs if initializer expression refers to omp_orig. */
3552 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3554 /* Don't add any barrier for #pragma omp simd or
3555 #pragma omp distribute. */
3556 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3557 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3558 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3561 /* If max_vf is non-zero, then we can use only a vectorization factor
3562 up to the max_vf we chose. So stick it into the safelen clause. */
3563 if (max_vf)
3565 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3566 OMP_CLAUSE_SAFELEN);
3567 if (c == NULL_TREE
3568 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3569 max_vf) == 1)
3571 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3572 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3573 max_vf);
3574 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3575 gimple_omp_for_set_clauses (ctx->stmt, c);
3581 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3582 both parallel and workshare constructs. PREDICATE may be NULL if it's
3583 always true. */
3585 static void
3586 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3587 omp_context *ctx)
3589 tree x, c, label = NULL, orig_clauses = clauses;
3590 bool par_clauses = false;
3591 tree simduid = NULL, lastlane = NULL;
3593 /* Early exit if there are no lastprivate or linear clauses. */
3594 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3595 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3596 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3597 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3598 break;
3599 if (clauses == NULL)
3601 /* If this was a workshare clause, see if it had been combined
3602 with its parallel. In that case, look for the clauses on the
3603 parallel statement itself. */
3604 if (is_parallel_ctx (ctx))
3605 return;
3607 ctx = ctx->outer;
3608 if (ctx == NULL || !is_parallel_ctx (ctx))
3609 return;
3611 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3612 OMP_CLAUSE_LASTPRIVATE);
3613 if (clauses == NULL)
3614 return;
3615 par_clauses = true;
3618 if (predicate)
3620 gimple stmt;
3621 tree label_true, arm1, arm2;
3623 label = create_artificial_label (UNKNOWN_LOCATION);
3624 label_true = create_artificial_label (UNKNOWN_LOCATION);
3625 arm1 = TREE_OPERAND (predicate, 0);
3626 arm2 = TREE_OPERAND (predicate, 1);
3627 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3628 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3629 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3630 label_true, label);
3631 gimple_seq_add_stmt (stmt_list, stmt);
3632 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3635 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3636 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3638 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3639 if (simduid)
3640 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3643 for (c = clauses; c ;)
3645 tree var, new_var;
3646 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3648 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3649 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3650 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3652 var = OMP_CLAUSE_DECL (c);
3653 new_var = lookup_decl (var, ctx);
3655 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3657 tree val = DECL_VALUE_EXPR (new_var);
3658 if (TREE_CODE (val) == ARRAY_REF
3659 && VAR_P (TREE_OPERAND (val, 0))
3660 && lookup_attribute ("omp simd array",
3661 DECL_ATTRIBUTES (TREE_OPERAND (val,
3662 0))))
3664 if (lastlane == NULL)
3666 lastlane = create_tmp_var (unsigned_type_node, NULL);
3667 gimple g
3668 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3669 2, simduid,
3670 TREE_OPERAND (val, 1));
3671 gimple_call_set_lhs (g, lastlane);
3672 gimple_seq_add_stmt (stmt_list, g);
3674 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3675 TREE_OPERAND (val, 0), lastlane,
3676 NULL_TREE, NULL_TREE);
3680 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3681 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3683 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3684 gimple_seq_add_seq (stmt_list,
3685 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3686 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3689 x = build_outer_var_ref (var, ctx);
3690 if (is_reference (var))
3691 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3692 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3693 gimplify_and_add (x, stmt_list);
3695 c = OMP_CLAUSE_CHAIN (c);
3696 if (c == NULL && !par_clauses)
3698 /* If this was a workshare clause, see if it had been combined
3699 with its parallel. In that case, continue looking for the
3700 clauses also on the parallel statement itself. */
3701 if (is_parallel_ctx (ctx))
3702 break;
3704 ctx = ctx->outer;
3705 if (ctx == NULL || !is_parallel_ctx (ctx))
3706 break;
3708 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3709 OMP_CLAUSE_LASTPRIVATE);
3710 par_clauses = true;
3714 if (label)
3715 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3719 /* Generate code to implement the REDUCTION clauses. */
3721 static void
3722 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3724 gimple_seq sub_seq = NULL;
3725 gimple stmt;
3726 tree x, c;
3727 int count = 0;
3729 /* SIMD reductions are handled in lower_rec_input_clauses. */
3730 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3731 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3732 return;
3734 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3735 update in that case, otherwise use a lock. */
3736 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3737 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3739 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3741 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3742 count = -1;
3743 break;
3745 count++;
3748 if (count == 0)
3749 return;
3751 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3753 tree var, ref, new_var;
3754 enum tree_code code;
3755 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3757 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3758 continue;
3760 var = OMP_CLAUSE_DECL (c);
3761 new_var = lookup_decl (var, ctx);
3762 if (is_reference (var))
3763 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3764 ref = build_outer_var_ref (var, ctx);
3765 code = OMP_CLAUSE_REDUCTION_CODE (c);
3767 /* reduction(-:var) sums up the partial results, so it acts
3768 identically to reduction(+:var). */
3769 if (code == MINUS_EXPR)
3770 code = PLUS_EXPR;
3772 if (count == 1)
3774 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3776 addr = save_expr (addr);
3777 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3778 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3779 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3780 gimplify_and_add (x, stmt_seqp);
3781 return;
3784 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3786 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3788 if (is_reference (var)
3789 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3790 TREE_TYPE (ref)))
3791 ref = build_fold_addr_expr_loc (clause_loc, ref);
3792 SET_DECL_VALUE_EXPR (placeholder, ref);
3793 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3794 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3795 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3796 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3797 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3799 else
3801 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3802 ref = build_outer_var_ref (var, ctx);
3803 gimplify_assign (ref, x, &sub_seq);
3807 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3809 gimple_seq_add_stmt (stmt_seqp, stmt);
3811 gimple_seq_add_seq (stmt_seqp, sub_seq);
3813 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3815 gimple_seq_add_stmt (stmt_seqp, stmt);
3819 /* Generate code to implement the COPYPRIVATE clauses. */
3821 static void
3822 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3823 omp_context *ctx)
3825 tree c;
3827 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3829 tree var, new_var, ref, x;
3830 bool by_ref;
3831 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3833 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3834 continue;
3836 var = OMP_CLAUSE_DECL (c);
3837 by_ref = use_pointer_for_field (var, NULL);
3839 ref = build_sender_ref (var, ctx);
3840 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3841 if (by_ref)
3843 x = build_fold_addr_expr_loc (clause_loc, new_var);
3844 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3846 gimplify_assign (ref, x, slist);
3848 ref = build_receiver_ref (var, false, ctx);
3849 if (by_ref)
3851 ref = fold_convert_loc (clause_loc,
3852 build_pointer_type (TREE_TYPE (new_var)),
3853 ref);
3854 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3856 if (is_reference (var))
3858 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3859 ref = build_simple_mem_ref_loc (clause_loc, ref);
3860 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3862 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3863 gimplify_and_add (x, rlist);
3868 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3869 and REDUCTION from the sender (aka parent) side. */
3871 static void
3872 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3873 omp_context *ctx)
3875 tree c;
3877 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3879 tree val, ref, x, var;
3880 bool by_ref, do_in = false, do_out = false;
3881 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3883 switch (OMP_CLAUSE_CODE (c))
3885 case OMP_CLAUSE_PRIVATE:
3886 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3887 break;
3888 continue;
3889 case OMP_CLAUSE_FIRSTPRIVATE:
3890 case OMP_CLAUSE_COPYIN:
3891 case OMP_CLAUSE_LASTPRIVATE:
3892 case OMP_CLAUSE_REDUCTION:
3893 case OMP_CLAUSE__LOOPTEMP_:
3894 break;
3895 default:
3896 continue;
3899 val = OMP_CLAUSE_DECL (c);
3900 var = lookup_decl_in_outer_ctx (val, ctx);
3902 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
3903 && is_global_var (var))
3904 continue;
3905 if (is_variable_sized (val))
3906 continue;
3907 by_ref = use_pointer_for_field (val, NULL);
3909 switch (OMP_CLAUSE_CODE (c))
3911 case OMP_CLAUSE_PRIVATE:
3912 case OMP_CLAUSE_FIRSTPRIVATE:
3913 case OMP_CLAUSE_COPYIN:
3914 case OMP_CLAUSE__LOOPTEMP_:
3915 do_in = true;
3916 break;
3918 case OMP_CLAUSE_LASTPRIVATE:
3919 if (by_ref || is_reference (val))
3921 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3922 continue;
3923 do_in = true;
3925 else
3927 do_out = true;
3928 if (lang_hooks.decls.omp_private_outer_ref (val))
3929 do_in = true;
3931 break;
3933 case OMP_CLAUSE_REDUCTION:
3934 do_in = true;
3935 do_out = !(by_ref || is_reference (val));
3936 break;
3938 default:
3939 gcc_unreachable ();
3942 if (do_in)
3944 ref = build_sender_ref (val, ctx);
3945 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
3946 gimplify_assign (ref, x, ilist);
3947 if (is_task_ctx (ctx))
3948 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
3951 if (do_out)
3953 ref = build_sender_ref (val, ctx);
3954 gimplify_assign (var, ref, olist);
3959 /* Generate code to implement SHARED from the sender (aka parent)
3960 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
3961 list things that got automatically shared. */
3963 static void
3964 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
3966 tree var, ovar, nvar, f, x, record_type;
3968 if (ctx->record_type == NULL)
3969 return;
3971 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
3972 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
3974 ovar = DECL_ABSTRACT_ORIGIN (f);
3975 nvar = maybe_lookup_decl (ovar, ctx);
3976 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
3977 continue;
3979 /* If CTX is a nested parallel directive. Find the immediately
3980 enclosing parallel or workshare construct that contains a
3981 mapping for OVAR. */
3982 var = lookup_decl_in_outer_ctx (ovar, ctx);
3984 if (use_pointer_for_field (ovar, ctx))
3986 x = build_sender_ref (ovar, ctx);
3987 var = build_fold_addr_expr (var);
3988 gimplify_assign (x, var, ilist);
3990 else
3992 x = build_sender_ref (ovar, ctx);
3993 gimplify_assign (x, var, ilist);
3995 if (!TREE_READONLY (var)
3996 /* We don't need to receive a new reference to a result
3997 or parm decl. In fact we may not store to it as we will
3998 invalidate any pending RSO and generate wrong gimple
3999 during inlining. */
4000 && !((TREE_CODE (var) == RESULT_DECL
4001 || TREE_CODE (var) == PARM_DECL)
4002 && DECL_BY_REFERENCE (var)))
4004 x = build_sender_ref (ovar, ctx);
4005 gimplify_assign (var, x, olist);
4012 /* A convenience function to build an empty GIMPLE_COND with just the
4013 condition. */
4015 static gimple
4016 gimple_build_cond_empty (tree cond)
4018 enum tree_code pred_code;
4019 tree lhs, rhs;
4021 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4022 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4026 /* Build the function calls to GOMP_parallel_start etc to actually
4027 generate the parallel operation. REGION is the parallel region
4028 being expanded. BB is the block where to insert the code. WS_ARGS
4029 will be set if this is a call to a combined parallel+workshare
4030 construct, it contains the list of additional arguments needed by
4031 the workshare construct. */
4033 static void
4034 expand_parallel_call (struct omp_region *region, basic_block bb,
4035 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4037 tree t, t1, t2, val, cond, c, clauses, flags;
4038 gimple_stmt_iterator gsi;
4039 gimple stmt;
4040 enum built_in_function start_ix;
4041 int start_ix2;
4042 location_t clause_loc;
4043 vec<tree, va_gc> *args;
4045 clauses = gimple_omp_parallel_clauses (entry_stmt);
4047 /* Determine what flavor of GOMP_parallel we will be
4048 emitting. */
4049 start_ix = BUILT_IN_GOMP_PARALLEL;
4050 if (is_combined_parallel (region))
4052 switch (region->inner->type)
4054 case GIMPLE_OMP_FOR:
4055 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4056 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4057 + (region->inner->sched_kind
4058 == OMP_CLAUSE_SCHEDULE_RUNTIME
4059 ? 3 : region->inner->sched_kind));
4060 start_ix = (enum built_in_function)start_ix2;
4061 break;
4062 case GIMPLE_OMP_SECTIONS:
4063 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4064 break;
4065 default:
4066 gcc_unreachable ();
4070 /* By default, the value of NUM_THREADS is zero (selected at run time)
4071 and there is no conditional. */
4072 cond = NULL_TREE;
4073 val = build_int_cst (unsigned_type_node, 0);
4074 flags = build_int_cst (unsigned_type_node, 0);
4076 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4077 if (c)
4078 cond = OMP_CLAUSE_IF_EXPR (c);
4080 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4081 if (c)
4083 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4084 clause_loc = OMP_CLAUSE_LOCATION (c);
4086 else
4087 clause_loc = gimple_location (entry_stmt);
4089 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4090 if (c)
4091 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4093 /* Ensure 'val' is of the correct type. */
4094 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4096 /* If we found the clause 'if (cond)', build either
4097 (cond != 0) or (cond ? val : 1u). */
4098 if (cond)
4100 gimple_stmt_iterator gsi;
4102 cond = gimple_boolify (cond);
4104 if (integer_zerop (val))
4105 val = fold_build2_loc (clause_loc,
4106 EQ_EXPR, unsigned_type_node, cond,
4107 build_int_cst (TREE_TYPE (cond), 0));
4108 else
4110 basic_block cond_bb, then_bb, else_bb;
4111 edge e, e_then, e_else;
4112 tree tmp_then, tmp_else, tmp_join, tmp_var;
4114 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4115 if (gimple_in_ssa_p (cfun))
4117 tmp_then = make_ssa_name (tmp_var, NULL);
4118 tmp_else = make_ssa_name (tmp_var, NULL);
4119 tmp_join = make_ssa_name (tmp_var, NULL);
4121 else
4123 tmp_then = tmp_var;
4124 tmp_else = tmp_var;
4125 tmp_join = tmp_var;
4128 e = split_block (bb, NULL);
4129 cond_bb = e->src;
4130 bb = e->dest;
4131 remove_edge (e);
4133 then_bb = create_empty_bb (cond_bb);
4134 else_bb = create_empty_bb (then_bb);
4135 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4136 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4138 stmt = gimple_build_cond_empty (cond);
4139 gsi = gsi_start_bb (cond_bb);
4140 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4142 gsi = gsi_start_bb (then_bb);
4143 stmt = gimple_build_assign (tmp_then, val);
4144 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4146 gsi = gsi_start_bb (else_bb);
4147 stmt = gimple_build_assign
4148 (tmp_else, build_int_cst (unsigned_type_node, 1));
4149 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4151 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4152 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4153 if (current_loops)
4155 add_bb_to_loop (then_bb, cond_bb->loop_father);
4156 add_bb_to_loop (else_bb, cond_bb->loop_father);
4158 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4159 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4161 if (gimple_in_ssa_p (cfun))
4163 gimple phi = create_phi_node (tmp_join, bb);
4164 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4165 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4168 val = tmp_join;
4171 gsi = gsi_start_bb (bb);
4172 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4173 false, GSI_CONTINUE_LINKING);
4176 gsi = gsi_last_bb (bb);
4177 t = gimple_omp_parallel_data_arg (entry_stmt);
4178 if (t == NULL)
4179 t1 = null_pointer_node;
4180 else
4181 t1 = build_fold_addr_expr (t);
4182 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4184 vec_alloc (args, 4 + vec_safe_length (ws_args));
4185 args->quick_push (t2);
4186 args->quick_push (t1);
4187 args->quick_push (val);
4188 if (ws_args)
4189 args->splice (*ws_args);
4190 args->quick_push (flags);
4192 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4193 builtin_decl_explicit (start_ix), args);
4195 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4196 false, GSI_CONTINUE_LINKING);
4200 /* Build the function call to GOMP_task to actually
4201 generate the task operation. BB is the block where to insert the code. */
4203 static void
4204 expand_task_call (basic_block bb, gimple entry_stmt)
4206 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4207 gimple_stmt_iterator gsi;
4208 location_t loc = gimple_location (entry_stmt);
4210 clauses = gimple_omp_task_clauses (entry_stmt);
4212 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4213 if (c)
4214 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4215 else
4216 cond = boolean_true_node;
4218 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4219 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4220 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4221 flags = build_int_cst (unsigned_type_node,
4222 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4224 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4225 if (c)
4227 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4228 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4229 build_int_cst (unsigned_type_node, 2),
4230 build_int_cst (unsigned_type_node, 0));
4231 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4233 if (depend)
4234 depend = OMP_CLAUSE_DECL (depend);
4235 else
4236 depend = build_int_cst (ptr_type_node, 0);
4238 gsi = gsi_last_bb (bb);
4239 t = gimple_omp_task_data_arg (entry_stmt);
4240 if (t == NULL)
4241 t2 = null_pointer_node;
4242 else
4243 t2 = build_fold_addr_expr_loc (loc, t);
4244 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4245 t = gimple_omp_task_copy_fn (entry_stmt);
4246 if (t == NULL)
4247 t3 = null_pointer_node;
4248 else
4249 t3 = build_fold_addr_expr_loc (loc, t);
4251 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4252 8, t1, t2, t3,
4253 gimple_omp_task_arg_size (entry_stmt),
4254 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4255 depend);
4257 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4258 false, GSI_CONTINUE_LINKING);
4262 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4263 catch handler and return it. This prevents programs from violating the
4264 structured block semantics with throws. */
4266 static gimple_seq
4267 maybe_catch_exception (gimple_seq body)
4269 gimple g;
4270 tree decl;
4272 if (!flag_exceptions)
4273 return body;
4275 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4276 decl = lang_hooks.eh_protect_cleanup_actions ();
4277 else
4278 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4280 g = gimple_build_eh_must_not_throw (decl);
4281 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4282 GIMPLE_TRY_CATCH);
4284 return gimple_seq_alloc_with_stmt (g);
4287 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4289 static tree
4290 vec2chain (vec<tree, va_gc> *v)
4292 tree chain = NULL_TREE, t;
4293 unsigned ix;
4295 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4297 DECL_CHAIN (t) = chain;
4298 chain = t;
4301 return chain;
4305 /* Remove barriers in REGION->EXIT's block. Note that this is only
4306 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4307 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4308 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4309 removed. */
4311 static void
4312 remove_exit_barrier (struct omp_region *region)
4314 gimple_stmt_iterator gsi;
4315 basic_block exit_bb;
4316 edge_iterator ei;
4317 edge e;
4318 gimple stmt;
4319 int any_addressable_vars = -1;
4321 exit_bb = region->exit;
4323 /* If the parallel region doesn't return, we don't have REGION->EXIT
4324 block at all. */
4325 if (! exit_bb)
4326 return;
4328 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4329 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4330 statements that can appear in between are extremely limited -- no
4331 memory operations at all. Here, we allow nothing at all, so the
4332 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4333 gsi = gsi_last_bb (exit_bb);
4334 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4335 gsi_prev (&gsi);
4336 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4337 return;
4339 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4341 gsi = gsi_last_bb (e->src);
4342 if (gsi_end_p (gsi))
4343 continue;
4344 stmt = gsi_stmt (gsi);
4345 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4346 && !gimple_omp_return_nowait_p (stmt))
4348 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4349 in many cases. If there could be tasks queued, the barrier
4350 might be needed to let the tasks run before some local
4351 variable of the parallel that the task uses as shared
4352 runs out of scope. The task can be spawned either
4353 from within current function (this would be easy to check)
4354 or from some function it calls and gets passed an address
4355 of such a variable. */
4356 if (any_addressable_vars < 0)
4358 gimple parallel_stmt = last_stmt (region->entry);
4359 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4360 tree local_decls, block, decl;
4361 unsigned ix;
4363 any_addressable_vars = 0;
4364 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4365 if (TREE_ADDRESSABLE (decl))
4367 any_addressable_vars = 1;
4368 break;
4370 for (block = gimple_block (stmt);
4371 !any_addressable_vars
4372 && block
4373 && TREE_CODE (block) == BLOCK;
4374 block = BLOCK_SUPERCONTEXT (block))
4376 for (local_decls = BLOCK_VARS (block);
4377 local_decls;
4378 local_decls = DECL_CHAIN (local_decls))
4379 if (TREE_ADDRESSABLE (local_decls))
4381 any_addressable_vars = 1;
4382 break;
4384 if (block == gimple_block (parallel_stmt))
4385 break;
4388 if (!any_addressable_vars)
4389 gimple_omp_return_set_nowait (stmt);
4394 static void
4395 remove_exit_barriers (struct omp_region *region)
4397 if (region->type == GIMPLE_OMP_PARALLEL)
4398 remove_exit_barrier (region);
4400 if (region->inner)
4402 region = region->inner;
4403 remove_exit_barriers (region);
4404 while (region->next)
4406 region = region->next;
4407 remove_exit_barriers (region);
4412 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4413 calls. These can't be declared as const functions, but
4414 within one parallel body they are constant, so they can be
4415 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4416 which are declared const. Similarly for task body, except
4417 that in untied task omp_get_thread_num () can change at any task
4418 scheduling point. */
4420 static void
4421 optimize_omp_library_calls (gimple entry_stmt)
4423 basic_block bb;
4424 gimple_stmt_iterator gsi;
4425 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4426 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4427 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4428 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4429 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4430 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4431 OMP_CLAUSE_UNTIED) != NULL);
4433 FOR_EACH_BB (bb)
4434 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4436 gimple call = gsi_stmt (gsi);
4437 tree decl;
4439 if (is_gimple_call (call)
4440 && (decl = gimple_call_fndecl (call))
4441 && DECL_EXTERNAL (decl)
4442 && TREE_PUBLIC (decl)
4443 && DECL_INITIAL (decl) == NULL)
4445 tree built_in;
4447 if (DECL_NAME (decl) == thr_num_id)
4449 /* In #pragma omp task untied omp_get_thread_num () can change
4450 during the execution of the task region. */
4451 if (untied_task)
4452 continue;
4453 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4455 else if (DECL_NAME (decl) == num_thr_id)
4456 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4457 else
4458 continue;
4460 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4461 || gimple_call_num_args (call) != 0)
4462 continue;
4464 if (flag_exceptions && !TREE_NOTHROW (decl))
4465 continue;
4467 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4468 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4469 TREE_TYPE (TREE_TYPE (built_in))))
4470 continue;
4472 gimple_call_set_fndecl (call, built_in);
4477 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4478 regimplified. */
4480 static tree
4481 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4483 tree t = *tp;
4485 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4486 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4487 return t;
4489 if (TREE_CODE (t) == ADDR_EXPR)
4490 recompute_tree_invariant_for_addr_expr (t);
4492 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4493 return NULL_TREE;
4496 /* Prepend TO = FROM assignment before *GSI_P. */
4498 static void
4499 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4501 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4502 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4503 true, GSI_SAME_STMT);
4504 gimple stmt = gimple_build_assign (to, from);
4505 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4506 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4507 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4509 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4510 gimple_regimplify_operands (stmt, &gsi);
4514 /* Expand the OpenMP parallel or task directive starting at REGION. */
4516 static void
4517 expand_omp_taskreg (struct omp_region *region)
4519 basic_block entry_bb, exit_bb, new_bb;
4520 struct function *child_cfun;
4521 tree child_fn, block, t;
4522 gimple_stmt_iterator gsi;
4523 gimple entry_stmt, stmt;
4524 edge e;
4525 vec<tree, va_gc> *ws_args;
4527 entry_stmt = last_stmt (region->entry);
4528 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4529 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4531 entry_bb = region->entry;
4532 exit_bb = region->exit;
4534 if (is_combined_parallel (region))
4535 ws_args = region->ws_args;
4536 else
4537 ws_args = NULL;
4539 if (child_cfun->cfg)
4541 /* Due to inlining, it may happen that we have already outlined
4542 the region, in which case all we need to do is make the
4543 sub-graph unreachable and emit the parallel call. */
4544 edge entry_succ_e, exit_succ_e;
4545 gimple_stmt_iterator gsi;
4547 entry_succ_e = single_succ_edge (entry_bb);
4549 gsi = gsi_last_bb (entry_bb);
4550 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4551 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4552 gsi_remove (&gsi, true);
4554 new_bb = entry_bb;
4555 if (exit_bb)
4557 exit_succ_e = single_succ_edge (exit_bb);
4558 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4560 remove_edge_and_dominated_blocks (entry_succ_e);
4562 else
4564 unsigned srcidx, dstidx, num;
4566 /* If the parallel region needs data sent from the parent
4567 function, then the very first statement (except possible
4568 tree profile counter updates) of the parallel body
4569 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4570 &.OMP_DATA_O is passed as an argument to the child function,
4571 we need to replace it with the argument as seen by the child
4572 function.
4574 In most cases, this will end up being the identity assignment
4575 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4576 a function call that has been inlined, the original PARM_DECL
4577 .OMP_DATA_I may have been converted into a different local
4578 variable. In which case, we need to keep the assignment. */
4579 if (gimple_omp_taskreg_data_arg (entry_stmt))
4581 basic_block entry_succ_bb = single_succ (entry_bb);
4582 gimple_stmt_iterator gsi;
4583 tree arg, narg;
4584 gimple parcopy_stmt = NULL;
4586 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4588 gimple stmt;
4590 gcc_assert (!gsi_end_p (gsi));
4591 stmt = gsi_stmt (gsi);
4592 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4593 continue;
4595 if (gimple_num_ops (stmt) == 2)
4597 tree arg = gimple_assign_rhs1 (stmt);
4599 /* We're ignore the subcode because we're
4600 effectively doing a STRIP_NOPS. */
4602 if (TREE_CODE (arg) == ADDR_EXPR
4603 && TREE_OPERAND (arg, 0)
4604 == gimple_omp_taskreg_data_arg (entry_stmt))
4606 parcopy_stmt = stmt;
4607 break;
4612 gcc_assert (parcopy_stmt != NULL);
4613 arg = DECL_ARGUMENTS (child_fn);
4615 if (!gimple_in_ssa_p (cfun))
4617 if (gimple_assign_lhs (parcopy_stmt) == arg)
4618 gsi_remove (&gsi, true);
4619 else
4621 /* ?? Is setting the subcode really necessary ?? */
4622 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4623 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4626 else
4628 /* If we are in ssa form, we must load the value from the default
4629 definition of the argument. That should not be defined now,
4630 since the argument is not used uninitialized. */
4631 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4632 narg = make_ssa_name (arg, gimple_build_nop ());
4633 set_ssa_default_def (cfun, arg, narg);
4634 /* ?? Is setting the subcode really necessary ?? */
4635 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4636 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4637 update_stmt (parcopy_stmt);
4641 /* Declare local variables needed in CHILD_CFUN. */
4642 block = DECL_INITIAL (child_fn);
4643 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4644 /* The gimplifier could record temporaries in parallel/task block
4645 rather than in containing function's local_decls chain,
4646 which would mean cgraph missed finalizing them. Do it now. */
4647 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4648 if (TREE_CODE (t) == VAR_DECL
4649 && TREE_STATIC (t)
4650 && !DECL_EXTERNAL (t))
4651 varpool_finalize_decl (t);
4652 DECL_SAVED_TREE (child_fn) = NULL;
4653 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4654 gimple_set_body (child_fn, NULL);
4655 TREE_USED (block) = 1;
4657 /* Reset DECL_CONTEXT on function arguments. */
4658 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4659 DECL_CONTEXT (t) = child_fn;
4661 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4662 so that it can be moved to the child function. */
4663 gsi = gsi_last_bb (entry_bb);
4664 stmt = gsi_stmt (gsi);
4665 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4666 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4667 gsi_remove (&gsi, true);
4668 e = split_block (entry_bb, stmt);
4669 entry_bb = e->dest;
4670 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4672 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4673 if (exit_bb)
4675 gsi = gsi_last_bb (exit_bb);
4676 gcc_assert (!gsi_end_p (gsi)
4677 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4678 stmt = gimple_build_return (NULL);
4679 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4680 gsi_remove (&gsi, true);
4683 /* Move the parallel region into CHILD_CFUN. */
4685 if (gimple_in_ssa_p (cfun))
4687 init_tree_ssa (child_cfun);
4688 init_ssa_operands (child_cfun);
4689 child_cfun->gimple_df->in_ssa_p = true;
4690 block = NULL_TREE;
4692 else
4693 block = gimple_block (entry_stmt);
4695 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4696 if (exit_bb)
4697 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4698 /* When the OMP expansion process cannot guarantee an up-to-date
4699 loop tree arrange for the child function to fixup loops. */
4700 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4701 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4703 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4704 num = vec_safe_length (child_cfun->local_decls);
4705 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4707 t = (*child_cfun->local_decls)[srcidx];
4708 if (DECL_CONTEXT (t) == cfun->decl)
4709 continue;
4710 if (srcidx != dstidx)
4711 (*child_cfun->local_decls)[dstidx] = t;
4712 dstidx++;
4714 if (dstidx != num)
4715 vec_safe_truncate (child_cfun->local_decls, dstidx);
4717 /* Inform the callgraph about the new function. */
4718 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4719 cgraph_add_new_function (child_fn, true);
4721 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4722 fixed in a following pass. */
4723 push_cfun (child_cfun);
4724 if (optimize)
4725 optimize_omp_library_calls (entry_stmt);
4726 rebuild_cgraph_edges ();
4728 /* Some EH regions might become dead, see PR34608. If
4729 pass_cleanup_cfg isn't the first pass to happen with the
4730 new child, these dead EH edges might cause problems.
4731 Clean them up now. */
4732 if (flag_exceptions)
4734 basic_block bb;
4735 bool changed = false;
4737 FOR_EACH_BB (bb)
4738 changed |= gimple_purge_dead_eh_edges (bb);
4739 if (changed)
4740 cleanup_tree_cfg ();
4742 if (gimple_in_ssa_p (cfun))
4743 update_ssa (TODO_update_ssa);
4744 pop_cfun ();
4747 /* Emit a library call to launch the children threads. */
4748 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4749 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4750 else
4751 expand_task_call (new_bb, entry_stmt);
4752 if (gimple_in_ssa_p (cfun))
4753 update_ssa (TODO_update_ssa_only_virtuals);
4757 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4758 of the combined collapse > 1 loop constructs, generate code like:
4759 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4760 if (cond3 is <)
4761 adj = STEP3 - 1;
4762 else
4763 adj = STEP3 + 1;
4764 count3 = (adj + N32 - N31) / STEP3;
4765 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4766 if (cond2 is <)
4767 adj = STEP2 - 1;
4768 else
4769 adj = STEP2 + 1;
4770 count2 = (adj + N22 - N21) / STEP2;
4771 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4772 if (cond1 is <)
4773 adj = STEP1 - 1;
4774 else
4775 adj = STEP1 + 1;
4776 count1 = (adj + N12 - N11) / STEP1;
4777 count = count1 * count2 * count3;
4778 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4779 count = 0;
4780 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4781 of the combined loop constructs, just initialize COUNTS array
4782 from the _looptemp_ clauses. */
4784 /* NOTE: It *could* be better to moosh all of the BBs together,
4785 creating one larger BB with all the computation and the unexpected
4786 jump at the end. I.e.
4788 bool zero3, zero2, zero1, zero;
4790 zero3 = N32 c3 N31;
4791 count3 = (N32 - N31) /[cl] STEP3;
4792 zero2 = N22 c2 N21;
4793 count2 = (N22 - N21) /[cl] STEP2;
4794 zero1 = N12 c1 N11;
4795 count1 = (N12 - N11) /[cl] STEP1;
4796 zero = zero3 || zero2 || zero1;
4797 count = count1 * count2 * count3;
4798 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4800 After all, we expect the zero=false, and thus we expect to have to
4801 evaluate all of the comparison expressions, so short-circuiting
4802 oughtn't be a win. Since the condition isn't protecting a
4803 denominator, we're not concerned about divide-by-zero, so we can
4804 fully evaluate count even if a numerator turned out to be wrong.
4806 It seems like putting this all together would create much better
4807 scheduling opportunities, and less pressure on the chip's branch
4808 predictor. */
4810 static void
4811 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4812 basic_block &entry_bb, tree *counts,
4813 basic_block &zero_iter_bb, int &first_zero_iter,
4814 basic_block &l2_dom_bb)
4816 tree t, type = TREE_TYPE (fd->loop.v);
4817 gimple stmt;
4818 edge e, ne;
4819 int i;
4821 /* Collapsed loops need work for expansion into SSA form. */
4822 gcc_assert (!gimple_in_ssa_p (cfun));
4824 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4825 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4827 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4828 isn't supposed to be handled, as the inner loop doesn't
4829 use it. */
4830 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4831 OMP_CLAUSE__LOOPTEMP_);
4832 gcc_assert (innerc);
4833 for (i = 0; i < fd->collapse; i++)
4835 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4836 OMP_CLAUSE__LOOPTEMP_);
4837 gcc_assert (innerc);
4838 if (i)
4839 counts[i] = OMP_CLAUSE_DECL (innerc);
4840 else
4841 counts[0] = NULL_TREE;
4843 return;
4846 for (i = 0; i < fd->collapse; i++)
4848 tree itype = TREE_TYPE (fd->loops[i].v);
4850 if (SSA_VAR_P (fd->loop.n2)
4851 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4852 fold_convert (itype, fd->loops[i].n1),
4853 fold_convert (itype, fd->loops[i].n2)))
4854 == NULL_TREE || !integer_onep (t)))
4856 tree n1, n2;
4857 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4858 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4859 true, GSI_SAME_STMT);
4860 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4861 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4862 true, GSI_SAME_STMT);
4863 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4864 NULL_TREE, NULL_TREE);
4865 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4866 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4867 expand_omp_regimplify_p, NULL, NULL)
4868 || walk_tree (gimple_cond_rhs_ptr (stmt),
4869 expand_omp_regimplify_p, NULL, NULL))
4871 *gsi = gsi_for_stmt (stmt);
4872 gimple_regimplify_operands (stmt, gsi);
4874 e = split_block (entry_bb, stmt);
4875 if (zero_iter_bb == NULL)
4877 first_zero_iter = i;
4878 zero_iter_bb = create_empty_bb (entry_bb);
4879 if (current_loops)
4880 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4881 *gsi = gsi_after_labels (zero_iter_bb);
4882 stmt = gimple_build_assign (fd->loop.n2,
4883 build_zero_cst (type));
4884 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4885 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
4886 entry_bb);
4888 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
4889 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
4890 e->flags = EDGE_TRUE_VALUE;
4891 e->probability = REG_BR_PROB_BASE - ne->probability;
4892 if (l2_dom_bb == NULL)
4893 l2_dom_bb = entry_bb;
4894 entry_bb = e->dest;
4895 *gsi = gsi_last_bb (entry_bb);
4898 if (POINTER_TYPE_P (itype))
4899 itype = signed_type_for (itype);
4900 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
4901 ? -1 : 1));
4902 t = fold_build2 (PLUS_EXPR, itype,
4903 fold_convert (itype, fd->loops[i].step), t);
4904 t = fold_build2 (PLUS_EXPR, itype, t,
4905 fold_convert (itype, fd->loops[i].n2));
4906 t = fold_build2 (MINUS_EXPR, itype, t,
4907 fold_convert (itype, fd->loops[i].n1));
4908 /* ?? We could probably use CEIL_DIV_EXPR instead of
4909 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4910 generate the same code in the end because generically we
4911 don't know that the values involved must be negative for
4912 GT?? */
4913 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
4914 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4915 fold_build1 (NEGATE_EXPR, itype, t),
4916 fold_build1 (NEGATE_EXPR, itype,
4917 fold_convert (itype,
4918 fd->loops[i].step)));
4919 else
4920 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
4921 fold_convert (itype, fd->loops[i].step));
4922 t = fold_convert (type, t);
4923 if (TREE_CODE (t) == INTEGER_CST)
4924 counts[i] = t;
4925 else
4927 counts[i] = create_tmp_reg (type, ".count");
4928 expand_omp_build_assign (gsi, counts[i], t);
4930 if (SSA_VAR_P (fd->loop.n2))
4932 if (i == 0)
4933 t = counts[0];
4934 else
4935 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
4936 expand_omp_build_assign (gsi, fd->loop.n2, t);
4942 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
4943 T = V;
4944 V3 = N31 + (T % count3) * STEP3;
4945 T = T / count3;
4946 V2 = N21 + (T % count2) * STEP2;
4947 T = T / count2;
4948 V1 = N11 + T * STEP1;
4949 if this loop doesn't have an inner loop construct combined with it.
4950 If it does have an inner loop construct combined with it and the
4951 iteration count isn't known constant, store values from counts array
4952 into its _looptemp_ temporaries instead. */
4954 static void
4955 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4956 tree *counts, gimple inner_stmt, tree startvar)
4958 int i;
4959 if (gimple_omp_for_combined_p (fd->for_stmt))
4961 /* If fd->loop.n2 is constant, then no propagation of the counts
4962 is needed, they are constant. */
4963 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
4964 return;
4966 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
4967 ? gimple_omp_parallel_clauses (inner_stmt)
4968 : gimple_omp_for_clauses (inner_stmt);
4969 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4970 isn't supposed to be handled, as the inner loop doesn't
4971 use it. */
4972 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
4973 gcc_assert (innerc);
4974 for (i = 0; i < fd->collapse; i++)
4976 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4977 OMP_CLAUSE__LOOPTEMP_);
4978 gcc_assert (innerc);
4979 if (i)
4981 tree tem = OMP_CLAUSE_DECL (innerc);
4982 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
4983 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
4984 false, GSI_CONTINUE_LINKING);
4985 gimple stmt = gimple_build_assign (tem, t);
4986 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4989 return;
4992 tree type = TREE_TYPE (fd->loop.v);
4993 tree tem = create_tmp_reg (type, ".tem");
4994 gimple stmt = gimple_build_assign (tem, startvar);
4995 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4997 for (i = fd->collapse - 1; i >= 0; i--)
4999 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5000 itype = vtype;
5001 if (POINTER_TYPE_P (vtype))
5002 itype = signed_type_for (vtype);
5003 if (i != 0)
5004 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5005 else
5006 t = tem;
5007 t = fold_convert (itype, t);
5008 t = fold_build2 (MULT_EXPR, itype, t,
5009 fold_convert (itype, fd->loops[i].step));
5010 if (POINTER_TYPE_P (vtype))
5011 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5012 else
5013 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5014 t = force_gimple_operand_gsi (gsi, t,
5015 DECL_P (fd->loops[i].v)
5016 && TREE_ADDRESSABLE (fd->loops[i].v),
5017 NULL_TREE, false,
5018 GSI_CONTINUE_LINKING);
5019 stmt = gimple_build_assign (fd->loops[i].v, t);
5020 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5021 if (i != 0)
5023 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5024 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5025 false, GSI_CONTINUE_LINKING);
5026 stmt = gimple_build_assign (tem, t);
5027 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5033 /* Helper function for expand_omp_for_*. Generate code like:
5034 L10:
5035 V3 += STEP3;
5036 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5037 L11:
5038 V3 = N31;
5039 V2 += STEP2;
5040 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5041 L12:
5042 V2 = N21;
5043 V1 += STEP1;
5044 goto BODY_BB; */
5046 static basic_block
5047 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5048 basic_block body_bb)
5050 basic_block last_bb, bb, collapse_bb = NULL;
5051 int i;
5052 gimple_stmt_iterator gsi;
5053 edge e;
5054 tree t;
5055 gimple stmt;
5057 last_bb = cont_bb;
5058 for (i = fd->collapse - 1; i >= 0; i--)
5060 tree vtype = TREE_TYPE (fd->loops[i].v);
5062 bb = create_empty_bb (last_bb);
5063 if (current_loops)
5064 add_bb_to_loop (bb, last_bb->loop_father);
5065 gsi = gsi_start_bb (bb);
5067 if (i < fd->collapse - 1)
5069 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5070 e->probability = REG_BR_PROB_BASE / 8;
5072 t = fd->loops[i + 1].n1;
5073 t = force_gimple_operand_gsi (&gsi, t,
5074 DECL_P (fd->loops[i + 1].v)
5075 && TREE_ADDRESSABLE (fd->loops[i
5076 + 1].v),
5077 NULL_TREE, false,
5078 GSI_CONTINUE_LINKING);
5079 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5080 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5082 else
5083 collapse_bb = bb;
5085 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5087 if (POINTER_TYPE_P (vtype))
5088 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5089 else
5090 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5091 t = force_gimple_operand_gsi (&gsi, t,
5092 DECL_P (fd->loops[i].v)
5093 && TREE_ADDRESSABLE (fd->loops[i].v),
5094 NULL_TREE, false, GSI_CONTINUE_LINKING);
5095 stmt = gimple_build_assign (fd->loops[i].v, t);
5096 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5098 if (i > 0)
5100 t = fd->loops[i].n2;
5101 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5102 false, GSI_CONTINUE_LINKING);
5103 tree v = fd->loops[i].v;
5104 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5105 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5106 false, GSI_CONTINUE_LINKING);
5107 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5108 stmt = gimple_build_cond_empty (t);
5109 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5110 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5111 e->probability = REG_BR_PROB_BASE * 7 / 8;
5113 else
5114 make_edge (bb, body_bb, EDGE_FALLTHRU);
5115 last_bb = bb;
5118 return collapse_bb;
5122 /* A subroutine of expand_omp_for. Generate code for a parallel
5123 loop with any schedule. Given parameters:
5125 for (V = N1; V cond N2; V += STEP) BODY;
5127 where COND is "<" or ">", we generate pseudocode
5129 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5130 if (more) goto L0; else goto L3;
5132 V = istart0;
5133 iend = iend0;
5135 BODY;
5136 V += STEP;
5137 if (V cond iend) goto L1; else goto L2;
5139 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5142 If this is a combined omp parallel loop, instead of the call to
5143 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5144 If this is gimple_omp_for_combined_p loop, then instead of assigning
5145 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5146 inner GIMPLE_OMP_FOR and V += STEP; and
5147 if (V cond iend) goto L1; else goto L2; are removed.
5149 For collapsed loops, given parameters:
5150 collapse(3)
5151 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5152 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5153 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5154 BODY;
5156 we generate pseudocode
5158 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5159 if (cond3 is <)
5160 adj = STEP3 - 1;
5161 else
5162 adj = STEP3 + 1;
5163 count3 = (adj + N32 - N31) / STEP3;
5164 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5165 if (cond2 is <)
5166 adj = STEP2 - 1;
5167 else
5168 adj = STEP2 + 1;
5169 count2 = (adj + N22 - N21) / STEP2;
5170 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5171 if (cond1 is <)
5172 adj = STEP1 - 1;
5173 else
5174 adj = STEP1 + 1;
5175 count1 = (adj + N12 - N11) / STEP1;
5176 count = count1 * count2 * count3;
5177 goto Z1;
5179 count = 0;
5181 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5182 if (more) goto L0; else goto L3;
5184 V = istart0;
5185 T = V;
5186 V3 = N31 + (T % count3) * STEP3;
5187 T = T / count3;
5188 V2 = N21 + (T % count2) * STEP2;
5189 T = T / count2;
5190 V1 = N11 + T * STEP1;
5191 iend = iend0;
5193 BODY;
5194 V += 1;
5195 if (V < iend) goto L10; else goto L2;
5196 L10:
5197 V3 += STEP3;
5198 if (V3 cond3 N32) goto L1; else goto L11;
5199 L11:
5200 V3 = N31;
5201 V2 += STEP2;
5202 if (V2 cond2 N22) goto L1; else goto L12;
5203 L12:
5204 V2 = N21;
5205 V1 += STEP1;
5206 goto L1;
5208 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5213 static void
5214 expand_omp_for_generic (struct omp_region *region,
5215 struct omp_for_data *fd,
5216 enum built_in_function start_fn,
5217 enum built_in_function next_fn,
5218 gimple inner_stmt)
5220 tree type, istart0, iend0, iend;
5221 tree t, vmain, vback, bias = NULL_TREE;
5222 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5223 basic_block l2_bb = NULL, l3_bb = NULL;
5224 gimple_stmt_iterator gsi;
5225 gimple stmt;
5226 bool in_combined_parallel = is_combined_parallel (region);
5227 bool broken_loop = region->cont == NULL;
5228 edge e, ne;
5229 tree *counts = NULL;
5230 int i;
5232 gcc_assert (!broken_loop || !in_combined_parallel);
5233 gcc_assert (fd->iter_type == long_integer_type_node
5234 || !in_combined_parallel);
5236 type = TREE_TYPE (fd->loop.v);
5237 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5238 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5239 TREE_ADDRESSABLE (istart0) = 1;
5240 TREE_ADDRESSABLE (iend0) = 1;
5242 /* See if we need to bias by LLONG_MIN. */
5243 if (fd->iter_type == long_long_unsigned_type_node
5244 && TREE_CODE (type) == INTEGER_TYPE
5245 && !TYPE_UNSIGNED (type))
5247 tree n1, n2;
5249 if (fd->loop.cond_code == LT_EXPR)
5251 n1 = fd->loop.n1;
5252 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5254 else
5256 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5257 n2 = fd->loop.n1;
5259 if (TREE_CODE (n1) != INTEGER_CST
5260 || TREE_CODE (n2) != INTEGER_CST
5261 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5262 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5265 entry_bb = region->entry;
5266 cont_bb = region->cont;
5267 collapse_bb = NULL;
5268 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5269 gcc_assert (broken_loop
5270 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5271 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5272 l1_bb = single_succ (l0_bb);
5273 if (!broken_loop)
5275 l2_bb = create_empty_bb (cont_bb);
5276 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5277 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5279 else
5280 l2_bb = NULL;
5281 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5282 exit_bb = region->exit;
5284 gsi = gsi_last_bb (entry_bb);
5286 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5287 if (fd->collapse > 1)
5289 int first_zero_iter = -1;
5290 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5292 counts = XALLOCAVEC (tree, fd->collapse);
5293 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5294 zero_iter_bb, first_zero_iter,
5295 l2_dom_bb);
5297 if (zero_iter_bb)
5299 /* Some counts[i] vars might be uninitialized if
5300 some loop has zero iterations. But the body shouldn't
5301 be executed in that case, so just avoid uninit warnings. */
5302 for (i = first_zero_iter; i < fd->collapse; i++)
5303 if (SSA_VAR_P (counts[i]))
5304 TREE_NO_WARNING (counts[i]) = 1;
5305 gsi_prev (&gsi);
5306 e = split_block (entry_bb, gsi_stmt (gsi));
5307 entry_bb = e->dest;
5308 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5309 gsi = gsi_last_bb (entry_bb);
5310 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5311 get_immediate_dominator (CDI_DOMINATORS,
5312 zero_iter_bb));
5315 if (in_combined_parallel)
5317 /* In a combined parallel loop, emit a call to
5318 GOMP_loop_foo_next. */
5319 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5320 build_fold_addr_expr (istart0),
5321 build_fold_addr_expr (iend0));
5323 else
5325 tree t0, t1, t2, t3, t4;
5326 /* If this is not a combined parallel loop, emit a call to
5327 GOMP_loop_foo_start in ENTRY_BB. */
5328 t4 = build_fold_addr_expr (iend0);
5329 t3 = build_fold_addr_expr (istart0);
5330 t2 = fold_convert (fd->iter_type, fd->loop.step);
5331 t1 = fd->loop.n2;
5332 t0 = fd->loop.n1;
5333 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5335 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5336 OMP_CLAUSE__LOOPTEMP_);
5337 gcc_assert (innerc);
5338 t0 = OMP_CLAUSE_DECL (innerc);
5339 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5340 OMP_CLAUSE__LOOPTEMP_);
5341 gcc_assert (innerc);
5342 t1 = OMP_CLAUSE_DECL (innerc);
5344 if (POINTER_TYPE_P (TREE_TYPE (t0))
5345 && TYPE_PRECISION (TREE_TYPE (t0))
5346 != TYPE_PRECISION (fd->iter_type))
5348 /* Avoid casting pointers to integer of a different size. */
5349 tree itype = signed_type_for (type);
5350 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5351 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5353 else
5355 t1 = fold_convert (fd->iter_type, t1);
5356 t0 = fold_convert (fd->iter_type, t0);
5358 if (bias)
5360 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5361 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5363 if (fd->iter_type == long_integer_type_node)
5365 if (fd->chunk_size)
5367 t = fold_convert (fd->iter_type, fd->chunk_size);
5368 t = build_call_expr (builtin_decl_explicit (start_fn),
5369 6, t0, t1, t2, t, t3, t4);
5371 else
5372 t = build_call_expr (builtin_decl_explicit (start_fn),
5373 5, t0, t1, t2, t3, t4);
5375 else
5377 tree t5;
5378 tree c_bool_type;
5379 tree bfn_decl;
5381 /* The GOMP_loop_ull_*start functions have additional boolean
5382 argument, true for < loops and false for > loops.
5383 In Fortran, the C bool type can be different from
5384 boolean_type_node. */
5385 bfn_decl = builtin_decl_explicit (start_fn);
5386 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5387 t5 = build_int_cst (c_bool_type,
5388 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5389 if (fd->chunk_size)
5391 tree bfn_decl = builtin_decl_explicit (start_fn);
5392 t = fold_convert (fd->iter_type, fd->chunk_size);
5393 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5395 else
5396 t = build_call_expr (builtin_decl_explicit (start_fn),
5397 6, t5, t0, t1, t2, t3, t4);
5400 if (TREE_TYPE (t) != boolean_type_node)
5401 t = fold_build2 (NE_EXPR, boolean_type_node,
5402 t, build_int_cst (TREE_TYPE (t), 0));
5403 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5404 true, GSI_SAME_STMT);
5405 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5407 /* Remove the GIMPLE_OMP_FOR statement. */
5408 gsi_remove (&gsi, true);
5410 /* Iteration setup for sequential loop goes in L0_BB. */
5411 tree startvar = fd->loop.v;
5412 tree endvar = NULL_TREE;
5414 if (gimple_omp_for_combined_p (fd->for_stmt))
5416 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5417 && gimple_omp_for_kind (inner_stmt)
5418 == GF_OMP_FOR_KIND_SIMD);
5419 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5420 OMP_CLAUSE__LOOPTEMP_);
5421 gcc_assert (innerc);
5422 startvar = OMP_CLAUSE_DECL (innerc);
5423 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5424 OMP_CLAUSE__LOOPTEMP_);
5425 gcc_assert (innerc);
5426 endvar = OMP_CLAUSE_DECL (innerc);
5429 gsi = gsi_start_bb (l0_bb);
5430 t = istart0;
5431 if (bias)
5432 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5433 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5434 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5435 t = fold_convert (TREE_TYPE (startvar), t);
5436 t = force_gimple_operand_gsi (&gsi, t,
5437 DECL_P (startvar)
5438 && TREE_ADDRESSABLE (startvar),
5439 NULL_TREE, false, GSI_CONTINUE_LINKING);
5440 stmt = gimple_build_assign (startvar, t);
5441 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5443 t = iend0;
5444 if (bias)
5445 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5446 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5447 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5448 t = fold_convert (TREE_TYPE (startvar), t);
5449 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5450 false, GSI_CONTINUE_LINKING);
5451 if (endvar)
5453 stmt = gimple_build_assign (endvar, iend);
5454 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5456 if (fd->collapse > 1)
5457 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5459 if (!broken_loop)
5461 /* Code to control the increment and predicate for the sequential
5462 loop goes in the CONT_BB. */
5463 gsi = gsi_last_bb (cont_bb);
5464 stmt = gsi_stmt (gsi);
5465 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5466 vmain = gimple_omp_continue_control_use (stmt);
5467 vback = gimple_omp_continue_control_def (stmt);
5469 if (!gimple_omp_for_combined_p (fd->for_stmt))
5471 if (POINTER_TYPE_P (type))
5472 t = fold_build_pointer_plus (vmain, fd->loop.step);
5473 else
5474 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5475 t = force_gimple_operand_gsi (&gsi, t,
5476 DECL_P (vback)
5477 && TREE_ADDRESSABLE (vback),
5478 NULL_TREE, true, GSI_SAME_STMT);
5479 stmt = gimple_build_assign (vback, t);
5480 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5482 t = build2 (fd->loop.cond_code, boolean_type_node,
5483 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5484 iend);
5485 stmt = gimple_build_cond_empty (t);
5486 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5489 /* Remove GIMPLE_OMP_CONTINUE. */
5490 gsi_remove (&gsi, true);
5492 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5493 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5495 /* Emit code to get the next parallel iteration in L2_BB. */
5496 gsi = gsi_start_bb (l2_bb);
5498 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5499 build_fold_addr_expr (istart0),
5500 build_fold_addr_expr (iend0));
5501 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5502 false, GSI_CONTINUE_LINKING);
5503 if (TREE_TYPE (t) != boolean_type_node)
5504 t = fold_build2 (NE_EXPR, boolean_type_node,
5505 t, build_int_cst (TREE_TYPE (t), 0));
5506 stmt = gimple_build_cond_empty (t);
5507 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5510 /* Add the loop cleanup function. */
5511 gsi = gsi_last_bb (exit_bb);
5512 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5513 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5514 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5515 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5516 else
5517 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5518 stmt = gimple_build_call (t, 0);
5519 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5520 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5521 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5522 gsi_remove (&gsi, true);
5524 /* Connect the new blocks. */
5525 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5526 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5528 if (!broken_loop)
5530 gimple_seq phis;
5532 e = find_edge (cont_bb, l3_bb);
5533 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5535 phis = phi_nodes (l3_bb);
5536 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5538 gimple phi = gsi_stmt (gsi);
5539 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5540 PHI_ARG_DEF_FROM_EDGE (phi, e));
5542 remove_edge (e);
5544 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5545 if (current_loops)
5546 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5547 e = find_edge (cont_bb, l1_bb);
5548 if (gimple_omp_for_combined_p (fd->for_stmt))
5550 remove_edge (e);
5551 e = NULL;
5553 else if (fd->collapse > 1)
5555 remove_edge (e);
5556 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5558 else
5559 e->flags = EDGE_TRUE_VALUE;
5560 if (e)
5562 e->probability = REG_BR_PROB_BASE * 7 / 8;
5563 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5565 else
5567 e = find_edge (cont_bb, l2_bb);
5568 e->flags = EDGE_FALLTHRU;
5570 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5572 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5573 recompute_dominator (CDI_DOMINATORS, l2_bb));
5574 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5575 recompute_dominator (CDI_DOMINATORS, l3_bb));
5576 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5577 recompute_dominator (CDI_DOMINATORS, l0_bb));
5578 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5579 recompute_dominator (CDI_DOMINATORS, l1_bb));
5581 struct loop *outer_loop = alloc_loop ();
5582 outer_loop->header = l0_bb;
5583 outer_loop->latch = l2_bb;
5584 add_loop (outer_loop, l0_bb->loop_father);
5586 if (!gimple_omp_for_combined_p (fd->for_stmt))
5588 struct loop *loop = alloc_loop ();
5589 loop->header = l1_bb;
5590 /* The loop may have multiple latches. */
5591 add_loop (loop, outer_loop);
5597 /* A subroutine of expand_omp_for. Generate code for a parallel
5598 loop with static schedule and no specified chunk size. Given
5599 parameters:
5601 for (V = N1; V cond N2; V += STEP) BODY;
5603 where COND is "<" or ">", we generate pseudocode
5605 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5606 if (cond is <)
5607 adj = STEP - 1;
5608 else
5609 adj = STEP + 1;
5610 if ((__typeof (V)) -1 > 0 && cond is >)
5611 n = -(adj + N2 - N1) / -STEP;
5612 else
5613 n = (adj + N2 - N1) / STEP;
5614 q = n / nthreads;
5615 tt = n % nthreads;
5616 if (threadid < tt) goto L3; else goto L4;
5618 tt = 0;
5619 q = q + 1;
5621 s0 = q * threadid + tt;
5622 e0 = s0 + q;
5623 V = s0 * STEP + N1;
5624 if (s0 >= e0) goto L2; else goto L0;
5626 e = e0 * STEP + N1;
5628 BODY;
5629 V += STEP;
5630 if (V cond e) goto L1;
5634 static void
5635 expand_omp_for_static_nochunk (struct omp_region *region,
5636 struct omp_for_data *fd,
5637 gimple inner_stmt)
5639 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5640 tree type, itype, vmain, vback;
5641 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5642 basic_block body_bb, cont_bb, collapse_bb = NULL;
5643 basic_block fin_bb;
5644 gimple_stmt_iterator gsi;
5645 gimple stmt;
5646 edge ep;
5647 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5648 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5649 bool broken_loop = region->cont == NULL;
5650 tree *counts = NULL;
5651 tree n1, n2, step;
5653 itype = type = TREE_TYPE (fd->loop.v);
5654 if (POINTER_TYPE_P (type))
5655 itype = signed_type_for (type);
5657 entry_bb = region->entry;
5658 cont_bb = region->cont;
5659 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5660 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5661 gcc_assert (broken_loop
5662 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5663 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5664 body_bb = single_succ (seq_start_bb);
5665 if (!broken_loop)
5667 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5668 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5670 exit_bb = region->exit;
5672 /* Iteration space partitioning goes in ENTRY_BB. */
5673 gsi = gsi_last_bb (entry_bb);
5674 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5676 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5678 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5679 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5682 if (fd->collapse > 1)
5684 int first_zero_iter = -1;
5685 basic_block l2_dom_bb = NULL;
5687 counts = XALLOCAVEC (tree, fd->collapse);
5688 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5689 fin_bb, first_zero_iter,
5690 l2_dom_bb);
5691 t = NULL_TREE;
5693 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5694 t = integer_one_node;
5695 else
5696 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5697 fold_convert (type, fd->loop.n1),
5698 fold_convert (type, fd->loop.n2));
5699 if (fd->collapse == 1
5700 && TYPE_UNSIGNED (type)
5701 && (t == NULL_TREE || !integer_onep (t)))
5703 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5704 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5705 true, GSI_SAME_STMT);
5706 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5707 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5708 true, GSI_SAME_STMT);
5709 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5710 NULL_TREE, NULL_TREE);
5711 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5712 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5713 expand_omp_regimplify_p, NULL, NULL)
5714 || walk_tree (gimple_cond_rhs_ptr (stmt),
5715 expand_omp_regimplify_p, NULL, NULL))
5717 gsi = gsi_for_stmt (stmt);
5718 gimple_regimplify_operands (stmt, &gsi);
5720 ep = split_block (entry_bb, stmt);
5721 ep->flags = EDGE_TRUE_VALUE;
5722 entry_bb = ep->dest;
5723 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5724 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5725 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5726 if (gimple_in_ssa_p (cfun))
5728 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5729 for (gsi = gsi_start_phis (fin_bb);
5730 !gsi_end_p (gsi); gsi_next (&gsi))
5732 gimple phi = gsi_stmt (gsi);
5733 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5734 ep, UNKNOWN_LOCATION);
5737 gsi = gsi_last_bb (entry_bb);
5740 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5741 t = fold_convert (itype, t);
5742 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5743 true, GSI_SAME_STMT);
5745 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5746 t = fold_convert (itype, t);
5747 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5748 true, GSI_SAME_STMT);
5750 n1 = fd->loop.n1;
5751 n2 = fd->loop.n2;
5752 step = fd->loop.step;
5753 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5755 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5756 OMP_CLAUSE__LOOPTEMP_);
5757 gcc_assert (innerc);
5758 n1 = OMP_CLAUSE_DECL (innerc);
5759 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5760 OMP_CLAUSE__LOOPTEMP_);
5761 gcc_assert (innerc);
5762 n2 = OMP_CLAUSE_DECL (innerc);
5764 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5765 true, NULL_TREE, true, GSI_SAME_STMT);
5766 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5767 true, NULL_TREE, true, GSI_SAME_STMT);
5768 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5769 true, NULL_TREE, true, GSI_SAME_STMT);
5771 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5772 t = fold_build2 (PLUS_EXPR, itype, step, t);
5773 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5774 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5775 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5776 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5777 fold_build1 (NEGATE_EXPR, itype, t),
5778 fold_build1 (NEGATE_EXPR, itype, step));
5779 else
5780 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5781 t = fold_convert (itype, t);
5782 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5784 q = create_tmp_reg (itype, "q");
5785 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5786 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5787 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5789 tt = create_tmp_reg (itype, "tt");
5790 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5791 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5792 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5794 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5795 stmt = gimple_build_cond_empty (t);
5796 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5798 second_bb = split_block (entry_bb, stmt)->dest;
5799 gsi = gsi_last_bb (second_bb);
5800 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5802 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5803 GSI_SAME_STMT);
5804 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5805 build_int_cst (itype, 1));
5806 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5808 third_bb = split_block (second_bb, stmt)->dest;
5809 gsi = gsi_last_bb (third_bb);
5810 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5812 t = build2 (MULT_EXPR, itype, q, threadid);
5813 t = build2 (PLUS_EXPR, itype, t, tt);
5814 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5816 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5817 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5819 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5820 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5822 /* Remove the GIMPLE_OMP_FOR statement. */
5823 gsi_remove (&gsi, true);
5825 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5826 gsi = gsi_start_bb (seq_start_bb);
5828 tree startvar = fd->loop.v;
5829 tree endvar = NULL_TREE;
5831 if (gimple_omp_for_combined_p (fd->for_stmt))
5833 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5834 ? gimple_omp_parallel_clauses (inner_stmt)
5835 : gimple_omp_for_clauses (inner_stmt);
5836 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5837 gcc_assert (innerc);
5838 startvar = OMP_CLAUSE_DECL (innerc);
5839 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5840 OMP_CLAUSE__LOOPTEMP_);
5841 gcc_assert (innerc);
5842 endvar = OMP_CLAUSE_DECL (innerc);
5844 t = fold_convert (itype, s0);
5845 t = fold_build2 (MULT_EXPR, itype, t, step);
5846 if (POINTER_TYPE_P (type))
5847 t = fold_build_pointer_plus (n1, t);
5848 else
5849 t = fold_build2 (PLUS_EXPR, type, t, n1);
5850 t = fold_convert (TREE_TYPE (startvar), t);
5851 t = force_gimple_operand_gsi (&gsi, t,
5852 DECL_P (startvar)
5853 && TREE_ADDRESSABLE (startvar),
5854 NULL_TREE, false, GSI_CONTINUE_LINKING);
5855 stmt = gimple_build_assign (startvar, t);
5856 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5858 t = fold_convert (itype, e0);
5859 t = fold_build2 (MULT_EXPR, itype, t, step);
5860 if (POINTER_TYPE_P (type))
5861 t = fold_build_pointer_plus (n1, t);
5862 else
5863 t = fold_build2 (PLUS_EXPR, type, t, n1);
5864 t = fold_convert (TREE_TYPE (startvar), t);
5865 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5866 false, GSI_CONTINUE_LINKING);
5867 if (endvar)
5869 stmt = gimple_build_assign (endvar, e);
5870 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5872 if (fd->collapse > 1)
5873 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5875 if (!broken_loop)
5877 /* The code controlling the sequential loop replaces the
5878 GIMPLE_OMP_CONTINUE. */
5879 gsi = gsi_last_bb (cont_bb);
5880 stmt = gsi_stmt (gsi);
5881 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5882 vmain = gimple_omp_continue_control_use (stmt);
5883 vback = gimple_omp_continue_control_def (stmt);
5885 if (!gimple_omp_for_combined_p (fd->for_stmt))
5887 if (POINTER_TYPE_P (type))
5888 t = fold_build_pointer_plus (vmain, step);
5889 else
5890 t = fold_build2 (PLUS_EXPR, type, vmain, step);
5891 t = force_gimple_operand_gsi (&gsi, t,
5892 DECL_P (vback)
5893 && TREE_ADDRESSABLE (vback),
5894 NULL_TREE, true, GSI_SAME_STMT);
5895 stmt = gimple_build_assign (vback, t);
5896 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5898 t = build2 (fd->loop.cond_code, boolean_type_node,
5899 DECL_P (vback) && TREE_ADDRESSABLE (vback)
5900 ? t : vback, e);
5901 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5904 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5905 gsi_remove (&gsi, true);
5907 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5908 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
5911 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5912 gsi = gsi_last_bb (exit_bb);
5913 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5915 t = gimple_omp_return_lhs (gsi_stmt (gsi));
5916 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
5918 gsi_remove (&gsi, true);
5920 /* Connect all the blocks. */
5921 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5922 ep->probability = REG_BR_PROB_BASE / 4 * 3;
5923 ep = find_edge (entry_bb, second_bb);
5924 ep->flags = EDGE_TRUE_VALUE;
5925 ep->probability = REG_BR_PROB_BASE / 4;
5926 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
5927 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
5929 if (!broken_loop)
5931 ep = find_edge (cont_bb, body_bb);
5932 if (gimple_omp_for_combined_p (fd->for_stmt))
5934 remove_edge (ep);
5935 ep = NULL;
5937 else if (fd->collapse > 1)
5939 remove_edge (ep);
5940 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5942 else
5943 ep->flags = EDGE_TRUE_VALUE;
5944 find_edge (cont_bb, fin_bb)->flags
5945 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
5948 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
5949 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
5950 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
5952 set_immediate_dominator (CDI_DOMINATORS, body_bb,
5953 recompute_dominator (CDI_DOMINATORS, body_bb));
5954 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5955 recompute_dominator (CDI_DOMINATORS, fin_bb));
5957 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
5959 struct loop *loop = alloc_loop ();
5960 loop->header = body_bb;
5961 if (collapse_bb == NULL)
5962 loop->latch = cont_bb;
5963 add_loop (loop, body_bb->loop_father);
5968 /* A subroutine of expand_omp_for. Generate code for a parallel
5969 loop with static schedule and a specified chunk size. Given
5970 parameters:
5972 for (V = N1; V cond N2; V += STEP) BODY;
5974 where COND is "<" or ">", we generate pseudocode
5976 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5977 if (cond is <)
5978 adj = STEP - 1;
5979 else
5980 adj = STEP + 1;
5981 if ((__typeof (V)) -1 > 0 && cond is >)
5982 n = -(adj + N2 - N1) / -STEP;
5983 else
5984 n = (adj + N2 - N1) / STEP;
5985 trip = 0;
5986 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
5987 here so that V is defined
5988 if the loop is not entered
5990 s0 = (trip * nthreads + threadid) * CHUNK;
5991 e0 = min(s0 + CHUNK, n);
5992 if (s0 < n) goto L1; else goto L4;
5994 V = s0 * STEP + N1;
5995 e = e0 * STEP + N1;
5997 BODY;
5998 V += STEP;
5999 if (V cond e) goto L2; else goto L3;
6001 trip += 1;
6002 goto L0;
6006 static void
6007 expand_omp_for_static_chunk (struct omp_region *region,
6008 struct omp_for_data *fd, gimple inner_stmt)
6010 tree n, s0, e0, e, t;
6011 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6012 tree type, itype, v_main, v_back, v_extra;
6013 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6014 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6015 gimple_stmt_iterator si;
6016 gimple stmt;
6017 edge se;
6018 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6019 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6020 bool broken_loop = region->cont == NULL;
6021 tree *counts = NULL;
6022 tree n1, n2, step;
6024 itype = type = TREE_TYPE (fd->loop.v);
6025 if (POINTER_TYPE_P (type))
6026 itype = signed_type_for (type);
6028 entry_bb = region->entry;
6029 se = split_block (entry_bb, last_stmt (entry_bb));
6030 entry_bb = se->src;
6031 iter_part_bb = se->dest;
6032 cont_bb = region->cont;
6033 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6034 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6035 gcc_assert (broken_loop
6036 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6037 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6038 body_bb = single_succ (seq_start_bb);
6039 if (!broken_loop)
6041 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6042 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6043 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6045 exit_bb = region->exit;
6047 /* Trip and adjustment setup goes in ENTRY_BB. */
6048 si = gsi_last_bb (entry_bb);
6049 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6051 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6053 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6054 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6057 if (fd->collapse > 1)
6059 int first_zero_iter = -1;
6060 basic_block l2_dom_bb = NULL;
6062 counts = XALLOCAVEC (tree, fd->collapse);
6063 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6064 fin_bb, first_zero_iter,
6065 l2_dom_bb);
6066 t = NULL_TREE;
6068 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6069 t = integer_one_node;
6070 else
6071 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6072 fold_convert (type, fd->loop.n1),
6073 fold_convert (type, fd->loop.n2));
6074 if (fd->collapse == 1
6075 && TYPE_UNSIGNED (type)
6076 && (t == NULL_TREE || !integer_onep (t)))
6078 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6079 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6080 true, GSI_SAME_STMT);
6081 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6082 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6083 true, GSI_SAME_STMT);
6084 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6085 NULL_TREE, NULL_TREE);
6086 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6087 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6088 expand_omp_regimplify_p, NULL, NULL)
6089 || walk_tree (gimple_cond_rhs_ptr (stmt),
6090 expand_omp_regimplify_p, NULL, NULL))
6092 si = gsi_for_stmt (stmt);
6093 gimple_regimplify_operands (stmt, &si);
6095 se = split_block (entry_bb, stmt);
6096 se->flags = EDGE_TRUE_VALUE;
6097 entry_bb = se->dest;
6098 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6099 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6100 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6101 if (gimple_in_ssa_p (cfun))
6103 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6104 for (si = gsi_start_phis (fin_bb);
6105 !gsi_end_p (si); gsi_next (&si))
6107 gimple phi = gsi_stmt (si);
6108 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6109 se, UNKNOWN_LOCATION);
6112 si = gsi_last_bb (entry_bb);
6115 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6116 t = fold_convert (itype, t);
6117 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6118 true, GSI_SAME_STMT);
6120 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6121 t = fold_convert (itype, t);
6122 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6123 true, GSI_SAME_STMT);
6125 n1 = fd->loop.n1;
6126 n2 = fd->loop.n2;
6127 step = fd->loop.step;
6128 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6130 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6131 OMP_CLAUSE__LOOPTEMP_);
6132 gcc_assert (innerc);
6133 n1 = OMP_CLAUSE_DECL (innerc);
6134 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6135 OMP_CLAUSE__LOOPTEMP_);
6136 gcc_assert (innerc);
6137 n2 = OMP_CLAUSE_DECL (innerc);
6139 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6140 true, NULL_TREE, true, GSI_SAME_STMT);
6141 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6142 true, NULL_TREE, true, GSI_SAME_STMT);
6143 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6144 true, NULL_TREE, true, GSI_SAME_STMT);
6145 fd->chunk_size
6146 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6147 true, NULL_TREE, true, GSI_SAME_STMT);
6149 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6150 t = fold_build2 (PLUS_EXPR, itype, step, t);
6151 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6152 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6153 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6154 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6155 fold_build1 (NEGATE_EXPR, itype, t),
6156 fold_build1 (NEGATE_EXPR, itype, step));
6157 else
6158 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6159 t = fold_convert (itype, t);
6160 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6161 true, GSI_SAME_STMT);
6163 trip_var = create_tmp_reg (itype, ".trip");
6164 if (gimple_in_ssa_p (cfun))
6166 trip_init = make_ssa_name (trip_var, NULL);
6167 trip_main = make_ssa_name (trip_var, NULL);
6168 trip_back = make_ssa_name (trip_var, NULL);
6170 else
6172 trip_init = trip_var;
6173 trip_main = trip_var;
6174 trip_back = trip_var;
6177 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6178 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6180 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6181 t = fold_build2 (MULT_EXPR, itype, t, step);
6182 if (POINTER_TYPE_P (type))
6183 t = fold_build_pointer_plus (n1, t);
6184 else
6185 t = fold_build2 (PLUS_EXPR, type, t, n1);
6186 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6187 true, GSI_SAME_STMT);
6189 /* Remove the GIMPLE_OMP_FOR. */
6190 gsi_remove (&si, true);
6192 /* Iteration space partitioning goes in ITER_PART_BB. */
6193 si = gsi_last_bb (iter_part_bb);
6195 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6196 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6197 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6198 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6199 false, GSI_CONTINUE_LINKING);
6201 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6202 t = fold_build2 (MIN_EXPR, itype, t, n);
6203 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6204 false, GSI_CONTINUE_LINKING);
6206 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6207 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6209 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6210 si = gsi_start_bb (seq_start_bb);
6212 tree startvar = fd->loop.v;
6213 tree endvar = NULL_TREE;
6215 if (gimple_omp_for_combined_p (fd->for_stmt))
6217 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6218 ? gimple_omp_parallel_clauses (inner_stmt)
6219 : gimple_omp_for_clauses (inner_stmt);
6220 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6221 gcc_assert (innerc);
6222 startvar = OMP_CLAUSE_DECL (innerc);
6223 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6224 OMP_CLAUSE__LOOPTEMP_);
6225 gcc_assert (innerc);
6226 endvar = OMP_CLAUSE_DECL (innerc);
6229 t = fold_convert (itype, s0);
6230 t = fold_build2 (MULT_EXPR, itype, t, step);
6231 if (POINTER_TYPE_P (type))
6232 t = fold_build_pointer_plus (n1, t);
6233 else
6234 t = fold_build2 (PLUS_EXPR, type, t, n1);
6235 t = fold_convert (TREE_TYPE (startvar), t);
6236 t = force_gimple_operand_gsi (&si, t,
6237 DECL_P (startvar)
6238 && TREE_ADDRESSABLE (startvar),
6239 NULL_TREE, false, GSI_CONTINUE_LINKING);
6240 stmt = gimple_build_assign (startvar, t);
6241 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6243 t = fold_convert (itype, e0);
6244 t = fold_build2 (MULT_EXPR, itype, t, step);
6245 if (POINTER_TYPE_P (type))
6246 t = fold_build_pointer_plus (n1, t);
6247 else
6248 t = fold_build2 (PLUS_EXPR, type, t, n1);
6249 t = fold_convert (TREE_TYPE (startvar), t);
6250 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6251 false, GSI_CONTINUE_LINKING);
6252 if (endvar)
6254 stmt = gimple_build_assign (endvar, e);
6255 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6257 if (fd->collapse > 1)
6258 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6260 if (!broken_loop)
6262 /* The code controlling the sequential loop goes in CONT_BB,
6263 replacing the GIMPLE_OMP_CONTINUE. */
6264 si = gsi_last_bb (cont_bb);
6265 stmt = gsi_stmt (si);
6266 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6267 v_main = gimple_omp_continue_control_use (stmt);
6268 v_back = gimple_omp_continue_control_def (stmt);
6270 if (!gimple_omp_for_combined_p (fd->for_stmt))
6272 if (POINTER_TYPE_P (type))
6273 t = fold_build_pointer_plus (v_main, step);
6274 else
6275 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6276 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6277 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6278 true, GSI_SAME_STMT);
6279 stmt = gimple_build_assign (v_back, t);
6280 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6282 t = build2 (fd->loop.cond_code, boolean_type_node,
6283 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6284 ? t : v_back, e);
6285 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6288 /* Remove GIMPLE_OMP_CONTINUE. */
6289 gsi_remove (&si, true);
6291 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6292 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6294 /* Trip update code goes into TRIP_UPDATE_BB. */
6295 si = gsi_start_bb (trip_update_bb);
6297 t = build_int_cst (itype, 1);
6298 t = build2 (PLUS_EXPR, itype, trip_main, t);
6299 stmt = gimple_build_assign (trip_back, t);
6300 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6303 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6304 si = gsi_last_bb (exit_bb);
6305 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6307 t = gimple_omp_return_lhs (gsi_stmt (si));
6308 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6310 gsi_remove (&si, true);
6312 /* Connect the new blocks. */
6313 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6314 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6316 if (!broken_loop)
6318 se = find_edge (cont_bb, body_bb);
6319 if (gimple_omp_for_combined_p (fd->for_stmt))
6321 remove_edge (se);
6322 se = NULL;
6324 else if (fd->collapse > 1)
6326 remove_edge (se);
6327 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6329 else
6330 se->flags = EDGE_TRUE_VALUE;
6331 find_edge (cont_bb, trip_update_bb)->flags
6332 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6334 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6337 if (gimple_in_ssa_p (cfun))
6339 gimple_stmt_iterator psi;
6340 gimple phi;
6341 edge re, ene;
6342 edge_var_map_vector *head;
6343 edge_var_map *vm;
6344 size_t i;
6346 gcc_assert (fd->collapse == 1 && !broken_loop);
6348 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6349 remove arguments of the phi nodes in fin_bb. We need to create
6350 appropriate phi nodes in iter_part_bb instead. */
6351 se = single_pred_edge (fin_bb);
6352 re = single_succ_edge (trip_update_bb);
6353 head = redirect_edge_var_map_vector (re);
6354 ene = single_succ_edge (entry_bb);
6356 psi = gsi_start_phis (fin_bb);
6357 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6358 gsi_next (&psi), ++i)
6360 gimple nphi;
6361 source_location locus;
6363 phi = gsi_stmt (psi);
6364 t = gimple_phi_result (phi);
6365 gcc_assert (t == redirect_edge_var_map_result (vm));
6366 nphi = create_phi_node (t, iter_part_bb);
6368 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6369 locus = gimple_phi_arg_location_from_edge (phi, se);
6371 /* A special case -- fd->loop.v is not yet computed in
6372 iter_part_bb, we need to use v_extra instead. */
6373 if (t == fd->loop.v)
6374 t = v_extra;
6375 add_phi_arg (nphi, t, ene, locus);
6376 locus = redirect_edge_var_map_location (vm);
6377 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6379 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6380 redirect_edge_var_map_clear (re);
6381 while (1)
6383 psi = gsi_start_phis (fin_bb);
6384 if (gsi_end_p (psi))
6385 break;
6386 remove_phi_node (&psi, false);
6389 /* Make phi node for trip. */
6390 phi = create_phi_node (trip_main, iter_part_bb);
6391 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6392 UNKNOWN_LOCATION);
6393 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6394 UNKNOWN_LOCATION);
6397 if (!broken_loop)
6398 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6399 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6400 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6401 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6402 recompute_dominator (CDI_DOMINATORS, fin_bb));
6403 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6404 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6405 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6406 recompute_dominator (CDI_DOMINATORS, body_bb));
6408 if (!broken_loop)
6410 struct loop *trip_loop = alloc_loop ();
6411 trip_loop->header = iter_part_bb;
6412 trip_loop->latch = trip_update_bb;
6413 add_loop (trip_loop, iter_part_bb->loop_father);
6415 if (!gimple_omp_for_combined_p (fd->for_stmt))
6417 struct loop *loop = alloc_loop ();
6418 loop->header = body_bb;
6419 loop->latch = cont_bb;
6420 add_loop (loop, trip_loop);
6426 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6427 loop. Given parameters:
6429 for (V = N1; V cond N2; V += STEP) BODY;
6431 where COND is "<" or ">", we generate pseudocode
6433 V = N1;
6434 goto L1;
6436 BODY;
6437 V += STEP;
6439 if (V cond N2) goto L0; else goto L2;
6442 For collapsed loops, given parameters:
6443 collapse(3)
6444 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6445 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6446 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6447 BODY;
6449 we generate pseudocode
6451 if (cond3 is <)
6452 adj = STEP3 - 1;
6453 else
6454 adj = STEP3 + 1;
6455 count3 = (adj + N32 - N31) / STEP3;
6456 if (cond2 is <)
6457 adj = STEP2 - 1;
6458 else
6459 adj = STEP2 + 1;
6460 count2 = (adj + N22 - N21) / STEP2;
6461 if (cond1 is <)
6462 adj = STEP1 - 1;
6463 else
6464 adj = STEP1 + 1;
6465 count1 = (adj + N12 - N11) / STEP1;
6466 count = count1 * count2 * count3;
6467 V = 0;
6468 V1 = N11;
6469 V2 = N21;
6470 V3 = N31;
6471 goto L1;
6473 BODY;
6474 V += 1;
6475 V3 += STEP3;
6476 V2 += (V3 cond3 N32) ? 0 : STEP2;
6477 V3 = (V3 cond3 N32) ? V3 : N31;
6478 V1 += (V2 cond2 N22) ? 0 : STEP1;
6479 V2 = (V2 cond2 N22) ? V2 : N21;
6481 if (V < count) goto L0; else goto L2;
6486 static void
6487 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6489 tree type, t;
6490 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6491 gimple_stmt_iterator gsi;
6492 gimple stmt;
6493 bool broken_loop = region->cont == NULL;
6494 edge e, ne;
6495 tree *counts = NULL;
6496 int i;
6497 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6498 OMP_CLAUSE_SAFELEN);
6499 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6500 OMP_CLAUSE__SIMDUID_);
6501 tree n1, n2;
6503 type = TREE_TYPE (fd->loop.v);
6504 entry_bb = region->entry;
6505 cont_bb = region->cont;
6506 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6507 gcc_assert (broken_loop
6508 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6509 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6510 if (!broken_loop)
6512 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6513 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6514 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6515 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6517 else
6519 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6520 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6521 l2_bb = single_succ (l1_bb);
6523 exit_bb = region->exit;
6524 l2_dom_bb = NULL;
6526 gsi = gsi_last_bb (entry_bb);
6528 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6529 /* Not needed in SSA form right now. */
6530 gcc_assert (!gimple_in_ssa_p (cfun));
6531 if (fd->collapse > 1)
6533 int first_zero_iter = -1;
6534 basic_block zero_iter_bb = l2_bb;
6536 counts = XALLOCAVEC (tree, fd->collapse);
6537 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6538 zero_iter_bb, first_zero_iter,
6539 l2_dom_bb);
6541 if (l2_dom_bb == NULL)
6542 l2_dom_bb = l1_bb;
6544 n1 = fd->loop.n1;
6545 n2 = fd->loop.n2;
6546 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6548 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6549 OMP_CLAUSE__LOOPTEMP_);
6550 gcc_assert (innerc);
6551 n1 = OMP_CLAUSE_DECL (innerc);
6552 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6553 OMP_CLAUSE__LOOPTEMP_);
6554 gcc_assert (innerc);
6555 n2 = OMP_CLAUSE_DECL (innerc);
6556 expand_omp_build_assign (&gsi, fd->loop.v,
6557 fold_convert (type, n1));
6558 if (fd->collapse > 1)
6560 gsi_prev (&gsi);
6561 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6562 gsi_next (&gsi);
6565 else
6567 expand_omp_build_assign (&gsi, fd->loop.v,
6568 fold_convert (type, fd->loop.n1));
6569 if (fd->collapse > 1)
6570 for (i = 0; i < fd->collapse; i++)
6572 tree itype = TREE_TYPE (fd->loops[i].v);
6573 if (POINTER_TYPE_P (itype))
6574 itype = signed_type_for (itype);
6575 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6576 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6580 /* Remove the GIMPLE_OMP_FOR statement. */
6581 gsi_remove (&gsi, true);
6583 if (!broken_loop)
6585 /* Code to control the increment goes in the CONT_BB. */
6586 gsi = gsi_last_bb (cont_bb);
6587 stmt = gsi_stmt (gsi);
6588 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6590 if (POINTER_TYPE_P (type))
6591 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6592 else
6593 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6594 expand_omp_build_assign (&gsi, fd->loop.v, t);
6596 if (fd->collapse > 1)
6598 i = fd->collapse - 1;
6599 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6601 t = fold_convert (sizetype, fd->loops[i].step);
6602 t = fold_build_pointer_plus (fd->loops[i].v, t);
6604 else
6606 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6607 fd->loops[i].step);
6608 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6609 fd->loops[i].v, t);
6611 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6613 for (i = fd->collapse - 1; i > 0; i--)
6615 tree itype = TREE_TYPE (fd->loops[i].v);
6616 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6617 if (POINTER_TYPE_P (itype2))
6618 itype2 = signed_type_for (itype2);
6619 t = build3 (COND_EXPR, itype2,
6620 build2 (fd->loops[i].cond_code, boolean_type_node,
6621 fd->loops[i].v,
6622 fold_convert (itype, fd->loops[i].n2)),
6623 build_int_cst (itype2, 0),
6624 fold_convert (itype2, fd->loops[i - 1].step));
6625 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6626 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6627 else
6628 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6629 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6631 t = build3 (COND_EXPR, itype,
6632 build2 (fd->loops[i].cond_code, boolean_type_node,
6633 fd->loops[i].v,
6634 fold_convert (itype, fd->loops[i].n2)),
6635 fd->loops[i].v,
6636 fold_convert (itype, fd->loops[i].n1));
6637 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6641 /* Remove GIMPLE_OMP_CONTINUE. */
6642 gsi_remove (&gsi, true);
6645 /* Emit the condition in L1_BB. */
6646 gsi = gsi_start_bb (l1_bb);
6648 t = fold_convert (type, n2);
6649 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6650 false, GSI_CONTINUE_LINKING);
6651 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6652 stmt = gimple_build_cond_empty (t);
6653 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6654 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6655 NULL, NULL)
6656 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6657 NULL, NULL))
6659 gsi = gsi_for_stmt (stmt);
6660 gimple_regimplify_operands (stmt, &gsi);
6663 /* Remove GIMPLE_OMP_RETURN. */
6664 gsi = gsi_last_bb (exit_bb);
6665 gsi_remove (&gsi, true);
6667 /* Connect the new blocks. */
6668 remove_edge (FALLTHRU_EDGE (entry_bb));
6670 if (!broken_loop)
6672 remove_edge (BRANCH_EDGE (entry_bb));
6673 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6675 e = BRANCH_EDGE (l1_bb);
6676 ne = FALLTHRU_EDGE (l1_bb);
6677 e->flags = EDGE_TRUE_VALUE;
6679 else
6681 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6683 ne = single_succ_edge (l1_bb);
6684 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6687 ne->flags = EDGE_FALSE_VALUE;
6688 e->probability = REG_BR_PROB_BASE * 7 / 8;
6689 ne->probability = REG_BR_PROB_BASE / 8;
6691 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6692 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6693 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6695 if (!broken_loop)
6697 struct loop *loop = alloc_loop ();
6698 loop->header = l1_bb;
6699 loop->latch = e->dest;
6700 add_loop (loop, l1_bb->loop_father);
6701 if (safelen == NULL_TREE)
6702 loop->safelen = INT_MAX;
6703 else
6705 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6706 if (!host_integerp (safelen, 1)
6707 || (unsigned HOST_WIDE_INT) tree_low_cst (safelen, 1)
6708 > INT_MAX)
6709 loop->safelen = INT_MAX;
6710 else
6711 loop->safelen = tree_low_cst (safelen, 1);
6712 if (loop->safelen == 1)
6713 loop->safelen = 0;
6715 if (simduid)
6717 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6718 cfun->has_simduid_loops = true;
6720 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6721 the loop. */
6722 if ((flag_tree_loop_vectorize
6723 || (!global_options_set.x_flag_tree_loop_vectorize
6724 && !global_options_set.x_flag_tree_vectorize))
6725 && loop->safelen > 1)
6727 loop->force_vect = true;
6728 cfun->has_force_vect_loops = true;
6734 /* Expand the OpenMP loop defined by REGION. */
6736 static void
6737 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6739 struct omp_for_data fd;
6740 struct omp_for_data_loop *loops;
6742 loops
6743 = (struct omp_for_data_loop *)
6744 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6745 * sizeof (struct omp_for_data_loop));
6746 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6747 region->sched_kind = fd.sched_kind;
6749 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6750 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6751 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6752 if (region->cont)
6754 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6755 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6756 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6758 else
6759 /* If there isn't a continue then this is a degerate case where
6760 the introduction of abnormal edges during lowering will prevent
6761 original loops from being detected. Fix that up. */
6762 loops_state_set (LOOPS_NEED_FIXUP);
6764 if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
6765 expand_omp_simd (region, &fd);
6766 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6767 && !fd.have_ordered)
6769 if (fd.chunk_size == NULL)
6770 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6771 else
6772 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6774 else
6776 int fn_index, start_ix, next_ix;
6778 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6779 == GF_OMP_FOR_KIND_FOR);
6780 if (fd.chunk_size == NULL
6781 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6782 fd.chunk_size = integer_zero_node;
6783 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6784 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6785 ? 3 : fd.sched_kind;
6786 fn_index += fd.have_ordered * 4;
6787 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6788 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6789 if (fd.iter_type == long_long_unsigned_type_node)
6791 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6792 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6793 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6794 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6796 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6797 (enum built_in_function) next_ix, inner_stmt);
6800 if (gimple_in_ssa_p (cfun))
6801 update_ssa (TODO_update_ssa_only_virtuals);
6805 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6807 v = GOMP_sections_start (n);
6809 switch (v)
6811 case 0:
6812 goto L2;
6813 case 1:
6814 section 1;
6815 goto L1;
6816 case 2:
6818 case n:
6820 default:
6821 abort ();
6824 v = GOMP_sections_next ();
6825 goto L0;
6827 reduction;
6829 If this is a combined parallel sections, replace the call to
6830 GOMP_sections_start with call to GOMP_sections_next. */
6832 static void
6833 expand_omp_sections (struct omp_region *region)
6835 tree t, u, vin = NULL, vmain, vnext, l2;
6836 vec<tree> label_vec;
6837 unsigned len;
6838 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6839 gimple_stmt_iterator si, switch_si;
6840 gimple sections_stmt, stmt, cont;
6841 edge_iterator ei;
6842 edge e;
6843 struct omp_region *inner;
6844 unsigned i, casei;
6845 bool exit_reachable = region->cont != NULL;
6847 gcc_assert (region->exit != NULL);
6848 entry_bb = region->entry;
6849 l0_bb = single_succ (entry_bb);
6850 l1_bb = region->cont;
6851 l2_bb = region->exit;
6852 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6853 l2 = gimple_block_label (l2_bb);
6854 else
6856 /* This can happen if there are reductions. */
6857 len = EDGE_COUNT (l0_bb->succs);
6858 gcc_assert (len > 0);
6859 e = EDGE_SUCC (l0_bb, len - 1);
6860 si = gsi_last_bb (e->dest);
6861 l2 = NULL_TREE;
6862 if (gsi_end_p (si)
6863 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6864 l2 = gimple_block_label (e->dest);
6865 else
6866 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6868 si = gsi_last_bb (e->dest);
6869 if (gsi_end_p (si)
6870 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6872 l2 = gimple_block_label (e->dest);
6873 break;
6877 if (exit_reachable)
6878 default_bb = create_empty_bb (l1_bb->prev_bb);
6879 else
6880 default_bb = create_empty_bb (l0_bb);
6882 /* We will build a switch() with enough cases for all the
6883 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
6884 and a default case to abort if something goes wrong. */
6885 len = EDGE_COUNT (l0_bb->succs);
6887 /* Use vec::quick_push on label_vec throughout, since we know the size
6888 in advance. */
6889 label_vec.create (len);
6891 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
6892 GIMPLE_OMP_SECTIONS statement. */
6893 si = gsi_last_bb (entry_bb);
6894 sections_stmt = gsi_stmt (si);
6895 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
6896 vin = gimple_omp_sections_control (sections_stmt);
6897 if (!is_combined_parallel (region))
6899 /* If we are not inside a combined parallel+sections region,
6900 call GOMP_sections_start. */
6901 t = build_int_cst (unsigned_type_node, len - 1);
6902 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
6903 stmt = gimple_build_call (u, 1, t);
6905 else
6907 /* Otherwise, call GOMP_sections_next. */
6908 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
6909 stmt = gimple_build_call (u, 0);
6911 gimple_call_set_lhs (stmt, vin);
6912 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
6913 gsi_remove (&si, true);
6915 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
6916 L0_BB. */
6917 switch_si = gsi_last_bb (l0_bb);
6918 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
6919 if (exit_reachable)
6921 cont = last_stmt (l1_bb);
6922 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
6923 vmain = gimple_omp_continue_control_use (cont);
6924 vnext = gimple_omp_continue_control_def (cont);
6926 else
6928 vmain = vin;
6929 vnext = NULL_TREE;
6932 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
6933 label_vec.quick_push (t);
6934 i = 1;
6936 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
6937 for (inner = region->inner, casei = 1;
6938 inner;
6939 inner = inner->next, i++, casei++)
6941 basic_block s_entry_bb, s_exit_bb;
6943 /* Skip optional reduction region. */
6944 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
6946 --i;
6947 --casei;
6948 continue;
6951 s_entry_bb = inner->entry;
6952 s_exit_bb = inner->exit;
6954 t = gimple_block_label (s_entry_bb);
6955 u = build_int_cst (unsigned_type_node, casei);
6956 u = build_case_label (u, NULL, t);
6957 label_vec.quick_push (u);
6959 si = gsi_last_bb (s_entry_bb);
6960 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
6961 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
6962 gsi_remove (&si, true);
6963 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
6965 if (s_exit_bb == NULL)
6966 continue;
6968 si = gsi_last_bb (s_exit_bb);
6969 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
6970 gsi_remove (&si, true);
6972 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
6975 /* Error handling code goes in DEFAULT_BB. */
6976 t = gimple_block_label (default_bb);
6977 u = build_case_label (NULL, NULL, t);
6978 make_edge (l0_bb, default_bb, 0);
6979 if (current_loops)
6980 add_bb_to_loop (default_bb, current_loops->tree_root);
6982 stmt = gimple_build_switch (vmain, u, label_vec);
6983 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
6984 gsi_remove (&switch_si, true);
6985 label_vec.release ();
6987 si = gsi_start_bb (default_bb);
6988 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
6989 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6991 if (exit_reachable)
6993 tree bfn_decl;
6995 /* Code to get the next section goes in L1_BB. */
6996 si = gsi_last_bb (l1_bb);
6997 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
6999 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7000 stmt = gimple_build_call (bfn_decl, 0);
7001 gimple_call_set_lhs (stmt, vnext);
7002 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7003 gsi_remove (&si, true);
7005 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7008 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7009 si = gsi_last_bb (l2_bb);
7010 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7011 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7012 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7013 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7014 else
7015 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7016 stmt = gimple_build_call (t, 0);
7017 if (gimple_omp_return_lhs (gsi_stmt (si)))
7018 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7019 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7020 gsi_remove (&si, true);
7022 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7026 /* Expand code for an OpenMP single directive. We've already expanded
7027 much of the code, here we simply place the GOMP_barrier call. */
7029 static void
7030 expand_omp_single (struct omp_region *region)
7032 basic_block entry_bb, exit_bb;
7033 gimple_stmt_iterator si;
7035 entry_bb = region->entry;
7036 exit_bb = region->exit;
7038 si = gsi_last_bb (entry_bb);
7039 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7040 gsi_remove (&si, true);
7041 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7043 si = gsi_last_bb (exit_bb);
7044 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7046 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7047 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7049 gsi_remove (&si, true);
7050 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7054 /* Generic expansion for OpenMP synchronization directives: master,
7055 ordered and critical. All we need to do here is remove the entry
7056 and exit markers for REGION. */
7058 static void
7059 expand_omp_synch (struct omp_region *region)
7061 basic_block entry_bb, exit_bb;
7062 gimple_stmt_iterator si;
7064 entry_bb = region->entry;
7065 exit_bb = region->exit;
7067 si = gsi_last_bb (entry_bb);
7068 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7069 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7070 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7071 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7072 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7073 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7074 gsi_remove (&si, true);
7075 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7077 if (exit_bb)
7079 si = gsi_last_bb (exit_bb);
7080 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7081 gsi_remove (&si, true);
7082 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7086 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7087 operation as a normal volatile load. */
7089 static bool
7090 expand_omp_atomic_load (basic_block load_bb, tree addr,
7091 tree loaded_val, int index)
7093 enum built_in_function tmpbase;
7094 gimple_stmt_iterator gsi;
7095 basic_block store_bb;
7096 location_t loc;
7097 gimple stmt;
7098 tree decl, call, type, itype;
7100 gsi = gsi_last_bb (load_bb);
7101 stmt = gsi_stmt (gsi);
7102 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7103 loc = gimple_location (stmt);
7105 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7106 is smaller than word size, then expand_atomic_load assumes that the load
7107 is atomic. We could avoid the builtin entirely in this case. */
7109 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7110 decl = builtin_decl_explicit (tmpbase);
7111 if (decl == NULL_TREE)
7112 return false;
7114 type = TREE_TYPE (loaded_val);
7115 itype = TREE_TYPE (TREE_TYPE (decl));
7117 call = build_call_expr_loc (loc, decl, 2, addr,
7118 build_int_cst (NULL,
7119 gimple_omp_atomic_seq_cst_p (stmt)
7120 ? MEMMODEL_SEQ_CST
7121 : MEMMODEL_RELAXED));
7122 if (!useless_type_conversion_p (type, itype))
7123 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7124 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7126 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7127 gsi_remove (&gsi, true);
7129 store_bb = single_succ (load_bb);
7130 gsi = gsi_last_bb (store_bb);
7131 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7132 gsi_remove (&gsi, true);
7134 if (gimple_in_ssa_p (cfun))
7135 update_ssa (TODO_update_ssa_no_phi);
7137 return true;
7140 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7141 operation as a normal volatile store. */
7143 static bool
7144 expand_omp_atomic_store (basic_block load_bb, tree addr,
7145 tree loaded_val, tree stored_val, int index)
7147 enum built_in_function tmpbase;
7148 gimple_stmt_iterator gsi;
7149 basic_block store_bb = single_succ (load_bb);
7150 location_t loc;
7151 gimple stmt;
7152 tree decl, call, type, itype;
7153 enum machine_mode imode;
7154 bool exchange;
7156 gsi = gsi_last_bb (load_bb);
7157 stmt = gsi_stmt (gsi);
7158 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7160 /* If the load value is needed, then this isn't a store but an exchange. */
7161 exchange = gimple_omp_atomic_need_value_p (stmt);
7163 gsi = gsi_last_bb (store_bb);
7164 stmt = gsi_stmt (gsi);
7165 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7166 loc = gimple_location (stmt);
7168 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7169 is smaller than word size, then expand_atomic_store assumes that the store
7170 is atomic. We could avoid the builtin entirely in this case. */
7172 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7173 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7174 decl = builtin_decl_explicit (tmpbase);
7175 if (decl == NULL_TREE)
7176 return false;
7178 type = TREE_TYPE (stored_val);
7180 /* Dig out the type of the function's second argument. */
7181 itype = TREE_TYPE (decl);
7182 itype = TYPE_ARG_TYPES (itype);
7183 itype = TREE_CHAIN (itype);
7184 itype = TREE_VALUE (itype);
7185 imode = TYPE_MODE (itype);
7187 if (exchange && !can_atomic_exchange_p (imode, true))
7188 return false;
7190 if (!useless_type_conversion_p (itype, type))
7191 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7192 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7193 build_int_cst (NULL,
7194 gimple_omp_atomic_seq_cst_p (stmt)
7195 ? MEMMODEL_SEQ_CST
7196 : MEMMODEL_RELAXED));
7197 if (exchange)
7199 if (!useless_type_conversion_p (type, itype))
7200 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7201 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7204 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7205 gsi_remove (&gsi, true);
7207 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7208 gsi = gsi_last_bb (load_bb);
7209 gsi_remove (&gsi, true);
7211 if (gimple_in_ssa_p (cfun))
7212 update_ssa (TODO_update_ssa_no_phi);
7214 return true;
7217 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7218 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7219 size of the data type, and thus usable to find the index of the builtin
7220 decl. Returns false if the expression is not of the proper form. */
7222 static bool
7223 expand_omp_atomic_fetch_op (basic_block load_bb,
7224 tree addr, tree loaded_val,
7225 tree stored_val, int index)
7227 enum built_in_function oldbase, newbase, tmpbase;
7228 tree decl, itype, call;
7229 tree lhs, rhs;
7230 basic_block store_bb = single_succ (load_bb);
7231 gimple_stmt_iterator gsi;
7232 gimple stmt;
7233 location_t loc;
7234 enum tree_code code;
7235 bool need_old, need_new;
7236 enum machine_mode imode;
7237 bool seq_cst;
7239 /* We expect to find the following sequences:
7241 load_bb:
7242 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7244 store_bb:
7245 val = tmp OP something; (or: something OP tmp)
7246 GIMPLE_OMP_STORE (val)
7248 ???FIXME: Allow a more flexible sequence.
7249 Perhaps use data flow to pick the statements.
7253 gsi = gsi_after_labels (store_bb);
7254 stmt = gsi_stmt (gsi);
7255 loc = gimple_location (stmt);
7256 if (!is_gimple_assign (stmt))
7257 return false;
7258 gsi_next (&gsi);
7259 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7260 return false;
7261 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7262 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7263 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7264 gcc_checking_assert (!need_old || !need_new);
7266 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7267 return false;
7269 /* Check for one of the supported fetch-op operations. */
7270 code = gimple_assign_rhs_code (stmt);
7271 switch (code)
7273 case PLUS_EXPR:
7274 case POINTER_PLUS_EXPR:
7275 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7276 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7277 break;
7278 case MINUS_EXPR:
7279 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7280 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7281 break;
7282 case BIT_AND_EXPR:
7283 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7284 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7285 break;
7286 case BIT_IOR_EXPR:
7287 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7288 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7289 break;
7290 case BIT_XOR_EXPR:
7291 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7292 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7293 break;
7294 default:
7295 return false;
7298 /* Make sure the expression is of the proper form. */
7299 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7300 rhs = gimple_assign_rhs2 (stmt);
7301 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7302 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7303 rhs = gimple_assign_rhs1 (stmt);
7304 else
7305 return false;
7307 tmpbase = ((enum built_in_function)
7308 ((need_new ? newbase : oldbase) + index + 1));
7309 decl = builtin_decl_explicit (tmpbase);
7310 if (decl == NULL_TREE)
7311 return false;
7312 itype = TREE_TYPE (TREE_TYPE (decl));
7313 imode = TYPE_MODE (itype);
7315 /* We could test all of the various optabs involved, but the fact of the
7316 matter is that (with the exception of i486 vs i586 and xadd) all targets
7317 that support any atomic operaton optab also implements compare-and-swap.
7318 Let optabs.c take care of expanding any compare-and-swap loop. */
7319 if (!can_compare_and_swap_p (imode, true))
7320 return false;
7322 gsi = gsi_last_bb (load_bb);
7323 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7325 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7326 It only requires that the operation happen atomically. Thus we can
7327 use the RELAXED memory model. */
7328 call = build_call_expr_loc (loc, decl, 3, addr,
7329 fold_convert_loc (loc, itype, rhs),
7330 build_int_cst (NULL,
7331 seq_cst ? MEMMODEL_SEQ_CST
7332 : MEMMODEL_RELAXED));
7334 if (need_old || need_new)
7336 lhs = need_old ? loaded_val : stored_val;
7337 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7338 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7340 else
7341 call = fold_convert_loc (loc, void_type_node, call);
7342 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7343 gsi_remove (&gsi, true);
7345 gsi = gsi_last_bb (store_bb);
7346 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7347 gsi_remove (&gsi, true);
7348 gsi = gsi_last_bb (store_bb);
7349 gsi_remove (&gsi, true);
7351 if (gimple_in_ssa_p (cfun))
7352 update_ssa (TODO_update_ssa_no_phi);
7354 return true;
7357 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7359 oldval = *addr;
7360 repeat:
7361 newval = rhs; // with oldval replacing *addr in rhs
7362 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7363 if (oldval != newval)
7364 goto repeat;
7366 INDEX is log2 of the size of the data type, and thus usable to find the
7367 index of the builtin decl. */
7369 static bool
7370 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7371 tree addr, tree loaded_val, tree stored_val,
7372 int index)
7374 tree loadedi, storedi, initial, new_storedi, old_vali;
7375 tree type, itype, cmpxchg, iaddr;
7376 gimple_stmt_iterator si;
7377 basic_block loop_header = single_succ (load_bb);
7378 gimple phi, stmt;
7379 edge e;
7380 enum built_in_function fncode;
7382 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7383 order to use the RELAXED memory model effectively. */
7384 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7385 + index + 1);
7386 cmpxchg = builtin_decl_explicit (fncode);
7387 if (cmpxchg == NULL_TREE)
7388 return false;
7389 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7390 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7392 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7393 return false;
7395 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7396 si = gsi_last_bb (load_bb);
7397 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7399 /* For floating-point values, we'll need to view-convert them to integers
7400 so that we can perform the atomic compare and swap. Simplify the
7401 following code by always setting up the "i"ntegral variables. */
7402 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7404 tree iaddr_val;
7406 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7407 true), NULL);
7408 iaddr_val
7409 = force_gimple_operand_gsi (&si,
7410 fold_convert (TREE_TYPE (iaddr), addr),
7411 false, NULL_TREE, true, GSI_SAME_STMT);
7412 stmt = gimple_build_assign (iaddr, iaddr_val);
7413 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7414 loadedi = create_tmp_var (itype, NULL);
7415 if (gimple_in_ssa_p (cfun))
7416 loadedi = make_ssa_name (loadedi, NULL);
7418 else
7420 iaddr = addr;
7421 loadedi = loaded_val;
7424 initial
7425 = force_gimple_operand_gsi (&si,
7426 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
7427 iaddr,
7428 build_int_cst (TREE_TYPE (iaddr), 0)),
7429 true, NULL_TREE, true, GSI_SAME_STMT);
7431 /* Move the value to the LOADEDI temporary. */
7432 if (gimple_in_ssa_p (cfun))
7434 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7435 phi = create_phi_node (loadedi, loop_header);
7436 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7437 initial);
7439 else
7440 gsi_insert_before (&si,
7441 gimple_build_assign (loadedi, initial),
7442 GSI_SAME_STMT);
7443 if (loadedi != loaded_val)
7445 gimple_stmt_iterator gsi2;
7446 tree x;
7448 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7449 gsi2 = gsi_start_bb (loop_header);
7450 if (gimple_in_ssa_p (cfun))
7452 gimple stmt;
7453 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7454 true, GSI_SAME_STMT);
7455 stmt = gimple_build_assign (loaded_val, x);
7456 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7458 else
7460 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7461 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7462 true, GSI_SAME_STMT);
7465 gsi_remove (&si, true);
7467 si = gsi_last_bb (store_bb);
7468 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7470 if (iaddr == addr)
7471 storedi = stored_val;
7472 else
7473 storedi =
7474 force_gimple_operand_gsi (&si,
7475 build1 (VIEW_CONVERT_EXPR, itype,
7476 stored_val), true, NULL_TREE, true,
7477 GSI_SAME_STMT);
7479 /* Build the compare&swap statement. */
7480 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7481 new_storedi = force_gimple_operand_gsi (&si,
7482 fold_convert (TREE_TYPE (loadedi),
7483 new_storedi),
7484 true, NULL_TREE,
7485 true, GSI_SAME_STMT);
7487 if (gimple_in_ssa_p (cfun))
7488 old_vali = loadedi;
7489 else
7491 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7492 stmt = gimple_build_assign (old_vali, loadedi);
7493 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7495 stmt = gimple_build_assign (loadedi, new_storedi);
7496 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7499 /* Note that we always perform the comparison as an integer, even for
7500 floating point. This allows the atomic operation to properly
7501 succeed even with NaNs and -0.0. */
7502 stmt = gimple_build_cond_empty
7503 (build2 (NE_EXPR, boolean_type_node,
7504 new_storedi, old_vali));
7505 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7507 /* Update cfg. */
7508 e = single_succ_edge (store_bb);
7509 e->flags &= ~EDGE_FALLTHRU;
7510 e->flags |= EDGE_FALSE_VALUE;
7512 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7514 /* Copy the new value to loadedi (we already did that before the condition
7515 if we are not in SSA). */
7516 if (gimple_in_ssa_p (cfun))
7518 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7519 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7522 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7523 gsi_remove (&si, true);
7525 struct loop *loop = alloc_loop ();
7526 loop->header = loop_header;
7527 loop->latch = store_bb;
7528 add_loop (loop, loop_header->loop_father);
7530 if (gimple_in_ssa_p (cfun))
7531 update_ssa (TODO_update_ssa_no_phi);
7533 return true;
7536 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7538 GOMP_atomic_start ();
7539 *addr = rhs;
7540 GOMP_atomic_end ();
7542 The result is not globally atomic, but works so long as all parallel
7543 references are within #pragma omp atomic directives. According to
7544 responses received from omp@openmp.org, appears to be within spec.
7545 Which makes sense, since that's how several other compilers handle
7546 this situation as well.
7547 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7548 expanding. STORED_VAL is the operand of the matching
7549 GIMPLE_OMP_ATOMIC_STORE.
7551 We replace
7552 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7553 loaded_val = *addr;
7555 and replace
7556 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7557 *addr = stored_val;
7560 static bool
7561 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7562 tree addr, tree loaded_val, tree stored_val)
7564 gimple_stmt_iterator si;
7565 gimple stmt;
7566 tree t;
7568 si = gsi_last_bb (load_bb);
7569 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7571 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7572 t = build_call_expr (t, 0);
7573 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7575 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7576 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7577 gsi_remove (&si, true);
7579 si = gsi_last_bb (store_bb);
7580 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7582 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7583 stored_val);
7584 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7586 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7587 t = build_call_expr (t, 0);
7588 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7589 gsi_remove (&si, true);
7591 if (gimple_in_ssa_p (cfun))
7592 update_ssa (TODO_update_ssa_no_phi);
7593 return true;
7596 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7597 using expand_omp_atomic_fetch_op. If it failed, we try to
7598 call expand_omp_atomic_pipeline, and if it fails too, the
7599 ultimate fallback is wrapping the operation in a mutex
7600 (expand_omp_atomic_mutex). REGION is the atomic region built
7601 by build_omp_regions_1(). */
7603 static void
7604 expand_omp_atomic (struct omp_region *region)
7606 basic_block load_bb = region->entry, store_bb = region->exit;
7607 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7608 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7609 tree addr = gimple_omp_atomic_load_rhs (load);
7610 tree stored_val = gimple_omp_atomic_store_val (store);
7611 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7612 HOST_WIDE_INT index;
7614 /* Make sure the type is one of the supported sizes. */
7615 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
7616 index = exact_log2 (index);
7617 if (index >= 0 && index <= 4)
7619 unsigned int align = TYPE_ALIGN_UNIT (type);
7621 /* __sync builtins require strict data alignment. */
7622 if (exact_log2 (align) >= index)
7624 /* Atomic load. */
7625 if (loaded_val == stored_val
7626 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7627 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7628 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7629 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7630 return;
7632 /* Atomic store. */
7633 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7634 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7635 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7636 && store_bb == single_succ (load_bb)
7637 && first_stmt (store_bb) == store
7638 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7639 stored_val, index))
7640 return;
7642 /* When possible, use specialized atomic update functions. */
7643 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7644 && store_bb == single_succ (load_bb)
7645 && expand_omp_atomic_fetch_op (load_bb, addr,
7646 loaded_val, stored_val, index))
7647 return;
7649 /* If we don't have specialized __sync builtins, try and implement
7650 as a compare and swap loop. */
7651 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7652 loaded_val, stored_val, index))
7653 return;
7657 /* The ultimate fallback is wrapping the operation in a mutex. */
7658 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7662 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7664 static void
7665 expand_omp_target (struct omp_region *region)
7667 basic_block entry_bb, exit_bb, new_bb;
7668 struct function *child_cfun = NULL;
7669 tree child_fn = NULL_TREE, block, t;
7670 gimple_stmt_iterator gsi;
7671 gimple entry_stmt, stmt;
7672 edge e;
7674 entry_stmt = last_stmt (region->entry);
7675 new_bb = region->entry;
7676 int kind = gimple_omp_target_kind (entry_stmt);
7677 if (kind == GF_OMP_TARGET_KIND_REGION)
7679 child_fn = gimple_omp_target_child_fn (entry_stmt);
7680 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7683 entry_bb = region->entry;
7684 exit_bb = region->exit;
7686 if (kind == GF_OMP_TARGET_KIND_REGION)
7688 unsigned srcidx, dstidx, num;
7690 /* If the target region needs data sent from the parent
7691 function, then the very first statement (except possible
7692 tree profile counter updates) of the parallel body
7693 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7694 &.OMP_DATA_O is passed as an argument to the child function,
7695 we need to replace it with the argument as seen by the child
7696 function.
7698 In most cases, this will end up being the identity assignment
7699 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7700 a function call that has been inlined, the original PARM_DECL
7701 .OMP_DATA_I may have been converted into a different local
7702 variable. In which case, we need to keep the assignment. */
7703 if (gimple_omp_target_data_arg (entry_stmt))
7705 basic_block entry_succ_bb = single_succ (entry_bb);
7706 gimple_stmt_iterator gsi;
7707 tree arg;
7708 gimple tgtcopy_stmt = NULL;
7709 tree sender
7710 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7712 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7714 gcc_assert (!gsi_end_p (gsi));
7715 stmt = gsi_stmt (gsi);
7716 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7717 continue;
7719 if (gimple_num_ops (stmt) == 2)
7721 tree arg = gimple_assign_rhs1 (stmt);
7723 /* We're ignoring the subcode because we're
7724 effectively doing a STRIP_NOPS. */
7726 if (TREE_CODE (arg) == ADDR_EXPR
7727 && TREE_OPERAND (arg, 0) == sender)
7729 tgtcopy_stmt = stmt;
7730 break;
7735 gcc_assert (tgtcopy_stmt != NULL);
7736 arg = DECL_ARGUMENTS (child_fn);
7738 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7739 gsi_remove (&gsi, true);
7742 /* Declare local variables needed in CHILD_CFUN. */
7743 block = DECL_INITIAL (child_fn);
7744 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7745 /* The gimplifier could record temporaries in target block
7746 rather than in containing function's local_decls chain,
7747 which would mean cgraph missed finalizing them. Do it now. */
7748 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7749 if (TREE_CODE (t) == VAR_DECL
7750 && TREE_STATIC (t)
7751 && !DECL_EXTERNAL (t))
7752 varpool_finalize_decl (t);
7753 DECL_SAVED_TREE (child_fn) = NULL;
7754 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7755 gimple_set_body (child_fn, NULL);
7756 TREE_USED (block) = 1;
7758 /* Reset DECL_CONTEXT on function arguments. */
7759 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7760 DECL_CONTEXT (t) = child_fn;
7762 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7763 so that it can be moved to the child function. */
7764 gsi = gsi_last_bb (entry_bb);
7765 stmt = gsi_stmt (gsi);
7766 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7767 && gimple_omp_target_kind (stmt)
7768 == GF_OMP_TARGET_KIND_REGION);
7769 gsi_remove (&gsi, true);
7770 e = split_block (entry_bb, stmt);
7771 entry_bb = e->dest;
7772 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7774 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7775 if (exit_bb)
7777 gsi = gsi_last_bb (exit_bb);
7778 gcc_assert (!gsi_end_p (gsi)
7779 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7780 stmt = gimple_build_return (NULL);
7781 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7782 gsi_remove (&gsi, true);
7785 /* Move the target region into CHILD_CFUN. */
7787 block = gimple_block (entry_stmt);
7789 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7790 if (exit_bb)
7791 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7792 /* When the OMP expansion process cannot guarantee an up-to-date
7793 loop tree arrange for the child function to fixup loops. */
7794 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7795 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7797 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7798 num = vec_safe_length (child_cfun->local_decls);
7799 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7801 t = (*child_cfun->local_decls)[srcidx];
7802 if (DECL_CONTEXT (t) == cfun->decl)
7803 continue;
7804 if (srcidx != dstidx)
7805 (*child_cfun->local_decls)[dstidx] = t;
7806 dstidx++;
7808 if (dstidx != num)
7809 vec_safe_truncate (child_cfun->local_decls, dstidx);
7811 /* Inform the callgraph about the new function. */
7812 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7813 cgraph_add_new_function (child_fn, true);
7815 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7816 fixed in a following pass. */
7817 push_cfun (child_cfun);
7818 rebuild_cgraph_edges ();
7820 /* Some EH regions might become dead, see PR34608. If
7821 pass_cleanup_cfg isn't the first pass to happen with the
7822 new child, these dead EH edges might cause problems.
7823 Clean them up now. */
7824 if (flag_exceptions)
7826 basic_block bb;
7827 bool changed = false;
7829 FOR_EACH_BB (bb)
7830 changed |= gimple_purge_dead_eh_edges (bb);
7831 if (changed)
7832 cleanup_tree_cfg ();
7834 pop_cfun ();
7837 /* Emit a library call to launch the target region, or do data
7838 transfers. */
7839 tree t1, t2, t3, t4, device, cond, c, clauses;
7840 enum built_in_function start_ix;
7841 location_t clause_loc;
7843 clauses = gimple_omp_target_clauses (entry_stmt);
7845 if (kind == GF_OMP_TARGET_KIND_REGION)
7846 start_ix = BUILT_IN_GOMP_TARGET;
7847 else if (kind == GF_OMP_TARGET_KIND_DATA)
7848 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7849 else
7850 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7852 /* By default, the value of DEVICE is -1 (let runtime library choose)
7853 and there is no conditional. */
7854 cond = NULL_TREE;
7855 device = build_int_cst (integer_type_node, -1);
7857 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7858 if (c)
7859 cond = OMP_CLAUSE_IF_EXPR (c);
7861 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7862 if (c)
7864 device = OMP_CLAUSE_DEVICE_ID (c);
7865 clause_loc = OMP_CLAUSE_LOCATION (c);
7867 else
7868 clause_loc = gimple_location (entry_stmt);
7870 /* Ensure 'device' is of the correct type. */
7871 device = fold_convert_loc (clause_loc, integer_type_node, device);
7873 /* If we found the clause 'if (cond)', build
7874 (cond ? device : -2). */
7875 if (cond)
7877 cond = gimple_boolify (cond);
7879 basic_block cond_bb, then_bb, else_bb;
7880 edge e;
7881 tree tmp_var;
7883 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
7884 if (kind != GF_OMP_TARGET_KIND_REGION)
7886 gsi = gsi_last_bb (new_bb);
7887 gsi_prev (&gsi);
7888 e = split_block (new_bb, gsi_stmt (gsi));
7890 else
7891 e = split_block (new_bb, NULL);
7892 cond_bb = e->src;
7893 new_bb = e->dest;
7894 remove_edge (e);
7896 then_bb = create_empty_bb (cond_bb);
7897 else_bb = create_empty_bb (then_bb);
7898 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
7899 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
7901 stmt = gimple_build_cond_empty (cond);
7902 gsi = gsi_last_bb (cond_bb);
7903 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7905 gsi = gsi_start_bb (then_bb);
7906 stmt = gimple_build_assign (tmp_var, device);
7907 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7909 gsi = gsi_start_bb (else_bb);
7910 stmt = gimple_build_assign (tmp_var,
7911 build_int_cst (integer_type_node, -2));
7912 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7914 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
7915 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
7916 if (current_loops)
7918 add_bb_to_loop (then_bb, cond_bb->loop_father);
7919 add_bb_to_loop (else_bb, cond_bb->loop_father);
7921 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
7922 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
7924 device = tmp_var;
7927 gsi = gsi_last_bb (new_bb);
7928 t = gimple_omp_target_data_arg (entry_stmt);
7929 if (t == NULL)
7931 t1 = size_zero_node;
7932 t2 = build_zero_cst (ptr_type_node);
7933 t3 = t2;
7934 t4 = t2;
7936 else
7938 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
7939 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
7940 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
7941 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
7942 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
7945 gimple g;
7946 /* FIXME: This will be address of
7947 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
7948 symbol, as soon as the linker plugin is able to create it for us. */
7949 tree openmp_target = build_zero_cst (ptr_type_node);
7950 if (kind == GF_OMP_TARGET_KIND_REGION)
7952 tree fnaddr = build_fold_addr_expr (child_fn);
7953 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
7954 device, fnaddr, openmp_target, t1, t2, t3, t4);
7956 else
7957 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
7958 device, openmp_target, t1, t2, t3, t4);
7959 gimple_set_location (g, gimple_location (entry_stmt));
7960 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
7961 if (kind != GF_OMP_TARGET_KIND_REGION)
7963 g = gsi_stmt (gsi);
7964 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
7965 gsi_remove (&gsi, true);
7967 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
7969 gsi = gsi_last_bb (region->exit);
7970 g = gsi_stmt (gsi);
7971 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
7972 gsi_remove (&gsi, true);
7977 /* Expand the parallel region tree rooted at REGION. Expansion
7978 proceeds in depth-first order. Innermost regions are expanded
7979 first. This way, parallel regions that require a new function to
7980 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
7981 internal dependencies in their body. */
7983 static void
7984 expand_omp (struct omp_region *region)
7986 while (region)
7988 location_t saved_location;
7989 gimple inner_stmt = NULL;
7991 /* First, determine whether this is a combined parallel+workshare
7992 region. */
7993 if (region->type == GIMPLE_OMP_PARALLEL)
7994 determine_parallel_type (region);
7996 if (region->type == GIMPLE_OMP_FOR
7997 && gimple_omp_for_combined_p (last_stmt (region->entry)))
7998 inner_stmt = last_stmt (region->inner->entry);
8000 if (region->inner)
8001 expand_omp (region->inner);
8003 saved_location = input_location;
8004 if (gimple_has_location (last_stmt (region->entry)))
8005 input_location = gimple_location (last_stmt (region->entry));
8007 switch (region->type)
8009 case GIMPLE_OMP_PARALLEL:
8010 case GIMPLE_OMP_TASK:
8011 expand_omp_taskreg (region);
8012 break;
8014 case GIMPLE_OMP_FOR:
8015 expand_omp_for (region, inner_stmt);
8016 break;
8018 case GIMPLE_OMP_SECTIONS:
8019 expand_omp_sections (region);
8020 break;
8022 case GIMPLE_OMP_SECTION:
8023 /* Individual omp sections are handled together with their
8024 parent GIMPLE_OMP_SECTIONS region. */
8025 break;
8027 case GIMPLE_OMP_SINGLE:
8028 expand_omp_single (region);
8029 break;
8031 case GIMPLE_OMP_MASTER:
8032 case GIMPLE_OMP_TASKGROUP:
8033 case GIMPLE_OMP_ORDERED:
8034 case GIMPLE_OMP_CRITICAL:
8035 case GIMPLE_OMP_TEAMS:
8036 expand_omp_synch (region);
8037 break;
8039 case GIMPLE_OMP_ATOMIC_LOAD:
8040 expand_omp_atomic (region);
8041 break;
8043 case GIMPLE_OMP_TARGET:
8044 expand_omp_target (region);
8045 break;
8047 default:
8048 gcc_unreachable ();
8051 input_location = saved_location;
8052 region = region->next;
8057 /* Helper for build_omp_regions. Scan the dominator tree starting at
8058 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8059 true, the function ends once a single tree is built (otherwise, whole
8060 forest of OMP constructs may be built). */
8062 static void
8063 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8064 bool single_tree)
8066 gimple_stmt_iterator gsi;
8067 gimple stmt;
8068 basic_block son;
8070 gsi = gsi_last_bb (bb);
8071 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8073 struct omp_region *region;
8074 enum gimple_code code;
8076 stmt = gsi_stmt (gsi);
8077 code = gimple_code (stmt);
8078 if (code == GIMPLE_OMP_RETURN)
8080 /* STMT is the return point out of region PARENT. Mark it
8081 as the exit point and make PARENT the immediately
8082 enclosing region. */
8083 gcc_assert (parent);
8084 region = parent;
8085 region->exit = bb;
8086 parent = parent->outer;
8088 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8090 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8091 GIMPLE_OMP_RETURN, but matches with
8092 GIMPLE_OMP_ATOMIC_LOAD. */
8093 gcc_assert (parent);
8094 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8095 region = parent;
8096 region->exit = bb;
8097 parent = parent->outer;
8100 else if (code == GIMPLE_OMP_CONTINUE)
8102 gcc_assert (parent);
8103 parent->cont = bb;
8105 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8107 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8108 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8111 else if (code == GIMPLE_OMP_TARGET
8112 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8113 new_omp_region (bb, code, parent);
8114 else
8116 /* Otherwise, this directive becomes the parent for a new
8117 region. */
8118 region = new_omp_region (bb, code, parent);
8119 parent = region;
8123 if (single_tree && !parent)
8124 return;
8126 for (son = first_dom_son (CDI_DOMINATORS, bb);
8127 son;
8128 son = next_dom_son (CDI_DOMINATORS, son))
8129 build_omp_regions_1 (son, parent, single_tree);
8132 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8133 root_omp_region. */
8135 static void
8136 build_omp_regions_root (basic_block root)
8138 gcc_assert (root_omp_region == NULL);
8139 build_omp_regions_1 (root, NULL, true);
8140 gcc_assert (root_omp_region != NULL);
8143 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8145 void
8146 omp_expand_local (basic_block head)
8148 build_omp_regions_root (head);
8149 if (dump_file && (dump_flags & TDF_DETAILS))
8151 fprintf (dump_file, "\nOMP region tree\n\n");
8152 dump_omp_region (dump_file, root_omp_region, 0);
8153 fprintf (dump_file, "\n");
8156 remove_exit_barriers (root_omp_region);
8157 expand_omp (root_omp_region);
8159 free_omp_regions ();
8162 /* Scan the CFG and build a tree of OMP regions. Return the root of
8163 the OMP region tree. */
8165 static void
8166 build_omp_regions (void)
8168 gcc_assert (root_omp_region == NULL);
8169 calculate_dominance_info (CDI_DOMINATORS);
8170 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
8173 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8175 static unsigned int
8176 execute_expand_omp (void)
8178 build_omp_regions ();
8180 if (!root_omp_region)
8181 return 0;
8183 if (dump_file)
8185 fprintf (dump_file, "\nOMP region tree\n\n");
8186 dump_omp_region (dump_file, root_omp_region, 0);
8187 fprintf (dump_file, "\n");
8190 remove_exit_barriers (root_omp_region);
8192 expand_omp (root_omp_region);
8194 cleanup_tree_cfg ();
8196 free_omp_regions ();
8198 return 0;
8201 /* OMP expansion -- the default pass, run before creation of SSA form. */
8203 static bool
8204 gate_expand_omp (void)
8206 return (flag_openmp != 0 && !seen_error ());
8209 namespace {
8211 const pass_data pass_data_expand_omp =
8213 GIMPLE_PASS, /* type */
8214 "ompexp", /* name */
8215 OPTGROUP_NONE, /* optinfo_flags */
8216 true, /* has_gate */
8217 true, /* has_execute */
8218 TV_NONE, /* tv_id */
8219 PROP_gimple_any, /* properties_required */
8220 0, /* properties_provided */
8221 0, /* properties_destroyed */
8222 0, /* todo_flags_start */
8223 0, /* todo_flags_finish */
8226 class pass_expand_omp : public gimple_opt_pass
8228 public:
8229 pass_expand_omp (gcc::context *ctxt)
8230 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8233 /* opt_pass methods: */
8234 bool gate () { return gate_expand_omp (); }
8235 unsigned int execute () { return execute_expand_omp (); }
8237 }; // class pass_expand_omp
8239 } // anon namespace
8241 gimple_opt_pass *
8242 make_pass_expand_omp (gcc::context *ctxt)
8244 return new pass_expand_omp (ctxt);
8247 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8249 /* If ctx is a worksharing context inside of a cancellable parallel
8250 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8251 and conditional branch to parallel's cancel_label to handle
8252 cancellation in the implicit barrier. */
8254 static void
8255 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8257 gimple omp_return = gimple_seq_last_stmt (*body);
8258 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8259 if (gimple_omp_return_nowait_p (omp_return))
8260 return;
8261 if (ctx->outer
8262 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8263 && ctx->outer->cancellable)
8265 tree lhs = create_tmp_var (boolean_type_node, NULL);
8266 gimple_omp_return_set_lhs (omp_return, lhs);
8267 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8268 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8269 ctx->outer->cancel_label, fallthru_label);
8270 gimple_seq_add_stmt (body, g);
8271 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8275 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8276 CTX is the enclosing OMP context for the current statement. */
8278 static void
8279 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8281 tree block, control;
8282 gimple_stmt_iterator tgsi;
8283 gimple stmt, new_stmt, bind, t;
8284 gimple_seq ilist, dlist, olist, new_body;
8285 struct gimplify_ctx gctx;
8287 stmt = gsi_stmt (*gsi_p);
8289 push_gimplify_context (&gctx);
8291 dlist = NULL;
8292 ilist = NULL;
8293 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8294 &ilist, &dlist, ctx, NULL);
8296 new_body = gimple_omp_body (stmt);
8297 gimple_omp_set_body (stmt, NULL);
8298 tgsi = gsi_start (new_body);
8299 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8301 omp_context *sctx;
8302 gimple sec_start;
8304 sec_start = gsi_stmt (tgsi);
8305 sctx = maybe_lookup_ctx (sec_start);
8306 gcc_assert (sctx);
8308 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8309 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8310 GSI_CONTINUE_LINKING);
8311 gimple_omp_set_body (sec_start, NULL);
8313 if (gsi_one_before_end_p (tgsi))
8315 gimple_seq l = NULL;
8316 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8317 &l, ctx);
8318 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8319 gimple_omp_section_set_last (sec_start);
8322 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8323 GSI_CONTINUE_LINKING);
8326 block = make_node (BLOCK);
8327 bind = gimple_build_bind (NULL, new_body, block);
8329 olist = NULL;
8330 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8332 block = make_node (BLOCK);
8333 new_stmt = gimple_build_bind (NULL, NULL, block);
8334 gsi_replace (gsi_p, new_stmt, true);
8336 pop_gimplify_context (new_stmt);
8337 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8338 BLOCK_VARS (block) = gimple_bind_vars (bind);
8339 if (BLOCK_VARS (block))
8340 TREE_USED (block) = 1;
8342 new_body = NULL;
8343 gimple_seq_add_seq (&new_body, ilist);
8344 gimple_seq_add_stmt (&new_body, stmt);
8345 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8346 gimple_seq_add_stmt (&new_body, bind);
8348 control = create_tmp_var (unsigned_type_node, ".section");
8349 t = gimple_build_omp_continue (control, control);
8350 gimple_omp_sections_set_control (stmt, control);
8351 gimple_seq_add_stmt (&new_body, t);
8353 gimple_seq_add_seq (&new_body, olist);
8354 if (ctx->cancellable)
8355 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8356 gimple_seq_add_seq (&new_body, dlist);
8358 new_body = maybe_catch_exception (new_body);
8360 t = gimple_build_omp_return
8361 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8362 OMP_CLAUSE_NOWAIT));
8363 gimple_seq_add_stmt (&new_body, t);
8364 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8366 gimple_bind_set_body (new_stmt, new_body);
8370 /* A subroutine of lower_omp_single. Expand the simple form of
8371 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8373 if (GOMP_single_start ())
8374 BODY;
8375 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8377 FIXME. It may be better to delay expanding the logic of this until
8378 pass_expand_omp. The expanded logic may make the job more difficult
8379 to a synchronization analysis pass. */
8381 static void
8382 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8384 location_t loc = gimple_location (single_stmt);
8385 tree tlabel = create_artificial_label (loc);
8386 tree flabel = create_artificial_label (loc);
8387 gimple call, cond;
8388 tree lhs, decl;
8390 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8391 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8392 call = gimple_build_call (decl, 0);
8393 gimple_call_set_lhs (call, lhs);
8394 gimple_seq_add_stmt (pre_p, call);
8396 cond = gimple_build_cond (EQ_EXPR, lhs,
8397 fold_convert_loc (loc, TREE_TYPE (lhs),
8398 boolean_true_node),
8399 tlabel, flabel);
8400 gimple_seq_add_stmt (pre_p, cond);
8401 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8402 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8403 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8407 /* A subroutine of lower_omp_single. Expand the simple form of
8408 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8410 #pragma omp single copyprivate (a, b, c)
8412 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8415 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8417 BODY;
8418 copyout.a = a;
8419 copyout.b = b;
8420 copyout.c = c;
8421 GOMP_single_copy_end (&copyout);
8423 else
8425 a = copyout_p->a;
8426 b = copyout_p->b;
8427 c = copyout_p->c;
8429 GOMP_barrier ();
8432 FIXME. It may be better to delay expanding the logic of this until
8433 pass_expand_omp. The expanded logic may make the job more difficult
8434 to a synchronization analysis pass. */
8436 static void
8437 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8439 tree ptr_type, t, l0, l1, l2, bfn_decl;
8440 gimple_seq copyin_seq;
8441 location_t loc = gimple_location (single_stmt);
8443 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8445 ptr_type = build_pointer_type (ctx->record_type);
8446 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8448 l0 = create_artificial_label (loc);
8449 l1 = create_artificial_label (loc);
8450 l2 = create_artificial_label (loc);
8452 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8453 t = build_call_expr_loc (loc, bfn_decl, 0);
8454 t = fold_convert_loc (loc, ptr_type, t);
8455 gimplify_assign (ctx->receiver_decl, t, pre_p);
8457 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8458 build_int_cst (ptr_type, 0));
8459 t = build3 (COND_EXPR, void_type_node, t,
8460 build_and_jump (&l0), build_and_jump (&l1));
8461 gimplify_and_add (t, pre_p);
8463 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8465 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8467 copyin_seq = NULL;
8468 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8469 &copyin_seq, ctx);
8471 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8472 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8473 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8474 gimplify_and_add (t, pre_p);
8476 t = build_and_jump (&l2);
8477 gimplify_and_add (t, pre_p);
8479 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8481 gimple_seq_add_seq (pre_p, copyin_seq);
8483 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8487 /* Expand code for an OpenMP single directive. */
8489 static void
8490 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8492 tree block;
8493 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8494 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8495 struct gimplify_ctx gctx;
8497 push_gimplify_context (&gctx);
8499 block = make_node (BLOCK);
8500 bind = gimple_build_bind (NULL, NULL, block);
8501 gsi_replace (gsi_p, bind, true);
8502 bind_body = NULL;
8503 dlist = NULL;
8504 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8505 &bind_body, &dlist, ctx, NULL);
8506 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8508 gimple_seq_add_stmt (&bind_body, single_stmt);
8510 if (ctx->record_type)
8511 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8512 else
8513 lower_omp_single_simple (single_stmt, &bind_body);
8515 gimple_omp_set_body (single_stmt, NULL);
8517 gimple_seq_add_seq (&bind_body, dlist);
8519 bind_body = maybe_catch_exception (bind_body);
8521 t = gimple_build_omp_return
8522 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8523 OMP_CLAUSE_NOWAIT));
8524 gimple_seq_add_stmt (&bind_body_tail, t);
8525 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8526 if (ctx->record_type)
8528 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8529 tree clobber = build_constructor (ctx->record_type, NULL);
8530 TREE_THIS_VOLATILE (clobber) = 1;
8531 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8532 clobber), GSI_SAME_STMT);
8534 gimple_seq_add_seq (&bind_body, bind_body_tail);
8535 gimple_bind_set_body (bind, bind_body);
8537 pop_gimplify_context (bind);
8539 gimple_bind_append_vars (bind, ctx->block_vars);
8540 BLOCK_VARS (block) = ctx->block_vars;
8541 if (BLOCK_VARS (block))
8542 TREE_USED (block) = 1;
8546 /* Expand code for an OpenMP master directive. */
8548 static void
8549 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8551 tree block, lab = NULL, x, bfn_decl;
8552 gimple stmt = gsi_stmt (*gsi_p), bind;
8553 location_t loc = gimple_location (stmt);
8554 gimple_seq tseq;
8555 struct gimplify_ctx gctx;
8557 push_gimplify_context (&gctx);
8559 block = make_node (BLOCK);
8560 bind = gimple_build_bind (NULL, NULL, block);
8561 gsi_replace (gsi_p, bind, true);
8562 gimple_bind_add_stmt (bind, stmt);
8564 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8565 x = build_call_expr_loc (loc, bfn_decl, 0);
8566 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8567 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8568 tseq = NULL;
8569 gimplify_and_add (x, &tseq);
8570 gimple_bind_add_seq (bind, tseq);
8572 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8573 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8574 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8575 gimple_omp_set_body (stmt, NULL);
8577 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8579 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8581 pop_gimplify_context (bind);
8583 gimple_bind_append_vars (bind, ctx->block_vars);
8584 BLOCK_VARS (block) = ctx->block_vars;
8588 /* Expand code for an OpenMP taskgroup directive. */
8590 static void
8591 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8593 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8594 tree block = make_node (BLOCK);
8596 bind = gimple_build_bind (NULL, NULL, block);
8597 gsi_replace (gsi_p, bind, true);
8598 gimple_bind_add_stmt (bind, stmt);
8600 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8602 gimple_bind_add_stmt (bind, x);
8604 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8605 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8606 gimple_omp_set_body (stmt, NULL);
8608 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8610 gimple_bind_append_vars (bind, ctx->block_vars);
8611 BLOCK_VARS (block) = ctx->block_vars;
8615 /* Expand code for an OpenMP ordered directive. */
8617 static void
8618 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8620 tree block;
8621 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8622 struct gimplify_ctx gctx;
8624 push_gimplify_context (&gctx);
8626 block = make_node (BLOCK);
8627 bind = gimple_build_bind (NULL, NULL, block);
8628 gsi_replace (gsi_p, bind, true);
8629 gimple_bind_add_stmt (bind, stmt);
8631 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8633 gimple_bind_add_stmt (bind, x);
8635 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8636 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8637 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8638 gimple_omp_set_body (stmt, NULL);
8640 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8641 gimple_bind_add_stmt (bind, x);
8643 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8645 pop_gimplify_context (bind);
8647 gimple_bind_append_vars (bind, ctx->block_vars);
8648 BLOCK_VARS (block) = gimple_bind_vars (bind);
8652 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8653 substitution of a couple of function calls. But in the NAMED case,
8654 requires that languages coordinate a symbol name. It is therefore
8655 best put here in common code. */
8657 static GTY((param1_is (tree), param2_is (tree)))
8658 splay_tree critical_name_mutexes;
8660 static void
8661 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8663 tree block;
8664 tree name, lock, unlock;
8665 gimple stmt = gsi_stmt (*gsi_p), bind;
8666 location_t loc = gimple_location (stmt);
8667 gimple_seq tbody;
8668 struct gimplify_ctx gctx;
8670 name = gimple_omp_critical_name (stmt);
8671 if (name)
8673 tree decl;
8674 splay_tree_node n;
8676 if (!critical_name_mutexes)
8677 critical_name_mutexes
8678 = splay_tree_new_ggc (splay_tree_compare_pointers,
8679 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8680 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8682 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8683 if (n == NULL)
8685 char *new_str;
8687 decl = create_tmp_var_raw (ptr_type_node, NULL);
8689 new_str = ACONCAT ((".gomp_critical_user_",
8690 IDENTIFIER_POINTER (name), NULL));
8691 DECL_NAME (decl) = get_identifier (new_str);
8692 TREE_PUBLIC (decl) = 1;
8693 TREE_STATIC (decl) = 1;
8694 DECL_COMMON (decl) = 1;
8695 DECL_ARTIFICIAL (decl) = 1;
8696 DECL_IGNORED_P (decl) = 1;
8697 varpool_finalize_decl (decl);
8699 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8700 (splay_tree_value) decl);
8702 else
8703 decl = (tree) n->value;
8705 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8706 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8708 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8709 unlock = build_call_expr_loc (loc, unlock, 1,
8710 build_fold_addr_expr_loc (loc, decl));
8712 else
8714 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8715 lock = build_call_expr_loc (loc, lock, 0);
8717 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8718 unlock = build_call_expr_loc (loc, unlock, 0);
8721 push_gimplify_context (&gctx);
8723 block = make_node (BLOCK);
8724 bind = gimple_build_bind (NULL, NULL, block);
8725 gsi_replace (gsi_p, bind, true);
8726 gimple_bind_add_stmt (bind, stmt);
8728 tbody = gimple_bind_body (bind);
8729 gimplify_and_add (lock, &tbody);
8730 gimple_bind_set_body (bind, tbody);
8732 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8733 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8734 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8735 gimple_omp_set_body (stmt, NULL);
8737 tbody = gimple_bind_body (bind);
8738 gimplify_and_add (unlock, &tbody);
8739 gimple_bind_set_body (bind, tbody);
8741 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8743 pop_gimplify_context (bind);
8744 gimple_bind_append_vars (bind, ctx->block_vars);
8745 BLOCK_VARS (block) = gimple_bind_vars (bind);
8749 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8750 for a lastprivate clause. Given a loop control predicate of (V
8751 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8752 is appended to *DLIST, iterator initialization is appended to
8753 *BODY_P. */
8755 static void
8756 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8757 gimple_seq *dlist, struct omp_context *ctx)
8759 tree clauses, cond, vinit;
8760 enum tree_code cond_code;
8761 gimple_seq stmts;
8763 cond_code = fd->loop.cond_code;
8764 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8766 /* When possible, use a strict equality expression. This can let VRP
8767 type optimizations deduce the value and remove a copy. */
8768 if (host_integerp (fd->loop.step, 0))
8770 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
8771 if (step == 1 || step == -1)
8772 cond_code = EQ_EXPR;
8775 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8777 clauses = gimple_omp_for_clauses (fd->for_stmt);
8778 stmts = NULL;
8779 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8780 if (!gimple_seq_empty_p (stmts))
8782 gimple_seq_add_seq (&stmts, *dlist);
8783 *dlist = stmts;
8785 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8786 vinit = fd->loop.n1;
8787 if (cond_code == EQ_EXPR
8788 && host_integerp (fd->loop.n2, 0)
8789 && ! integer_zerop (fd->loop.n2))
8790 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8791 else
8792 vinit = unshare_expr (vinit);
8794 /* Initialize the iterator variable, so that threads that don't execute
8795 any iterations don't execute the lastprivate clauses by accident. */
8796 gimplify_assign (fd->loop.v, vinit, body_p);
8801 /* Lower code for an OpenMP loop directive. */
8803 static void
8804 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8806 tree *rhs_p, block;
8807 struct omp_for_data fd, *fdp = NULL;
8808 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8809 gimple_seq omp_for_body, body, dlist;
8810 size_t i;
8811 struct gimplify_ctx gctx;
8813 push_gimplify_context (&gctx);
8815 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8817 block = make_node (BLOCK);
8818 new_stmt = gimple_build_bind (NULL, NULL, block);
8819 /* Replace at gsi right away, so that 'stmt' is no member
8820 of a sequence anymore as we're going to add to to a different
8821 one below. */
8822 gsi_replace (gsi_p, new_stmt, true);
8824 /* Move declaration of temporaries in the loop body before we make
8825 it go away. */
8826 omp_for_body = gimple_omp_body (stmt);
8827 if (!gimple_seq_empty_p (omp_for_body)
8828 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8830 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
8831 gimple_bind_append_vars (new_stmt, vars);
8834 if (gimple_omp_for_combined_into_p (stmt))
8836 extract_omp_for_data (stmt, &fd, NULL);
8837 fdp = &fd;
8839 /* We need two temporaries with fd.loop.v type (istart/iend)
8840 and then (fd.collapse - 1) temporaries with the same
8841 type for count2 ... countN-1 vars if not constant. */
8842 size_t count = 2;
8843 tree type = fd.iter_type;
8844 if (fd.collapse > 1
8845 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8846 count += fd.collapse - 1;
8847 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8848 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8849 tree clauses = *pc;
8850 if (parallel_for)
8851 outerc
8852 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8853 OMP_CLAUSE__LOOPTEMP_);
8854 for (i = 0; i < count; i++)
8856 tree temp;
8857 if (parallel_for)
8859 gcc_assert (outerc);
8860 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8861 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8862 OMP_CLAUSE__LOOPTEMP_);
8864 else
8865 temp = create_tmp_var (type, NULL);
8866 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8867 OMP_CLAUSE_DECL (*pc) = temp;
8868 pc = &OMP_CLAUSE_CHAIN (*pc);
8870 *pc = clauses;
8873 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8874 dlist = NULL;
8875 body = NULL;
8876 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
8877 fdp);
8878 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
8880 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8882 /* Lower the header expressions. At this point, we can assume that
8883 the header is of the form:
8885 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
8887 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
8888 using the .omp_data_s mapping, if needed. */
8889 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
8891 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
8892 if (!is_gimple_min_invariant (*rhs_p))
8893 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8895 rhs_p = gimple_omp_for_final_ptr (stmt, i);
8896 if (!is_gimple_min_invariant (*rhs_p))
8897 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8899 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
8900 if (!is_gimple_min_invariant (*rhs_p))
8901 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8904 /* Once lowered, extract the bounds and clauses. */
8905 extract_omp_for_data (stmt, &fd, NULL);
8907 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
8909 gimple_seq_add_stmt (&body, stmt);
8910 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
8912 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
8913 fd.loop.v));
8915 /* After the loop, add exit clauses. */
8916 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
8918 if (ctx->cancellable)
8919 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
8921 gimple_seq_add_seq (&body, dlist);
8923 body = maybe_catch_exception (body);
8925 /* Region exit marker goes at the end of the loop body. */
8926 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
8927 maybe_add_implicit_barrier_cancel (ctx, &body);
8928 pop_gimplify_context (new_stmt);
8930 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8931 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
8932 if (BLOCK_VARS (block))
8933 TREE_USED (block) = 1;
8935 gimple_bind_set_body (new_stmt, body);
8936 gimple_omp_set_body (stmt, NULL);
8937 gimple_omp_for_set_pre_body (stmt, NULL);
8940 /* Callback for walk_stmts. Check if the current statement only contains
8941 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
8943 static tree
8944 check_combined_parallel (gimple_stmt_iterator *gsi_p,
8945 bool *handled_ops_p,
8946 struct walk_stmt_info *wi)
8948 int *info = (int *) wi->info;
8949 gimple stmt = gsi_stmt (*gsi_p);
8951 *handled_ops_p = true;
8952 switch (gimple_code (stmt))
8954 WALK_SUBSTMTS;
8956 case GIMPLE_OMP_FOR:
8957 case GIMPLE_OMP_SECTIONS:
8958 *info = *info == 0 ? 1 : -1;
8959 break;
8960 default:
8961 *info = -1;
8962 break;
8964 return NULL;
8967 struct omp_taskcopy_context
8969 /* This field must be at the beginning, as we do "inheritance": Some
8970 callback functions for tree-inline.c (e.g., omp_copy_decl)
8971 receive a copy_body_data pointer that is up-casted to an
8972 omp_context pointer. */
8973 copy_body_data cb;
8974 omp_context *ctx;
8977 static tree
8978 task_copyfn_copy_decl (tree var, copy_body_data *cb)
8980 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
8982 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
8983 return create_tmp_var (TREE_TYPE (var), NULL);
8985 return var;
8988 static tree
8989 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
8991 tree name, new_fields = NULL, type, f;
8993 type = lang_hooks.types.make_type (RECORD_TYPE);
8994 name = DECL_NAME (TYPE_NAME (orig_type));
8995 name = build_decl (gimple_location (tcctx->ctx->stmt),
8996 TYPE_DECL, name, type);
8997 TYPE_NAME (type) = name;
8999 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9001 tree new_f = copy_node (f);
9002 DECL_CONTEXT (new_f) = type;
9003 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9004 TREE_CHAIN (new_f) = new_fields;
9005 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9006 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9007 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9008 &tcctx->cb, NULL);
9009 new_fields = new_f;
9010 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9012 TYPE_FIELDS (type) = nreverse (new_fields);
9013 layout_type (type);
9014 return type;
9017 /* Create task copyfn. */
9019 static void
9020 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9022 struct function *child_cfun;
9023 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9024 tree record_type, srecord_type, bind, list;
9025 bool record_needs_remap = false, srecord_needs_remap = false;
9026 splay_tree_node n;
9027 struct omp_taskcopy_context tcctx;
9028 struct gimplify_ctx gctx;
9029 location_t loc = gimple_location (task_stmt);
9031 child_fn = gimple_omp_task_copy_fn (task_stmt);
9032 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9033 gcc_assert (child_cfun->cfg == NULL);
9034 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9036 /* Reset DECL_CONTEXT on function arguments. */
9037 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9038 DECL_CONTEXT (t) = child_fn;
9040 /* Populate the function. */
9041 push_gimplify_context (&gctx);
9042 push_cfun (child_cfun);
9044 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9045 TREE_SIDE_EFFECTS (bind) = 1;
9046 list = NULL;
9047 DECL_SAVED_TREE (child_fn) = bind;
9048 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9050 /* Remap src and dst argument types if needed. */
9051 record_type = ctx->record_type;
9052 srecord_type = ctx->srecord_type;
9053 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9054 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9056 record_needs_remap = true;
9057 break;
9059 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9060 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9062 srecord_needs_remap = true;
9063 break;
9066 if (record_needs_remap || srecord_needs_remap)
9068 memset (&tcctx, '\0', sizeof (tcctx));
9069 tcctx.cb.src_fn = ctx->cb.src_fn;
9070 tcctx.cb.dst_fn = child_fn;
9071 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9072 gcc_checking_assert (tcctx.cb.src_node);
9073 tcctx.cb.dst_node = tcctx.cb.src_node;
9074 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9075 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9076 tcctx.cb.eh_lp_nr = 0;
9077 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9078 tcctx.cb.decl_map = pointer_map_create ();
9079 tcctx.ctx = ctx;
9081 if (record_needs_remap)
9082 record_type = task_copyfn_remap_type (&tcctx, record_type);
9083 if (srecord_needs_remap)
9084 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9086 else
9087 tcctx.cb.decl_map = NULL;
9089 arg = DECL_ARGUMENTS (child_fn);
9090 TREE_TYPE (arg) = build_pointer_type (record_type);
9091 sarg = DECL_CHAIN (arg);
9092 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9094 /* First pass: initialize temporaries used in record_type and srecord_type
9095 sizes and field offsets. */
9096 if (tcctx.cb.decl_map)
9097 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9098 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9100 tree *p;
9102 decl = OMP_CLAUSE_DECL (c);
9103 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9104 if (p == NULL)
9105 continue;
9106 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9107 sf = (tree) n->value;
9108 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9109 src = build_simple_mem_ref_loc (loc, sarg);
9110 src = omp_build_component_ref (src, sf);
9111 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9112 append_to_statement_list (t, &list);
9115 /* Second pass: copy shared var pointers and copy construct non-VLA
9116 firstprivate vars. */
9117 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9118 switch (OMP_CLAUSE_CODE (c))
9120 case OMP_CLAUSE_SHARED:
9121 decl = OMP_CLAUSE_DECL (c);
9122 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9123 if (n == NULL)
9124 break;
9125 f = (tree) n->value;
9126 if (tcctx.cb.decl_map)
9127 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9128 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9129 sf = (tree) n->value;
9130 if (tcctx.cb.decl_map)
9131 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9132 src = build_simple_mem_ref_loc (loc, sarg);
9133 src = omp_build_component_ref (src, sf);
9134 dst = build_simple_mem_ref_loc (loc, arg);
9135 dst = omp_build_component_ref (dst, f);
9136 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9137 append_to_statement_list (t, &list);
9138 break;
9139 case OMP_CLAUSE_FIRSTPRIVATE:
9140 decl = OMP_CLAUSE_DECL (c);
9141 if (is_variable_sized (decl))
9142 break;
9143 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9144 if (n == NULL)
9145 break;
9146 f = (tree) n->value;
9147 if (tcctx.cb.decl_map)
9148 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9149 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9150 if (n != NULL)
9152 sf = (tree) n->value;
9153 if (tcctx.cb.decl_map)
9154 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9155 src = build_simple_mem_ref_loc (loc, sarg);
9156 src = omp_build_component_ref (src, sf);
9157 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9158 src = build_simple_mem_ref_loc (loc, src);
9160 else
9161 src = decl;
9162 dst = build_simple_mem_ref_loc (loc, arg);
9163 dst = omp_build_component_ref (dst, f);
9164 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9165 append_to_statement_list (t, &list);
9166 break;
9167 case OMP_CLAUSE_PRIVATE:
9168 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9169 break;
9170 decl = OMP_CLAUSE_DECL (c);
9171 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9172 f = (tree) n->value;
9173 if (tcctx.cb.decl_map)
9174 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9175 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9176 if (n != NULL)
9178 sf = (tree) n->value;
9179 if (tcctx.cb.decl_map)
9180 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9181 src = build_simple_mem_ref_loc (loc, sarg);
9182 src = omp_build_component_ref (src, sf);
9183 if (use_pointer_for_field (decl, NULL))
9184 src = build_simple_mem_ref_loc (loc, src);
9186 else
9187 src = decl;
9188 dst = build_simple_mem_ref_loc (loc, arg);
9189 dst = omp_build_component_ref (dst, f);
9190 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9191 append_to_statement_list (t, &list);
9192 break;
9193 default:
9194 break;
9197 /* Last pass: handle VLA firstprivates. */
9198 if (tcctx.cb.decl_map)
9199 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9200 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9202 tree ind, ptr, df;
9204 decl = OMP_CLAUSE_DECL (c);
9205 if (!is_variable_sized (decl))
9206 continue;
9207 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9208 if (n == NULL)
9209 continue;
9210 f = (tree) n->value;
9211 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9212 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9213 ind = DECL_VALUE_EXPR (decl);
9214 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9215 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9216 n = splay_tree_lookup (ctx->sfield_map,
9217 (splay_tree_key) TREE_OPERAND (ind, 0));
9218 sf = (tree) n->value;
9219 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9220 src = build_simple_mem_ref_loc (loc, sarg);
9221 src = omp_build_component_ref (src, sf);
9222 src = build_simple_mem_ref_loc (loc, src);
9223 dst = build_simple_mem_ref_loc (loc, arg);
9224 dst = omp_build_component_ref (dst, f);
9225 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9226 append_to_statement_list (t, &list);
9227 n = splay_tree_lookup (ctx->field_map,
9228 (splay_tree_key) TREE_OPERAND (ind, 0));
9229 df = (tree) n->value;
9230 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9231 ptr = build_simple_mem_ref_loc (loc, arg);
9232 ptr = omp_build_component_ref (ptr, df);
9233 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9234 build_fold_addr_expr_loc (loc, dst));
9235 append_to_statement_list (t, &list);
9238 t = build1 (RETURN_EXPR, void_type_node, NULL);
9239 append_to_statement_list (t, &list);
9241 if (tcctx.cb.decl_map)
9242 pointer_map_destroy (tcctx.cb.decl_map);
9243 pop_gimplify_context (NULL);
9244 BIND_EXPR_BODY (bind) = list;
9245 pop_cfun ();
9248 static void
9249 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9251 tree c, clauses;
9252 gimple g;
9253 size_t n_in = 0, n_out = 0, idx = 2, i;
9255 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9256 OMP_CLAUSE_DEPEND);
9257 gcc_assert (clauses);
9258 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9259 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9260 switch (OMP_CLAUSE_DEPEND_KIND (c))
9262 case OMP_CLAUSE_DEPEND_IN:
9263 n_in++;
9264 break;
9265 case OMP_CLAUSE_DEPEND_OUT:
9266 case OMP_CLAUSE_DEPEND_INOUT:
9267 n_out++;
9268 break;
9269 default:
9270 gcc_unreachable ();
9272 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9273 tree array = create_tmp_var (type, NULL);
9274 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9275 NULL_TREE);
9276 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9277 gimple_seq_add_stmt (iseq, g);
9278 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9279 NULL_TREE);
9280 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9281 gimple_seq_add_stmt (iseq, g);
9282 for (i = 0; i < 2; i++)
9284 if ((i ? n_in : n_out) == 0)
9285 continue;
9286 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9287 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9288 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9290 tree t = OMP_CLAUSE_DECL (c);
9291 t = fold_convert (ptr_type_node, t);
9292 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9293 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9294 NULL_TREE, NULL_TREE);
9295 g = gimple_build_assign (r, t);
9296 gimple_seq_add_stmt (iseq, g);
9299 tree *p = gimple_omp_task_clauses_ptr (stmt);
9300 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9301 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9302 OMP_CLAUSE_CHAIN (c) = *p;
9303 *p = c;
9304 tree clobber = build_constructor (type, NULL);
9305 TREE_THIS_VOLATILE (clobber) = 1;
9306 g = gimple_build_assign (array, clobber);
9307 gimple_seq_add_stmt (oseq, g);
9310 /* Lower the OpenMP parallel or task directive in the current statement
9311 in GSI_P. CTX holds context information for the directive. */
9313 static void
9314 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9316 tree clauses;
9317 tree child_fn, t;
9318 gimple stmt = gsi_stmt (*gsi_p);
9319 gimple par_bind, bind, dep_bind = NULL;
9320 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9321 struct gimplify_ctx gctx, dep_gctx;
9322 location_t loc = gimple_location (stmt);
9324 clauses = gimple_omp_taskreg_clauses (stmt);
9325 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9326 par_body = gimple_bind_body (par_bind);
9327 child_fn = ctx->cb.dst_fn;
9328 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9329 && !gimple_omp_parallel_combined_p (stmt))
9331 struct walk_stmt_info wi;
9332 int ws_num = 0;
9334 memset (&wi, 0, sizeof (wi));
9335 wi.info = &ws_num;
9336 wi.val_only = true;
9337 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9338 if (ws_num == 1)
9339 gimple_omp_parallel_set_combined_p (stmt, true);
9341 gimple_seq dep_ilist = NULL;
9342 gimple_seq dep_olist = NULL;
9343 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9344 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9346 push_gimplify_context (&dep_gctx);
9347 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9348 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9351 if (ctx->srecord_type)
9352 create_task_copyfn (stmt, ctx);
9354 push_gimplify_context (&gctx);
9356 par_olist = NULL;
9357 par_ilist = NULL;
9358 par_rlist = NULL;
9359 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9360 lower_omp (&par_body, ctx);
9361 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9362 lower_reduction_clauses (clauses, &par_rlist, ctx);
9364 /* Declare all the variables created by mapping and the variables
9365 declared in the scope of the parallel body. */
9366 record_vars_into (ctx->block_vars, child_fn);
9367 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9369 if (ctx->record_type)
9371 ctx->sender_decl
9372 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9373 : ctx->record_type, ".omp_data_o");
9374 DECL_NAMELESS (ctx->sender_decl) = 1;
9375 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9376 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9379 olist = NULL;
9380 ilist = NULL;
9381 lower_send_clauses (clauses, &ilist, &olist, ctx);
9382 lower_send_shared_vars (&ilist, &olist, ctx);
9384 if (ctx->record_type)
9386 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9387 TREE_THIS_VOLATILE (clobber) = 1;
9388 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9389 clobber));
9392 /* Once all the expansions are done, sequence all the different
9393 fragments inside gimple_omp_body. */
9395 new_body = NULL;
9397 if (ctx->record_type)
9399 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9400 /* fixup_child_record_type might have changed receiver_decl's type. */
9401 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9402 gimple_seq_add_stmt (&new_body,
9403 gimple_build_assign (ctx->receiver_decl, t));
9406 gimple_seq_add_seq (&new_body, par_ilist);
9407 gimple_seq_add_seq (&new_body, par_body);
9408 gimple_seq_add_seq (&new_body, par_rlist);
9409 if (ctx->cancellable)
9410 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9411 gimple_seq_add_seq (&new_body, par_olist);
9412 new_body = maybe_catch_exception (new_body);
9413 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9414 gimple_omp_set_body (stmt, new_body);
9416 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9417 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9418 gimple_bind_add_seq (bind, ilist);
9419 gimple_bind_add_stmt (bind, stmt);
9420 gimple_bind_add_seq (bind, olist);
9422 pop_gimplify_context (NULL);
9424 if (dep_bind)
9426 gimple_bind_add_seq (dep_bind, dep_ilist);
9427 gimple_bind_add_stmt (dep_bind, bind);
9428 gimple_bind_add_seq (dep_bind, dep_olist);
9429 pop_gimplify_context (dep_bind);
9433 /* Lower the OpenMP target directive in the current statement
9434 in GSI_P. CTX holds context information for the directive. */
9436 static void
9437 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9439 tree clauses;
9440 tree child_fn, t, c;
9441 gimple stmt = gsi_stmt (*gsi_p);
9442 gimple tgt_bind = NULL, bind;
9443 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9444 struct gimplify_ctx gctx;
9445 location_t loc = gimple_location (stmt);
9446 int kind = gimple_omp_target_kind (stmt);
9447 unsigned int map_cnt = 0;
9449 clauses = gimple_omp_target_clauses (stmt);
9450 if (kind == GF_OMP_TARGET_KIND_REGION)
9452 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9453 tgt_body = gimple_bind_body (tgt_bind);
9455 else if (kind == GF_OMP_TARGET_KIND_DATA)
9456 tgt_body = gimple_omp_body (stmt);
9457 child_fn = ctx->cb.dst_fn;
9459 push_gimplify_context (&gctx);
9461 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9462 switch (OMP_CLAUSE_CODE (c))
9464 tree var, x;
9466 default:
9467 break;
9468 case OMP_CLAUSE_MAP:
9469 case OMP_CLAUSE_TO:
9470 case OMP_CLAUSE_FROM:
9471 var = OMP_CLAUSE_DECL (c);
9472 if (!DECL_P (var))
9474 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9475 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9476 map_cnt++;
9477 continue;
9480 if (DECL_SIZE (var)
9481 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9483 tree var2 = DECL_VALUE_EXPR (var);
9484 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9485 var2 = TREE_OPERAND (var2, 0);
9486 gcc_assert (DECL_P (var2));
9487 var = var2;
9490 if (!maybe_lookup_field (var, ctx))
9491 continue;
9493 if (kind == GF_OMP_TARGET_KIND_REGION)
9495 x = build_receiver_ref (var, true, ctx);
9496 tree new_var = lookup_decl (var, ctx);
9497 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9498 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9499 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9500 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9501 x = build_simple_mem_ref (x);
9502 SET_DECL_VALUE_EXPR (new_var, x);
9503 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9505 map_cnt++;
9508 if (kind == GF_OMP_TARGET_KIND_REGION)
9510 target_nesting_level++;
9511 lower_omp (&tgt_body, ctx);
9512 target_nesting_level--;
9514 else if (kind == GF_OMP_TARGET_KIND_DATA)
9515 lower_omp (&tgt_body, ctx);
9517 if (kind == GF_OMP_TARGET_KIND_REGION)
9519 /* Declare all the variables created by mapping and the variables
9520 declared in the scope of the target body. */
9521 record_vars_into (ctx->block_vars, child_fn);
9522 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9525 olist = NULL;
9526 ilist = NULL;
9527 if (ctx->record_type)
9529 ctx->sender_decl
9530 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9531 DECL_NAMELESS (ctx->sender_decl) = 1;
9532 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9533 t = make_tree_vec (3);
9534 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9535 TREE_VEC_ELT (t, 1)
9536 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9537 ".omp_data_sizes");
9538 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9539 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9540 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9541 TREE_VEC_ELT (t, 2)
9542 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9543 map_cnt),
9544 ".omp_data_kinds");
9545 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9546 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9547 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9548 gimple_omp_target_set_data_arg (stmt, t);
9550 vec<constructor_elt, va_gc> *vsize;
9551 vec<constructor_elt, va_gc> *vkind;
9552 vec_alloc (vsize, map_cnt);
9553 vec_alloc (vkind, map_cnt);
9554 unsigned int map_idx = 0;
9556 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9557 switch (OMP_CLAUSE_CODE (c))
9559 tree ovar, nc;
9561 default:
9562 break;
9563 case OMP_CLAUSE_MAP:
9564 case OMP_CLAUSE_TO:
9565 case OMP_CLAUSE_FROM:
9566 nc = c;
9567 ovar = OMP_CLAUSE_DECL (c);
9568 if (!DECL_P (ovar))
9570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9571 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9573 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9574 == get_base_address (ovar));
9575 nc = OMP_CLAUSE_CHAIN (c);
9576 ovar = OMP_CLAUSE_DECL (nc);
9578 else
9580 tree x = build_sender_ref (ovar, ctx);
9581 tree v
9582 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9583 gimplify_assign (x, v, &ilist);
9584 nc = NULL_TREE;
9587 else
9589 if (DECL_SIZE (ovar)
9590 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9592 tree ovar2 = DECL_VALUE_EXPR (ovar);
9593 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9594 ovar2 = TREE_OPERAND (ovar2, 0);
9595 gcc_assert (DECL_P (ovar2));
9596 ovar = ovar2;
9598 if (!maybe_lookup_field (ovar, ctx))
9599 continue;
9602 if (nc)
9604 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9605 tree x = build_sender_ref (ovar, ctx);
9606 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9607 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9608 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9609 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9611 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9612 tree avar
9613 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9614 mark_addressable (avar);
9615 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9616 avar = build_fold_addr_expr (avar);
9617 gimplify_assign (x, avar, &ilist);
9619 else if (is_gimple_reg (var))
9621 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9622 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9623 mark_addressable (avar);
9624 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9625 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9626 gimplify_assign (avar, var, &ilist);
9627 avar = build_fold_addr_expr (avar);
9628 gimplify_assign (x, avar, &ilist);
9629 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9630 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9631 && !TYPE_READONLY (TREE_TYPE (var)))
9633 x = build_sender_ref (ovar, ctx);
9634 x = build_simple_mem_ref (x);
9635 gimplify_assign (var, x, &olist);
9638 else
9640 var = build_fold_addr_expr (var);
9641 gimplify_assign (x, var, &ilist);
9644 tree s = OMP_CLAUSE_SIZE (c);
9645 if (s == NULL_TREE)
9646 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9647 s = fold_convert (size_type_node, s);
9648 tree purpose = size_int (map_idx++);
9649 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9650 if (TREE_CODE (s) != INTEGER_CST)
9651 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9653 unsigned char tkind = 0;
9654 switch (OMP_CLAUSE_CODE (c))
9656 case OMP_CLAUSE_MAP:
9657 tkind = OMP_CLAUSE_MAP_KIND (c);
9658 break;
9659 case OMP_CLAUSE_TO:
9660 tkind = OMP_CLAUSE_MAP_TO;
9661 break;
9662 case OMP_CLAUSE_FROM:
9663 tkind = OMP_CLAUSE_MAP_FROM;
9664 break;
9665 default:
9666 gcc_unreachable ();
9668 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9669 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9670 talign = DECL_ALIGN_UNIT (ovar);
9671 talign = ceil_log2 (talign);
9672 tkind |= talign << 3;
9673 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9674 build_int_cst (unsigned_char_type_node,
9675 tkind));
9676 if (nc && nc != c)
9677 c = nc;
9680 gcc_assert (map_idx == map_cnt);
9682 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9683 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9684 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9685 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9686 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9688 gimple_seq initlist = NULL;
9689 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9690 TREE_VEC_ELT (t, 1)),
9691 &initlist, true, NULL_TREE);
9692 gimple_seq_add_seq (&ilist, initlist);
9695 tree clobber = build_constructor (ctx->record_type, NULL);
9696 TREE_THIS_VOLATILE (clobber) = 1;
9697 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9698 clobber));
9701 /* Once all the expansions are done, sequence all the different
9702 fragments inside gimple_omp_body. */
9704 new_body = NULL;
9706 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9708 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9709 /* fixup_child_record_type might have changed receiver_decl's type. */
9710 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9711 gimple_seq_add_stmt (&new_body,
9712 gimple_build_assign (ctx->receiver_decl, t));
9715 if (kind == GF_OMP_TARGET_KIND_REGION)
9717 gimple_seq_add_seq (&new_body, tgt_body);
9718 new_body = maybe_catch_exception (new_body);
9720 else if (kind == GF_OMP_TARGET_KIND_DATA)
9721 new_body = tgt_body;
9722 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9724 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9725 gimple_omp_set_body (stmt, new_body);
9728 bind = gimple_build_bind (NULL, NULL,
9729 tgt_bind ? gimple_bind_block (tgt_bind)
9730 : NULL_TREE);
9731 gsi_replace (gsi_p, bind, true);
9732 gimple_bind_add_seq (bind, ilist);
9733 gimple_bind_add_stmt (bind, stmt);
9734 gimple_bind_add_seq (bind, olist);
9736 pop_gimplify_context (NULL);
9739 /* Expand code for an OpenMP teams directive. */
9741 static void
9742 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9744 gimple teams_stmt = gsi_stmt (*gsi_p);
9745 struct gimplify_ctx gctx;
9746 push_gimplify_context (&gctx);
9748 tree block = make_node (BLOCK);
9749 gimple bind = gimple_build_bind (NULL, NULL, block);
9750 gsi_replace (gsi_p, bind, true);
9751 gimple_seq bind_body = NULL;
9752 gimple_seq dlist = NULL;
9753 gimple_seq olist = NULL;
9755 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9756 OMP_CLAUSE_NUM_TEAMS);
9757 if (num_teams == NULL_TREE)
9758 num_teams = build_int_cst (unsigned_type_node, 0);
9759 else
9761 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9762 num_teams = fold_convert (unsigned_type_node, num_teams);
9763 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9765 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9766 OMP_CLAUSE_THREAD_LIMIT);
9767 if (thread_limit == NULL_TREE)
9768 thread_limit = build_int_cst (unsigned_type_node, 0);
9769 else
9771 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9772 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9773 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9774 fb_rvalue);
9777 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9778 &bind_body, &dlist, ctx, NULL);
9779 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9780 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9781 gimple_seq_add_stmt (&bind_body, teams_stmt);
9783 location_t loc = gimple_location (teams_stmt);
9784 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9785 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9786 gimple_set_location (call, loc);
9787 gimple_seq_add_stmt (&bind_body, call);
9789 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9790 gimple_omp_set_body (teams_stmt, NULL);
9791 gimple_seq_add_seq (&bind_body, olist);
9792 gimple_seq_add_seq (&bind_body, dlist);
9793 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9794 gimple_bind_set_body (bind, bind_body);
9796 pop_gimplify_context (bind);
9798 gimple_bind_append_vars (bind, ctx->block_vars);
9799 BLOCK_VARS (block) = ctx->block_vars;
9800 if (BLOCK_VARS (block))
9801 TREE_USED (block) = 1;
9805 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9806 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9807 of OpenMP context, but with task_shared_vars set. */
9809 static tree
9810 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9811 void *data)
9813 tree t = *tp;
9815 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9816 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9817 return t;
9819 if (task_shared_vars
9820 && DECL_P (t)
9821 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9822 return t;
9824 /* If a global variable has been privatized, TREE_CONSTANT on
9825 ADDR_EXPR might be wrong. */
9826 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9827 recompute_tree_invariant_for_addr_expr (t);
9829 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9830 return NULL_TREE;
9833 static void
9834 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9836 gimple stmt = gsi_stmt (*gsi_p);
9837 struct walk_stmt_info wi;
9839 if (gimple_has_location (stmt))
9840 input_location = gimple_location (stmt);
9842 if (task_shared_vars)
9843 memset (&wi, '\0', sizeof (wi));
9845 /* If we have issued syntax errors, avoid doing any heavy lifting.
9846 Just replace the OpenMP directives with a NOP to avoid
9847 confusing RTL expansion. */
9848 if (seen_error () && is_gimple_omp (stmt))
9850 gsi_replace (gsi_p, gimple_build_nop (), true);
9851 return;
9854 switch (gimple_code (stmt))
9856 case GIMPLE_COND:
9857 if ((ctx || task_shared_vars)
9858 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9859 ctx ? NULL : &wi, NULL)
9860 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9861 ctx ? NULL : &wi, NULL)))
9862 gimple_regimplify_operands (stmt, gsi_p);
9863 break;
9864 case GIMPLE_CATCH:
9865 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9866 break;
9867 case GIMPLE_EH_FILTER:
9868 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9869 break;
9870 case GIMPLE_TRY:
9871 lower_omp (gimple_try_eval_ptr (stmt), ctx);
9872 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
9873 break;
9874 case GIMPLE_TRANSACTION:
9875 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
9876 break;
9877 case GIMPLE_BIND:
9878 lower_omp (gimple_bind_body_ptr (stmt), ctx);
9879 break;
9880 case GIMPLE_OMP_PARALLEL:
9881 case GIMPLE_OMP_TASK:
9882 ctx = maybe_lookup_ctx (stmt);
9883 gcc_assert (ctx);
9884 if (ctx->cancellable)
9885 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9886 lower_omp_taskreg (gsi_p, ctx);
9887 break;
9888 case GIMPLE_OMP_FOR:
9889 ctx = maybe_lookup_ctx (stmt);
9890 gcc_assert (ctx);
9891 if (ctx->cancellable)
9892 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9893 lower_omp_for (gsi_p, ctx);
9894 break;
9895 case GIMPLE_OMP_SECTIONS:
9896 ctx = maybe_lookup_ctx (stmt);
9897 gcc_assert (ctx);
9898 if (ctx->cancellable)
9899 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9900 lower_omp_sections (gsi_p, ctx);
9901 break;
9902 case GIMPLE_OMP_SINGLE:
9903 ctx = maybe_lookup_ctx (stmt);
9904 gcc_assert (ctx);
9905 lower_omp_single (gsi_p, ctx);
9906 break;
9907 case GIMPLE_OMP_MASTER:
9908 ctx = maybe_lookup_ctx (stmt);
9909 gcc_assert (ctx);
9910 lower_omp_master (gsi_p, ctx);
9911 break;
9912 case GIMPLE_OMP_TASKGROUP:
9913 ctx = maybe_lookup_ctx (stmt);
9914 gcc_assert (ctx);
9915 lower_omp_taskgroup (gsi_p, ctx);
9916 break;
9917 case GIMPLE_OMP_ORDERED:
9918 ctx = maybe_lookup_ctx (stmt);
9919 gcc_assert (ctx);
9920 lower_omp_ordered (gsi_p, ctx);
9921 break;
9922 case GIMPLE_OMP_CRITICAL:
9923 ctx = maybe_lookup_ctx (stmt);
9924 gcc_assert (ctx);
9925 lower_omp_critical (gsi_p, ctx);
9926 break;
9927 case GIMPLE_OMP_ATOMIC_LOAD:
9928 if ((ctx || task_shared_vars)
9929 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
9930 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
9931 gimple_regimplify_operands (stmt, gsi_p);
9932 break;
9933 case GIMPLE_OMP_TARGET:
9934 ctx = maybe_lookup_ctx (stmt);
9935 gcc_assert (ctx);
9936 lower_omp_target (gsi_p, ctx);
9937 break;
9938 case GIMPLE_OMP_TEAMS:
9939 ctx = maybe_lookup_ctx (stmt);
9940 gcc_assert (ctx);
9941 lower_omp_teams (gsi_p, ctx);
9942 break;
9943 case GIMPLE_CALL:
9944 tree fndecl;
9945 fndecl = gimple_call_fndecl (stmt);
9946 if (fndecl
9947 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
9948 switch (DECL_FUNCTION_CODE (fndecl))
9950 case BUILT_IN_GOMP_BARRIER:
9951 if (ctx == NULL)
9952 break;
9953 /* FALLTHRU */
9954 case BUILT_IN_GOMP_CANCEL:
9955 case BUILT_IN_GOMP_CANCELLATION_POINT:
9956 omp_context *cctx;
9957 cctx = ctx;
9958 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
9959 cctx = cctx->outer;
9960 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
9961 if (!cctx->cancellable)
9963 if (DECL_FUNCTION_CODE (fndecl)
9964 == BUILT_IN_GOMP_CANCELLATION_POINT)
9966 stmt = gimple_build_nop ();
9967 gsi_replace (gsi_p, stmt, false);
9969 break;
9971 tree lhs;
9972 lhs = create_tmp_var (boolean_type_node, NULL);
9973 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
9975 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
9976 gimple_call_set_fndecl (stmt, fndecl);
9977 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
9979 gimple_call_set_lhs (stmt, lhs);
9980 tree fallthru_label;
9981 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9982 gimple g;
9983 g = gimple_build_label (fallthru_label);
9984 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
9985 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
9986 cctx->cancel_label, fallthru_label);
9987 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
9988 break;
9989 default:
9990 break;
9992 /* FALLTHRU */
9993 default:
9994 if ((ctx || task_shared_vars)
9995 && walk_gimple_op (stmt, lower_omp_regimplify_p,
9996 ctx ? NULL : &wi))
9997 gimple_regimplify_operands (stmt, gsi_p);
9998 break;
10002 static void
10003 lower_omp (gimple_seq *body, omp_context *ctx)
10005 location_t saved_location = input_location;
10006 gimple_stmt_iterator gsi;
10007 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10008 lower_omp_1 (&gsi, ctx);
10009 /* Inside target region we haven't called fold_stmt during gimplification,
10010 because it can break code by adding decl references that weren't in the
10011 source. Call fold_stmt now. */
10012 if (target_nesting_level)
10013 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10014 fold_stmt (&gsi);
10015 input_location = saved_location;
10018 /* Main entry point. */
10020 static unsigned int
10021 execute_lower_omp (void)
10023 gimple_seq body;
10025 /* This pass always runs, to provide PROP_gimple_lomp.
10026 But there is nothing to do unless -fopenmp is given. */
10027 if (flag_openmp == 0)
10028 return 0;
10030 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10031 delete_omp_context);
10033 body = gimple_body (current_function_decl);
10034 scan_omp (&body, NULL);
10035 gcc_assert (taskreg_nesting_level == 0);
10037 if (all_contexts->root)
10039 struct gimplify_ctx gctx;
10041 if (task_shared_vars)
10042 push_gimplify_context (&gctx);
10043 lower_omp (&body, NULL);
10044 if (task_shared_vars)
10045 pop_gimplify_context (NULL);
10048 if (all_contexts)
10050 splay_tree_delete (all_contexts);
10051 all_contexts = NULL;
10053 BITMAP_FREE (task_shared_vars);
10054 return 0;
10057 namespace {
10059 const pass_data pass_data_lower_omp =
10061 GIMPLE_PASS, /* type */
10062 "omplower", /* name */
10063 OPTGROUP_NONE, /* optinfo_flags */
10064 false, /* has_gate */
10065 true, /* has_execute */
10066 TV_NONE, /* tv_id */
10067 PROP_gimple_any, /* properties_required */
10068 PROP_gimple_lomp, /* properties_provided */
10069 0, /* properties_destroyed */
10070 0, /* todo_flags_start */
10071 0, /* todo_flags_finish */
10074 class pass_lower_omp : public gimple_opt_pass
10076 public:
10077 pass_lower_omp (gcc::context *ctxt)
10078 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10081 /* opt_pass methods: */
10082 unsigned int execute () { return execute_lower_omp (); }
10084 }; // class pass_lower_omp
10086 } // anon namespace
10088 gimple_opt_pass *
10089 make_pass_lower_omp (gcc::context *ctxt)
10091 return new pass_lower_omp (ctxt);
10094 /* The following is a utility to diagnose OpenMP structured block violations.
10095 It is not part of the "omplower" pass, as that's invoked too late. It
10096 should be invoked by the respective front ends after gimplification. */
10098 static splay_tree all_labels;
10100 /* Check for mismatched contexts and generate an error if needed. Return
10101 true if an error is detected. */
10103 static bool
10104 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10105 gimple branch_ctx, gimple label_ctx)
10107 if (label_ctx == branch_ctx)
10108 return false;
10112 Previously we kept track of the label's entire context in diagnose_sb_[12]
10113 so we could traverse it and issue a correct "exit" or "enter" error
10114 message upon a structured block violation.
10116 We built the context by building a list with tree_cons'ing, but there is
10117 no easy counterpart in gimple tuples. It seems like far too much work
10118 for issuing exit/enter error messages. If someone really misses the
10119 distinct error message... patches welcome.
10122 #if 0
10123 /* Try to avoid confusing the user by producing and error message
10124 with correct "exit" or "enter" verbiage. We prefer "exit"
10125 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10126 if (branch_ctx == NULL)
10127 exit_p = false;
10128 else
10130 while (label_ctx)
10132 if (TREE_VALUE (label_ctx) == branch_ctx)
10134 exit_p = false;
10135 break;
10137 label_ctx = TREE_CHAIN (label_ctx);
10141 if (exit_p)
10142 error ("invalid exit from OpenMP structured block");
10143 else
10144 error ("invalid entry to OpenMP structured block");
10145 #endif
10147 /* If it's obvious we have an invalid entry, be specific about the error. */
10148 if (branch_ctx == NULL)
10149 error ("invalid entry to OpenMP structured block");
10150 else
10151 /* Otherwise, be vague and lazy, but efficient. */
10152 error ("invalid branch to/from an OpenMP structured block");
10154 gsi_replace (gsi_p, gimple_build_nop (), false);
10155 return true;
10158 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10159 where each label is found. */
10161 static tree
10162 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10163 struct walk_stmt_info *wi)
10165 gimple context = (gimple) wi->info;
10166 gimple inner_context;
10167 gimple stmt = gsi_stmt (*gsi_p);
10169 *handled_ops_p = true;
10171 switch (gimple_code (stmt))
10173 WALK_SUBSTMTS;
10175 case GIMPLE_OMP_PARALLEL:
10176 case GIMPLE_OMP_TASK:
10177 case GIMPLE_OMP_SECTIONS:
10178 case GIMPLE_OMP_SINGLE:
10179 case GIMPLE_OMP_SECTION:
10180 case GIMPLE_OMP_MASTER:
10181 case GIMPLE_OMP_ORDERED:
10182 case GIMPLE_OMP_CRITICAL:
10183 case GIMPLE_OMP_TARGET:
10184 case GIMPLE_OMP_TEAMS:
10185 case GIMPLE_OMP_TASKGROUP:
10186 /* The minimal context here is just the current OMP construct. */
10187 inner_context = stmt;
10188 wi->info = inner_context;
10189 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10190 wi->info = context;
10191 break;
10193 case GIMPLE_OMP_FOR:
10194 inner_context = stmt;
10195 wi->info = inner_context;
10196 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10197 walk them. */
10198 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10199 diagnose_sb_1, NULL, wi);
10200 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10201 wi->info = context;
10202 break;
10204 case GIMPLE_LABEL:
10205 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10206 (splay_tree_value) context);
10207 break;
10209 default:
10210 break;
10213 return NULL_TREE;
10216 /* Pass 2: Check each branch and see if its context differs from that of
10217 the destination label's context. */
10219 static tree
10220 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10221 struct walk_stmt_info *wi)
10223 gimple context = (gimple) wi->info;
10224 splay_tree_node n;
10225 gimple stmt = gsi_stmt (*gsi_p);
10227 *handled_ops_p = true;
10229 switch (gimple_code (stmt))
10231 WALK_SUBSTMTS;
10233 case GIMPLE_OMP_PARALLEL:
10234 case GIMPLE_OMP_TASK:
10235 case GIMPLE_OMP_SECTIONS:
10236 case GIMPLE_OMP_SINGLE:
10237 case GIMPLE_OMP_SECTION:
10238 case GIMPLE_OMP_MASTER:
10239 case GIMPLE_OMP_ORDERED:
10240 case GIMPLE_OMP_CRITICAL:
10241 case GIMPLE_OMP_TARGET:
10242 case GIMPLE_OMP_TEAMS:
10243 case GIMPLE_OMP_TASKGROUP:
10244 wi->info = stmt;
10245 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10246 wi->info = context;
10247 break;
10249 case GIMPLE_OMP_FOR:
10250 wi->info = stmt;
10251 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10252 walk them. */
10253 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10254 diagnose_sb_2, NULL, wi);
10255 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10256 wi->info = context;
10257 break;
10259 case GIMPLE_COND:
10261 tree lab = gimple_cond_true_label (stmt);
10262 if (lab)
10264 n = splay_tree_lookup (all_labels,
10265 (splay_tree_key) lab);
10266 diagnose_sb_0 (gsi_p, context,
10267 n ? (gimple) n->value : NULL);
10269 lab = gimple_cond_false_label (stmt);
10270 if (lab)
10272 n = splay_tree_lookup (all_labels,
10273 (splay_tree_key) lab);
10274 diagnose_sb_0 (gsi_p, context,
10275 n ? (gimple) n->value : NULL);
10278 break;
10280 case GIMPLE_GOTO:
10282 tree lab = gimple_goto_dest (stmt);
10283 if (TREE_CODE (lab) != LABEL_DECL)
10284 break;
10286 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10287 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10289 break;
10291 case GIMPLE_SWITCH:
10293 unsigned int i;
10294 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10296 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10297 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10298 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10299 break;
10302 break;
10304 case GIMPLE_RETURN:
10305 diagnose_sb_0 (gsi_p, context, NULL);
10306 break;
10308 default:
10309 break;
10312 return NULL_TREE;
10315 static unsigned int
10316 diagnose_omp_structured_block_errors (void)
10318 struct walk_stmt_info wi;
10319 gimple_seq body = gimple_body (current_function_decl);
10321 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10323 memset (&wi, 0, sizeof (wi));
10324 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10326 memset (&wi, 0, sizeof (wi));
10327 wi.want_locations = true;
10328 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10330 gimple_set_body (current_function_decl, body);
10332 splay_tree_delete (all_labels);
10333 all_labels = NULL;
10335 return 0;
10338 static bool
10339 gate_diagnose_omp_blocks (void)
10341 return flag_openmp != 0;
10344 namespace {
10346 const pass_data pass_data_diagnose_omp_blocks =
10348 GIMPLE_PASS, /* type */
10349 "*diagnose_omp_blocks", /* name */
10350 OPTGROUP_NONE, /* optinfo_flags */
10351 true, /* has_gate */
10352 true, /* has_execute */
10353 TV_NONE, /* tv_id */
10354 PROP_gimple_any, /* properties_required */
10355 0, /* properties_provided */
10356 0, /* properties_destroyed */
10357 0, /* todo_flags_start */
10358 0, /* todo_flags_finish */
10361 class pass_diagnose_omp_blocks : public gimple_opt_pass
10363 public:
10364 pass_diagnose_omp_blocks (gcc::context *ctxt)
10365 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10368 /* opt_pass methods: */
10369 bool gate () { return gate_diagnose_omp_blocks (); }
10370 unsigned int execute () {
10371 return diagnose_omp_structured_block_errors ();
10374 }; // class pass_diagnose_omp_blocks
10376 } // anon namespace
10378 gimple_opt_pass *
10379 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10381 return new pass_diagnose_omp_blocks (ctxt);
10384 #include "gt-omp-low.h"