2013-11-25 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / omp-low.c
blobdf9cd25b4019dcd6436a6baa45f6826b59091ea4
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 "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "tree-nested.h"
73 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
74 phases. The first phase scans the function looking for OMP statements
75 and then for variables that must be replaced to satisfy data sharing
76 clauses. The second phase expands code for the constructs, as well as
77 re-gimplifying things when variables have been replaced with complex
78 expressions.
80 Final code generation is done by pass_expand_omp. The flowgraph is
81 scanned for parallel regions which are then moved to a new
82 function, to be invoked by the thread library. */
84 /* Parallel region information. Every parallel and workshare
85 directive is enclosed between two markers, the OMP_* directive
86 and a corresponding OMP_RETURN statement. */
88 struct omp_region
90 /* The enclosing region. */
91 struct omp_region *outer;
93 /* First child region. */
94 struct omp_region *inner;
96 /* Next peer region. */
97 struct omp_region *next;
99 /* Block containing the omp directive as its last stmt. */
100 basic_block entry;
102 /* Block containing the OMP_RETURN as its last stmt. */
103 basic_block exit;
105 /* Block containing the OMP_CONTINUE as its last stmt. */
106 basic_block cont;
108 /* If this is a combined parallel+workshare region, this is a list
109 of additional arguments needed by the combined parallel+workshare
110 library call. */
111 vec<tree, va_gc> *ws_args;
113 /* The code for the omp directive of this region. */
114 enum gimple_code type;
116 /* Schedule kind, only used for OMP_FOR type regions. */
117 enum omp_clause_schedule_kind sched_kind;
119 /* True if this is a combined parallel+workshare region. */
120 bool is_combined_parallel;
123 /* Context structure. Used to store information about each parallel
124 directive in the code. */
126 typedef struct omp_context
128 /* This field must be at the beginning, as we do "inheritance": Some
129 callback functions for tree-inline.c (e.g., omp_copy_decl)
130 receive a copy_body_data pointer that is up-casted to an
131 omp_context pointer. */
132 copy_body_data cb;
134 /* The tree of contexts corresponding to the encountered constructs. */
135 struct omp_context *outer;
136 gimple stmt;
138 /* Map variables to fields in a structure that allows communication
139 between sending and receiving threads. */
140 splay_tree field_map;
141 tree record_type;
142 tree sender_decl;
143 tree receiver_decl;
145 /* These are used just by task contexts, if task firstprivate fn is
146 needed. srecord_type is used to communicate from the thread
147 that encountered the task construct to task firstprivate fn,
148 record_type is allocated by GOMP_task, initialized by task firstprivate
149 fn and passed to the task body fn. */
150 splay_tree sfield_map;
151 tree srecord_type;
153 /* A chain of variables to add to the top-level block surrounding the
154 construct. In the case of a parallel, this is in the child function. */
155 tree block_vars;
157 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
158 barriers should jump to during omplower pass. */
159 tree cancel_label;
161 /* What to do with variables with implicitly determined sharing
162 attributes. */
163 enum omp_clause_default_kind default_kind;
165 /* Nesting depth of this context. Used to beautify error messages re
166 invalid gotos. The outermost ctx is depth 1, with depth 0 being
167 reserved for the main body of the function. */
168 int depth;
170 /* True if this parallel directive is nested within another. */
171 bool is_nested;
173 /* True if this construct can be cancelled. */
174 bool cancellable;
175 } omp_context;
178 struct omp_for_data_loop
180 tree v, n1, n2, step;
181 enum tree_code cond_code;
184 /* A structure describing the main elements of a parallel loop. */
186 struct omp_for_data
188 struct omp_for_data_loop loop;
189 tree chunk_size;
190 gimple for_stmt;
191 tree pre, iter_type;
192 int collapse;
193 bool have_nowait, have_ordered;
194 enum omp_clause_schedule_kind sched_kind;
195 struct omp_for_data_loop *loops;
199 static splay_tree all_contexts;
200 static int taskreg_nesting_level;
201 static int target_nesting_level;
202 static struct omp_region *root_omp_region;
203 static bitmap task_shared_vars;
205 static void scan_omp (gimple_seq *, omp_context *);
206 static tree scan_omp_1_op (tree *, int *, void *);
208 #define WALK_SUBSTMTS \
209 case GIMPLE_BIND: \
210 case GIMPLE_TRY: \
211 case GIMPLE_CATCH: \
212 case GIMPLE_EH_FILTER: \
213 case GIMPLE_TRANSACTION: \
214 /* The sub-statements for these should be walked. */ \
215 *handled_ops_p = false; \
216 break;
218 /* Convenience function for calling scan_omp_1_op on tree operands. */
220 static inline tree
221 scan_omp_op (tree *tp, omp_context *ctx)
223 struct walk_stmt_info wi;
225 memset (&wi, 0, sizeof (wi));
226 wi.info = ctx;
227 wi.want_locations = true;
229 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
232 static void lower_omp (gimple_seq *, omp_context *);
233 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
234 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
236 /* Find an OpenMP clause of type KIND within CLAUSES. */
238 tree
239 find_omp_clause (tree clauses, enum omp_clause_code kind)
241 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
242 if (OMP_CLAUSE_CODE (clauses) == kind)
243 return clauses;
245 return NULL_TREE;
248 /* Return true if CTX is for an omp parallel. */
250 static inline bool
251 is_parallel_ctx (omp_context *ctx)
253 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
257 /* Return true if CTX is for an omp task. */
259 static inline bool
260 is_task_ctx (omp_context *ctx)
262 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
266 /* Return true if CTX is for an omp parallel or omp task. */
268 static inline bool
269 is_taskreg_ctx (omp_context *ctx)
271 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
272 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
276 /* Return true if REGION is a combined parallel+workshare region. */
278 static inline bool
279 is_combined_parallel (struct omp_region *region)
281 return region->is_combined_parallel;
285 /* Extract the header elements of parallel loop FOR_STMT and store
286 them into *FD. */
288 static void
289 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
290 struct omp_for_data_loop *loops)
292 tree t, var, *collapse_iter, *collapse_count;
293 tree count = NULL_TREE, iter_type = long_integer_type_node;
294 struct omp_for_data_loop *loop;
295 int i;
296 struct omp_for_data_loop dummy_loop;
297 location_t loc = gimple_location (for_stmt);
298 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
299 bool distribute = gimple_omp_for_kind (for_stmt)
300 == GF_OMP_FOR_KIND_DISTRIBUTE;
302 fd->for_stmt = for_stmt;
303 fd->pre = NULL;
304 fd->collapse = gimple_omp_for_collapse (for_stmt);
305 if (fd->collapse > 1)
306 fd->loops = loops;
307 else
308 fd->loops = &fd->loop;
310 fd->have_nowait = distribute || simd;
311 fd->have_ordered = false;
312 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
313 fd->chunk_size = NULL_TREE;
314 collapse_iter = NULL;
315 collapse_count = NULL;
317 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
318 switch (OMP_CLAUSE_CODE (t))
320 case OMP_CLAUSE_NOWAIT:
321 fd->have_nowait = true;
322 break;
323 case OMP_CLAUSE_ORDERED:
324 fd->have_ordered = true;
325 break;
326 case OMP_CLAUSE_SCHEDULE:
327 gcc_assert (!distribute);
328 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
329 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
330 break;
331 case OMP_CLAUSE_DIST_SCHEDULE:
332 gcc_assert (distribute);
333 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
334 break;
335 case OMP_CLAUSE_COLLAPSE:
336 if (fd->collapse > 1)
338 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
339 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
341 default:
342 break;
345 /* FIXME: for now map schedule(auto) to schedule(static).
346 There should be analysis to determine whether all iterations
347 are approximately the same amount of work (then schedule(static)
348 is best) or if it varies (then schedule(dynamic,N) is better). */
349 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
351 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
352 gcc_assert (fd->chunk_size == NULL);
354 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
355 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
356 gcc_assert (fd->chunk_size == NULL);
357 else if (fd->chunk_size == NULL)
359 /* We only need to compute a default chunk size for ordered
360 static loops and dynamic loops. */
361 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
362 || fd->have_ordered)
363 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
364 ? integer_zero_node : integer_one_node;
367 for (i = 0; i < fd->collapse; i++)
369 if (fd->collapse == 1)
370 loop = &fd->loop;
371 else if (loops != NULL)
372 loop = loops + i;
373 else
374 loop = &dummy_loop;
376 loop->v = gimple_omp_for_index (for_stmt, i);
377 gcc_assert (SSA_VAR_P (loop->v));
378 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
379 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
380 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
381 loop->n1 = gimple_omp_for_initial (for_stmt, i);
383 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
384 loop->n2 = gimple_omp_for_final (for_stmt, i);
385 switch (loop->cond_code)
387 case LT_EXPR:
388 case GT_EXPR:
389 break;
390 case NE_EXPR:
391 gcc_assert (gimple_omp_for_kind (for_stmt)
392 == GF_OMP_FOR_KIND_CILKSIMD);
393 break;
394 case LE_EXPR:
395 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
396 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
397 else
398 loop->n2 = fold_build2_loc (loc,
399 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
400 build_int_cst (TREE_TYPE (loop->n2), 1));
401 loop->cond_code = LT_EXPR;
402 break;
403 case GE_EXPR:
404 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
405 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
406 else
407 loop->n2 = fold_build2_loc (loc,
408 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
409 build_int_cst (TREE_TYPE (loop->n2), 1));
410 loop->cond_code = GT_EXPR;
411 break;
412 default:
413 gcc_unreachable ();
416 t = gimple_omp_for_incr (for_stmt, i);
417 gcc_assert (TREE_OPERAND (t, 0) == var);
418 switch (TREE_CODE (t))
420 case PLUS_EXPR:
421 loop->step = TREE_OPERAND (t, 1);
422 break;
423 case POINTER_PLUS_EXPR:
424 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
425 break;
426 case MINUS_EXPR:
427 loop->step = TREE_OPERAND (t, 1);
428 loop->step = fold_build1_loc (loc,
429 NEGATE_EXPR, TREE_TYPE (loop->step),
430 loop->step);
431 break;
432 default:
433 gcc_unreachable ();
436 if (simd
437 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
438 && !fd->have_ordered))
440 if (fd->collapse == 1)
441 iter_type = TREE_TYPE (loop->v);
442 else if (i == 0
443 || TYPE_PRECISION (iter_type)
444 < TYPE_PRECISION (TREE_TYPE (loop->v)))
445 iter_type
446 = build_nonstandard_integer_type
447 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
449 else if (iter_type != long_long_unsigned_type_node)
451 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
452 iter_type = long_long_unsigned_type_node;
453 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
454 && TYPE_PRECISION (TREE_TYPE (loop->v))
455 >= TYPE_PRECISION (iter_type))
457 tree n;
459 if (loop->cond_code == LT_EXPR)
460 n = fold_build2_loc (loc,
461 PLUS_EXPR, TREE_TYPE (loop->v),
462 loop->n2, loop->step);
463 else
464 n = loop->n1;
465 if (TREE_CODE (n) != INTEGER_CST
466 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
467 iter_type = long_long_unsigned_type_node;
469 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
470 > TYPE_PRECISION (iter_type))
472 tree n1, n2;
474 if (loop->cond_code == LT_EXPR)
476 n1 = loop->n1;
477 n2 = fold_build2_loc (loc,
478 PLUS_EXPR, TREE_TYPE (loop->v),
479 loop->n2, loop->step);
481 else
483 n1 = fold_build2_loc (loc,
484 MINUS_EXPR, TREE_TYPE (loop->v),
485 loop->n2, loop->step);
486 n2 = loop->n1;
488 if (TREE_CODE (n1) != INTEGER_CST
489 || TREE_CODE (n2) != INTEGER_CST
490 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
491 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
492 iter_type = long_long_unsigned_type_node;
496 if (collapse_count && *collapse_count == NULL)
498 t = fold_binary (loop->cond_code, boolean_type_node,
499 fold_convert (TREE_TYPE (loop->v), loop->n1),
500 fold_convert (TREE_TYPE (loop->v), loop->n2));
501 if (t && integer_zerop (t))
502 count = build_zero_cst (long_long_unsigned_type_node);
503 else if ((i == 0 || count != NULL_TREE)
504 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
505 && TREE_CONSTANT (loop->n1)
506 && TREE_CONSTANT (loop->n2)
507 && TREE_CODE (loop->step) == INTEGER_CST)
509 tree itype = TREE_TYPE (loop->v);
511 if (POINTER_TYPE_P (itype))
512 itype = signed_type_for (itype);
513 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
514 t = fold_build2_loc (loc,
515 PLUS_EXPR, itype,
516 fold_convert_loc (loc, itype, loop->step), t);
517 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
518 fold_convert_loc (loc, itype, loop->n2));
519 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
520 fold_convert_loc (loc, itype, loop->n1));
521 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
522 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
523 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
524 fold_build1_loc (loc, NEGATE_EXPR, itype,
525 fold_convert_loc (loc, itype,
526 loop->step)));
527 else
528 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
529 fold_convert_loc (loc, itype, loop->step));
530 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
531 if (count != NULL_TREE)
532 count = fold_build2_loc (loc,
533 MULT_EXPR, long_long_unsigned_type_node,
534 count, t);
535 else
536 count = t;
537 if (TREE_CODE (count) != INTEGER_CST)
538 count = NULL_TREE;
540 else if (count && !integer_zerop (count))
541 count = NULL_TREE;
545 if (count
546 && !simd
547 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
548 || fd->have_ordered))
550 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
551 iter_type = long_long_unsigned_type_node;
552 else
553 iter_type = long_integer_type_node;
555 else if (collapse_iter && *collapse_iter != NULL)
556 iter_type = TREE_TYPE (*collapse_iter);
557 fd->iter_type = iter_type;
558 if (collapse_iter && *collapse_iter == NULL)
559 *collapse_iter = create_tmp_var (iter_type, ".iter");
560 if (collapse_count && *collapse_count == NULL)
562 if (count)
563 *collapse_count = fold_convert_loc (loc, iter_type, count);
564 else
565 *collapse_count = create_tmp_var (iter_type, ".count");
568 if (fd->collapse > 1)
570 fd->loop.v = *collapse_iter;
571 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
572 fd->loop.n2 = *collapse_count;
573 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
574 fd->loop.cond_code = LT_EXPR;
579 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
580 is the immediate dominator of PAR_ENTRY_BB, return true if there
581 are no data dependencies that would prevent expanding the parallel
582 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
584 When expanding a combined parallel+workshare region, the call to
585 the child function may need additional arguments in the case of
586 GIMPLE_OMP_FOR regions. In some cases, these arguments are
587 computed out of variables passed in from the parent to the child
588 via 'struct .omp_data_s'. For instance:
590 #pragma omp parallel for schedule (guided, i * 4)
591 for (j ...)
593 Is lowered into:
595 # BLOCK 2 (PAR_ENTRY_BB)
596 .omp_data_o.i = i;
597 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
599 # BLOCK 3 (WS_ENTRY_BB)
600 .omp_data_i = &.omp_data_o;
601 D.1667 = .omp_data_i->i;
602 D.1598 = D.1667 * 4;
603 #pragma omp for schedule (guided, D.1598)
605 When we outline the parallel region, the call to the child function
606 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
607 that value is computed *after* the call site. So, in principle we
608 cannot do the transformation.
610 To see whether the code in WS_ENTRY_BB blocks the combined
611 parallel+workshare call, we collect all the variables used in the
612 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
613 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
614 call.
616 FIXME. If we had the SSA form built at this point, we could merely
617 hoist the code in block 3 into block 2 and be done with it. But at
618 this point we don't have dataflow information and though we could
619 hack something up here, it is really not worth the aggravation. */
621 static bool
622 workshare_safe_to_combine_p (basic_block ws_entry_bb)
624 struct omp_for_data fd;
625 gimple ws_stmt = last_stmt (ws_entry_bb);
627 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
628 return true;
630 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
632 extract_omp_for_data (ws_stmt, &fd, NULL);
634 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
635 return false;
636 if (fd.iter_type != long_integer_type_node)
637 return false;
639 /* FIXME. We give up too easily here. If any of these arguments
640 are not constants, they will likely involve variables that have
641 been mapped into fields of .omp_data_s for sharing with the child
642 function. With appropriate data flow, it would be possible to
643 see through this. */
644 if (!is_gimple_min_invariant (fd.loop.n1)
645 || !is_gimple_min_invariant (fd.loop.n2)
646 || !is_gimple_min_invariant (fd.loop.step)
647 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
648 return false;
650 return true;
654 /* Collect additional arguments needed to emit a combined
655 parallel+workshare call. WS_STMT is the workshare directive being
656 expanded. */
658 static vec<tree, va_gc> *
659 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
661 tree t;
662 location_t loc = gimple_location (ws_stmt);
663 vec<tree, va_gc> *ws_args;
665 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
667 struct omp_for_data fd;
668 tree n1, n2;
670 extract_omp_for_data (ws_stmt, &fd, NULL);
671 n1 = fd.loop.n1;
672 n2 = fd.loop.n2;
674 if (gimple_omp_for_combined_into_p (ws_stmt))
676 tree innerc
677 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
678 OMP_CLAUSE__LOOPTEMP_);
679 gcc_assert (innerc);
680 n1 = OMP_CLAUSE_DECL (innerc);
681 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
682 OMP_CLAUSE__LOOPTEMP_);
683 gcc_assert (innerc);
684 n2 = OMP_CLAUSE_DECL (innerc);
687 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
689 t = fold_convert_loc (loc, long_integer_type_node, n1);
690 ws_args->quick_push (t);
692 t = fold_convert_loc (loc, long_integer_type_node, n2);
693 ws_args->quick_push (t);
695 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
696 ws_args->quick_push (t);
698 if (fd.chunk_size)
700 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
701 ws_args->quick_push (t);
704 return ws_args;
706 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
708 /* Number of sections is equal to the number of edges from the
709 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
710 the exit of the sections region. */
711 basic_block bb = single_succ (gimple_bb (ws_stmt));
712 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
713 vec_alloc (ws_args, 1);
714 ws_args->quick_push (t);
715 return ws_args;
718 gcc_unreachable ();
722 /* Discover whether REGION is a combined parallel+workshare region. */
724 static void
725 determine_parallel_type (struct omp_region *region)
727 basic_block par_entry_bb, par_exit_bb;
728 basic_block ws_entry_bb, ws_exit_bb;
730 if (region == NULL || region->inner == NULL
731 || region->exit == NULL || region->inner->exit == NULL
732 || region->inner->cont == NULL)
733 return;
735 /* We only support parallel+for and parallel+sections. */
736 if (region->type != GIMPLE_OMP_PARALLEL
737 || (region->inner->type != GIMPLE_OMP_FOR
738 && region->inner->type != GIMPLE_OMP_SECTIONS))
739 return;
741 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
742 WS_EXIT_BB -> PAR_EXIT_BB. */
743 par_entry_bb = region->entry;
744 par_exit_bb = region->exit;
745 ws_entry_bb = region->inner->entry;
746 ws_exit_bb = region->inner->exit;
748 if (single_succ (par_entry_bb) == ws_entry_bb
749 && single_succ (ws_exit_bb) == par_exit_bb
750 && workshare_safe_to_combine_p (ws_entry_bb)
751 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
752 || (last_and_only_stmt (ws_entry_bb)
753 && last_and_only_stmt (par_exit_bb))))
755 gimple par_stmt = last_stmt (par_entry_bb);
756 gimple ws_stmt = last_stmt (ws_entry_bb);
758 if (region->inner->type == GIMPLE_OMP_FOR)
760 /* If this is a combined parallel loop, we need to determine
761 whether or not to use the combined library calls. There
762 are two cases where we do not apply the transformation:
763 static loops and any kind of ordered loop. In the first
764 case, we already open code the loop so there is no need
765 to do anything else. In the latter case, the combined
766 parallel loop call would still need extra synchronization
767 to implement ordered semantics, so there would not be any
768 gain in using the combined call. */
769 tree clauses = gimple_omp_for_clauses (ws_stmt);
770 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
771 if (c == NULL
772 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
773 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
775 region->is_combined_parallel = false;
776 region->inner->is_combined_parallel = false;
777 return;
781 region->is_combined_parallel = true;
782 region->inner->is_combined_parallel = true;
783 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
788 /* Return true if EXPR is variable sized. */
790 static inline bool
791 is_variable_sized (const_tree expr)
793 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
796 /* Return true if DECL is a reference type. */
798 static inline bool
799 is_reference (tree decl)
801 return lang_hooks.decls.omp_privatize_by_reference (decl);
804 /* Lookup variables in the decl or field splay trees. The "maybe" form
805 allows for the variable form to not have been entered, otherwise we
806 assert that the variable must have been entered. */
808 static inline tree
809 lookup_decl (tree var, omp_context *ctx)
811 tree *n;
812 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
813 return *n;
816 static inline tree
817 maybe_lookup_decl (const_tree var, omp_context *ctx)
819 tree *n;
820 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
821 return n ? *n : NULL_TREE;
824 static inline tree
825 lookup_field (tree var, omp_context *ctx)
827 splay_tree_node n;
828 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
829 return (tree) n->value;
832 static inline tree
833 lookup_sfield (tree var, omp_context *ctx)
835 splay_tree_node n;
836 n = splay_tree_lookup (ctx->sfield_map
837 ? ctx->sfield_map : ctx->field_map,
838 (splay_tree_key) var);
839 return (tree) n->value;
842 static inline tree
843 maybe_lookup_field (tree var, omp_context *ctx)
845 splay_tree_node n;
846 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
847 return n ? (tree) n->value : NULL_TREE;
850 /* Return true if DECL should be copied by pointer. SHARED_CTX is
851 the parallel context if DECL is to be shared. */
853 static bool
854 use_pointer_for_field (tree decl, omp_context *shared_ctx)
856 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
857 return true;
859 /* We can only use copy-in/copy-out semantics for shared variables
860 when we know the value is not accessible from an outer scope. */
861 if (shared_ctx)
863 /* ??? Trivially accessible from anywhere. But why would we even
864 be passing an address in this case? Should we simply assert
865 this to be false, or should we have a cleanup pass that removes
866 these from the list of mappings? */
867 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
868 return true;
870 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
871 without analyzing the expression whether or not its location
872 is accessible to anyone else. In the case of nested parallel
873 regions it certainly may be. */
874 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
875 return true;
877 /* Do not use copy-in/copy-out for variables that have their
878 address taken. */
879 if (TREE_ADDRESSABLE (decl))
880 return true;
882 /* lower_send_shared_vars only uses copy-in, but not copy-out
883 for these. */
884 if (TREE_READONLY (decl)
885 || ((TREE_CODE (decl) == RESULT_DECL
886 || TREE_CODE (decl) == PARM_DECL)
887 && DECL_BY_REFERENCE (decl)))
888 return false;
890 /* Disallow copy-in/out in nested parallel if
891 decl is shared in outer parallel, otherwise
892 each thread could store the shared variable
893 in its own copy-in location, making the
894 variable no longer really shared. */
895 if (shared_ctx->is_nested)
897 omp_context *up;
899 for (up = shared_ctx->outer; up; up = up->outer)
900 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
901 break;
903 if (up)
905 tree c;
907 for (c = gimple_omp_taskreg_clauses (up->stmt);
908 c; c = OMP_CLAUSE_CHAIN (c))
909 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
910 && OMP_CLAUSE_DECL (c) == decl)
911 break;
913 if (c)
914 goto maybe_mark_addressable_and_ret;
918 /* For tasks avoid using copy-in/out. As tasks can be
919 deferred or executed in different thread, when GOMP_task
920 returns, the task hasn't necessarily terminated. */
921 if (is_task_ctx (shared_ctx))
923 tree outer;
924 maybe_mark_addressable_and_ret:
925 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
926 if (is_gimple_reg (outer))
928 /* Taking address of OUTER in lower_send_shared_vars
929 might need regimplification of everything that uses the
930 variable. */
931 if (!task_shared_vars)
932 task_shared_vars = BITMAP_ALLOC (NULL);
933 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
934 TREE_ADDRESSABLE (outer) = 1;
936 return true;
940 return false;
943 /* Construct a new automatic decl similar to VAR. */
945 static tree
946 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
948 tree copy = copy_var_decl (var, name, type);
950 DECL_CONTEXT (copy) = current_function_decl;
951 DECL_CHAIN (copy) = ctx->block_vars;
952 ctx->block_vars = copy;
954 return copy;
957 static tree
958 omp_copy_decl_1 (tree var, omp_context *ctx)
960 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
963 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
964 as appropriate. */
965 static tree
966 omp_build_component_ref (tree obj, tree field)
968 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
969 if (TREE_THIS_VOLATILE (field))
970 TREE_THIS_VOLATILE (ret) |= 1;
971 if (TREE_READONLY (field))
972 TREE_READONLY (ret) |= 1;
973 return ret;
976 /* Build tree nodes to access the field for VAR on the receiver side. */
978 static tree
979 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
981 tree x, field = lookup_field (var, ctx);
983 /* If the receiver record type was remapped in the child function,
984 remap the field into the new record type. */
985 x = maybe_lookup_field (field, ctx);
986 if (x != NULL)
987 field = x;
989 x = build_simple_mem_ref (ctx->receiver_decl);
990 x = omp_build_component_ref (x, field);
991 if (by_ref)
992 x = build_simple_mem_ref (x);
994 return x;
997 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
998 of a parallel, this is a component reference; for workshare constructs
999 this is some variable. */
1001 static tree
1002 build_outer_var_ref (tree var, omp_context *ctx)
1004 tree x;
1006 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1007 x = var;
1008 else if (is_variable_sized (var))
1010 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1011 x = build_outer_var_ref (x, ctx);
1012 x = build_simple_mem_ref (x);
1014 else if (is_taskreg_ctx (ctx))
1016 bool by_ref = use_pointer_for_field (var, NULL);
1017 x = build_receiver_ref (var, by_ref, ctx);
1019 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1020 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1022 /* #pragma omp simd isn't a worksharing construct, and can reference even
1023 private vars in its linear etc. clauses. */
1024 x = NULL_TREE;
1025 if (ctx->outer && is_taskreg_ctx (ctx))
1026 x = lookup_decl (var, ctx->outer);
1027 else if (ctx->outer)
1028 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1029 if (x == NULL_TREE)
1030 x = var;
1032 else if (ctx->outer)
1033 x = lookup_decl (var, ctx->outer);
1034 else if (is_reference (var))
1035 /* This can happen with orphaned constructs. If var is reference, it is
1036 possible it is shared and as such valid. */
1037 x = var;
1038 else
1039 gcc_unreachable ();
1041 if (is_reference (var))
1042 x = build_simple_mem_ref (x);
1044 return x;
1047 /* Build tree nodes to access the field for VAR on the sender side. */
1049 static tree
1050 build_sender_ref (tree var, omp_context *ctx)
1052 tree field = lookup_sfield (var, ctx);
1053 return omp_build_component_ref (ctx->sender_decl, field);
1056 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1058 static void
1059 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1061 tree field, type, sfield = NULL_TREE;
1063 gcc_assert ((mask & 1) == 0
1064 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1065 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1066 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1068 type = TREE_TYPE (var);
1069 if (mask & 4)
1071 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1072 type = build_pointer_type (build_pointer_type (type));
1074 else if (by_ref)
1075 type = build_pointer_type (type);
1076 else if ((mask & 3) == 1 && is_reference (var))
1077 type = TREE_TYPE (type);
1079 field = build_decl (DECL_SOURCE_LOCATION (var),
1080 FIELD_DECL, DECL_NAME (var), type);
1082 /* Remember what variable this field was created for. This does have a
1083 side effect of making dwarf2out ignore this member, so for helpful
1084 debugging we clear it later in delete_omp_context. */
1085 DECL_ABSTRACT_ORIGIN (field) = var;
1086 if (type == TREE_TYPE (var))
1088 DECL_ALIGN (field) = DECL_ALIGN (var);
1089 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1090 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1092 else
1093 DECL_ALIGN (field) = TYPE_ALIGN (type);
1095 if ((mask & 3) == 3)
1097 insert_field_into_struct (ctx->record_type, field);
1098 if (ctx->srecord_type)
1100 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1101 FIELD_DECL, DECL_NAME (var), type);
1102 DECL_ABSTRACT_ORIGIN (sfield) = var;
1103 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1104 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1105 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1106 insert_field_into_struct (ctx->srecord_type, sfield);
1109 else
1111 if (ctx->srecord_type == NULL_TREE)
1113 tree t;
1115 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1116 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1117 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1119 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1120 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1121 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1122 insert_field_into_struct (ctx->srecord_type, sfield);
1123 splay_tree_insert (ctx->sfield_map,
1124 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1125 (splay_tree_value) sfield);
1128 sfield = field;
1129 insert_field_into_struct ((mask & 1) ? ctx->record_type
1130 : ctx->srecord_type, field);
1133 if (mask & 1)
1134 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1135 (splay_tree_value) field);
1136 if ((mask & 2) && ctx->sfield_map)
1137 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1138 (splay_tree_value) sfield);
1141 static tree
1142 install_var_local (tree var, omp_context *ctx)
1144 tree new_var = omp_copy_decl_1 (var, ctx);
1145 insert_decl_map (&ctx->cb, var, new_var);
1146 return new_var;
1149 /* Adjust the replacement for DECL in CTX for the new context. This means
1150 copying the DECL_VALUE_EXPR, and fixing up the type. */
1152 static void
1153 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1155 tree new_decl, size;
1157 new_decl = lookup_decl (decl, ctx);
1159 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1161 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1162 && DECL_HAS_VALUE_EXPR_P (decl))
1164 tree ve = DECL_VALUE_EXPR (decl);
1165 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1166 SET_DECL_VALUE_EXPR (new_decl, ve);
1167 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1170 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1172 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1173 if (size == error_mark_node)
1174 size = TYPE_SIZE (TREE_TYPE (new_decl));
1175 DECL_SIZE (new_decl) = size;
1177 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1178 if (size == error_mark_node)
1179 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1180 DECL_SIZE_UNIT (new_decl) = size;
1184 /* The callback for remap_decl. Search all containing contexts for a
1185 mapping of the variable; this avoids having to duplicate the splay
1186 tree ahead of time. We know a mapping doesn't already exist in the
1187 given context. Create new mappings to implement default semantics. */
1189 static tree
1190 omp_copy_decl (tree var, copy_body_data *cb)
1192 omp_context *ctx = (omp_context *) cb;
1193 tree new_var;
1195 if (TREE_CODE (var) == LABEL_DECL)
1197 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1198 DECL_CONTEXT (new_var) = current_function_decl;
1199 insert_decl_map (&ctx->cb, var, new_var);
1200 return new_var;
1203 while (!is_taskreg_ctx (ctx))
1205 ctx = ctx->outer;
1206 if (ctx == NULL)
1207 return var;
1208 new_var = maybe_lookup_decl (var, ctx);
1209 if (new_var)
1210 return new_var;
1213 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1214 return var;
1216 return error_mark_node;
1220 /* Return the parallel region associated with STMT. */
1222 /* Debugging dumps for parallel regions. */
1223 void dump_omp_region (FILE *, struct omp_region *, int);
1224 void debug_omp_region (struct omp_region *);
1225 void debug_all_omp_regions (void);
1227 /* Dump the parallel region tree rooted at REGION. */
1229 void
1230 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1232 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1233 gimple_code_name[region->type]);
1235 if (region->inner)
1236 dump_omp_region (file, region->inner, indent + 4);
1238 if (region->cont)
1240 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1241 region->cont->index);
1244 if (region->exit)
1245 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1246 region->exit->index);
1247 else
1248 fprintf (file, "%*s[no exit marker]\n", indent, "");
1250 if (region->next)
1251 dump_omp_region (file, region->next, indent);
1254 DEBUG_FUNCTION void
1255 debug_omp_region (struct omp_region *region)
1257 dump_omp_region (stderr, region, 0);
1260 DEBUG_FUNCTION void
1261 debug_all_omp_regions (void)
1263 dump_omp_region (stderr, root_omp_region, 0);
1267 /* Create a new parallel region starting at STMT inside region PARENT. */
1269 static struct omp_region *
1270 new_omp_region (basic_block bb, enum gimple_code type,
1271 struct omp_region *parent)
1273 struct omp_region *region = XCNEW (struct omp_region);
1275 region->outer = parent;
1276 region->entry = bb;
1277 region->type = type;
1279 if (parent)
1281 /* This is a nested region. Add it to the list of inner
1282 regions in PARENT. */
1283 region->next = parent->inner;
1284 parent->inner = region;
1286 else
1288 /* This is a toplevel region. Add it to the list of toplevel
1289 regions in ROOT_OMP_REGION. */
1290 region->next = root_omp_region;
1291 root_omp_region = region;
1294 return region;
1297 /* Release the memory associated with the region tree rooted at REGION. */
1299 static void
1300 free_omp_region_1 (struct omp_region *region)
1302 struct omp_region *i, *n;
1304 for (i = region->inner; i ; i = n)
1306 n = i->next;
1307 free_omp_region_1 (i);
1310 free (region);
1313 /* Release the memory for the entire omp region tree. */
1315 void
1316 free_omp_regions (void)
1318 struct omp_region *r, *n;
1319 for (r = root_omp_region; r ; r = n)
1321 n = r->next;
1322 free_omp_region_1 (r);
1324 root_omp_region = NULL;
1328 /* Create a new context, with OUTER_CTX being the surrounding context. */
1330 static omp_context *
1331 new_omp_context (gimple stmt, omp_context *outer_ctx)
1333 omp_context *ctx = XCNEW (omp_context);
1335 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1336 (splay_tree_value) ctx);
1337 ctx->stmt = stmt;
1339 if (outer_ctx)
1341 ctx->outer = outer_ctx;
1342 ctx->cb = outer_ctx->cb;
1343 ctx->cb.block = NULL;
1344 ctx->depth = outer_ctx->depth + 1;
1346 else
1348 ctx->cb.src_fn = current_function_decl;
1349 ctx->cb.dst_fn = current_function_decl;
1350 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1351 gcc_checking_assert (ctx->cb.src_node);
1352 ctx->cb.dst_node = ctx->cb.src_node;
1353 ctx->cb.src_cfun = cfun;
1354 ctx->cb.copy_decl = omp_copy_decl;
1355 ctx->cb.eh_lp_nr = 0;
1356 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1357 ctx->depth = 1;
1360 ctx->cb.decl_map = pointer_map_create ();
1362 return ctx;
1365 static gimple_seq maybe_catch_exception (gimple_seq);
1367 /* Finalize task copyfn. */
1369 static void
1370 finalize_task_copyfn (gimple task_stmt)
1372 struct function *child_cfun;
1373 tree child_fn;
1374 gimple_seq seq = NULL, new_seq;
1375 gimple bind;
1377 child_fn = gimple_omp_task_copy_fn (task_stmt);
1378 if (child_fn == NULL_TREE)
1379 return;
1381 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1382 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1384 push_cfun (child_cfun);
1385 bind = gimplify_body (child_fn, false);
1386 gimple_seq_add_stmt (&seq, bind);
1387 new_seq = maybe_catch_exception (seq);
1388 if (new_seq != seq)
1390 bind = gimple_build_bind (NULL, new_seq, NULL);
1391 seq = NULL;
1392 gimple_seq_add_stmt (&seq, bind);
1394 gimple_set_body (child_fn, seq);
1395 pop_cfun ();
1397 /* Inform the callgraph about the new function. */
1398 cgraph_add_new_function (child_fn, false);
1401 /* Destroy a omp_context data structures. Called through the splay tree
1402 value delete callback. */
1404 static void
1405 delete_omp_context (splay_tree_value value)
1407 omp_context *ctx = (omp_context *) value;
1409 pointer_map_destroy (ctx->cb.decl_map);
1411 if (ctx->field_map)
1412 splay_tree_delete (ctx->field_map);
1413 if (ctx->sfield_map)
1414 splay_tree_delete (ctx->sfield_map);
1416 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1417 it produces corrupt debug information. */
1418 if (ctx->record_type)
1420 tree t;
1421 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1422 DECL_ABSTRACT_ORIGIN (t) = NULL;
1424 if (ctx->srecord_type)
1426 tree t;
1427 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1428 DECL_ABSTRACT_ORIGIN (t) = NULL;
1431 if (is_task_ctx (ctx))
1432 finalize_task_copyfn (ctx->stmt);
1434 XDELETE (ctx);
1437 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1438 context. */
1440 static void
1441 fixup_child_record_type (omp_context *ctx)
1443 tree f, type = ctx->record_type;
1445 /* ??? It isn't sufficient to just call remap_type here, because
1446 variably_modified_type_p doesn't work the way we expect for
1447 record types. Testing each field for whether it needs remapping
1448 and creating a new record by hand works, however. */
1449 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1450 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1451 break;
1452 if (f)
1454 tree name, new_fields = NULL;
1456 type = lang_hooks.types.make_type (RECORD_TYPE);
1457 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1458 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1459 TYPE_DECL, name, type);
1460 TYPE_NAME (type) = name;
1462 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1464 tree new_f = copy_node (f);
1465 DECL_CONTEXT (new_f) = type;
1466 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1467 DECL_CHAIN (new_f) = new_fields;
1468 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1469 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1470 &ctx->cb, NULL);
1471 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1472 &ctx->cb, NULL);
1473 new_fields = new_f;
1475 /* Arrange to be able to look up the receiver field
1476 given the sender field. */
1477 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1478 (splay_tree_value) new_f);
1480 TYPE_FIELDS (type) = nreverse (new_fields);
1481 layout_type (type);
1484 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1487 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1488 specified by CLAUSES. */
1490 static void
1491 scan_sharing_clauses (tree clauses, omp_context *ctx)
1493 tree c, decl;
1494 bool scan_array_reductions = false;
1496 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1498 bool by_ref;
1500 switch (OMP_CLAUSE_CODE (c))
1502 case OMP_CLAUSE_PRIVATE:
1503 decl = OMP_CLAUSE_DECL (c);
1504 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1505 goto do_private;
1506 else if (!is_variable_sized (decl))
1507 install_var_local (decl, ctx);
1508 break;
1510 case OMP_CLAUSE_SHARED:
1511 /* Ignore shared directives in teams construct. */
1512 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1513 break;
1514 gcc_assert (is_taskreg_ctx (ctx));
1515 decl = OMP_CLAUSE_DECL (c);
1516 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1517 || !is_variable_sized (decl));
1518 /* Global variables don't need to be copied,
1519 the receiver side will use them directly. */
1520 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1521 break;
1522 by_ref = use_pointer_for_field (decl, ctx);
1523 if (! TREE_READONLY (decl)
1524 || TREE_ADDRESSABLE (decl)
1525 || by_ref
1526 || is_reference (decl))
1528 install_var_field (decl, by_ref, 3, ctx);
1529 install_var_local (decl, ctx);
1530 break;
1532 /* We don't need to copy const scalar vars back. */
1533 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1534 goto do_private;
1536 case OMP_CLAUSE_LASTPRIVATE:
1537 /* Let the corresponding firstprivate clause create
1538 the variable. */
1539 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1540 break;
1541 /* FALLTHRU */
1543 case OMP_CLAUSE_FIRSTPRIVATE:
1544 case OMP_CLAUSE_REDUCTION:
1545 case OMP_CLAUSE_LINEAR:
1546 decl = OMP_CLAUSE_DECL (c);
1547 do_private:
1548 if (is_variable_sized (decl))
1550 if (is_task_ctx (ctx))
1551 install_var_field (decl, false, 1, ctx);
1552 break;
1554 else if (is_taskreg_ctx (ctx))
1556 bool global
1557 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1558 by_ref = use_pointer_for_field (decl, NULL);
1560 if (is_task_ctx (ctx)
1561 && (global || by_ref || is_reference (decl)))
1563 install_var_field (decl, false, 1, ctx);
1564 if (!global)
1565 install_var_field (decl, by_ref, 2, ctx);
1567 else if (!global)
1568 install_var_field (decl, by_ref, 3, ctx);
1570 install_var_local (decl, ctx);
1571 break;
1573 case OMP_CLAUSE__LOOPTEMP_:
1574 gcc_assert (is_parallel_ctx (ctx));
1575 decl = OMP_CLAUSE_DECL (c);
1576 install_var_field (decl, false, 3, ctx);
1577 install_var_local (decl, ctx);
1578 break;
1580 case OMP_CLAUSE_COPYPRIVATE:
1581 case OMP_CLAUSE_COPYIN:
1582 decl = OMP_CLAUSE_DECL (c);
1583 by_ref = use_pointer_for_field (decl, NULL);
1584 install_var_field (decl, by_ref, 3, ctx);
1585 break;
1587 case OMP_CLAUSE_DEFAULT:
1588 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1589 break;
1591 case OMP_CLAUSE_FINAL:
1592 case OMP_CLAUSE_IF:
1593 case OMP_CLAUSE_NUM_THREADS:
1594 case OMP_CLAUSE_NUM_TEAMS:
1595 case OMP_CLAUSE_THREAD_LIMIT:
1596 case OMP_CLAUSE_DEVICE:
1597 case OMP_CLAUSE_SCHEDULE:
1598 case OMP_CLAUSE_DIST_SCHEDULE:
1599 case OMP_CLAUSE_DEPEND:
1600 if (ctx->outer)
1601 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1602 break;
1604 case OMP_CLAUSE_TO:
1605 case OMP_CLAUSE_FROM:
1606 case OMP_CLAUSE_MAP:
1607 if (ctx->outer)
1608 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1609 decl = OMP_CLAUSE_DECL (c);
1610 /* Global variables with "omp declare target" attribute
1611 don't need to be copied, the receiver side will use them
1612 directly. */
1613 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1614 && DECL_P (decl)
1615 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1616 && lookup_attribute ("omp declare target",
1617 DECL_ATTRIBUTES (decl)))
1618 break;
1619 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1620 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1622 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1623 #pragma omp target data, there is nothing to map for
1624 those. */
1625 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1626 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1627 break;
1629 if (DECL_P (decl))
1631 if (DECL_SIZE (decl)
1632 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1634 tree decl2 = DECL_VALUE_EXPR (decl);
1635 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1636 decl2 = TREE_OPERAND (decl2, 0);
1637 gcc_assert (DECL_P (decl2));
1638 install_var_field (decl2, true, 3, ctx);
1639 install_var_local (decl2, ctx);
1640 install_var_local (decl, ctx);
1642 else
1644 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1645 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1646 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1647 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1648 install_var_field (decl, true, 7, ctx);
1649 else
1650 install_var_field (decl, true, 3, ctx);
1651 if (gimple_omp_target_kind (ctx->stmt)
1652 == GF_OMP_TARGET_KIND_REGION)
1653 install_var_local (decl, ctx);
1656 else
1658 tree base = get_base_address (decl);
1659 tree nc = OMP_CLAUSE_CHAIN (c);
1660 if (DECL_P (base)
1661 && nc != NULL_TREE
1662 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1663 && OMP_CLAUSE_DECL (nc) == base
1664 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1665 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1667 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1668 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1670 else
1672 gcc_assert (!splay_tree_lookup (ctx->field_map,
1673 (splay_tree_key) decl));
1674 tree field
1675 = build_decl (OMP_CLAUSE_LOCATION (c),
1676 FIELD_DECL, NULL_TREE, ptr_type_node);
1677 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1678 insert_field_into_struct (ctx->record_type, field);
1679 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1680 (splay_tree_value) field);
1683 break;
1685 case OMP_CLAUSE_NOWAIT:
1686 case OMP_CLAUSE_ORDERED:
1687 case OMP_CLAUSE_COLLAPSE:
1688 case OMP_CLAUSE_UNTIED:
1689 case OMP_CLAUSE_MERGEABLE:
1690 case OMP_CLAUSE_PROC_BIND:
1691 case OMP_CLAUSE_SAFELEN:
1692 break;
1694 case OMP_CLAUSE_ALIGNED:
1695 decl = OMP_CLAUSE_DECL (c);
1696 if (is_global_var (decl)
1697 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1698 install_var_local (decl, ctx);
1699 break;
1701 default:
1702 gcc_unreachable ();
1706 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1708 switch (OMP_CLAUSE_CODE (c))
1710 case OMP_CLAUSE_LASTPRIVATE:
1711 /* Let the corresponding firstprivate clause create
1712 the variable. */
1713 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1714 scan_array_reductions = true;
1715 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1716 break;
1717 /* FALLTHRU */
1719 case OMP_CLAUSE_PRIVATE:
1720 case OMP_CLAUSE_FIRSTPRIVATE:
1721 case OMP_CLAUSE_REDUCTION:
1722 case OMP_CLAUSE_LINEAR:
1723 decl = OMP_CLAUSE_DECL (c);
1724 if (is_variable_sized (decl))
1725 install_var_local (decl, ctx);
1726 fixup_remapped_decl (decl, ctx,
1727 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1728 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1729 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1730 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1731 scan_array_reductions = true;
1732 break;
1734 case OMP_CLAUSE_SHARED:
1735 /* Ignore shared directives in teams construct. */
1736 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1737 break;
1738 decl = OMP_CLAUSE_DECL (c);
1739 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1740 fixup_remapped_decl (decl, ctx, false);
1741 break;
1743 case OMP_CLAUSE_MAP:
1744 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1745 break;
1746 decl = OMP_CLAUSE_DECL (c);
1747 if (DECL_P (decl)
1748 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1749 && lookup_attribute ("omp declare target",
1750 DECL_ATTRIBUTES (decl)))
1751 break;
1752 if (DECL_P (decl))
1754 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1755 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1756 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1758 tree new_decl = lookup_decl (decl, ctx);
1759 TREE_TYPE (new_decl)
1760 = remap_type (TREE_TYPE (decl), &ctx->cb);
1762 else if (DECL_SIZE (decl)
1763 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1765 tree decl2 = DECL_VALUE_EXPR (decl);
1766 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1767 decl2 = TREE_OPERAND (decl2, 0);
1768 gcc_assert (DECL_P (decl2));
1769 fixup_remapped_decl (decl2, ctx, false);
1770 fixup_remapped_decl (decl, ctx, true);
1772 else
1773 fixup_remapped_decl (decl, ctx, false);
1775 break;
1777 case OMP_CLAUSE_COPYPRIVATE:
1778 case OMP_CLAUSE_COPYIN:
1779 case OMP_CLAUSE_DEFAULT:
1780 case OMP_CLAUSE_IF:
1781 case OMP_CLAUSE_NUM_THREADS:
1782 case OMP_CLAUSE_NUM_TEAMS:
1783 case OMP_CLAUSE_THREAD_LIMIT:
1784 case OMP_CLAUSE_DEVICE:
1785 case OMP_CLAUSE_SCHEDULE:
1786 case OMP_CLAUSE_DIST_SCHEDULE:
1787 case OMP_CLAUSE_NOWAIT:
1788 case OMP_CLAUSE_ORDERED:
1789 case OMP_CLAUSE_COLLAPSE:
1790 case OMP_CLAUSE_UNTIED:
1791 case OMP_CLAUSE_FINAL:
1792 case OMP_CLAUSE_MERGEABLE:
1793 case OMP_CLAUSE_PROC_BIND:
1794 case OMP_CLAUSE_SAFELEN:
1795 case OMP_CLAUSE_ALIGNED:
1796 case OMP_CLAUSE_DEPEND:
1797 case OMP_CLAUSE__LOOPTEMP_:
1798 case OMP_CLAUSE_TO:
1799 case OMP_CLAUSE_FROM:
1800 break;
1802 default:
1803 gcc_unreachable ();
1807 if (scan_array_reductions)
1808 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1810 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1812 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1813 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1815 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1816 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1817 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1820 /* Create a new name for omp child function. Returns an identifier. */
1822 static GTY(()) unsigned int tmp_ompfn_id_num;
1824 static tree
1825 create_omp_child_function_name (bool task_copy)
1827 return (clone_function_name (current_function_decl,
1828 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1831 /* Build a decl for the omp child function. It'll not contain a body
1832 yet, just the bare decl. */
1834 static void
1835 create_omp_child_function (omp_context *ctx, bool task_copy)
1837 tree decl, type, name, t;
1839 name = create_omp_child_function_name (task_copy);
1840 if (task_copy)
1841 type = build_function_type_list (void_type_node, ptr_type_node,
1842 ptr_type_node, NULL_TREE);
1843 else
1844 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1846 decl = build_decl (gimple_location (ctx->stmt),
1847 FUNCTION_DECL, name, type);
1849 if (!task_copy)
1850 ctx->cb.dst_fn = decl;
1851 else
1852 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1854 TREE_STATIC (decl) = 1;
1855 TREE_USED (decl) = 1;
1856 DECL_ARTIFICIAL (decl) = 1;
1857 DECL_NAMELESS (decl) = 1;
1858 DECL_IGNORED_P (decl) = 0;
1859 TREE_PUBLIC (decl) = 0;
1860 DECL_UNINLINABLE (decl) = 1;
1861 DECL_EXTERNAL (decl) = 0;
1862 DECL_CONTEXT (decl) = NULL_TREE;
1863 DECL_INITIAL (decl) = make_node (BLOCK);
1864 bool target_p = false;
1865 if (lookup_attribute ("omp declare target",
1866 DECL_ATTRIBUTES (current_function_decl)))
1867 target_p = true;
1868 else
1870 omp_context *octx;
1871 for (octx = ctx; octx; octx = octx->outer)
1872 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1873 && gimple_omp_target_kind (octx->stmt)
1874 == GF_OMP_TARGET_KIND_REGION)
1876 target_p = true;
1877 break;
1880 if (target_p)
1881 DECL_ATTRIBUTES (decl)
1882 = tree_cons (get_identifier ("omp declare target"),
1883 NULL_TREE, DECL_ATTRIBUTES (decl));
1885 t = build_decl (DECL_SOURCE_LOCATION (decl),
1886 RESULT_DECL, NULL_TREE, void_type_node);
1887 DECL_ARTIFICIAL (t) = 1;
1888 DECL_IGNORED_P (t) = 1;
1889 DECL_CONTEXT (t) = decl;
1890 DECL_RESULT (decl) = t;
1892 t = build_decl (DECL_SOURCE_LOCATION (decl),
1893 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1894 DECL_ARTIFICIAL (t) = 1;
1895 DECL_NAMELESS (t) = 1;
1896 DECL_ARG_TYPE (t) = ptr_type_node;
1897 DECL_CONTEXT (t) = current_function_decl;
1898 TREE_USED (t) = 1;
1899 DECL_ARGUMENTS (decl) = t;
1900 if (!task_copy)
1901 ctx->receiver_decl = t;
1902 else
1904 t = build_decl (DECL_SOURCE_LOCATION (decl),
1905 PARM_DECL, get_identifier (".omp_data_o"),
1906 ptr_type_node);
1907 DECL_ARTIFICIAL (t) = 1;
1908 DECL_NAMELESS (t) = 1;
1909 DECL_ARG_TYPE (t) = ptr_type_node;
1910 DECL_CONTEXT (t) = current_function_decl;
1911 TREE_USED (t) = 1;
1912 TREE_ADDRESSABLE (t) = 1;
1913 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1914 DECL_ARGUMENTS (decl) = t;
1917 /* Allocate memory for the function structure. The call to
1918 allocate_struct_function clobbers CFUN, so we need to restore
1919 it afterward. */
1920 push_struct_function (decl);
1921 cfun->function_end_locus = gimple_location (ctx->stmt);
1922 pop_cfun ();
1925 /* Callback for walk_gimple_seq. Check if combined parallel
1926 contains gimple_omp_for_combined_into_p OMP_FOR. */
1928 static tree
1929 find_combined_for (gimple_stmt_iterator *gsi_p,
1930 bool *handled_ops_p,
1931 struct walk_stmt_info *wi)
1933 gimple stmt = gsi_stmt (*gsi_p);
1935 *handled_ops_p = true;
1936 switch (gimple_code (stmt))
1938 WALK_SUBSTMTS;
1940 case GIMPLE_OMP_FOR:
1941 if (gimple_omp_for_combined_into_p (stmt)
1942 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1944 wi->info = stmt;
1945 return integer_zero_node;
1947 break;
1948 default:
1949 break;
1951 return NULL;
1954 /* Scan an OpenMP parallel directive. */
1956 static void
1957 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1959 omp_context *ctx;
1960 tree name;
1961 gimple stmt = gsi_stmt (*gsi);
1963 /* Ignore parallel directives with empty bodies, unless there
1964 are copyin clauses. */
1965 if (optimize > 0
1966 && empty_body_p (gimple_omp_body (stmt))
1967 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1968 OMP_CLAUSE_COPYIN) == NULL)
1970 gsi_replace (gsi, gimple_build_nop (), false);
1971 return;
1974 if (gimple_omp_parallel_combined_p (stmt))
1976 gimple for_stmt;
1977 struct walk_stmt_info wi;
1979 memset (&wi, 0, sizeof (wi));
1980 wi.val_only = true;
1981 walk_gimple_seq (gimple_omp_body (stmt),
1982 find_combined_for, NULL, &wi);
1983 for_stmt = (gimple) wi.info;
1984 if (for_stmt)
1986 struct omp_for_data fd;
1987 extract_omp_for_data (for_stmt, &fd, NULL);
1988 /* We need two temporaries with fd.loop.v type (istart/iend)
1989 and then (fd.collapse - 1) temporaries with the same
1990 type for count2 ... countN-1 vars if not constant. */
1991 size_t count = 2, i;
1992 tree type = fd.iter_type;
1993 if (fd.collapse > 1
1994 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
1995 count += fd.collapse - 1;
1996 for (i = 0; i < count; i++)
1998 tree temp = create_tmp_var (type, NULL);
1999 tree c = build_omp_clause (UNKNOWN_LOCATION,
2000 OMP_CLAUSE__LOOPTEMP_);
2001 OMP_CLAUSE_DECL (c) = temp;
2002 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2003 gimple_omp_parallel_set_clauses (stmt, c);
2008 ctx = new_omp_context (stmt, outer_ctx);
2009 if (taskreg_nesting_level > 1)
2010 ctx->is_nested = true;
2011 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2012 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2013 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2014 name = create_tmp_var_name (".omp_data_s");
2015 name = build_decl (gimple_location (stmt),
2016 TYPE_DECL, name, ctx->record_type);
2017 DECL_ARTIFICIAL (name) = 1;
2018 DECL_NAMELESS (name) = 1;
2019 TYPE_NAME (ctx->record_type) = name;
2020 create_omp_child_function (ctx, false);
2021 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2023 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2024 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2026 if (TYPE_FIELDS (ctx->record_type) == NULL)
2027 ctx->record_type = ctx->receiver_decl = NULL;
2028 else
2030 layout_type (ctx->record_type);
2031 fixup_child_record_type (ctx);
2035 /* Scan an OpenMP task directive. */
2037 static void
2038 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2040 omp_context *ctx;
2041 tree name, t;
2042 gimple stmt = gsi_stmt (*gsi);
2043 location_t loc = gimple_location (stmt);
2045 /* Ignore task directives with empty bodies. */
2046 if (optimize > 0
2047 && empty_body_p (gimple_omp_body (stmt)))
2049 gsi_replace (gsi, gimple_build_nop (), false);
2050 return;
2053 ctx = new_omp_context (stmt, outer_ctx);
2054 if (taskreg_nesting_level > 1)
2055 ctx->is_nested = true;
2056 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2057 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2058 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2059 name = create_tmp_var_name (".omp_data_s");
2060 name = build_decl (gimple_location (stmt),
2061 TYPE_DECL, name, ctx->record_type);
2062 DECL_ARTIFICIAL (name) = 1;
2063 DECL_NAMELESS (name) = 1;
2064 TYPE_NAME (ctx->record_type) = name;
2065 create_omp_child_function (ctx, false);
2066 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2068 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2070 if (ctx->srecord_type)
2072 name = create_tmp_var_name (".omp_data_a");
2073 name = build_decl (gimple_location (stmt),
2074 TYPE_DECL, name, ctx->srecord_type);
2075 DECL_ARTIFICIAL (name) = 1;
2076 DECL_NAMELESS (name) = 1;
2077 TYPE_NAME (ctx->srecord_type) = name;
2078 create_omp_child_function (ctx, true);
2081 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2083 if (TYPE_FIELDS (ctx->record_type) == NULL)
2085 ctx->record_type = ctx->receiver_decl = NULL;
2086 t = build_int_cst (long_integer_type_node, 0);
2087 gimple_omp_task_set_arg_size (stmt, t);
2088 t = build_int_cst (long_integer_type_node, 1);
2089 gimple_omp_task_set_arg_align (stmt, t);
2091 else
2093 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2094 /* Move VLA fields to the end. */
2095 p = &TYPE_FIELDS (ctx->record_type);
2096 while (*p)
2097 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2098 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2100 *q = *p;
2101 *p = TREE_CHAIN (*p);
2102 TREE_CHAIN (*q) = NULL_TREE;
2103 q = &TREE_CHAIN (*q);
2105 else
2106 p = &DECL_CHAIN (*p);
2107 *p = vla_fields;
2108 layout_type (ctx->record_type);
2109 fixup_child_record_type (ctx);
2110 if (ctx->srecord_type)
2111 layout_type (ctx->srecord_type);
2112 t = fold_convert_loc (loc, long_integer_type_node,
2113 TYPE_SIZE_UNIT (ctx->record_type));
2114 gimple_omp_task_set_arg_size (stmt, t);
2115 t = build_int_cst (long_integer_type_node,
2116 TYPE_ALIGN_UNIT (ctx->record_type));
2117 gimple_omp_task_set_arg_align (stmt, t);
2122 /* Scan an OpenMP loop directive. */
2124 static void
2125 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2127 omp_context *ctx;
2128 size_t i;
2130 ctx = new_omp_context (stmt, outer_ctx);
2132 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2134 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2135 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2137 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2138 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2139 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2140 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2142 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2145 /* Scan an OpenMP sections directive. */
2147 static void
2148 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2150 omp_context *ctx;
2152 ctx = new_omp_context (stmt, outer_ctx);
2153 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2154 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2157 /* Scan an OpenMP single directive. */
2159 static void
2160 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2162 omp_context *ctx;
2163 tree name;
2165 ctx = new_omp_context (stmt, outer_ctx);
2166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2167 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2168 name = create_tmp_var_name (".omp_copy_s");
2169 name = build_decl (gimple_location (stmt),
2170 TYPE_DECL, name, ctx->record_type);
2171 TYPE_NAME (ctx->record_type) = name;
2173 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2174 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2176 if (TYPE_FIELDS (ctx->record_type) == NULL)
2177 ctx->record_type = NULL;
2178 else
2179 layout_type (ctx->record_type);
2182 /* Scan an OpenMP target{, data, update} directive. */
2184 static void
2185 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2187 omp_context *ctx;
2188 tree name;
2189 int kind = gimple_omp_target_kind (stmt);
2191 ctx = new_omp_context (stmt, outer_ctx);
2192 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2193 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2194 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2195 name = create_tmp_var_name (".omp_data_t");
2196 name = build_decl (gimple_location (stmt),
2197 TYPE_DECL, name, ctx->record_type);
2198 DECL_ARTIFICIAL (name) = 1;
2199 DECL_NAMELESS (name) = 1;
2200 TYPE_NAME (ctx->record_type) = name;
2201 if (kind == GF_OMP_TARGET_KIND_REGION)
2203 create_omp_child_function (ctx, false);
2204 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2207 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2208 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2210 if (TYPE_FIELDS (ctx->record_type) == NULL)
2211 ctx->record_type = ctx->receiver_decl = NULL;
2212 else
2214 TYPE_FIELDS (ctx->record_type)
2215 = nreverse (TYPE_FIELDS (ctx->record_type));
2216 #ifdef ENABLE_CHECKING
2217 tree field;
2218 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2219 for (field = TYPE_FIELDS (ctx->record_type);
2220 field;
2221 field = DECL_CHAIN (field))
2222 gcc_assert (DECL_ALIGN (field) == align);
2223 #endif
2224 layout_type (ctx->record_type);
2225 if (kind == GF_OMP_TARGET_KIND_REGION)
2226 fixup_child_record_type (ctx);
2230 /* Scan an OpenMP teams directive. */
2232 static void
2233 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2235 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2236 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2237 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2240 /* Check OpenMP nesting restrictions. */
2241 static bool
2242 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2244 if (ctx != NULL)
2246 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2247 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2249 error_at (gimple_location (stmt),
2250 "OpenMP constructs may not be nested inside simd region");
2251 return false;
2253 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2255 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2256 || (gimple_omp_for_kind (stmt)
2257 != GF_OMP_FOR_KIND_DISTRIBUTE))
2258 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2260 error_at (gimple_location (stmt),
2261 "only distribute or parallel constructs are allowed to "
2262 "be closely nested inside teams construct");
2263 return false;
2267 switch (gimple_code (stmt))
2269 case GIMPLE_OMP_FOR:
2270 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2271 return true;
2272 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2274 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2276 error_at (gimple_location (stmt),
2277 "distribute construct must be closely nested inside "
2278 "teams construct");
2279 return false;
2281 return true;
2283 /* FALLTHRU */
2284 case GIMPLE_CALL:
2285 if (is_gimple_call (stmt)
2286 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2287 == BUILT_IN_GOMP_CANCEL
2288 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2289 == BUILT_IN_GOMP_CANCELLATION_POINT))
2291 const char *bad = NULL;
2292 const char *kind = NULL;
2293 if (ctx == NULL)
2295 error_at (gimple_location (stmt), "orphaned %qs construct",
2296 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2297 == BUILT_IN_GOMP_CANCEL
2298 ? "#pragma omp cancel"
2299 : "#pragma omp cancellation point");
2300 return false;
2302 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2303 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2304 : 0)
2306 case 1:
2307 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2308 bad = "#pragma omp parallel";
2309 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2310 == BUILT_IN_GOMP_CANCEL
2311 && !integer_zerop (gimple_call_arg (stmt, 1)))
2312 ctx->cancellable = true;
2313 kind = "parallel";
2314 break;
2315 case 2:
2316 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2317 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2318 bad = "#pragma omp for";
2319 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2320 == BUILT_IN_GOMP_CANCEL
2321 && !integer_zerop (gimple_call_arg (stmt, 1)))
2323 ctx->cancellable = true;
2324 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2325 OMP_CLAUSE_NOWAIT))
2326 warning_at (gimple_location (stmt), 0,
2327 "%<#pragma omp cancel for%> inside "
2328 "%<nowait%> for construct");
2329 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2330 OMP_CLAUSE_ORDERED))
2331 warning_at (gimple_location (stmt), 0,
2332 "%<#pragma omp cancel for%> inside "
2333 "%<ordered%> for construct");
2335 kind = "for";
2336 break;
2337 case 4:
2338 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2339 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2340 bad = "#pragma omp sections";
2341 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2342 == BUILT_IN_GOMP_CANCEL
2343 && !integer_zerop (gimple_call_arg (stmt, 1)))
2345 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2347 ctx->cancellable = true;
2348 if (find_omp_clause (gimple_omp_sections_clauses
2349 (ctx->stmt),
2350 OMP_CLAUSE_NOWAIT))
2351 warning_at (gimple_location (stmt), 0,
2352 "%<#pragma omp cancel sections%> inside "
2353 "%<nowait%> sections construct");
2355 else
2357 gcc_assert (ctx->outer
2358 && gimple_code (ctx->outer->stmt)
2359 == GIMPLE_OMP_SECTIONS);
2360 ctx->outer->cancellable = true;
2361 if (find_omp_clause (gimple_omp_sections_clauses
2362 (ctx->outer->stmt),
2363 OMP_CLAUSE_NOWAIT))
2364 warning_at (gimple_location (stmt), 0,
2365 "%<#pragma omp cancel sections%> inside "
2366 "%<nowait%> sections construct");
2369 kind = "sections";
2370 break;
2371 case 8:
2372 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2373 bad = "#pragma omp task";
2374 else
2375 ctx->cancellable = true;
2376 kind = "taskgroup";
2377 break;
2378 default:
2379 error_at (gimple_location (stmt), "invalid arguments");
2380 return false;
2382 if (bad)
2384 error_at (gimple_location (stmt),
2385 "%<%s %s%> construct not closely nested inside of %qs",
2386 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2387 == BUILT_IN_GOMP_CANCEL
2388 ? "#pragma omp cancel"
2389 : "#pragma omp cancellation point", kind, bad);
2390 return false;
2393 /* FALLTHRU */
2394 case GIMPLE_OMP_SECTIONS:
2395 case GIMPLE_OMP_SINGLE:
2396 for (; ctx != NULL; ctx = ctx->outer)
2397 switch (gimple_code (ctx->stmt))
2399 case GIMPLE_OMP_FOR:
2400 case GIMPLE_OMP_SECTIONS:
2401 case GIMPLE_OMP_SINGLE:
2402 case GIMPLE_OMP_ORDERED:
2403 case GIMPLE_OMP_MASTER:
2404 case GIMPLE_OMP_TASK:
2405 case GIMPLE_OMP_CRITICAL:
2406 if (is_gimple_call (stmt))
2408 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2409 != BUILT_IN_GOMP_BARRIER)
2410 return true;
2411 error_at (gimple_location (stmt),
2412 "barrier region may not be closely nested inside "
2413 "of work-sharing, critical, ordered, master or "
2414 "explicit task region");
2415 return false;
2417 error_at (gimple_location (stmt),
2418 "work-sharing region may not be closely nested inside "
2419 "of work-sharing, critical, ordered, master or explicit "
2420 "task region");
2421 return false;
2422 case GIMPLE_OMP_PARALLEL:
2423 return true;
2424 default:
2425 break;
2427 break;
2428 case GIMPLE_OMP_MASTER:
2429 for (; ctx != NULL; ctx = ctx->outer)
2430 switch (gimple_code (ctx->stmt))
2432 case GIMPLE_OMP_FOR:
2433 case GIMPLE_OMP_SECTIONS:
2434 case GIMPLE_OMP_SINGLE:
2435 case GIMPLE_OMP_TASK:
2436 error_at (gimple_location (stmt),
2437 "master region may not be closely nested inside "
2438 "of work-sharing or explicit task region");
2439 return false;
2440 case GIMPLE_OMP_PARALLEL:
2441 return true;
2442 default:
2443 break;
2445 break;
2446 case GIMPLE_OMP_ORDERED:
2447 for (; ctx != NULL; ctx = ctx->outer)
2448 switch (gimple_code (ctx->stmt))
2450 case GIMPLE_OMP_CRITICAL:
2451 case GIMPLE_OMP_TASK:
2452 error_at (gimple_location (stmt),
2453 "ordered region may not be closely nested inside "
2454 "of critical or explicit task region");
2455 return false;
2456 case GIMPLE_OMP_FOR:
2457 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2458 OMP_CLAUSE_ORDERED) == NULL)
2460 error_at (gimple_location (stmt),
2461 "ordered region must be closely nested inside "
2462 "a loop region with an ordered clause");
2463 return false;
2465 return true;
2466 case GIMPLE_OMP_PARALLEL:
2467 error_at (gimple_location (stmt),
2468 "ordered region must be closely nested inside "
2469 "a loop region with an ordered clause");
2470 return false;
2471 default:
2472 break;
2474 break;
2475 case GIMPLE_OMP_CRITICAL:
2476 for (; ctx != NULL; ctx = ctx->outer)
2477 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2478 && (gimple_omp_critical_name (stmt)
2479 == gimple_omp_critical_name (ctx->stmt)))
2481 error_at (gimple_location (stmt),
2482 "critical region may not be nested inside a critical "
2483 "region with the same name");
2484 return false;
2486 break;
2487 case GIMPLE_OMP_TEAMS:
2488 if (ctx == NULL
2489 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2490 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2492 error_at (gimple_location (stmt),
2493 "teams construct not closely nested inside of target "
2494 "region");
2495 return false;
2497 break;
2498 default:
2499 break;
2501 return true;
2505 /* Helper function scan_omp.
2507 Callback for walk_tree or operators in walk_gimple_stmt used to
2508 scan for OpenMP directives in TP. */
2510 static tree
2511 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2513 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2514 omp_context *ctx = (omp_context *) wi->info;
2515 tree t = *tp;
2517 switch (TREE_CODE (t))
2519 case VAR_DECL:
2520 case PARM_DECL:
2521 case LABEL_DECL:
2522 case RESULT_DECL:
2523 if (ctx)
2524 *tp = remap_decl (t, &ctx->cb);
2525 break;
2527 default:
2528 if (ctx && TYPE_P (t))
2529 *tp = remap_type (t, &ctx->cb);
2530 else if (!DECL_P (t))
2532 *walk_subtrees = 1;
2533 if (ctx)
2535 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2536 if (tem != TREE_TYPE (t))
2538 if (TREE_CODE (t) == INTEGER_CST)
2539 *tp = build_int_cst_wide (tem,
2540 TREE_INT_CST_LOW (t),
2541 TREE_INT_CST_HIGH (t));
2542 else
2543 TREE_TYPE (t) = tem;
2547 break;
2550 return NULL_TREE;
2553 /* Return true if FNDECL is a setjmp or a longjmp. */
2555 static bool
2556 setjmp_or_longjmp_p (const_tree fndecl)
2558 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2559 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2560 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2561 return true;
2563 tree declname = DECL_NAME (fndecl);
2564 if (!declname)
2565 return false;
2566 const char *name = IDENTIFIER_POINTER (declname);
2567 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2571 /* Helper function for scan_omp.
2573 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2574 the current statement in GSI. */
2576 static tree
2577 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2578 struct walk_stmt_info *wi)
2580 gimple stmt = gsi_stmt (*gsi);
2581 omp_context *ctx = (omp_context *) wi->info;
2583 if (gimple_has_location (stmt))
2584 input_location = gimple_location (stmt);
2586 /* Check the OpenMP nesting restrictions. */
2587 bool remove = false;
2588 if (is_gimple_omp (stmt))
2589 remove = !check_omp_nesting_restrictions (stmt, ctx);
2590 else if (is_gimple_call (stmt))
2592 tree fndecl = gimple_call_fndecl (stmt);
2593 if (fndecl)
2595 if (setjmp_or_longjmp_p (fndecl)
2596 && ctx
2597 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2598 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2600 remove = true;
2601 error_at (gimple_location (stmt),
2602 "setjmp/longjmp inside simd construct");
2604 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2605 switch (DECL_FUNCTION_CODE (fndecl))
2607 case BUILT_IN_GOMP_BARRIER:
2608 case BUILT_IN_GOMP_CANCEL:
2609 case BUILT_IN_GOMP_CANCELLATION_POINT:
2610 case BUILT_IN_GOMP_TASKYIELD:
2611 case BUILT_IN_GOMP_TASKWAIT:
2612 case BUILT_IN_GOMP_TASKGROUP_START:
2613 case BUILT_IN_GOMP_TASKGROUP_END:
2614 remove = !check_omp_nesting_restrictions (stmt, ctx);
2615 break;
2616 default:
2617 break;
2621 if (remove)
2623 stmt = gimple_build_nop ();
2624 gsi_replace (gsi, stmt, false);
2627 *handled_ops_p = true;
2629 switch (gimple_code (stmt))
2631 case GIMPLE_OMP_PARALLEL:
2632 taskreg_nesting_level++;
2633 scan_omp_parallel (gsi, ctx);
2634 taskreg_nesting_level--;
2635 break;
2637 case GIMPLE_OMP_TASK:
2638 taskreg_nesting_level++;
2639 scan_omp_task (gsi, ctx);
2640 taskreg_nesting_level--;
2641 break;
2643 case GIMPLE_OMP_FOR:
2644 scan_omp_for (stmt, ctx);
2645 break;
2647 case GIMPLE_OMP_SECTIONS:
2648 scan_omp_sections (stmt, ctx);
2649 break;
2651 case GIMPLE_OMP_SINGLE:
2652 scan_omp_single (stmt, ctx);
2653 break;
2655 case GIMPLE_OMP_SECTION:
2656 case GIMPLE_OMP_MASTER:
2657 case GIMPLE_OMP_TASKGROUP:
2658 case GIMPLE_OMP_ORDERED:
2659 case GIMPLE_OMP_CRITICAL:
2660 ctx = new_omp_context (stmt, ctx);
2661 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2662 break;
2664 case GIMPLE_OMP_TARGET:
2665 scan_omp_target (stmt, ctx);
2666 break;
2668 case GIMPLE_OMP_TEAMS:
2669 scan_omp_teams (stmt, ctx);
2670 break;
2672 case GIMPLE_BIND:
2674 tree var;
2676 *handled_ops_p = false;
2677 if (ctx)
2678 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2679 insert_decl_map (&ctx->cb, var, var);
2681 break;
2682 default:
2683 *handled_ops_p = false;
2684 break;
2687 return NULL_TREE;
2691 /* Scan all the statements starting at the current statement. CTX
2692 contains context information about the OpenMP directives and
2693 clauses found during the scan. */
2695 static void
2696 scan_omp (gimple_seq *body_p, omp_context *ctx)
2698 location_t saved_location;
2699 struct walk_stmt_info wi;
2701 memset (&wi, 0, sizeof (wi));
2702 wi.info = ctx;
2703 wi.want_locations = true;
2705 saved_location = input_location;
2706 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2707 input_location = saved_location;
2710 /* Re-gimplification and code generation routines. */
2712 /* Build a call to GOMP_barrier. */
2714 static gimple
2715 build_omp_barrier (tree lhs)
2717 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2718 : BUILT_IN_GOMP_BARRIER);
2719 gimple g = gimple_build_call (fndecl, 0);
2720 if (lhs)
2721 gimple_call_set_lhs (g, lhs);
2722 return g;
2725 /* If a context was created for STMT when it was scanned, return it. */
2727 static omp_context *
2728 maybe_lookup_ctx (gimple stmt)
2730 splay_tree_node n;
2731 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2732 return n ? (omp_context *) n->value : NULL;
2736 /* Find the mapping for DECL in CTX or the immediately enclosing
2737 context that has a mapping for DECL.
2739 If CTX is a nested parallel directive, we may have to use the decl
2740 mappings created in CTX's parent context. Suppose that we have the
2741 following parallel nesting (variable UIDs showed for clarity):
2743 iD.1562 = 0;
2744 #omp parallel shared(iD.1562) -> outer parallel
2745 iD.1562 = iD.1562 + 1;
2747 #omp parallel shared (iD.1562) -> inner parallel
2748 iD.1562 = iD.1562 - 1;
2750 Each parallel structure will create a distinct .omp_data_s structure
2751 for copying iD.1562 in/out of the directive:
2753 outer parallel .omp_data_s.1.i -> iD.1562
2754 inner parallel .omp_data_s.2.i -> iD.1562
2756 A shared variable mapping will produce a copy-out operation before
2757 the parallel directive and a copy-in operation after it. So, in
2758 this case we would have:
2760 iD.1562 = 0;
2761 .omp_data_o.1.i = iD.1562;
2762 #omp parallel shared(iD.1562) -> outer parallel
2763 .omp_data_i.1 = &.omp_data_o.1
2764 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2766 .omp_data_o.2.i = iD.1562; -> **
2767 #omp parallel shared(iD.1562) -> inner parallel
2768 .omp_data_i.2 = &.omp_data_o.2
2769 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2772 ** This is a problem. The symbol iD.1562 cannot be referenced
2773 inside the body of the outer parallel region. But since we are
2774 emitting this copy operation while expanding the inner parallel
2775 directive, we need to access the CTX structure of the outer
2776 parallel directive to get the correct mapping:
2778 .omp_data_o.2.i = .omp_data_i.1->i
2780 Since there may be other workshare or parallel directives enclosing
2781 the parallel directive, it may be necessary to walk up the context
2782 parent chain. This is not a problem in general because nested
2783 parallelism happens only rarely. */
2785 static tree
2786 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2788 tree t;
2789 omp_context *up;
2791 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2792 t = maybe_lookup_decl (decl, up);
2794 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2796 return t ? t : decl;
2800 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2801 in outer contexts. */
2803 static tree
2804 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2806 tree t = NULL;
2807 omp_context *up;
2809 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2810 t = maybe_lookup_decl (decl, up);
2812 return t ? t : decl;
2816 /* Construct the initialization value for reduction CLAUSE. */
2818 tree
2819 omp_reduction_init (tree clause, tree type)
2821 location_t loc = OMP_CLAUSE_LOCATION (clause);
2822 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2824 case PLUS_EXPR:
2825 case MINUS_EXPR:
2826 case BIT_IOR_EXPR:
2827 case BIT_XOR_EXPR:
2828 case TRUTH_OR_EXPR:
2829 case TRUTH_ORIF_EXPR:
2830 case TRUTH_XOR_EXPR:
2831 case NE_EXPR:
2832 return build_zero_cst (type);
2834 case MULT_EXPR:
2835 case TRUTH_AND_EXPR:
2836 case TRUTH_ANDIF_EXPR:
2837 case EQ_EXPR:
2838 return fold_convert_loc (loc, type, integer_one_node);
2840 case BIT_AND_EXPR:
2841 return fold_convert_loc (loc, type, integer_minus_one_node);
2843 case MAX_EXPR:
2844 if (SCALAR_FLOAT_TYPE_P (type))
2846 REAL_VALUE_TYPE max, min;
2847 if (HONOR_INFINITIES (TYPE_MODE (type)))
2849 real_inf (&max);
2850 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2852 else
2853 real_maxval (&min, 1, TYPE_MODE (type));
2854 return build_real (type, min);
2856 else
2858 gcc_assert (INTEGRAL_TYPE_P (type));
2859 return TYPE_MIN_VALUE (type);
2862 case MIN_EXPR:
2863 if (SCALAR_FLOAT_TYPE_P (type))
2865 REAL_VALUE_TYPE max;
2866 if (HONOR_INFINITIES (TYPE_MODE (type)))
2867 real_inf (&max);
2868 else
2869 real_maxval (&max, 0, TYPE_MODE (type));
2870 return build_real (type, max);
2872 else
2874 gcc_assert (INTEGRAL_TYPE_P (type));
2875 return TYPE_MAX_VALUE (type);
2878 default:
2879 gcc_unreachable ();
2883 /* Return alignment to be assumed for var in CLAUSE, which should be
2884 OMP_CLAUSE_ALIGNED. */
2886 static tree
2887 omp_clause_aligned_alignment (tree clause)
2889 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2890 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2892 /* Otherwise return implementation defined alignment. */
2893 unsigned int al = 1;
2894 enum machine_mode mode, vmode;
2895 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2896 if (vs)
2897 vs = 1 << floor_log2 (vs);
2898 static enum mode_class classes[]
2899 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2900 for (int i = 0; i < 4; i += 2)
2901 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2902 mode != VOIDmode;
2903 mode = GET_MODE_WIDER_MODE (mode))
2905 vmode = targetm.vectorize.preferred_simd_mode (mode);
2906 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2907 continue;
2908 while (vs
2909 && GET_MODE_SIZE (vmode) < vs
2910 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2911 vmode = GET_MODE_2XWIDER_MODE (vmode);
2913 tree type = lang_hooks.types.type_for_mode (mode, 1);
2914 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2915 continue;
2916 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2917 / GET_MODE_SIZE (mode));
2918 if (TYPE_MODE (type) != vmode)
2919 continue;
2920 if (TYPE_ALIGN_UNIT (type) > al)
2921 al = TYPE_ALIGN_UNIT (type);
2923 return build_int_cst (integer_type_node, al);
2926 /* Return maximum possible vectorization factor for the target. */
2928 static int
2929 omp_max_vf (void)
2931 if (!optimize
2932 || optimize_debug
2933 || (!flag_tree_loop_vectorize
2934 && (global_options_set.x_flag_tree_loop_vectorize
2935 || global_options_set.x_flag_tree_vectorize)))
2936 return 1;
2938 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2939 if (vs)
2941 vs = 1 << floor_log2 (vs);
2942 return vs;
2944 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2945 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2946 return GET_MODE_NUNITS (vqimode);
2947 return 1;
2950 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2951 privatization. */
2953 static bool
2954 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2955 tree &idx, tree &lane, tree &ivar, tree &lvar)
2957 if (max_vf == 0)
2959 max_vf = omp_max_vf ();
2960 if (max_vf > 1)
2962 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2963 OMP_CLAUSE_SAFELEN);
2964 if (c
2965 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2966 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2968 if (max_vf > 1)
2970 idx = create_tmp_var (unsigned_type_node, NULL);
2971 lane = create_tmp_var (unsigned_type_node, NULL);
2974 if (max_vf == 1)
2975 return false;
2977 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2978 tree avar = create_tmp_var_raw (atype, NULL);
2979 if (TREE_ADDRESSABLE (new_var))
2980 TREE_ADDRESSABLE (avar) = 1;
2981 DECL_ATTRIBUTES (avar)
2982 = tree_cons (get_identifier ("omp simd array"), NULL,
2983 DECL_ATTRIBUTES (avar));
2984 gimple_add_tmp_var (avar);
2985 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2986 NULL_TREE, NULL_TREE);
2987 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2988 NULL_TREE, NULL_TREE);
2989 if (DECL_P (new_var))
2991 SET_DECL_VALUE_EXPR (new_var, lvar);
2992 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2994 return true;
2997 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2998 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2999 private variables. Initialization statements go in ILIST, while calls
3000 to destructors go in DLIST. */
3002 static void
3003 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3004 omp_context *ctx, struct omp_for_data *fd)
3006 tree c, dtor, copyin_seq, x, ptr;
3007 bool copyin_by_ref = false;
3008 bool lastprivate_firstprivate = false;
3009 bool reduction_omp_orig_ref = false;
3010 int pass;
3011 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3012 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3013 int max_vf = 0;
3014 tree lane = NULL_TREE, idx = NULL_TREE;
3015 tree ivar = NULL_TREE, lvar = NULL_TREE;
3016 gimple_seq llist[2] = { NULL, NULL };
3018 copyin_seq = NULL;
3020 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3021 with data sharing clauses referencing variable sized vars. That
3022 is unnecessarily hard to support and very unlikely to result in
3023 vectorized code anyway. */
3024 if (is_simd)
3025 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3026 switch (OMP_CLAUSE_CODE (c))
3028 case OMP_CLAUSE_REDUCTION:
3029 case OMP_CLAUSE_PRIVATE:
3030 case OMP_CLAUSE_FIRSTPRIVATE:
3031 case OMP_CLAUSE_LASTPRIVATE:
3032 case OMP_CLAUSE_LINEAR:
3033 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3034 max_vf = 1;
3035 break;
3036 default:
3037 continue;
3040 /* Do all the fixed sized types in the first pass, and the variable sized
3041 types in the second pass. This makes sure that the scalar arguments to
3042 the variable sized types are processed before we use them in the
3043 variable sized operations. */
3044 for (pass = 0; pass < 2; ++pass)
3046 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3048 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3049 tree var, new_var;
3050 bool by_ref;
3051 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3053 switch (c_kind)
3055 case OMP_CLAUSE_PRIVATE:
3056 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3057 continue;
3058 break;
3059 case OMP_CLAUSE_SHARED:
3060 /* Ignore shared directives in teams construct. */
3061 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3062 continue;
3063 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3065 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3066 continue;
3068 case OMP_CLAUSE_FIRSTPRIVATE:
3069 case OMP_CLAUSE_COPYIN:
3070 case OMP_CLAUSE_LINEAR:
3071 break;
3072 case OMP_CLAUSE_REDUCTION:
3073 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3074 reduction_omp_orig_ref = true;
3075 break;
3076 case OMP_CLAUSE__LOOPTEMP_:
3077 /* Handle _looptemp_ clauses only on parallel. */
3078 if (fd)
3079 continue;
3080 break;
3081 case OMP_CLAUSE_LASTPRIVATE:
3082 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3084 lastprivate_firstprivate = true;
3085 if (pass != 0)
3086 continue;
3088 break;
3089 case OMP_CLAUSE_ALIGNED:
3090 if (pass == 0)
3091 continue;
3092 var = OMP_CLAUSE_DECL (c);
3093 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3094 && !is_global_var (var))
3096 new_var = maybe_lookup_decl (var, ctx);
3097 if (new_var == NULL_TREE)
3098 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3099 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3100 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3101 omp_clause_aligned_alignment (c));
3102 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3103 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3104 gimplify_and_add (x, ilist);
3106 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3107 && is_global_var (var))
3109 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3110 new_var = lookup_decl (var, ctx);
3111 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3112 t = build_fold_addr_expr_loc (clause_loc, t);
3113 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3114 t = build_call_expr_loc (clause_loc, t2, 2, t,
3115 omp_clause_aligned_alignment (c));
3116 t = fold_convert_loc (clause_loc, ptype, t);
3117 x = create_tmp_var (ptype, NULL);
3118 t = build2 (MODIFY_EXPR, ptype, x, t);
3119 gimplify_and_add (t, ilist);
3120 t = build_simple_mem_ref_loc (clause_loc, x);
3121 SET_DECL_VALUE_EXPR (new_var, t);
3122 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3124 continue;
3125 default:
3126 continue;
3129 new_var = var = OMP_CLAUSE_DECL (c);
3130 if (c_kind != OMP_CLAUSE_COPYIN)
3131 new_var = lookup_decl (var, ctx);
3133 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3135 if (pass != 0)
3136 continue;
3138 else if (is_variable_sized (var))
3140 /* For variable sized types, we need to allocate the
3141 actual storage here. Call alloca and store the
3142 result in the pointer decl that we created elsewhere. */
3143 if (pass == 0)
3144 continue;
3146 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3148 gimple stmt;
3149 tree tmp, atmp;
3151 ptr = DECL_VALUE_EXPR (new_var);
3152 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3153 ptr = TREE_OPERAND (ptr, 0);
3154 gcc_assert (DECL_P (ptr));
3155 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3157 /* void *tmp = __builtin_alloca */
3158 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3159 stmt = gimple_build_call (atmp, 1, x);
3160 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3161 gimple_add_tmp_var (tmp);
3162 gimple_call_set_lhs (stmt, tmp);
3164 gimple_seq_add_stmt (ilist, stmt);
3166 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3167 gimplify_assign (ptr, x, ilist);
3170 else if (is_reference (var))
3172 /* For references that are being privatized for Fortran,
3173 allocate new backing storage for the new pointer
3174 variable. This allows us to avoid changing all the
3175 code that expects a pointer to something that expects
3176 a direct variable. */
3177 if (pass == 0)
3178 continue;
3180 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3181 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3183 x = build_receiver_ref (var, false, ctx);
3184 x = build_fold_addr_expr_loc (clause_loc, x);
3186 else if (TREE_CONSTANT (x))
3188 const char *name = NULL;
3189 if (DECL_NAME (var))
3190 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3192 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3193 name);
3194 gimple_add_tmp_var (x);
3195 TREE_ADDRESSABLE (x) = 1;
3196 x = build_fold_addr_expr_loc (clause_loc, x);
3198 else
3200 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3201 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3204 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3205 gimplify_assign (new_var, x, ilist);
3207 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3209 else if (c_kind == OMP_CLAUSE_REDUCTION
3210 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3212 if (pass == 0)
3213 continue;
3215 else if (pass != 0)
3216 continue;
3218 switch (OMP_CLAUSE_CODE (c))
3220 case OMP_CLAUSE_SHARED:
3221 /* Ignore shared directives in teams construct. */
3222 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3223 continue;
3224 /* Shared global vars are just accessed directly. */
3225 if (is_global_var (new_var))
3226 break;
3227 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3228 needs to be delayed until after fixup_child_record_type so
3229 that we get the correct type during the dereference. */
3230 by_ref = use_pointer_for_field (var, ctx);
3231 x = build_receiver_ref (var, by_ref, ctx);
3232 SET_DECL_VALUE_EXPR (new_var, x);
3233 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3235 /* ??? If VAR is not passed by reference, and the variable
3236 hasn't been initialized yet, then we'll get a warning for
3237 the store into the omp_data_s structure. Ideally, we'd be
3238 able to notice this and not store anything at all, but
3239 we're generating code too early. Suppress the warning. */
3240 if (!by_ref)
3241 TREE_NO_WARNING (var) = 1;
3242 break;
3244 case OMP_CLAUSE_LASTPRIVATE:
3245 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3246 break;
3247 /* FALLTHRU */
3249 case OMP_CLAUSE_PRIVATE:
3250 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3251 x = build_outer_var_ref (var, ctx);
3252 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3254 if (is_task_ctx (ctx))
3255 x = build_receiver_ref (var, false, ctx);
3256 else
3257 x = build_outer_var_ref (var, ctx);
3259 else
3260 x = NULL;
3261 do_private:
3262 tree nx;
3263 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3264 if (is_simd)
3266 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3267 if ((TREE_ADDRESSABLE (new_var) || nx || y
3268 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3269 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3270 idx, lane, ivar, lvar))
3272 if (nx)
3273 x = lang_hooks.decls.omp_clause_default_ctor
3274 (c, unshare_expr (ivar), x);
3275 if (nx && x)
3276 gimplify_and_add (x, &llist[0]);
3277 if (y)
3279 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3280 if (y)
3282 gimple_seq tseq = NULL;
3284 dtor = y;
3285 gimplify_stmt (&dtor, &tseq);
3286 gimple_seq_add_seq (&llist[1], tseq);
3289 break;
3292 if (nx)
3293 gimplify_and_add (nx, ilist);
3294 /* FALLTHRU */
3296 do_dtor:
3297 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3298 if (x)
3300 gimple_seq tseq = NULL;
3302 dtor = x;
3303 gimplify_stmt (&dtor, &tseq);
3304 gimple_seq_add_seq (dlist, tseq);
3306 break;
3308 case OMP_CLAUSE_LINEAR:
3309 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3310 goto do_firstprivate;
3311 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3312 x = NULL;
3313 else
3314 x = build_outer_var_ref (var, ctx);
3315 goto do_private;
3317 case OMP_CLAUSE_FIRSTPRIVATE:
3318 if (is_task_ctx (ctx))
3320 if (is_reference (var) || is_variable_sized (var))
3321 goto do_dtor;
3322 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3323 ctx))
3324 || use_pointer_for_field (var, NULL))
3326 x = build_receiver_ref (var, false, ctx);
3327 SET_DECL_VALUE_EXPR (new_var, x);
3328 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3329 goto do_dtor;
3332 do_firstprivate:
3333 x = build_outer_var_ref (var, ctx);
3334 if (is_simd)
3336 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3337 && gimple_omp_for_combined_into_p (ctx->stmt))
3339 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3340 ? sizetype : TREE_TYPE (x);
3341 tree t = fold_convert (stept,
3342 OMP_CLAUSE_LINEAR_STEP (c));
3343 tree c = find_omp_clause (clauses,
3344 OMP_CLAUSE__LOOPTEMP_);
3345 gcc_assert (c);
3346 tree l = OMP_CLAUSE_DECL (c);
3347 if (fd->collapse == 1)
3349 tree n1 = fd->loop.n1;
3350 tree step = fd->loop.step;
3351 tree itype = TREE_TYPE (l);
3352 if (POINTER_TYPE_P (itype))
3353 itype = signed_type_for (itype);
3354 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3355 if (TYPE_UNSIGNED (itype)
3356 && fd->loop.cond_code == GT_EXPR)
3357 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3358 fold_build1 (NEGATE_EXPR,
3359 itype, l),
3360 fold_build1 (NEGATE_EXPR,
3361 itype, step));
3362 else
3363 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3365 t = fold_build2 (MULT_EXPR, stept,
3366 fold_convert (stept, l), t);
3367 if (POINTER_TYPE_P (TREE_TYPE (x)))
3368 x = fold_build2 (POINTER_PLUS_EXPR,
3369 TREE_TYPE (x), x, t);
3370 else
3371 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3374 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3375 || TREE_ADDRESSABLE (new_var))
3376 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3377 idx, lane, ivar, lvar))
3379 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3381 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3382 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3383 gimplify_and_add (x, ilist);
3384 gimple_stmt_iterator gsi
3385 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3386 gimple g
3387 = gimple_build_assign (unshare_expr (lvar), iv);
3388 gsi_insert_before_without_update (&gsi, g,
3389 GSI_SAME_STMT);
3390 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3391 ? sizetype : TREE_TYPE (x);
3392 tree t = fold_convert (stept,
3393 OMP_CLAUSE_LINEAR_STEP (c));
3394 enum tree_code code = PLUS_EXPR;
3395 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3396 code = POINTER_PLUS_EXPR;
3397 g = gimple_build_assign_with_ops (code, iv, iv, t);
3398 gsi_insert_before_without_update (&gsi, g,
3399 GSI_SAME_STMT);
3400 break;
3402 x = lang_hooks.decls.omp_clause_copy_ctor
3403 (c, unshare_expr (ivar), x);
3404 gimplify_and_add (x, &llist[0]);
3405 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3406 if (x)
3408 gimple_seq tseq = NULL;
3410 dtor = x;
3411 gimplify_stmt (&dtor, &tseq);
3412 gimple_seq_add_seq (&llist[1], tseq);
3414 break;
3417 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3418 gimplify_and_add (x, ilist);
3419 goto do_dtor;
3421 case OMP_CLAUSE__LOOPTEMP_:
3422 gcc_assert (is_parallel_ctx (ctx));
3423 x = build_outer_var_ref (var, ctx);
3424 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3425 gimplify_and_add (x, ilist);
3426 break;
3428 case OMP_CLAUSE_COPYIN:
3429 by_ref = use_pointer_for_field (var, NULL);
3430 x = build_receiver_ref (var, by_ref, ctx);
3431 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3432 append_to_statement_list (x, &copyin_seq);
3433 copyin_by_ref |= by_ref;
3434 break;
3436 case OMP_CLAUSE_REDUCTION:
3437 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3439 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3440 gimple tseq;
3441 x = build_outer_var_ref (var, ctx);
3443 if (is_reference (var)
3444 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3445 TREE_TYPE (x)))
3446 x = build_fold_addr_expr_loc (clause_loc, x);
3447 SET_DECL_VALUE_EXPR (placeholder, x);
3448 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3449 tree new_vard = new_var;
3450 if (is_reference (var))
3452 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3453 new_vard = TREE_OPERAND (new_var, 0);
3454 gcc_assert (DECL_P (new_vard));
3456 if (is_simd
3457 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3458 idx, lane, ivar, lvar))
3460 if (new_vard == new_var)
3462 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3463 SET_DECL_VALUE_EXPR (new_var, ivar);
3465 else
3467 SET_DECL_VALUE_EXPR (new_vard,
3468 build_fold_addr_expr (ivar));
3469 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3471 x = lang_hooks.decls.omp_clause_default_ctor
3472 (c, unshare_expr (ivar),
3473 build_outer_var_ref (var, ctx));
3474 if (x)
3475 gimplify_and_add (x, &llist[0]);
3476 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3478 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3479 lower_omp (&tseq, ctx);
3480 gimple_seq_add_seq (&llist[0], tseq);
3482 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3483 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3484 lower_omp (&tseq, ctx);
3485 gimple_seq_add_seq (&llist[1], tseq);
3486 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3487 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3488 if (new_vard == new_var)
3489 SET_DECL_VALUE_EXPR (new_var, lvar);
3490 else
3491 SET_DECL_VALUE_EXPR (new_vard,
3492 build_fold_addr_expr (lvar));
3493 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3494 if (x)
3496 tseq = NULL;
3497 dtor = x;
3498 gimplify_stmt (&dtor, &tseq);
3499 gimple_seq_add_seq (&llist[1], tseq);
3501 break;
3503 x = lang_hooks.decls.omp_clause_default_ctor
3504 (c, new_var, unshare_expr (x));
3505 if (x)
3506 gimplify_and_add (x, ilist);
3507 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3509 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3510 lower_omp (&tseq, ctx);
3511 gimple_seq_add_seq (ilist, tseq);
3513 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3514 if (is_simd)
3516 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3517 lower_omp (&tseq, ctx);
3518 gimple_seq_add_seq (dlist, tseq);
3519 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3521 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3522 goto do_dtor;
3524 else
3526 x = omp_reduction_init (c, TREE_TYPE (new_var));
3527 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3528 if (is_simd
3529 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3530 idx, lane, ivar, lvar))
3532 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3533 tree ref = build_outer_var_ref (var, ctx);
3535 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3537 /* reduction(-:var) sums up the partial results, so it
3538 acts identically to reduction(+:var). */
3539 if (code == MINUS_EXPR)
3540 code = PLUS_EXPR;
3542 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3543 ref = build_outer_var_ref (var, ctx);
3544 gimplify_assign (ref, x, &llist[1]);
3546 else
3548 gimplify_assign (new_var, x, ilist);
3549 if (is_simd)
3550 gimplify_assign (build_outer_var_ref (var, ctx),
3551 new_var, dlist);
3554 break;
3556 default:
3557 gcc_unreachable ();
3562 if (lane)
3564 tree uid = create_tmp_var (ptr_type_node, "simduid");
3565 /* Don't want uninit warnings on simduid, it is always uninitialized,
3566 but we use it not for the value, but for the DECL_UID only. */
3567 TREE_NO_WARNING (uid) = 1;
3568 gimple g
3569 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3570 gimple_call_set_lhs (g, lane);
3571 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3572 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3573 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3574 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3575 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3576 gimple_omp_for_set_clauses (ctx->stmt, c);
3577 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3578 build_int_cst (unsigned_type_node, 0),
3579 NULL_TREE);
3580 gimple_seq_add_stmt (ilist, g);
3581 for (int i = 0; i < 2; i++)
3582 if (llist[i])
3584 tree vf = create_tmp_var (unsigned_type_node, NULL);
3585 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3586 gimple_call_set_lhs (g, vf);
3587 gimple_seq *seq = i == 0 ? ilist : dlist;
3588 gimple_seq_add_stmt (seq, g);
3589 tree t = build_int_cst (unsigned_type_node, 0);
3590 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3591 gimple_seq_add_stmt (seq, g);
3592 tree body = create_artificial_label (UNKNOWN_LOCATION);
3593 tree header = create_artificial_label (UNKNOWN_LOCATION);
3594 tree end = create_artificial_label (UNKNOWN_LOCATION);
3595 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3596 gimple_seq_add_stmt (seq, gimple_build_label (body));
3597 gimple_seq_add_seq (seq, llist[i]);
3598 t = build_int_cst (unsigned_type_node, 1);
3599 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3600 gimple_seq_add_stmt (seq, g);
3601 gimple_seq_add_stmt (seq, gimple_build_label (header));
3602 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3603 gimple_seq_add_stmt (seq, g);
3604 gimple_seq_add_stmt (seq, gimple_build_label (end));
3608 /* The copyin sequence is not to be executed by the main thread, since
3609 that would result in self-copies. Perhaps not visible to scalars,
3610 but it certainly is to C++ operator=. */
3611 if (copyin_seq)
3613 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3615 x = build2 (NE_EXPR, boolean_type_node, x,
3616 build_int_cst (TREE_TYPE (x), 0));
3617 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3618 gimplify_and_add (x, ilist);
3621 /* If any copyin variable is passed by reference, we must ensure the
3622 master thread doesn't modify it before it is copied over in all
3623 threads. Similarly for variables in both firstprivate and
3624 lastprivate clauses we need to ensure the lastprivate copying
3625 happens after firstprivate copying in all threads. And similarly
3626 for UDRs if initializer expression refers to omp_orig. */
3627 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3629 /* Don't add any barrier for #pragma omp simd or
3630 #pragma omp distribute. */
3631 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3632 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3633 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3636 /* If max_vf is non-zero, then we can use only a vectorization factor
3637 up to the max_vf we chose. So stick it into the safelen clause. */
3638 if (max_vf)
3640 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3641 OMP_CLAUSE_SAFELEN);
3642 if (c == NULL_TREE
3643 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3644 max_vf) == 1)
3646 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3647 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3648 max_vf);
3649 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3650 gimple_omp_for_set_clauses (ctx->stmt, c);
3656 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3657 both parallel and workshare constructs. PREDICATE may be NULL if it's
3658 always true. */
3660 static void
3661 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3662 omp_context *ctx)
3664 tree x, c, label = NULL, orig_clauses = clauses;
3665 bool par_clauses = false;
3666 tree simduid = NULL, lastlane = NULL;
3668 /* Early exit if there are no lastprivate or linear clauses. */
3669 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3670 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3671 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3672 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3673 break;
3674 if (clauses == NULL)
3676 /* If this was a workshare clause, see if it had been combined
3677 with its parallel. In that case, look for the clauses on the
3678 parallel statement itself. */
3679 if (is_parallel_ctx (ctx))
3680 return;
3682 ctx = ctx->outer;
3683 if (ctx == NULL || !is_parallel_ctx (ctx))
3684 return;
3686 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3687 OMP_CLAUSE_LASTPRIVATE);
3688 if (clauses == NULL)
3689 return;
3690 par_clauses = true;
3693 if (predicate)
3695 gimple stmt;
3696 tree label_true, arm1, arm2;
3698 label = create_artificial_label (UNKNOWN_LOCATION);
3699 label_true = create_artificial_label (UNKNOWN_LOCATION);
3700 arm1 = TREE_OPERAND (predicate, 0);
3701 arm2 = TREE_OPERAND (predicate, 1);
3702 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3703 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3704 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3705 label_true, label);
3706 gimple_seq_add_stmt (stmt_list, stmt);
3707 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3710 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3711 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3713 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3714 if (simduid)
3715 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3718 for (c = clauses; c ;)
3720 tree var, new_var;
3721 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3723 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3724 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3725 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3727 var = OMP_CLAUSE_DECL (c);
3728 new_var = lookup_decl (var, ctx);
3730 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3732 tree val = DECL_VALUE_EXPR (new_var);
3733 if (TREE_CODE (val) == ARRAY_REF
3734 && VAR_P (TREE_OPERAND (val, 0))
3735 && lookup_attribute ("omp simd array",
3736 DECL_ATTRIBUTES (TREE_OPERAND (val,
3737 0))))
3739 if (lastlane == NULL)
3741 lastlane = create_tmp_var (unsigned_type_node, NULL);
3742 gimple g
3743 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3744 2, simduid,
3745 TREE_OPERAND (val, 1));
3746 gimple_call_set_lhs (g, lastlane);
3747 gimple_seq_add_stmt (stmt_list, g);
3749 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3750 TREE_OPERAND (val, 0), lastlane,
3751 NULL_TREE, NULL_TREE);
3755 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3756 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3758 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3759 gimple_seq_add_seq (stmt_list,
3760 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3761 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3764 x = build_outer_var_ref (var, ctx);
3765 if (is_reference (var))
3766 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3767 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3768 gimplify_and_add (x, stmt_list);
3770 c = OMP_CLAUSE_CHAIN (c);
3771 if (c == NULL && !par_clauses)
3773 /* If this was a workshare clause, see if it had been combined
3774 with its parallel. In that case, continue looking for the
3775 clauses also on the parallel statement itself. */
3776 if (is_parallel_ctx (ctx))
3777 break;
3779 ctx = ctx->outer;
3780 if (ctx == NULL || !is_parallel_ctx (ctx))
3781 break;
3783 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3784 OMP_CLAUSE_LASTPRIVATE);
3785 par_clauses = true;
3789 if (label)
3790 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3794 /* Generate code to implement the REDUCTION clauses. */
3796 static void
3797 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3799 gimple_seq sub_seq = NULL;
3800 gimple stmt;
3801 tree x, c;
3802 int count = 0;
3804 /* SIMD reductions are handled in lower_rec_input_clauses. */
3805 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3806 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3807 return;
3809 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3810 update in that case, otherwise use a lock. */
3811 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3812 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3814 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3816 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3817 count = -1;
3818 break;
3820 count++;
3823 if (count == 0)
3824 return;
3826 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3828 tree var, ref, new_var;
3829 enum tree_code code;
3830 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3832 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3833 continue;
3835 var = OMP_CLAUSE_DECL (c);
3836 new_var = lookup_decl (var, ctx);
3837 if (is_reference (var))
3838 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3839 ref = build_outer_var_ref (var, ctx);
3840 code = OMP_CLAUSE_REDUCTION_CODE (c);
3842 /* reduction(-:var) sums up the partial results, so it acts
3843 identically to reduction(+:var). */
3844 if (code == MINUS_EXPR)
3845 code = PLUS_EXPR;
3847 if (count == 1)
3849 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3851 addr = save_expr (addr);
3852 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3853 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3854 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3855 gimplify_and_add (x, stmt_seqp);
3856 return;
3859 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3861 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3863 if (is_reference (var)
3864 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3865 TREE_TYPE (ref)))
3866 ref = build_fold_addr_expr_loc (clause_loc, ref);
3867 SET_DECL_VALUE_EXPR (placeholder, ref);
3868 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3869 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3870 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3871 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3872 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3874 else
3876 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3877 ref = build_outer_var_ref (var, ctx);
3878 gimplify_assign (ref, x, &sub_seq);
3882 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3884 gimple_seq_add_stmt (stmt_seqp, stmt);
3886 gimple_seq_add_seq (stmt_seqp, sub_seq);
3888 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3890 gimple_seq_add_stmt (stmt_seqp, stmt);
3894 /* Generate code to implement the COPYPRIVATE clauses. */
3896 static void
3897 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3898 omp_context *ctx)
3900 tree c;
3902 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3904 tree var, new_var, ref, x;
3905 bool by_ref;
3906 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3908 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3909 continue;
3911 var = OMP_CLAUSE_DECL (c);
3912 by_ref = use_pointer_for_field (var, NULL);
3914 ref = build_sender_ref (var, ctx);
3915 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3916 if (by_ref)
3918 x = build_fold_addr_expr_loc (clause_loc, new_var);
3919 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3921 gimplify_assign (ref, x, slist);
3923 ref = build_receiver_ref (var, false, ctx);
3924 if (by_ref)
3926 ref = fold_convert_loc (clause_loc,
3927 build_pointer_type (TREE_TYPE (new_var)),
3928 ref);
3929 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3931 if (is_reference (var))
3933 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3934 ref = build_simple_mem_ref_loc (clause_loc, ref);
3935 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3937 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3938 gimplify_and_add (x, rlist);
3943 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3944 and REDUCTION from the sender (aka parent) side. */
3946 static void
3947 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3948 omp_context *ctx)
3950 tree c;
3952 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3954 tree val, ref, x, var;
3955 bool by_ref, do_in = false, do_out = false;
3956 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3958 switch (OMP_CLAUSE_CODE (c))
3960 case OMP_CLAUSE_PRIVATE:
3961 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3962 break;
3963 continue;
3964 case OMP_CLAUSE_FIRSTPRIVATE:
3965 case OMP_CLAUSE_COPYIN:
3966 case OMP_CLAUSE_LASTPRIVATE:
3967 case OMP_CLAUSE_REDUCTION:
3968 case OMP_CLAUSE__LOOPTEMP_:
3969 break;
3970 default:
3971 continue;
3974 val = OMP_CLAUSE_DECL (c);
3975 var = lookup_decl_in_outer_ctx (val, ctx);
3977 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
3978 && is_global_var (var))
3979 continue;
3980 if (is_variable_sized (val))
3981 continue;
3982 by_ref = use_pointer_for_field (val, NULL);
3984 switch (OMP_CLAUSE_CODE (c))
3986 case OMP_CLAUSE_PRIVATE:
3987 case OMP_CLAUSE_FIRSTPRIVATE:
3988 case OMP_CLAUSE_COPYIN:
3989 case OMP_CLAUSE__LOOPTEMP_:
3990 do_in = true;
3991 break;
3993 case OMP_CLAUSE_LASTPRIVATE:
3994 if (by_ref || is_reference (val))
3996 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3997 continue;
3998 do_in = true;
4000 else
4002 do_out = true;
4003 if (lang_hooks.decls.omp_private_outer_ref (val))
4004 do_in = true;
4006 break;
4008 case OMP_CLAUSE_REDUCTION:
4009 do_in = true;
4010 do_out = !(by_ref || is_reference (val));
4011 break;
4013 default:
4014 gcc_unreachable ();
4017 if (do_in)
4019 ref = build_sender_ref (val, ctx);
4020 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4021 gimplify_assign (ref, x, ilist);
4022 if (is_task_ctx (ctx))
4023 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4026 if (do_out)
4028 ref = build_sender_ref (val, ctx);
4029 gimplify_assign (var, ref, olist);
4034 /* Generate code to implement SHARED from the sender (aka parent)
4035 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4036 list things that got automatically shared. */
4038 static void
4039 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4041 tree var, ovar, nvar, f, x, record_type;
4043 if (ctx->record_type == NULL)
4044 return;
4046 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4047 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4049 ovar = DECL_ABSTRACT_ORIGIN (f);
4050 nvar = maybe_lookup_decl (ovar, ctx);
4051 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4052 continue;
4054 /* If CTX is a nested parallel directive. Find the immediately
4055 enclosing parallel or workshare construct that contains a
4056 mapping for OVAR. */
4057 var = lookup_decl_in_outer_ctx (ovar, ctx);
4059 if (use_pointer_for_field (ovar, ctx))
4061 x = build_sender_ref (ovar, ctx);
4062 var = build_fold_addr_expr (var);
4063 gimplify_assign (x, var, ilist);
4065 else
4067 x = build_sender_ref (ovar, ctx);
4068 gimplify_assign (x, var, ilist);
4070 if (!TREE_READONLY (var)
4071 /* We don't need to receive a new reference to a result
4072 or parm decl. In fact we may not store to it as we will
4073 invalidate any pending RSO and generate wrong gimple
4074 during inlining. */
4075 && !((TREE_CODE (var) == RESULT_DECL
4076 || TREE_CODE (var) == PARM_DECL)
4077 && DECL_BY_REFERENCE (var)))
4079 x = build_sender_ref (ovar, ctx);
4080 gimplify_assign (var, x, olist);
4087 /* A convenience function to build an empty GIMPLE_COND with just the
4088 condition. */
4090 static gimple
4091 gimple_build_cond_empty (tree cond)
4093 enum tree_code pred_code;
4094 tree lhs, rhs;
4096 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4097 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4101 /* Build the function calls to GOMP_parallel_start etc to actually
4102 generate the parallel operation. REGION is the parallel region
4103 being expanded. BB is the block where to insert the code. WS_ARGS
4104 will be set if this is a call to a combined parallel+workshare
4105 construct, it contains the list of additional arguments needed by
4106 the workshare construct. */
4108 static void
4109 expand_parallel_call (struct omp_region *region, basic_block bb,
4110 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4112 tree t, t1, t2, val, cond, c, clauses, flags;
4113 gimple_stmt_iterator gsi;
4114 gimple stmt;
4115 enum built_in_function start_ix;
4116 int start_ix2;
4117 location_t clause_loc;
4118 vec<tree, va_gc> *args;
4120 clauses = gimple_omp_parallel_clauses (entry_stmt);
4122 /* Determine what flavor of GOMP_parallel we will be
4123 emitting. */
4124 start_ix = BUILT_IN_GOMP_PARALLEL;
4125 if (is_combined_parallel (region))
4127 switch (region->inner->type)
4129 case GIMPLE_OMP_FOR:
4130 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4131 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4132 + (region->inner->sched_kind
4133 == OMP_CLAUSE_SCHEDULE_RUNTIME
4134 ? 3 : region->inner->sched_kind));
4135 start_ix = (enum built_in_function)start_ix2;
4136 break;
4137 case GIMPLE_OMP_SECTIONS:
4138 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4139 break;
4140 default:
4141 gcc_unreachable ();
4145 /* By default, the value of NUM_THREADS is zero (selected at run time)
4146 and there is no conditional. */
4147 cond = NULL_TREE;
4148 val = build_int_cst (unsigned_type_node, 0);
4149 flags = build_int_cst (unsigned_type_node, 0);
4151 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4152 if (c)
4153 cond = OMP_CLAUSE_IF_EXPR (c);
4155 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4156 if (c)
4158 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4159 clause_loc = OMP_CLAUSE_LOCATION (c);
4161 else
4162 clause_loc = gimple_location (entry_stmt);
4164 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4165 if (c)
4166 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4168 /* Ensure 'val' is of the correct type. */
4169 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4171 /* If we found the clause 'if (cond)', build either
4172 (cond != 0) or (cond ? val : 1u). */
4173 if (cond)
4175 gimple_stmt_iterator gsi;
4177 cond = gimple_boolify (cond);
4179 if (integer_zerop (val))
4180 val = fold_build2_loc (clause_loc,
4181 EQ_EXPR, unsigned_type_node, cond,
4182 build_int_cst (TREE_TYPE (cond), 0));
4183 else
4185 basic_block cond_bb, then_bb, else_bb;
4186 edge e, e_then, e_else;
4187 tree tmp_then, tmp_else, tmp_join, tmp_var;
4189 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4190 if (gimple_in_ssa_p (cfun))
4192 tmp_then = make_ssa_name (tmp_var, NULL);
4193 tmp_else = make_ssa_name (tmp_var, NULL);
4194 tmp_join = make_ssa_name (tmp_var, NULL);
4196 else
4198 tmp_then = tmp_var;
4199 tmp_else = tmp_var;
4200 tmp_join = tmp_var;
4203 e = split_block (bb, NULL);
4204 cond_bb = e->src;
4205 bb = e->dest;
4206 remove_edge (e);
4208 then_bb = create_empty_bb (cond_bb);
4209 else_bb = create_empty_bb (then_bb);
4210 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4211 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4213 stmt = gimple_build_cond_empty (cond);
4214 gsi = gsi_start_bb (cond_bb);
4215 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4217 gsi = gsi_start_bb (then_bb);
4218 stmt = gimple_build_assign (tmp_then, val);
4219 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4221 gsi = gsi_start_bb (else_bb);
4222 stmt = gimple_build_assign
4223 (tmp_else, build_int_cst (unsigned_type_node, 1));
4224 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4226 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4227 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4228 if (current_loops)
4230 add_bb_to_loop (then_bb, cond_bb->loop_father);
4231 add_bb_to_loop (else_bb, cond_bb->loop_father);
4233 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4234 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4236 if (gimple_in_ssa_p (cfun))
4238 gimple phi = create_phi_node (tmp_join, bb);
4239 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4240 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4243 val = tmp_join;
4246 gsi = gsi_start_bb (bb);
4247 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4248 false, GSI_CONTINUE_LINKING);
4251 gsi = gsi_last_bb (bb);
4252 t = gimple_omp_parallel_data_arg (entry_stmt);
4253 if (t == NULL)
4254 t1 = null_pointer_node;
4255 else
4256 t1 = build_fold_addr_expr (t);
4257 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4259 vec_alloc (args, 4 + vec_safe_length (ws_args));
4260 args->quick_push (t2);
4261 args->quick_push (t1);
4262 args->quick_push (val);
4263 if (ws_args)
4264 args->splice (*ws_args);
4265 args->quick_push (flags);
4267 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4268 builtin_decl_explicit (start_ix), args);
4270 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4271 false, GSI_CONTINUE_LINKING);
4275 /* Build the function call to GOMP_task to actually
4276 generate the task operation. BB is the block where to insert the code. */
4278 static void
4279 expand_task_call (basic_block bb, gimple entry_stmt)
4281 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4282 gimple_stmt_iterator gsi;
4283 location_t loc = gimple_location (entry_stmt);
4285 clauses = gimple_omp_task_clauses (entry_stmt);
4287 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4288 if (c)
4289 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4290 else
4291 cond = boolean_true_node;
4293 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4294 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4295 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4296 flags = build_int_cst (unsigned_type_node,
4297 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4299 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4300 if (c)
4302 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4303 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4304 build_int_cst (unsigned_type_node, 2),
4305 build_int_cst (unsigned_type_node, 0));
4306 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4308 if (depend)
4309 depend = OMP_CLAUSE_DECL (depend);
4310 else
4311 depend = build_int_cst (ptr_type_node, 0);
4313 gsi = gsi_last_bb (bb);
4314 t = gimple_omp_task_data_arg (entry_stmt);
4315 if (t == NULL)
4316 t2 = null_pointer_node;
4317 else
4318 t2 = build_fold_addr_expr_loc (loc, t);
4319 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4320 t = gimple_omp_task_copy_fn (entry_stmt);
4321 if (t == NULL)
4322 t3 = null_pointer_node;
4323 else
4324 t3 = build_fold_addr_expr_loc (loc, t);
4326 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4327 8, t1, t2, t3,
4328 gimple_omp_task_arg_size (entry_stmt),
4329 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4330 depend);
4332 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4333 false, GSI_CONTINUE_LINKING);
4337 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4338 catch handler and return it. This prevents programs from violating the
4339 structured block semantics with throws. */
4341 static gimple_seq
4342 maybe_catch_exception (gimple_seq body)
4344 gimple g;
4345 tree decl;
4347 if (!flag_exceptions)
4348 return body;
4350 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4351 decl = lang_hooks.eh_protect_cleanup_actions ();
4352 else
4353 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4355 g = gimple_build_eh_must_not_throw (decl);
4356 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4357 GIMPLE_TRY_CATCH);
4359 return gimple_seq_alloc_with_stmt (g);
4362 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4364 static tree
4365 vec2chain (vec<tree, va_gc> *v)
4367 tree chain = NULL_TREE, t;
4368 unsigned ix;
4370 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4372 DECL_CHAIN (t) = chain;
4373 chain = t;
4376 return chain;
4380 /* Remove barriers in REGION->EXIT's block. Note that this is only
4381 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4382 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4383 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4384 removed. */
4386 static void
4387 remove_exit_barrier (struct omp_region *region)
4389 gimple_stmt_iterator gsi;
4390 basic_block exit_bb;
4391 edge_iterator ei;
4392 edge e;
4393 gimple stmt;
4394 int any_addressable_vars = -1;
4396 exit_bb = region->exit;
4398 /* If the parallel region doesn't return, we don't have REGION->EXIT
4399 block at all. */
4400 if (! exit_bb)
4401 return;
4403 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4404 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4405 statements that can appear in between are extremely limited -- no
4406 memory operations at all. Here, we allow nothing at all, so the
4407 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4408 gsi = gsi_last_bb (exit_bb);
4409 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4410 gsi_prev (&gsi);
4411 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4412 return;
4414 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4416 gsi = gsi_last_bb (e->src);
4417 if (gsi_end_p (gsi))
4418 continue;
4419 stmt = gsi_stmt (gsi);
4420 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4421 && !gimple_omp_return_nowait_p (stmt))
4423 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4424 in many cases. If there could be tasks queued, the barrier
4425 might be needed to let the tasks run before some local
4426 variable of the parallel that the task uses as shared
4427 runs out of scope. The task can be spawned either
4428 from within current function (this would be easy to check)
4429 or from some function it calls and gets passed an address
4430 of such a variable. */
4431 if (any_addressable_vars < 0)
4433 gimple parallel_stmt = last_stmt (region->entry);
4434 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4435 tree local_decls, block, decl;
4436 unsigned ix;
4438 any_addressable_vars = 0;
4439 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4440 if (TREE_ADDRESSABLE (decl))
4442 any_addressable_vars = 1;
4443 break;
4445 for (block = gimple_block (stmt);
4446 !any_addressable_vars
4447 && block
4448 && TREE_CODE (block) == BLOCK;
4449 block = BLOCK_SUPERCONTEXT (block))
4451 for (local_decls = BLOCK_VARS (block);
4452 local_decls;
4453 local_decls = DECL_CHAIN (local_decls))
4454 if (TREE_ADDRESSABLE (local_decls))
4456 any_addressable_vars = 1;
4457 break;
4459 if (block == gimple_block (parallel_stmt))
4460 break;
4463 if (!any_addressable_vars)
4464 gimple_omp_return_set_nowait (stmt);
4469 static void
4470 remove_exit_barriers (struct omp_region *region)
4472 if (region->type == GIMPLE_OMP_PARALLEL)
4473 remove_exit_barrier (region);
4475 if (region->inner)
4477 region = region->inner;
4478 remove_exit_barriers (region);
4479 while (region->next)
4481 region = region->next;
4482 remove_exit_barriers (region);
4487 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4488 calls. These can't be declared as const functions, but
4489 within one parallel body they are constant, so they can be
4490 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4491 which are declared const. Similarly for task body, except
4492 that in untied task omp_get_thread_num () can change at any task
4493 scheduling point. */
4495 static void
4496 optimize_omp_library_calls (gimple entry_stmt)
4498 basic_block bb;
4499 gimple_stmt_iterator gsi;
4500 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4501 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4502 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4503 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4504 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4505 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4506 OMP_CLAUSE_UNTIED) != NULL);
4508 FOR_EACH_BB (bb)
4509 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4511 gimple call = gsi_stmt (gsi);
4512 tree decl;
4514 if (is_gimple_call (call)
4515 && (decl = gimple_call_fndecl (call))
4516 && DECL_EXTERNAL (decl)
4517 && TREE_PUBLIC (decl)
4518 && DECL_INITIAL (decl) == NULL)
4520 tree built_in;
4522 if (DECL_NAME (decl) == thr_num_id)
4524 /* In #pragma omp task untied omp_get_thread_num () can change
4525 during the execution of the task region. */
4526 if (untied_task)
4527 continue;
4528 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4530 else if (DECL_NAME (decl) == num_thr_id)
4531 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4532 else
4533 continue;
4535 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4536 || gimple_call_num_args (call) != 0)
4537 continue;
4539 if (flag_exceptions && !TREE_NOTHROW (decl))
4540 continue;
4542 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4543 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4544 TREE_TYPE (TREE_TYPE (built_in))))
4545 continue;
4547 gimple_call_set_fndecl (call, built_in);
4552 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4553 regimplified. */
4555 static tree
4556 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4558 tree t = *tp;
4560 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4561 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4562 return t;
4564 if (TREE_CODE (t) == ADDR_EXPR)
4565 recompute_tree_invariant_for_addr_expr (t);
4567 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4568 return NULL_TREE;
4571 /* Prepend TO = FROM assignment before *GSI_P. */
4573 static void
4574 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4576 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4577 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4578 true, GSI_SAME_STMT);
4579 gimple stmt = gimple_build_assign (to, from);
4580 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4581 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4582 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4584 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4585 gimple_regimplify_operands (stmt, &gsi);
4589 /* Expand the OpenMP parallel or task directive starting at REGION. */
4591 static void
4592 expand_omp_taskreg (struct omp_region *region)
4594 basic_block entry_bb, exit_bb, new_bb;
4595 struct function *child_cfun;
4596 tree child_fn, block, t;
4597 gimple_stmt_iterator gsi;
4598 gimple entry_stmt, stmt;
4599 edge e;
4600 vec<tree, va_gc> *ws_args;
4602 entry_stmt = last_stmt (region->entry);
4603 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4604 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4606 entry_bb = region->entry;
4607 exit_bb = region->exit;
4609 if (is_combined_parallel (region))
4610 ws_args = region->ws_args;
4611 else
4612 ws_args = NULL;
4614 if (child_cfun->cfg)
4616 /* Due to inlining, it may happen that we have already outlined
4617 the region, in which case all we need to do is make the
4618 sub-graph unreachable and emit the parallel call. */
4619 edge entry_succ_e, exit_succ_e;
4620 gimple_stmt_iterator gsi;
4622 entry_succ_e = single_succ_edge (entry_bb);
4624 gsi = gsi_last_bb (entry_bb);
4625 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4626 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4627 gsi_remove (&gsi, true);
4629 new_bb = entry_bb;
4630 if (exit_bb)
4632 exit_succ_e = single_succ_edge (exit_bb);
4633 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4635 remove_edge_and_dominated_blocks (entry_succ_e);
4637 else
4639 unsigned srcidx, dstidx, num;
4641 /* If the parallel region needs data sent from the parent
4642 function, then the very first statement (except possible
4643 tree profile counter updates) of the parallel body
4644 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4645 &.OMP_DATA_O is passed as an argument to the child function,
4646 we need to replace it with the argument as seen by the child
4647 function.
4649 In most cases, this will end up being the identity assignment
4650 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4651 a function call that has been inlined, the original PARM_DECL
4652 .OMP_DATA_I may have been converted into a different local
4653 variable. In which case, we need to keep the assignment. */
4654 if (gimple_omp_taskreg_data_arg (entry_stmt))
4656 basic_block entry_succ_bb = single_succ (entry_bb);
4657 gimple_stmt_iterator gsi;
4658 tree arg, narg;
4659 gimple parcopy_stmt = NULL;
4661 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4663 gimple stmt;
4665 gcc_assert (!gsi_end_p (gsi));
4666 stmt = gsi_stmt (gsi);
4667 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4668 continue;
4670 if (gimple_num_ops (stmt) == 2)
4672 tree arg = gimple_assign_rhs1 (stmt);
4674 /* We're ignore the subcode because we're
4675 effectively doing a STRIP_NOPS. */
4677 if (TREE_CODE (arg) == ADDR_EXPR
4678 && TREE_OPERAND (arg, 0)
4679 == gimple_omp_taskreg_data_arg (entry_stmt))
4681 parcopy_stmt = stmt;
4682 break;
4687 gcc_assert (parcopy_stmt != NULL);
4688 arg = DECL_ARGUMENTS (child_fn);
4690 if (!gimple_in_ssa_p (cfun))
4692 if (gimple_assign_lhs (parcopy_stmt) == arg)
4693 gsi_remove (&gsi, true);
4694 else
4696 /* ?? Is setting the subcode really necessary ?? */
4697 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4698 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4701 else
4703 /* If we are in ssa form, we must load the value from the default
4704 definition of the argument. That should not be defined now,
4705 since the argument is not used uninitialized. */
4706 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4707 narg = make_ssa_name (arg, gimple_build_nop ());
4708 set_ssa_default_def (cfun, arg, narg);
4709 /* ?? Is setting the subcode really necessary ?? */
4710 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4711 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4712 update_stmt (parcopy_stmt);
4716 /* Declare local variables needed in CHILD_CFUN. */
4717 block = DECL_INITIAL (child_fn);
4718 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4719 /* The gimplifier could record temporaries in parallel/task block
4720 rather than in containing function's local_decls chain,
4721 which would mean cgraph missed finalizing them. Do it now. */
4722 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4723 if (TREE_CODE (t) == VAR_DECL
4724 && TREE_STATIC (t)
4725 && !DECL_EXTERNAL (t))
4726 varpool_finalize_decl (t);
4727 DECL_SAVED_TREE (child_fn) = NULL;
4728 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4729 gimple_set_body (child_fn, NULL);
4730 TREE_USED (block) = 1;
4732 /* Reset DECL_CONTEXT on function arguments. */
4733 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4734 DECL_CONTEXT (t) = child_fn;
4736 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4737 so that it can be moved to the child function. */
4738 gsi = gsi_last_bb (entry_bb);
4739 stmt = gsi_stmt (gsi);
4740 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4741 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4742 gsi_remove (&gsi, true);
4743 e = split_block (entry_bb, stmt);
4744 entry_bb = e->dest;
4745 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4747 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4748 if (exit_bb)
4750 gsi = gsi_last_bb (exit_bb);
4751 gcc_assert (!gsi_end_p (gsi)
4752 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4753 stmt = gimple_build_return (NULL);
4754 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4755 gsi_remove (&gsi, true);
4758 /* Move the parallel region into CHILD_CFUN. */
4760 if (gimple_in_ssa_p (cfun))
4762 init_tree_ssa (child_cfun);
4763 init_ssa_operands (child_cfun);
4764 child_cfun->gimple_df->in_ssa_p = true;
4765 block = NULL_TREE;
4767 else
4768 block = gimple_block (entry_stmt);
4770 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4771 if (exit_bb)
4772 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4773 /* When the OMP expansion process cannot guarantee an up-to-date
4774 loop tree arrange for the child function to fixup loops. */
4775 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4776 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4778 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4779 num = vec_safe_length (child_cfun->local_decls);
4780 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4782 t = (*child_cfun->local_decls)[srcidx];
4783 if (DECL_CONTEXT (t) == cfun->decl)
4784 continue;
4785 if (srcidx != dstidx)
4786 (*child_cfun->local_decls)[dstidx] = t;
4787 dstidx++;
4789 if (dstidx != num)
4790 vec_safe_truncate (child_cfun->local_decls, dstidx);
4792 /* Inform the callgraph about the new function. */
4793 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4794 cgraph_add_new_function (child_fn, true);
4796 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4797 fixed in a following pass. */
4798 push_cfun (child_cfun);
4799 if (optimize)
4800 optimize_omp_library_calls (entry_stmt);
4801 rebuild_cgraph_edges ();
4803 /* Some EH regions might become dead, see PR34608. If
4804 pass_cleanup_cfg isn't the first pass to happen with the
4805 new child, these dead EH edges might cause problems.
4806 Clean them up now. */
4807 if (flag_exceptions)
4809 basic_block bb;
4810 bool changed = false;
4812 FOR_EACH_BB (bb)
4813 changed |= gimple_purge_dead_eh_edges (bb);
4814 if (changed)
4815 cleanup_tree_cfg ();
4817 if (gimple_in_ssa_p (cfun))
4818 update_ssa (TODO_update_ssa);
4819 pop_cfun ();
4822 /* Emit a library call to launch the children threads. */
4823 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4824 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4825 else
4826 expand_task_call (new_bb, entry_stmt);
4827 if (gimple_in_ssa_p (cfun))
4828 update_ssa (TODO_update_ssa_only_virtuals);
4832 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4833 of the combined collapse > 1 loop constructs, generate code like:
4834 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4835 if (cond3 is <)
4836 adj = STEP3 - 1;
4837 else
4838 adj = STEP3 + 1;
4839 count3 = (adj + N32 - N31) / STEP3;
4840 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4841 if (cond2 is <)
4842 adj = STEP2 - 1;
4843 else
4844 adj = STEP2 + 1;
4845 count2 = (adj + N22 - N21) / STEP2;
4846 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4847 if (cond1 is <)
4848 adj = STEP1 - 1;
4849 else
4850 adj = STEP1 + 1;
4851 count1 = (adj + N12 - N11) / STEP1;
4852 count = count1 * count2 * count3;
4853 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4854 count = 0;
4855 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4856 of the combined loop constructs, just initialize COUNTS array
4857 from the _looptemp_ clauses. */
4859 /* NOTE: It *could* be better to moosh all of the BBs together,
4860 creating one larger BB with all the computation and the unexpected
4861 jump at the end. I.e.
4863 bool zero3, zero2, zero1, zero;
4865 zero3 = N32 c3 N31;
4866 count3 = (N32 - N31) /[cl] STEP3;
4867 zero2 = N22 c2 N21;
4868 count2 = (N22 - N21) /[cl] STEP2;
4869 zero1 = N12 c1 N11;
4870 count1 = (N12 - N11) /[cl] STEP1;
4871 zero = zero3 || zero2 || zero1;
4872 count = count1 * count2 * count3;
4873 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4875 After all, we expect the zero=false, and thus we expect to have to
4876 evaluate all of the comparison expressions, so short-circuiting
4877 oughtn't be a win. Since the condition isn't protecting a
4878 denominator, we're not concerned about divide-by-zero, so we can
4879 fully evaluate count even if a numerator turned out to be wrong.
4881 It seems like putting this all together would create much better
4882 scheduling opportunities, and less pressure on the chip's branch
4883 predictor. */
4885 static void
4886 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4887 basic_block &entry_bb, tree *counts,
4888 basic_block &zero_iter_bb, int &first_zero_iter,
4889 basic_block &l2_dom_bb)
4891 tree t, type = TREE_TYPE (fd->loop.v);
4892 gimple stmt;
4893 edge e, ne;
4894 int i;
4896 /* Collapsed loops need work for expansion into SSA form. */
4897 gcc_assert (!gimple_in_ssa_p (cfun));
4899 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4900 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4902 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4903 isn't supposed to be handled, as the inner loop doesn't
4904 use it. */
4905 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4906 OMP_CLAUSE__LOOPTEMP_);
4907 gcc_assert (innerc);
4908 for (i = 0; i < fd->collapse; i++)
4910 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4911 OMP_CLAUSE__LOOPTEMP_);
4912 gcc_assert (innerc);
4913 if (i)
4914 counts[i] = OMP_CLAUSE_DECL (innerc);
4915 else
4916 counts[0] = NULL_TREE;
4918 return;
4921 for (i = 0; i < fd->collapse; i++)
4923 tree itype = TREE_TYPE (fd->loops[i].v);
4925 if (SSA_VAR_P (fd->loop.n2)
4926 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4927 fold_convert (itype, fd->loops[i].n1),
4928 fold_convert (itype, fd->loops[i].n2)))
4929 == NULL_TREE || !integer_onep (t)))
4931 tree n1, n2;
4932 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4933 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4934 true, GSI_SAME_STMT);
4935 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4936 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4937 true, GSI_SAME_STMT);
4938 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4939 NULL_TREE, NULL_TREE);
4940 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4941 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4942 expand_omp_regimplify_p, NULL, NULL)
4943 || walk_tree (gimple_cond_rhs_ptr (stmt),
4944 expand_omp_regimplify_p, NULL, NULL))
4946 *gsi = gsi_for_stmt (stmt);
4947 gimple_regimplify_operands (stmt, gsi);
4949 e = split_block (entry_bb, stmt);
4950 if (zero_iter_bb == NULL)
4952 first_zero_iter = i;
4953 zero_iter_bb = create_empty_bb (entry_bb);
4954 if (current_loops)
4955 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4956 *gsi = gsi_after_labels (zero_iter_bb);
4957 stmt = gimple_build_assign (fd->loop.n2,
4958 build_zero_cst (type));
4959 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4960 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
4961 entry_bb);
4963 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
4964 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
4965 e->flags = EDGE_TRUE_VALUE;
4966 e->probability = REG_BR_PROB_BASE - ne->probability;
4967 if (l2_dom_bb == NULL)
4968 l2_dom_bb = entry_bb;
4969 entry_bb = e->dest;
4970 *gsi = gsi_last_bb (entry_bb);
4973 if (POINTER_TYPE_P (itype))
4974 itype = signed_type_for (itype);
4975 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
4976 ? -1 : 1));
4977 t = fold_build2 (PLUS_EXPR, itype,
4978 fold_convert (itype, fd->loops[i].step), t);
4979 t = fold_build2 (PLUS_EXPR, itype, t,
4980 fold_convert (itype, fd->loops[i].n2));
4981 t = fold_build2 (MINUS_EXPR, itype, t,
4982 fold_convert (itype, fd->loops[i].n1));
4983 /* ?? We could probably use CEIL_DIV_EXPR instead of
4984 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4985 generate the same code in the end because generically we
4986 don't know that the values involved must be negative for
4987 GT?? */
4988 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
4989 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4990 fold_build1 (NEGATE_EXPR, itype, t),
4991 fold_build1 (NEGATE_EXPR, itype,
4992 fold_convert (itype,
4993 fd->loops[i].step)));
4994 else
4995 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
4996 fold_convert (itype, fd->loops[i].step));
4997 t = fold_convert (type, t);
4998 if (TREE_CODE (t) == INTEGER_CST)
4999 counts[i] = t;
5000 else
5002 counts[i] = create_tmp_reg (type, ".count");
5003 expand_omp_build_assign (gsi, counts[i], t);
5005 if (SSA_VAR_P (fd->loop.n2))
5007 if (i == 0)
5008 t = counts[0];
5009 else
5010 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5011 expand_omp_build_assign (gsi, fd->loop.n2, t);
5017 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5018 T = V;
5019 V3 = N31 + (T % count3) * STEP3;
5020 T = T / count3;
5021 V2 = N21 + (T % count2) * STEP2;
5022 T = T / count2;
5023 V1 = N11 + T * STEP1;
5024 if this loop doesn't have an inner loop construct combined with it.
5025 If it does have an inner loop construct combined with it and the
5026 iteration count isn't known constant, store values from counts array
5027 into its _looptemp_ temporaries instead. */
5029 static void
5030 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5031 tree *counts, gimple inner_stmt, tree startvar)
5033 int i;
5034 if (gimple_omp_for_combined_p (fd->for_stmt))
5036 /* If fd->loop.n2 is constant, then no propagation of the counts
5037 is needed, they are constant. */
5038 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5039 return;
5041 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5042 ? gimple_omp_parallel_clauses (inner_stmt)
5043 : gimple_omp_for_clauses (inner_stmt);
5044 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5045 isn't supposed to be handled, as the inner loop doesn't
5046 use it. */
5047 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5048 gcc_assert (innerc);
5049 for (i = 0; i < fd->collapse; i++)
5051 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5052 OMP_CLAUSE__LOOPTEMP_);
5053 gcc_assert (innerc);
5054 if (i)
5056 tree tem = OMP_CLAUSE_DECL (innerc);
5057 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5058 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5059 false, GSI_CONTINUE_LINKING);
5060 gimple stmt = gimple_build_assign (tem, t);
5061 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5064 return;
5067 tree type = TREE_TYPE (fd->loop.v);
5068 tree tem = create_tmp_reg (type, ".tem");
5069 gimple stmt = gimple_build_assign (tem, startvar);
5070 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5072 for (i = fd->collapse - 1; i >= 0; i--)
5074 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5075 itype = vtype;
5076 if (POINTER_TYPE_P (vtype))
5077 itype = signed_type_for (vtype);
5078 if (i != 0)
5079 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5080 else
5081 t = tem;
5082 t = fold_convert (itype, t);
5083 t = fold_build2 (MULT_EXPR, itype, t,
5084 fold_convert (itype, fd->loops[i].step));
5085 if (POINTER_TYPE_P (vtype))
5086 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5087 else
5088 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5089 t = force_gimple_operand_gsi (gsi, t,
5090 DECL_P (fd->loops[i].v)
5091 && TREE_ADDRESSABLE (fd->loops[i].v),
5092 NULL_TREE, false,
5093 GSI_CONTINUE_LINKING);
5094 stmt = gimple_build_assign (fd->loops[i].v, t);
5095 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5096 if (i != 0)
5098 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5099 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5100 false, GSI_CONTINUE_LINKING);
5101 stmt = gimple_build_assign (tem, t);
5102 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5108 /* Helper function for expand_omp_for_*. Generate code like:
5109 L10:
5110 V3 += STEP3;
5111 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5112 L11:
5113 V3 = N31;
5114 V2 += STEP2;
5115 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5116 L12:
5117 V2 = N21;
5118 V1 += STEP1;
5119 goto BODY_BB; */
5121 static basic_block
5122 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5123 basic_block body_bb)
5125 basic_block last_bb, bb, collapse_bb = NULL;
5126 int i;
5127 gimple_stmt_iterator gsi;
5128 edge e;
5129 tree t;
5130 gimple stmt;
5132 last_bb = cont_bb;
5133 for (i = fd->collapse - 1; i >= 0; i--)
5135 tree vtype = TREE_TYPE (fd->loops[i].v);
5137 bb = create_empty_bb (last_bb);
5138 if (current_loops)
5139 add_bb_to_loop (bb, last_bb->loop_father);
5140 gsi = gsi_start_bb (bb);
5142 if (i < fd->collapse - 1)
5144 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5145 e->probability = REG_BR_PROB_BASE / 8;
5147 t = fd->loops[i + 1].n1;
5148 t = force_gimple_operand_gsi (&gsi, t,
5149 DECL_P (fd->loops[i + 1].v)
5150 && TREE_ADDRESSABLE (fd->loops[i
5151 + 1].v),
5152 NULL_TREE, false,
5153 GSI_CONTINUE_LINKING);
5154 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5155 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5157 else
5158 collapse_bb = bb;
5160 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5162 if (POINTER_TYPE_P (vtype))
5163 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5164 else
5165 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5166 t = force_gimple_operand_gsi (&gsi, t,
5167 DECL_P (fd->loops[i].v)
5168 && TREE_ADDRESSABLE (fd->loops[i].v),
5169 NULL_TREE, false, GSI_CONTINUE_LINKING);
5170 stmt = gimple_build_assign (fd->loops[i].v, t);
5171 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5173 if (i > 0)
5175 t = fd->loops[i].n2;
5176 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5177 false, GSI_CONTINUE_LINKING);
5178 tree v = fd->loops[i].v;
5179 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5180 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5181 false, GSI_CONTINUE_LINKING);
5182 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5183 stmt = gimple_build_cond_empty (t);
5184 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5185 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5186 e->probability = REG_BR_PROB_BASE * 7 / 8;
5188 else
5189 make_edge (bb, body_bb, EDGE_FALLTHRU);
5190 last_bb = bb;
5193 return collapse_bb;
5197 /* A subroutine of expand_omp_for. Generate code for a parallel
5198 loop with any schedule. Given parameters:
5200 for (V = N1; V cond N2; V += STEP) BODY;
5202 where COND is "<" or ">", we generate pseudocode
5204 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5205 if (more) goto L0; else goto L3;
5207 V = istart0;
5208 iend = iend0;
5210 BODY;
5211 V += STEP;
5212 if (V cond iend) goto L1; else goto L2;
5214 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5217 If this is a combined omp parallel loop, instead of the call to
5218 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5219 If this is gimple_omp_for_combined_p loop, then instead of assigning
5220 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5221 inner GIMPLE_OMP_FOR and V += STEP; and
5222 if (V cond iend) goto L1; else goto L2; are removed.
5224 For collapsed loops, given parameters:
5225 collapse(3)
5226 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5227 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5228 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5229 BODY;
5231 we generate pseudocode
5233 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5234 if (cond3 is <)
5235 adj = STEP3 - 1;
5236 else
5237 adj = STEP3 + 1;
5238 count3 = (adj + N32 - N31) / STEP3;
5239 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5240 if (cond2 is <)
5241 adj = STEP2 - 1;
5242 else
5243 adj = STEP2 + 1;
5244 count2 = (adj + N22 - N21) / STEP2;
5245 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5246 if (cond1 is <)
5247 adj = STEP1 - 1;
5248 else
5249 adj = STEP1 + 1;
5250 count1 = (adj + N12 - N11) / STEP1;
5251 count = count1 * count2 * count3;
5252 goto Z1;
5254 count = 0;
5256 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5257 if (more) goto L0; else goto L3;
5259 V = istart0;
5260 T = V;
5261 V3 = N31 + (T % count3) * STEP3;
5262 T = T / count3;
5263 V2 = N21 + (T % count2) * STEP2;
5264 T = T / count2;
5265 V1 = N11 + T * STEP1;
5266 iend = iend0;
5268 BODY;
5269 V += 1;
5270 if (V < iend) goto L10; else goto L2;
5271 L10:
5272 V3 += STEP3;
5273 if (V3 cond3 N32) goto L1; else goto L11;
5274 L11:
5275 V3 = N31;
5276 V2 += STEP2;
5277 if (V2 cond2 N22) goto L1; else goto L12;
5278 L12:
5279 V2 = N21;
5280 V1 += STEP1;
5281 goto L1;
5283 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5288 static void
5289 expand_omp_for_generic (struct omp_region *region,
5290 struct omp_for_data *fd,
5291 enum built_in_function start_fn,
5292 enum built_in_function next_fn,
5293 gimple inner_stmt)
5295 tree type, istart0, iend0, iend;
5296 tree t, vmain, vback, bias = NULL_TREE;
5297 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5298 basic_block l2_bb = NULL, l3_bb = NULL;
5299 gimple_stmt_iterator gsi;
5300 gimple stmt;
5301 bool in_combined_parallel = is_combined_parallel (region);
5302 bool broken_loop = region->cont == NULL;
5303 edge e, ne;
5304 tree *counts = NULL;
5305 int i;
5307 gcc_assert (!broken_loop || !in_combined_parallel);
5308 gcc_assert (fd->iter_type == long_integer_type_node
5309 || !in_combined_parallel);
5311 type = TREE_TYPE (fd->loop.v);
5312 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5313 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5314 TREE_ADDRESSABLE (istart0) = 1;
5315 TREE_ADDRESSABLE (iend0) = 1;
5317 /* See if we need to bias by LLONG_MIN. */
5318 if (fd->iter_type == long_long_unsigned_type_node
5319 && TREE_CODE (type) == INTEGER_TYPE
5320 && !TYPE_UNSIGNED (type))
5322 tree n1, n2;
5324 if (fd->loop.cond_code == LT_EXPR)
5326 n1 = fd->loop.n1;
5327 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5329 else
5331 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5332 n2 = fd->loop.n1;
5334 if (TREE_CODE (n1) != INTEGER_CST
5335 || TREE_CODE (n2) != INTEGER_CST
5336 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5337 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5340 entry_bb = region->entry;
5341 cont_bb = region->cont;
5342 collapse_bb = NULL;
5343 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5344 gcc_assert (broken_loop
5345 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5346 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5347 l1_bb = single_succ (l0_bb);
5348 if (!broken_loop)
5350 l2_bb = create_empty_bb (cont_bb);
5351 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5352 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5354 else
5355 l2_bb = NULL;
5356 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5357 exit_bb = region->exit;
5359 gsi = gsi_last_bb (entry_bb);
5361 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5362 if (fd->collapse > 1)
5364 int first_zero_iter = -1;
5365 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5367 counts = XALLOCAVEC (tree, fd->collapse);
5368 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5369 zero_iter_bb, first_zero_iter,
5370 l2_dom_bb);
5372 if (zero_iter_bb)
5374 /* Some counts[i] vars might be uninitialized if
5375 some loop has zero iterations. But the body shouldn't
5376 be executed in that case, so just avoid uninit warnings. */
5377 for (i = first_zero_iter; i < fd->collapse; i++)
5378 if (SSA_VAR_P (counts[i]))
5379 TREE_NO_WARNING (counts[i]) = 1;
5380 gsi_prev (&gsi);
5381 e = split_block (entry_bb, gsi_stmt (gsi));
5382 entry_bb = e->dest;
5383 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5384 gsi = gsi_last_bb (entry_bb);
5385 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5386 get_immediate_dominator (CDI_DOMINATORS,
5387 zero_iter_bb));
5390 if (in_combined_parallel)
5392 /* In a combined parallel loop, emit a call to
5393 GOMP_loop_foo_next. */
5394 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5395 build_fold_addr_expr (istart0),
5396 build_fold_addr_expr (iend0));
5398 else
5400 tree t0, t1, t2, t3, t4;
5401 /* If this is not a combined parallel loop, emit a call to
5402 GOMP_loop_foo_start in ENTRY_BB. */
5403 t4 = build_fold_addr_expr (iend0);
5404 t3 = build_fold_addr_expr (istart0);
5405 t2 = fold_convert (fd->iter_type, fd->loop.step);
5406 t1 = fd->loop.n2;
5407 t0 = fd->loop.n1;
5408 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5410 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5411 OMP_CLAUSE__LOOPTEMP_);
5412 gcc_assert (innerc);
5413 t0 = OMP_CLAUSE_DECL (innerc);
5414 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5415 OMP_CLAUSE__LOOPTEMP_);
5416 gcc_assert (innerc);
5417 t1 = OMP_CLAUSE_DECL (innerc);
5419 if (POINTER_TYPE_P (TREE_TYPE (t0))
5420 && TYPE_PRECISION (TREE_TYPE (t0))
5421 != TYPE_PRECISION (fd->iter_type))
5423 /* Avoid casting pointers to integer of a different size. */
5424 tree itype = signed_type_for (type);
5425 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5426 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5428 else
5430 t1 = fold_convert (fd->iter_type, t1);
5431 t0 = fold_convert (fd->iter_type, t0);
5433 if (bias)
5435 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5436 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5438 if (fd->iter_type == long_integer_type_node)
5440 if (fd->chunk_size)
5442 t = fold_convert (fd->iter_type, fd->chunk_size);
5443 t = build_call_expr (builtin_decl_explicit (start_fn),
5444 6, t0, t1, t2, t, t3, t4);
5446 else
5447 t = build_call_expr (builtin_decl_explicit (start_fn),
5448 5, t0, t1, t2, t3, t4);
5450 else
5452 tree t5;
5453 tree c_bool_type;
5454 tree bfn_decl;
5456 /* The GOMP_loop_ull_*start functions have additional boolean
5457 argument, true for < loops and false for > loops.
5458 In Fortran, the C bool type can be different from
5459 boolean_type_node. */
5460 bfn_decl = builtin_decl_explicit (start_fn);
5461 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5462 t5 = build_int_cst (c_bool_type,
5463 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5464 if (fd->chunk_size)
5466 tree bfn_decl = builtin_decl_explicit (start_fn);
5467 t = fold_convert (fd->iter_type, fd->chunk_size);
5468 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5470 else
5471 t = build_call_expr (builtin_decl_explicit (start_fn),
5472 6, t5, t0, t1, t2, t3, t4);
5475 if (TREE_TYPE (t) != boolean_type_node)
5476 t = fold_build2 (NE_EXPR, boolean_type_node,
5477 t, build_int_cst (TREE_TYPE (t), 0));
5478 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5479 true, GSI_SAME_STMT);
5480 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5482 /* Remove the GIMPLE_OMP_FOR statement. */
5483 gsi_remove (&gsi, true);
5485 /* Iteration setup for sequential loop goes in L0_BB. */
5486 tree startvar = fd->loop.v;
5487 tree endvar = NULL_TREE;
5489 if (gimple_omp_for_combined_p (fd->for_stmt))
5491 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5492 && gimple_omp_for_kind (inner_stmt)
5493 == GF_OMP_FOR_KIND_SIMD);
5494 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5495 OMP_CLAUSE__LOOPTEMP_);
5496 gcc_assert (innerc);
5497 startvar = OMP_CLAUSE_DECL (innerc);
5498 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5499 OMP_CLAUSE__LOOPTEMP_);
5500 gcc_assert (innerc);
5501 endvar = OMP_CLAUSE_DECL (innerc);
5504 gsi = gsi_start_bb (l0_bb);
5505 t = istart0;
5506 if (bias)
5507 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5508 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5509 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5510 t = fold_convert (TREE_TYPE (startvar), t);
5511 t = force_gimple_operand_gsi (&gsi, t,
5512 DECL_P (startvar)
5513 && TREE_ADDRESSABLE (startvar),
5514 NULL_TREE, false, GSI_CONTINUE_LINKING);
5515 stmt = gimple_build_assign (startvar, t);
5516 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5518 t = iend0;
5519 if (bias)
5520 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5521 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5522 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5523 t = fold_convert (TREE_TYPE (startvar), t);
5524 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5525 false, GSI_CONTINUE_LINKING);
5526 if (endvar)
5528 stmt = gimple_build_assign (endvar, iend);
5529 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5531 if (fd->collapse > 1)
5532 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5534 if (!broken_loop)
5536 /* Code to control the increment and predicate for the sequential
5537 loop goes in the CONT_BB. */
5538 gsi = gsi_last_bb (cont_bb);
5539 stmt = gsi_stmt (gsi);
5540 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5541 vmain = gimple_omp_continue_control_use (stmt);
5542 vback = gimple_omp_continue_control_def (stmt);
5544 if (!gimple_omp_for_combined_p (fd->for_stmt))
5546 if (POINTER_TYPE_P (type))
5547 t = fold_build_pointer_plus (vmain, fd->loop.step);
5548 else
5549 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5550 t = force_gimple_operand_gsi (&gsi, t,
5551 DECL_P (vback)
5552 && TREE_ADDRESSABLE (vback),
5553 NULL_TREE, true, GSI_SAME_STMT);
5554 stmt = gimple_build_assign (vback, t);
5555 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5557 t = build2 (fd->loop.cond_code, boolean_type_node,
5558 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5559 iend);
5560 stmt = gimple_build_cond_empty (t);
5561 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5564 /* Remove GIMPLE_OMP_CONTINUE. */
5565 gsi_remove (&gsi, true);
5567 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5568 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5570 /* Emit code to get the next parallel iteration in L2_BB. */
5571 gsi = gsi_start_bb (l2_bb);
5573 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5574 build_fold_addr_expr (istart0),
5575 build_fold_addr_expr (iend0));
5576 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5577 false, GSI_CONTINUE_LINKING);
5578 if (TREE_TYPE (t) != boolean_type_node)
5579 t = fold_build2 (NE_EXPR, boolean_type_node,
5580 t, build_int_cst (TREE_TYPE (t), 0));
5581 stmt = gimple_build_cond_empty (t);
5582 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5585 /* Add the loop cleanup function. */
5586 gsi = gsi_last_bb (exit_bb);
5587 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5588 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5589 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5590 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5591 else
5592 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5593 stmt = gimple_build_call (t, 0);
5594 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5595 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5596 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5597 gsi_remove (&gsi, true);
5599 /* Connect the new blocks. */
5600 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5601 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5603 if (!broken_loop)
5605 gimple_seq phis;
5607 e = find_edge (cont_bb, l3_bb);
5608 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5610 phis = phi_nodes (l3_bb);
5611 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5613 gimple phi = gsi_stmt (gsi);
5614 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5615 PHI_ARG_DEF_FROM_EDGE (phi, e));
5617 remove_edge (e);
5619 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5620 if (current_loops)
5621 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5622 e = find_edge (cont_bb, l1_bb);
5623 if (gimple_omp_for_combined_p (fd->for_stmt))
5625 remove_edge (e);
5626 e = NULL;
5628 else if (fd->collapse > 1)
5630 remove_edge (e);
5631 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5633 else
5634 e->flags = EDGE_TRUE_VALUE;
5635 if (e)
5637 e->probability = REG_BR_PROB_BASE * 7 / 8;
5638 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5640 else
5642 e = find_edge (cont_bb, l2_bb);
5643 e->flags = EDGE_FALLTHRU;
5645 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5647 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5648 recompute_dominator (CDI_DOMINATORS, l2_bb));
5649 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5650 recompute_dominator (CDI_DOMINATORS, l3_bb));
5651 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5652 recompute_dominator (CDI_DOMINATORS, l0_bb));
5653 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5654 recompute_dominator (CDI_DOMINATORS, l1_bb));
5656 struct loop *outer_loop = alloc_loop ();
5657 outer_loop->header = l0_bb;
5658 outer_loop->latch = l2_bb;
5659 add_loop (outer_loop, l0_bb->loop_father);
5661 if (!gimple_omp_for_combined_p (fd->for_stmt))
5663 struct loop *loop = alloc_loop ();
5664 loop->header = l1_bb;
5665 /* The loop may have multiple latches. */
5666 add_loop (loop, outer_loop);
5672 /* A subroutine of expand_omp_for. Generate code for a parallel
5673 loop with static schedule and no specified chunk size. Given
5674 parameters:
5676 for (V = N1; V cond N2; V += STEP) BODY;
5678 where COND is "<" or ">", we generate pseudocode
5680 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5681 if (cond is <)
5682 adj = STEP - 1;
5683 else
5684 adj = STEP + 1;
5685 if ((__typeof (V)) -1 > 0 && cond is >)
5686 n = -(adj + N2 - N1) / -STEP;
5687 else
5688 n = (adj + N2 - N1) / STEP;
5689 q = n / nthreads;
5690 tt = n % nthreads;
5691 if (threadid < tt) goto L3; else goto L4;
5693 tt = 0;
5694 q = q + 1;
5696 s0 = q * threadid + tt;
5697 e0 = s0 + q;
5698 V = s0 * STEP + N1;
5699 if (s0 >= e0) goto L2; else goto L0;
5701 e = e0 * STEP + N1;
5703 BODY;
5704 V += STEP;
5705 if (V cond e) goto L1;
5709 static void
5710 expand_omp_for_static_nochunk (struct omp_region *region,
5711 struct omp_for_data *fd,
5712 gimple inner_stmt)
5714 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5715 tree type, itype, vmain, vback;
5716 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5717 basic_block body_bb, cont_bb, collapse_bb = NULL;
5718 basic_block fin_bb;
5719 gimple_stmt_iterator gsi;
5720 gimple stmt;
5721 edge ep;
5722 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5723 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5724 bool broken_loop = region->cont == NULL;
5725 tree *counts = NULL;
5726 tree n1, n2, step;
5728 itype = type = TREE_TYPE (fd->loop.v);
5729 if (POINTER_TYPE_P (type))
5730 itype = signed_type_for (type);
5732 entry_bb = region->entry;
5733 cont_bb = region->cont;
5734 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5735 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5736 gcc_assert (broken_loop
5737 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5738 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5739 body_bb = single_succ (seq_start_bb);
5740 if (!broken_loop)
5742 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5743 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5745 exit_bb = region->exit;
5747 /* Iteration space partitioning goes in ENTRY_BB. */
5748 gsi = gsi_last_bb (entry_bb);
5749 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5751 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5753 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5754 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5757 if (fd->collapse > 1)
5759 int first_zero_iter = -1;
5760 basic_block l2_dom_bb = NULL;
5762 counts = XALLOCAVEC (tree, fd->collapse);
5763 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5764 fin_bb, first_zero_iter,
5765 l2_dom_bb);
5766 t = NULL_TREE;
5768 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5769 t = integer_one_node;
5770 else
5771 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5772 fold_convert (type, fd->loop.n1),
5773 fold_convert (type, fd->loop.n2));
5774 if (fd->collapse == 1
5775 && TYPE_UNSIGNED (type)
5776 && (t == NULL_TREE || !integer_onep (t)))
5778 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5779 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5780 true, GSI_SAME_STMT);
5781 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5782 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5783 true, GSI_SAME_STMT);
5784 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5785 NULL_TREE, NULL_TREE);
5786 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5787 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5788 expand_omp_regimplify_p, NULL, NULL)
5789 || walk_tree (gimple_cond_rhs_ptr (stmt),
5790 expand_omp_regimplify_p, NULL, NULL))
5792 gsi = gsi_for_stmt (stmt);
5793 gimple_regimplify_operands (stmt, &gsi);
5795 ep = split_block (entry_bb, stmt);
5796 ep->flags = EDGE_TRUE_VALUE;
5797 entry_bb = ep->dest;
5798 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5799 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5800 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5801 if (gimple_in_ssa_p (cfun))
5803 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5804 for (gsi = gsi_start_phis (fin_bb);
5805 !gsi_end_p (gsi); gsi_next (&gsi))
5807 gimple phi = gsi_stmt (gsi);
5808 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5809 ep, UNKNOWN_LOCATION);
5812 gsi = gsi_last_bb (entry_bb);
5815 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5816 t = fold_convert (itype, t);
5817 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5818 true, GSI_SAME_STMT);
5820 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5821 t = fold_convert (itype, t);
5822 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5823 true, GSI_SAME_STMT);
5825 n1 = fd->loop.n1;
5826 n2 = fd->loop.n2;
5827 step = fd->loop.step;
5828 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5830 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5831 OMP_CLAUSE__LOOPTEMP_);
5832 gcc_assert (innerc);
5833 n1 = OMP_CLAUSE_DECL (innerc);
5834 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5835 OMP_CLAUSE__LOOPTEMP_);
5836 gcc_assert (innerc);
5837 n2 = OMP_CLAUSE_DECL (innerc);
5839 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5840 true, NULL_TREE, true, GSI_SAME_STMT);
5841 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5842 true, NULL_TREE, true, GSI_SAME_STMT);
5843 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5844 true, NULL_TREE, true, GSI_SAME_STMT);
5846 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5847 t = fold_build2 (PLUS_EXPR, itype, step, t);
5848 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5849 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5850 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5851 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5852 fold_build1 (NEGATE_EXPR, itype, t),
5853 fold_build1 (NEGATE_EXPR, itype, step));
5854 else
5855 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5856 t = fold_convert (itype, t);
5857 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5859 q = create_tmp_reg (itype, "q");
5860 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5861 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5862 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5864 tt = create_tmp_reg (itype, "tt");
5865 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5866 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5867 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5869 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5870 stmt = gimple_build_cond_empty (t);
5871 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5873 second_bb = split_block (entry_bb, stmt)->dest;
5874 gsi = gsi_last_bb (second_bb);
5875 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5877 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5878 GSI_SAME_STMT);
5879 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5880 build_int_cst (itype, 1));
5881 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5883 third_bb = split_block (second_bb, stmt)->dest;
5884 gsi = gsi_last_bb (third_bb);
5885 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5887 t = build2 (MULT_EXPR, itype, q, threadid);
5888 t = build2 (PLUS_EXPR, itype, t, tt);
5889 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5891 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5892 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5894 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5895 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5897 /* Remove the GIMPLE_OMP_FOR statement. */
5898 gsi_remove (&gsi, true);
5900 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5901 gsi = gsi_start_bb (seq_start_bb);
5903 tree startvar = fd->loop.v;
5904 tree endvar = NULL_TREE;
5906 if (gimple_omp_for_combined_p (fd->for_stmt))
5908 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5909 ? gimple_omp_parallel_clauses (inner_stmt)
5910 : gimple_omp_for_clauses (inner_stmt);
5911 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5912 gcc_assert (innerc);
5913 startvar = OMP_CLAUSE_DECL (innerc);
5914 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5915 OMP_CLAUSE__LOOPTEMP_);
5916 gcc_assert (innerc);
5917 endvar = OMP_CLAUSE_DECL (innerc);
5919 t = fold_convert (itype, s0);
5920 t = fold_build2 (MULT_EXPR, itype, t, step);
5921 if (POINTER_TYPE_P (type))
5922 t = fold_build_pointer_plus (n1, t);
5923 else
5924 t = fold_build2 (PLUS_EXPR, type, t, n1);
5925 t = fold_convert (TREE_TYPE (startvar), t);
5926 t = force_gimple_operand_gsi (&gsi, t,
5927 DECL_P (startvar)
5928 && TREE_ADDRESSABLE (startvar),
5929 NULL_TREE, false, GSI_CONTINUE_LINKING);
5930 stmt = gimple_build_assign (startvar, t);
5931 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5933 t = fold_convert (itype, e0);
5934 t = fold_build2 (MULT_EXPR, itype, t, step);
5935 if (POINTER_TYPE_P (type))
5936 t = fold_build_pointer_plus (n1, t);
5937 else
5938 t = fold_build2 (PLUS_EXPR, type, t, n1);
5939 t = fold_convert (TREE_TYPE (startvar), t);
5940 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5941 false, GSI_CONTINUE_LINKING);
5942 if (endvar)
5944 stmt = gimple_build_assign (endvar, e);
5945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5947 if (fd->collapse > 1)
5948 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5950 if (!broken_loop)
5952 /* The code controlling the sequential loop replaces the
5953 GIMPLE_OMP_CONTINUE. */
5954 gsi = gsi_last_bb (cont_bb);
5955 stmt = gsi_stmt (gsi);
5956 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5957 vmain = gimple_omp_continue_control_use (stmt);
5958 vback = gimple_omp_continue_control_def (stmt);
5960 if (!gimple_omp_for_combined_p (fd->for_stmt))
5962 if (POINTER_TYPE_P (type))
5963 t = fold_build_pointer_plus (vmain, step);
5964 else
5965 t = fold_build2 (PLUS_EXPR, type, vmain, step);
5966 t = force_gimple_operand_gsi (&gsi, t,
5967 DECL_P (vback)
5968 && TREE_ADDRESSABLE (vback),
5969 NULL_TREE, true, GSI_SAME_STMT);
5970 stmt = gimple_build_assign (vback, t);
5971 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5973 t = build2 (fd->loop.cond_code, boolean_type_node,
5974 DECL_P (vback) && TREE_ADDRESSABLE (vback)
5975 ? t : vback, e);
5976 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5979 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5980 gsi_remove (&gsi, true);
5982 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5983 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
5986 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5987 gsi = gsi_last_bb (exit_bb);
5988 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5990 t = gimple_omp_return_lhs (gsi_stmt (gsi));
5991 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
5993 gsi_remove (&gsi, true);
5995 /* Connect all the blocks. */
5996 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5997 ep->probability = REG_BR_PROB_BASE / 4 * 3;
5998 ep = find_edge (entry_bb, second_bb);
5999 ep->flags = EDGE_TRUE_VALUE;
6000 ep->probability = REG_BR_PROB_BASE / 4;
6001 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6002 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6004 if (!broken_loop)
6006 ep = find_edge (cont_bb, body_bb);
6007 if (gimple_omp_for_combined_p (fd->for_stmt))
6009 remove_edge (ep);
6010 ep = NULL;
6012 else if (fd->collapse > 1)
6014 remove_edge (ep);
6015 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6017 else
6018 ep->flags = EDGE_TRUE_VALUE;
6019 find_edge (cont_bb, fin_bb)->flags
6020 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6023 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6024 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6025 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6027 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6028 recompute_dominator (CDI_DOMINATORS, body_bb));
6029 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6030 recompute_dominator (CDI_DOMINATORS, fin_bb));
6032 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6034 struct loop *loop = alloc_loop ();
6035 loop->header = body_bb;
6036 if (collapse_bb == NULL)
6037 loop->latch = cont_bb;
6038 add_loop (loop, body_bb->loop_father);
6043 /* A subroutine of expand_omp_for. Generate code for a parallel
6044 loop with static schedule and a specified chunk size. Given
6045 parameters:
6047 for (V = N1; V cond N2; V += STEP) BODY;
6049 where COND is "<" or ">", we generate pseudocode
6051 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6052 if (cond is <)
6053 adj = STEP - 1;
6054 else
6055 adj = STEP + 1;
6056 if ((__typeof (V)) -1 > 0 && cond is >)
6057 n = -(adj + N2 - N1) / -STEP;
6058 else
6059 n = (adj + N2 - N1) / STEP;
6060 trip = 0;
6061 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6062 here so that V is defined
6063 if the loop is not entered
6065 s0 = (trip * nthreads + threadid) * CHUNK;
6066 e0 = min(s0 + CHUNK, n);
6067 if (s0 < n) goto L1; else goto L4;
6069 V = s0 * STEP + N1;
6070 e = e0 * STEP + N1;
6072 BODY;
6073 V += STEP;
6074 if (V cond e) goto L2; else goto L3;
6076 trip += 1;
6077 goto L0;
6081 static void
6082 expand_omp_for_static_chunk (struct omp_region *region,
6083 struct omp_for_data *fd, gimple inner_stmt)
6085 tree n, s0, e0, e, t;
6086 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6087 tree type, itype, v_main, v_back, v_extra;
6088 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6089 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6090 gimple_stmt_iterator si;
6091 gimple stmt;
6092 edge se;
6093 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6094 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6095 bool broken_loop = region->cont == NULL;
6096 tree *counts = NULL;
6097 tree n1, n2, step;
6099 itype = type = TREE_TYPE (fd->loop.v);
6100 if (POINTER_TYPE_P (type))
6101 itype = signed_type_for (type);
6103 entry_bb = region->entry;
6104 se = split_block (entry_bb, last_stmt (entry_bb));
6105 entry_bb = se->src;
6106 iter_part_bb = se->dest;
6107 cont_bb = region->cont;
6108 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6109 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6110 gcc_assert (broken_loop
6111 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6112 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6113 body_bb = single_succ (seq_start_bb);
6114 if (!broken_loop)
6116 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6117 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6118 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6120 exit_bb = region->exit;
6122 /* Trip and adjustment setup goes in ENTRY_BB. */
6123 si = gsi_last_bb (entry_bb);
6124 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6126 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6128 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6129 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6132 if (fd->collapse > 1)
6134 int first_zero_iter = -1;
6135 basic_block l2_dom_bb = NULL;
6137 counts = XALLOCAVEC (tree, fd->collapse);
6138 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6139 fin_bb, first_zero_iter,
6140 l2_dom_bb);
6141 t = NULL_TREE;
6143 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6144 t = integer_one_node;
6145 else
6146 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6147 fold_convert (type, fd->loop.n1),
6148 fold_convert (type, fd->loop.n2));
6149 if (fd->collapse == 1
6150 && TYPE_UNSIGNED (type)
6151 && (t == NULL_TREE || !integer_onep (t)))
6153 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6154 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6155 true, GSI_SAME_STMT);
6156 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6157 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6158 true, GSI_SAME_STMT);
6159 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6160 NULL_TREE, NULL_TREE);
6161 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6162 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6163 expand_omp_regimplify_p, NULL, NULL)
6164 || walk_tree (gimple_cond_rhs_ptr (stmt),
6165 expand_omp_regimplify_p, NULL, NULL))
6167 si = gsi_for_stmt (stmt);
6168 gimple_regimplify_operands (stmt, &si);
6170 se = split_block (entry_bb, stmt);
6171 se->flags = EDGE_TRUE_VALUE;
6172 entry_bb = se->dest;
6173 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6174 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6175 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6176 if (gimple_in_ssa_p (cfun))
6178 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6179 for (si = gsi_start_phis (fin_bb);
6180 !gsi_end_p (si); gsi_next (&si))
6182 gimple phi = gsi_stmt (si);
6183 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6184 se, UNKNOWN_LOCATION);
6187 si = gsi_last_bb (entry_bb);
6190 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6191 t = fold_convert (itype, t);
6192 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6193 true, GSI_SAME_STMT);
6195 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6196 t = fold_convert (itype, t);
6197 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6198 true, GSI_SAME_STMT);
6200 n1 = fd->loop.n1;
6201 n2 = fd->loop.n2;
6202 step = fd->loop.step;
6203 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6205 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6206 OMP_CLAUSE__LOOPTEMP_);
6207 gcc_assert (innerc);
6208 n1 = OMP_CLAUSE_DECL (innerc);
6209 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6210 OMP_CLAUSE__LOOPTEMP_);
6211 gcc_assert (innerc);
6212 n2 = OMP_CLAUSE_DECL (innerc);
6214 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6215 true, NULL_TREE, true, GSI_SAME_STMT);
6216 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6217 true, NULL_TREE, true, GSI_SAME_STMT);
6218 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6219 true, NULL_TREE, true, GSI_SAME_STMT);
6220 fd->chunk_size
6221 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6222 true, NULL_TREE, true, GSI_SAME_STMT);
6224 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6225 t = fold_build2 (PLUS_EXPR, itype, step, t);
6226 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6227 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6228 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6229 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6230 fold_build1 (NEGATE_EXPR, itype, t),
6231 fold_build1 (NEGATE_EXPR, itype, step));
6232 else
6233 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6234 t = fold_convert (itype, t);
6235 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6236 true, GSI_SAME_STMT);
6238 trip_var = create_tmp_reg (itype, ".trip");
6239 if (gimple_in_ssa_p (cfun))
6241 trip_init = make_ssa_name (trip_var, NULL);
6242 trip_main = make_ssa_name (trip_var, NULL);
6243 trip_back = make_ssa_name (trip_var, NULL);
6245 else
6247 trip_init = trip_var;
6248 trip_main = trip_var;
6249 trip_back = trip_var;
6252 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6253 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6255 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6256 t = fold_build2 (MULT_EXPR, itype, t, step);
6257 if (POINTER_TYPE_P (type))
6258 t = fold_build_pointer_plus (n1, t);
6259 else
6260 t = fold_build2 (PLUS_EXPR, type, t, n1);
6261 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6262 true, GSI_SAME_STMT);
6264 /* Remove the GIMPLE_OMP_FOR. */
6265 gsi_remove (&si, true);
6267 /* Iteration space partitioning goes in ITER_PART_BB. */
6268 si = gsi_last_bb (iter_part_bb);
6270 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6271 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6272 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6273 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6274 false, GSI_CONTINUE_LINKING);
6276 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6277 t = fold_build2 (MIN_EXPR, itype, t, n);
6278 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6279 false, GSI_CONTINUE_LINKING);
6281 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6282 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6284 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6285 si = gsi_start_bb (seq_start_bb);
6287 tree startvar = fd->loop.v;
6288 tree endvar = NULL_TREE;
6290 if (gimple_omp_for_combined_p (fd->for_stmt))
6292 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6293 ? gimple_omp_parallel_clauses (inner_stmt)
6294 : gimple_omp_for_clauses (inner_stmt);
6295 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6296 gcc_assert (innerc);
6297 startvar = OMP_CLAUSE_DECL (innerc);
6298 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 endvar = OMP_CLAUSE_DECL (innerc);
6304 t = fold_convert (itype, s0);
6305 t = fold_build2 (MULT_EXPR, itype, t, step);
6306 if (POINTER_TYPE_P (type))
6307 t = fold_build_pointer_plus (n1, t);
6308 else
6309 t = fold_build2 (PLUS_EXPR, type, t, n1);
6310 t = fold_convert (TREE_TYPE (startvar), t);
6311 t = force_gimple_operand_gsi (&si, t,
6312 DECL_P (startvar)
6313 && TREE_ADDRESSABLE (startvar),
6314 NULL_TREE, false, GSI_CONTINUE_LINKING);
6315 stmt = gimple_build_assign (startvar, t);
6316 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6318 t = fold_convert (itype, e0);
6319 t = fold_build2 (MULT_EXPR, itype, t, step);
6320 if (POINTER_TYPE_P (type))
6321 t = fold_build_pointer_plus (n1, t);
6322 else
6323 t = fold_build2 (PLUS_EXPR, type, t, n1);
6324 t = fold_convert (TREE_TYPE (startvar), t);
6325 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6326 false, GSI_CONTINUE_LINKING);
6327 if (endvar)
6329 stmt = gimple_build_assign (endvar, e);
6330 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6332 if (fd->collapse > 1)
6333 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6335 if (!broken_loop)
6337 /* The code controlling the sequential loop goes in CONT_BB,
6338 replacing the GIMPLE_OMP_CONTINUE. */
6339 si = gsi_last_bb (cont_bb);
6340 stmt = gsi_stmt (si);
6341 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6342 v_main = gimple_omp_continue_control_use (stmt);
6343 v_back = gimple_omp_continue_control_def (stmt);
6345 if (!gimple_omp_for_combined_p (fd->for_stmt))
6347 if (POINTER_TYPE_P (type))
6348 t = fold_build_pointer_plus (v_main, step);
6349 else
6350 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6351 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6352 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6353 true, GSI_SAME_STMT);
6354 stmt = gimple_build_assign (v_back, t);
6355 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6357 t = build2 (fd->loop.cond_code, boolean_type_node,
6358 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6359 ? t : v_back, e);
6360 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6363 /* Remove GIMPLE_OMP_CONTINUE. */
6364 gsi_remove (&si, true);
6366 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6367 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6369 /* Trip update code goes into TRIP_UPDATE_BB. */
6370 si = gsi_start_bb (trip_update_bb);
6372 t = build_int_cst (itype, 1);
6373 t = build2 (PLUS_EXPR, itype, trip_main, t);
6374 stmt = gimple_build_assign (trip_back, t);
6375 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6378 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6379 si = gsi_last_bb (exit_bb);
6380 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6382 t = gimple_omp_return_lhs (gsi_stmt (si));
6383 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6385 gsi_remove (&si, true);
6387 /* Connect the new blocks. */
6388 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6389 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6391 if (!broken_loop)
6393 se = find_edge (cont_bb, body_bb);
6394 if (gimple_omp_for_combined_p (fd->for_stmt))
6396 remove_edge (se);
6397 se = NULL;
6399 else if (fd->collapse > 1)
6401 remove_edge (se);
6402 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6404 else
6405 se->flags = EDGE_TRUE_VALUE;
6406 find_edge (cont_bb, trip_update_bb)->flags
6407 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6409 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6412 if (gimple_in_ssa_p (cfun))
6414 gimple_stmt_iterator psi;
6415 gimple phi;
6416 edge re, ene;
6417 edge_var_map_vector *head;
6418 edge_var_map *vm;
6419 size_t i;
6421 gcc_assert (fd->collapse == 1 && !broken_loop);
6423 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6424 remove arguments of the phi nodes in fin_bb. We need to create
6425 appropriate phi nodes in iter_part_bb instead. */
6426 se = single_pred_edge (fin_bb);
6427 re = single_succ_edge (trip_update_bb);
6428 head = redirect_edge_var_map_vector (re);
6429 ene = single_succ_edge (entry_bb);
6431 psi = gsi_start_phis (fin_bb);
6432 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6433 gsi_next (&psi), ++i)
6435 gimple nphi;
6436 source_location locus;
6438 phi = gsi_stmt (psi);
6439 t = gimple_phi_result (phi);
6440 gcc_assert (t == redirect_edge_var_map_result (vm));
6441 nphi = create_phi_node (t, iter_part_bb);
6443 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6444 locus = gimple_phi_arg_location_from_edge (phi, se);
6446 /* A special case -- fd->loop.v is not yet computed in
6447 iter_part_bb, we need to use v_extra instead. */
6448 if (t == fd->loop.v)
6449 t = v_extra;
6450 add_phi_arg (nphi, t, ene, locus);
6451 locus = redirect_edge_var_map_location (vm);
6452 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6454 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6455 redirect_edge_var_map_clear (re);
6456 while (1)
6458 psi = gsi_start_phis (fin_bb);
6459 if (gsi_end_p (psi))
6460 break;
6461 remove_phi_node (&psi, false);
6464 /* Make phi node for trip. */
6465 phi = create_phi_node (trip_main, iter_part_bb);
6466 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6467 UNKNOWN_LOCATION);
6468 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6469 UNKNOWN_LOCATION);
6472 if (!broken_loop)
6473 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6474 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6475 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6476 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6477 recompute_dominator (CDI_DOMINATORS, fin_bb));
6478 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6479 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6480 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6481 recompute_dominator (CDI_DOMINATORS, body_bb));
6483 if (!broken_loop)
6485 struct loop *trip_loop = alloc_loop ();
6486 trip_loop->header = iter_part_bb;
6487 trip_loop->latch = trip_update_bb;
6488 add_loop (trip_loop, iter_part_bb->loop_father);
6490 if (!gimple_omp_for_combined_p (fd->for_stmt))
6492 struct loop *loop = alloc_loop ();
6493 loop->header = body_bb;
6494 loop->latch = cont_bb;
6495 add_loop (loop, trip_loop);
6501 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6502 loop. Given parameters:
6504 for (V = N1; V cond N2; V += STEP) BODY;
6506 where COND is "<" or ">", we generate pseudocode
6508 V = N1;
6509 goto L1;
6511 BODY;
6512 V += STEP;
6514 if (V cond N2) goto L0; else goto L2;
6517 For collapsed loops, given parameters:
6518 collapse(3)
6519 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6520 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6521 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6522 BODY;
6524 we generate pseudocode
6526 if (cond3 is <)
6527 adj = STEP3 - 1;
6528 else
6529 adj = STEP3 + 1;
6530 count3 = (adj + N32 - N31) / STEP3;
6531 if (cond2 is <)
6532 adj = STEP2 - 1;
6533 else
6534 adj = STEP2 + 1;
6535 count2 = (adj + N22 - N21) / STEP2;
6536 if (cond1 is <)
6537 adj = STEP1 - 1;
6538 else
6539 adj = STEP1 + 1;
6540 count1 = (adj + N12 - N11) / STEP1;
6541 count = count1 * count2 * count3;
6542 V = 0;
6543 V1 = N11;
6544 V2 = N21;
6545 V3 = N31;
6546 goto L1;
6548 BODY;
6549 V += 1;
6550 V3 += STEP3;
6551 V2 += (V3 cond3 N32) ? 0 : STEP2;
6552 V3 = (V3 cond3 N32) ? V3 : N31;
6553 V1 += (V2 cond2 N22) ? 0 : STEP1;
6554 V2 = (V2 cond2 N22) ? V2 : N21;
6556 if (V < count) goto L0; else goto L2;
6561 static void
6562 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6564 tree type, t;
6565 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6566 gimple_stmt_iterator gsi;
6567 gimple stmt;
6568 bool broken_loop = region->cont == NULL;
6569 edge e, ne;
6570 tree *counts = NULL;
6571 int i;
6572 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6573 OMP_CLAUSE_SAFELEN);
6574 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6575 OMP_CLAUSE__SIMDUID_);
6576 tree n1, n2;
6578 type = TREE_TYPE (fd->loop.v);
6579 entry_bb = region->entry;
6580 cont_bb = region->cont;
6581 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6582 gcc_assert (broken_loop
6583 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6584 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6585 if (!broken_loop)
6587 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6588 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6589 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6590 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6592 else
6594 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6595 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6596 l2_bb = single_succ (l1_bb);
6598 exit_bb = region->exit;
6599 l2_dom_bb = NULL;
6601 gsi = gsi_last_bb (entry_bb);
6603 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6604 /* Not needed in SSA form right now. */
6605 gcc_assert (!gimple_in_ssa_p (cfun));
6606 if (fd->collapse > 1)
6608 int first_zero_iter = -1;
6609 basic_block zero_iter_bb = l2_bb;
6611 counts = XALLOCAVEC (tree, fd->collapse);
6612 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6613 zero_iter_bb, first_zero_iter,
6614 l2_dom_bb);
6616 if (l2_dom_bb == NULL)
6617 l2_dom_bb = l1_bb;
6619 n1 = fd->loop.n1;
6620 n2 = fd->loop.n2;
6621 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6623 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6624 OMP_CLAUSE__LOOPTEMP_);
6625 gcc_assert (innerc);
6626 n1 = OMP_CLAUSE_DECL (innerc);
6627 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6628 OMP_CLAUSE__LOOPTEMP_);
6629 gcc_assert (innerc);
6630 n2 = OMP_CLAUSE_DECL (innerc);
6631 expand_omp_build_assign (&gsi, fd->loop.v,
6632 fold_convert (type, n1));
6633 if (fd->collapse > 1)
6635 gsi_prev (&gsi);
6636 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6637 gsi_next (&gsi);
6640 else
6642 expand_omp_build_assign (&gsi, fd->loop.v,
6643 fold_convert (type, fd->loop.n1));
6644 if (fd->collapse > 1)
6645 for (i = 0; i < fd->collapse; i++)
6647 tree itype = TREE_TYPE (fd->loops[i].v);
6648 if (POINTER_TYPE_P (itype))
6649 itype = signed_type_for (itype);
6650 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6651 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6655 /* Remove the GIMPLE_OMP_FOR statement. */
6656 gsi_remove (&gsi, true);
6658 if (!broken_loop)
6660 /* Code to control the increment goes in the CONT_BB. */
6661 gsi = gsi_last_bb (cont_bb);
6662 stmt = gsi_stmt (gsi);
6663 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6665 if (POINTER_TYPE_P (type))
6666 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6667 else
6668 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6669 expand_omp_build_assign (&gsi, fd->loop.v, t);
6671 if (fd->collapse > 1)
6673 i = fd->collapse - 1;
6674 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6676 t = fold_convert (sizetype, fd->loops[i].step);
6677 t = fold_build_pointer_plus (fd->loops[i].v, t);
6679 else
6681 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6682 fd->loops[i].step);
6683 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6684 fd->loops[i].v, t);
6686 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6688 for (i = fd->collapse - 1; i > 0; i--)
6690 tree itype = TREE_TYPE (fd->loops[i].v);
6691 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6692 if (POINTER_TYPE_P (itype2))
6693 itype2 = signed_type_for (itype2);
6694 t = build3 (COND_EXPR, itype2,
6695 build2 (fd->loops[i].cond_code, boolean_type_node,
6696 fd->loops[i].v,
6697 fold_convert (itype, fd->loops[i].n2)),
6698 build_int_cst (itype2, 0),
6699 fold_convert (itype2, fd->loops[i - 1].step));
6700 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6701 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6702 else
6703 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6704 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6706 t = build3 (COND_EXPR, itype,
6707 build2 (fd->loops[i].cond_code, boolean_type_node,
6708 fd->loops[i].v,
6709 fold_convert (itype, fd->loops[i].n2)),
6710 fd->loops[i].v,
6711 fold_convert (itype, fd->loops[i].n1));
6712 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6716 /* Remove GIMPLE_OMP_CONTINUE. */
6717 gsi_remove (&gsi, true);
6720 /* Emit the condition in L1_BB. */
6721 gsi = gsi_start_bb (l1_bb);
6723 t = fold_convert (type, n2);
6724 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6725 false, GSI_CONTINUE_LINKING);
6726 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6727 stmt = gimple_build_cond_empty (t);
6728 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6729 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6730 NULL, NULL)
6731 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6732 NULL, NULL))
6734 gsi = gsi_for_stmt (stmt);
6735 gimple_regimplify_operands (stmt, &gsi);
6738 /* Remove GIMPLE_OMP_RETURN. */
6739 gsi = gsi_last_bb (exit_bb);
6740 gsi_remove (&gsi, true);
6742 /* Connect the new blocks. */
6743 remove_edge (FALLTHRU_EDGE (entry_bb));
6745 if (!broken_loop)
6747 remove_edge (BRANCH_EDGE (entry_bb));
6748 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6750 e = BRANCH_EDGE (l1_bb);
6751 ne = FALLTHRU_EDGE (l1_bb);
6752 e->flags = EDGE_TRUE_VALUE;
6754 else
6756 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6758 ne = single_succ_edge (l1_bb);
6759 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6762 ne->flags = EDGE_FALSE_VALUE;
6763 e->probability = REG_BR_PROB_BASE * 7 / 8;
6764 ne->probability = REG_BR_PROB_BASE / 8;
6766 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6767 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6768 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6770 if (!broken_loop)
6772 struct loop *loop = alloc_loop ();
6773 loop->header = l1_bb;
6774 loop->latch = e->dest;
6775 add_loop (loop, l1_bb->loop_father);
6776 if (safelen == NULL_TREE)
6777 loop->safelen = INT_MAX;
6778 else
6780 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6781 if (!tree_fits_uhwi_p (safelen)
6782 || tree_to_uhwi (safelen) > INT_MAX)
6783 loop->safelen = INT_MAX;
6784 else
6785 loop->safelen = tree_to_uhwi (safelen);
6786 if (loop->safelen == 1)
6787 loop->safelen = 0;
6789 if (simduid)
6791 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6792 cfun->has_simduid_loops = true;
6794 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6795 the loop. */
6796 if ((flag_tree_loop_vectorize
6797 || (!global_options_set.x_flag_tree_loop_vectorize
6798 && !global_options_set.x_flag_tree_vectorize))
6799 && loop->safelen > 1)
6801 loop->force_vect = true;
6802 cfun->has_force_vect_loops = true;
6808 /* Expand the OpenMP loop defined by REGION. */
6810 static void
6811 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6813 struct omp_for_data fd;
6814 struct omp_for_data_loop *loops;
6816 loops
6817 = (struct omp_for_data_loop *)
6818 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6819 * sizeof (struct omp_for_data_loop));
6820 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6821 region->sched_kind = fd.sched_kind;
6823 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6824 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6825 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6826 if (region->cont)
6828 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6829 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6830 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6832 else
6833 /* If there isn't a continue then this is a degerate case where
6834 the introduction of abnormal edges during lowering will prevent
6835 original loops from being detected. Fix that up. */
6836 loops_state_set (LOOPS_NEED_FIXUP);
6838 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6839 expand_omp_simd (region, &fd);
6840 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6841 && !fd.have_ordered)
6843 if (fd.chunk_size == NULL)
6844 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6845 else
6846 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6848 else
6850 int fn_index, start_ix, next_ix;
6852 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6853 == GF_OMP_FOR_KIND_FOR);
6854 if (fd.chunk_size == NULL
6855 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6856 fd.chunk_size = integer_zero_node;
6857 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6858 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6859 ? 3 : fd.sched_kind;
6860 fn_index += fd.have_ordered * 4;
6861 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6862 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6863 if (fd.iter_type == long_long_unsigned_type_node)
6865 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6866 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6867 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6868 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6870 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6871 (enum built_in_function) next_ix, inner_stmt);
6874 if (gimple_in_ssa_p (cfun))
6875 update_ssa (TODO_update_ssa_only_virtuals);
6879 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6881 v = GOMP_sections_start (n);
6883 switch (v)
6885 case 0:
6886 goto L2;
6887 case 1:
6888 section 1;
6889 goto L1;
6890 case 2:
6892 case n:
6894 default:
6895 abort ();
6898 v = GOMP_sections_next ();
6899 goto L0;
6901 reduction;
6903 If this is a combined parallel sections, replace the call to
6904 GOMP_sections_start with call to GOMP_sections_next. */
6906 static void
6907 expand_omp_sections (struct omp_region *region)
6909 tree t, u, vin = NULL, vmain, vnext, l2;
6910 unsigned len;
6911 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6912 gimple_stmt_iterator si, switch_si;
6913 gimple sections_stmt, stmt, cont;
6914 edge_iterator ei;
6915 edge e;
6916 struct omp_region *inner;
6917 unsigned i, casei;
6918 bool exit_reachable = region->cont != NULL;
6920 gcc_assert (region->exit != NULL);
6921 entry_bb = region->entry;
6922 l0_bb = single_succ (entry_bb);
6923 l1_bb = region->cont;
6924 l2_bb = region->exit;
6925 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6926 l2 = gimple_block_label (l2_bb);
6927 else
6929 /* This can happen if there are reductions. */
6930 len = EDGE_COUNT (l0_bb->succs);
6931 gcc_assert (len > 0);
6932 e = EDGE_SUCC (l0_bb, len - 1);
6933 si = gsi_last_bb (e->dest);
6934 l2 = NULL_TREE;
6935 if (gsi_end_p (si)
6936 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6937 l2 = gimple_block_label (e->dest);
6938 else
6939 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6941 si = gsi_last_bb (e->dest);
6942 if (gsi_end_p (si)
6943 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6945 l2 = gimple_block_label (e->dest);
6946 break;
6950 if (exit_reachable)
6951 default_bb = create_empty_bb (l1_bb->prev_bb);
6952 else
6953 default_bb = create_empty_bb (l0_bb);
6955 /* We will build a switch() with enough cases for all the
6956 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
6957 and a default case to abort if something goes wrong. */
6958 len = EDGE_COUNT (l0_bb->succs);
6960 /* Use vec::quick_push on label_vec throughout, since we know the size
6961 in advance. */
6962 auto_vec<tree> label_vec (len);
6964 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
6965 GIMPLE_OMP_SECTIONS statement. */
6966 si = gsi_last_bb (entry_bb);
6967 sections_stmt = gsi_stmt (si);
6968 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
6969 vin = gimple_omp_sections_control (sections_stmt);
6970 if (!is_combined_parallel (region))
6972 /* If we are not inside a combined parallel+sections region,
6973 call GOMP_sections_start. */
6974 t = build_int_cst (unsigned_type_node, len - 1);
6975 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
6976 stmt = gimple_build_call (u, 1, t);
6978 else
6980 /* Otherwise, call GOMP_sections_next. */
6981 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
6982 stmt = gimple_build_call (u, 0);
6984 gimple_call_set_lhs (stmt, vin);
6985 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
6986 gsi_remove (&si, true);
6988 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
6989 L0_BB. */
6990 switch_si = gsi_last_bb (l0_bb);
6991 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
6992 if (exit_reachable)
6994 cont = last_stmt (l1_bb);
6995 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
6996 vmain = gimple_omp_continue_control_use (cont);
6997 vnext = gimple_omp_continue_control_def (cont);
6999 else
7001 vmain = vin;
7002 vnext = NULL_TREE;
7005 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7006 label_vec.quick_push (t);
7007 i = 1;
7009 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7010 for (inner = region->inner, casei = 1;
7011 inner;
7012 inner = inner->next, i++, casei++)
7014 basic_block s_entry_bb, s_exit_bb;
7016 /* Skip optional reduction region. */
7017 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7019 --i;
7020 --casei;
7021 continue;
7024 s_entry_bb = inner->entry;
7025 s_exit_bb = inner->exit;
7027 t = gimple_block_label (s_entry_bb);
7028 u = build_int_cst (unsigned_type_node, casei);
7029 u = build_case_label (u, NULL, t);
7030 label_vec.quick_push (u);
7032 si = gsi_last_bb (s_entry_bb);
7033 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7034 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7035 gsi_remove (&si, true);
7036 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7038 if (s_exit_bb == NULL)
7039 continue;
7041 si = gsi_last_bb (s_exit_bb);
7042 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7043 gsi_remove (&si, true);
7045 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7048 /* Error handling code goes in DEFAULT_BB. */
7049 t = gimple_block_label (default_bb);
7050 u = build_case_label (NULL, NULL, t);
7051 make_edge (l0_bb, default_bb, 0);
7052 if (current_loops)
7053 add_bb_to_loop (default_bb, current_loops->tree_root);
7055 stmt = gimple_build_switch (vmain, u, label_vec);
7056 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7057 gsi_remove (&switch_si, true);
7059 si = gsi_start_bb (default_bb);
7060 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7061 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7063 if (exit_reachable)
7065 tree bfn_decl;
7067 /* Code to get the next section goes in L1_BB. */
7068 si = gsi_last_bb (l1_bb);
7069 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7071 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7072 stmt = gimple_build_call (bfn_decl, 0);
7073 gimple_call_set_lhs (stmt, vnext);
7074 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7075 gsi_remove (&si, true);
7077 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7080 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7081 si = gsi_last_bb (l2_bb);
7082 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7083 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7084 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7085 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7086 else
7087 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7088 stmt = gimple_build_call (t, 0);
7089 if (gimple_omp_return_lhs (gsi_stmt (si)))
7090 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7091 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7092 gsi_remove (&si, true);
7094 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7098 /* Expand code for an OpenMP single directive. We've already expanded
7099 much of the code, here we simply place the GOMP_barrier call. */
7101 static void
7102 expand_omp_single (struct omp_region *region)
7104 basic_block entry_bb, exit_bb;
7105 gimple_stmt_iterator si;
7107 entry_bb = region->entry;
7108 exit_bb = region->exit;
7110 si = gsi_last_bb (entry_bb);
7111 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7112 gsi_remove (&si, true);
7113 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7115 si = gsi_last_bb (exit_bb);
7116 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7118 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7119 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7121 gsi_remove (&si, true);
7122 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7126 /* Generic expansion for OpenMP synchronization directives: master,
7127 ordered and critical. All we need to do here is remove the entry
7128 and exit markers for REGION. */
7130 static void
7131 expand_omp_synch (struct omp_region *region)
7133 basic_block entry_bb, exit_bb;
7134 gimple_stmt_iterator si;
7136 entry_bb = region->entry;
7137 exit_bb = region->exit;
7139 si = gsi_last_bb (entry_bb);
7140 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7141 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7142 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7143 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7144 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7145 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7146 gsi_remove (&si, true);
7147 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7149 if (exit_bb)
7151 si = gsi_last_bb (exit_bb);
7152 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7153 gsi_remove (&si, true);
7154 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7158 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7159 operation as a normal volatile load. */
7161 static bool
7162 expand_omp_atomic_load (basic_block load_bb, tree addr,
7163 tree loaded_val, int index)
7165 enum built_in_function tmpbase;
7166 gimple_stmt_iterator gsi;
7167 basic_block store_bb;
7168 location_t loc;
7169 gimple stmt;
7170 tree decl, call, type, itype;
7172 gsi = gsi_last_bb (load_bb);
7173 stmt = gsi_stmt (gsi);
7174 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7175 loc = gimple_location (stmt);
7177 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7178 is smaller than word size, then expand_atomic_load assumes that the load
7179 is atomic. We could avoid the builtin entirely in this case. */
7181 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7182 decl = builtin_decl_explicit (tmpbase);
7183 if (decl == NULL_TREE)
7184 return false;
7186 type = TREE_TYPE (loaded_val);
7187 itype = TREE_TYPE (TREE_TYPE (decl));
7189 call = build_call_expr_loc (loc, decl, 2, addr,
7190 build_int_cst (NULL,
7191 gimple_omp_atomic_seq_cst_p (stmt)
7192 ? MEMMODEL_SEQ_CST
7193 : MEMMODEL_RELAXED));
7194 if (!useless_type_conversion_p (type, itype))
7195 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7196 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7198 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7199 gsi_remove (&gsi, true);
7201 store_bb = single_succ (load_bb);
7202 gsi = gsi_last_bb (store_bb);
7203 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7204 gsi_remove (&gsi, true);
7206 if (gimple_in_ssa_p (cfun))
7207 update_ssa (TODO_update_ssa_no_phi);
7209 return true;
7212 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7213 operation as a normal volatile store. */
7215 static bool
7216 expand_omp_atomic_store (basic_block load_bb, tree addr,
7217 tree loaded_val, tree stored_val, int index)
7219 enum built_in_function tmpbase;
7220 gimple_stmt_iterator gsi;
7221 basic_block store_bb = single_succ (load_bb);
7222 location_t loc;
7223 gimple stmt;
7224 tree decl, call, type, itype;
7225 enum machine_mode imode;
7226 bool exchange;
7228 gsi = gsi_last_bb (load_bb);
7229 stmt = gsi_stmt (gsi);
7230 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7232 /* If the load value is needed, then this isn't a store but an exchange. */
7233 exchange = gimple_omp_atomic_need_value_p (stmt);
7235 gsi = gsi_last_bb (store_bb);
7236 stmt = gsi_stmt (gsi);
7237 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7238 loc = gimple_location (stmt);
7240 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7241 is smaller than word size, then expand_atomic_store assumes that the store
7242 is atomic. We could avoid the builtin entirely in this case. */
7244 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7245 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7246 decl = builtin_decl_explicit (tmpbase);
7247 if (decl == NULL_TREE)
7248 return false;
7250 type = TREE_TYPE (stored_val);
7252 /* Dig out the type of the function's second argument. */
7253 itype = TREE_TYPE (decl);
7254 itype = TYPE_ARG_TYPES (itype);
7255 itype = TREE_CHAIN (itype);
7256 itype = TREE_VALUE (itype);
7257 imode = TYPE_MODE (itype);
7259 if (exchange && !can_atomic_exchange_p (imode, true))
7260 return false;
7262 if (!useless_type_conversion_p (itype, type))
7263 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7264 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7265 build_int_cst (NULL,
7266 gimple_omp_atomic_seq_cst_p (stmt)
7267 ? MEMMODEL_SEQ_CST
7268 : MEMMODEL_RELAXED));
7269 if (exchange)
7271 if (!useless_type_conversion_p (type, itype))
7272 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7273 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7276 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7277 gsi_remove (&gsi, true);
7279 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7280 gsi = gsi_last_bb (load_bb);
7281 gsi_remove (&gsi, true);
7283 if (gimple_in_ssa_p (cfun))
7284 update_ssa (TODO_update_ssa_no_phi);
7286 return true;
7289 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7290 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7291 size of the data type, and thus usable to find the index of the builtin
7292 decl. Returns false if the expression is not of the proper form. */
7294 static bool
7295 expand_omp_atomic_fetch_op (basic_block load_bb,
7296 tree addr, tree loaded_val,
7297 tree stored_val, int index)
7299 enum built_in_function oldbase, newbase, tmpbase;
7300 tree decl, itype, call;
7301 tree lhs, rhs;
7302 basic_block store_bb = single_succ (load_bb);
7303 gimple_stmt_iterator gsi;
7304 gimple stmt;
7305 location_t loc;
7306 enum tree_code code;
7307 bool need_old, need_new;
7308 enum machine_mode imode;
7309 bool seq_cst;
7311 /* We expect to find the following sequences:
7313 load_bb:
7314 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7316 store_bb:
7317 val = tmp OP something; (or: something OP tmp)
7318 GIMPLE_OMP_STORE (val)
7320 ???FIXME: Allow a more flexible sequence.
7321 Perhaps use data flow to pick the statements.
7325 gsi = gsi_after_labels (store_bb);
7326 stmt = gsi_stmt (gsi);
7327 loc = gimple_location (stmt);
7328 if (!is_gimple_assign (stmt))
7329 return false;
7330 gsi_next (&gsi);
7331 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7332 return false;
7333 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7334 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7335 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7336 gcc_checking_assert (!need_old || !need_new);
7338 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7339 return false;
7341 /* Check for one of the supported fetch-op operations. */
7342 code = gimple_assign_rhs_code (stmt);
7343 switch (code)
7345 case PLUS_EXPR:
7346 case POINTER_PLUS_EXPR:
7347 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7348 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7349 break;
7350 case MINUS_EXPR:
7351 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7352 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7353 break;
7354 case BIT_AND_EXPR:
7355 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7356 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7357 break;
7358 case BIT_IOR_EXPR:
7359 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7360 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7361 break;
7362 case BIT_XOR_EXPR:
7363 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7364 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7365 break;
7366 default:
7367 return false;
7370 /* Make sure the expression is of the proper form. */
7371 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7372 rhs = gimple_assign_rhs2 (stmt);
7373 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7374 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7375 rhs = gimple_assign_rhs1 (stmt);
7376 else
7377 return false;
7379 tmpbase = ((enum built_in_function)
7380 ((need_new ? newbase : oldbase) + index + 1));
7381 decl = builtin_decl_explicit (tmpbase);
7382 if (decl == NULL_TREE)
7383 return false;
7384 itype = TREE_TYPE (TREE_TYPE (decl));
7385 imode = TYPE_MODE (itype);
7387 /* We could test all of the various optabs involved, but the fact of the
7388 matter is that (with the exception of i486 vs i586 and xadd) all targets
7389 that support any atomic operaton optab also implements compare-and-swap.
7390 Let optabs.c take care of expanding any compare-and-swap loop. */
7391 if (!can_compare_and_swap_p (imode, true))
7392 return false;
7394 gsi = gsi_last_bb (load_bb);
7395 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7397 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7398 It only requires that the operation happen atomically. Thus we can
7399 use the RELAXED memory model. */
7400 call = build_call_expr_loc (loc, decl, 3, addr,
7401 fold_convert_loc (loc, itype, rhs),
7402 build_int_cst (NULL,
7403 seq_cst ? MEMMODEL_SEQ_CST
7404 : MEMMODEL_RELAXED));
7406 if (need_old || need_new)
7408 lhs = need_old ? loaded_val : stored_val;
7409 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7410 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7412 else
7413 call = fold_convert_loc (loc, void_type_node, call);
7414 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7415 gsi_remove (&gsi, true);
7417 gsi = gsi_last_bb (store_bb);
7418 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7419 gsi_remove (&gsi, true);
7420 gsi = gsi_last_bb (store_bb);
7421 gsi_remove (&gsi, true);
7423 if (gimple_in_ssa_p (cfun))
7424 update_ssa (TODO_update_ssa_no_phi);
7426 return true;
7429 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7431 oldval = *addr;
7432 repeat:
7433 newval = rhs; // with oldval replacing *addr in rhs
7434 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7435 if (oldval != newval)
7436 goto repeat;
7438 INDEX is log2 of the size of the data type, and thus usable to find the
7439 index of the builtin decl. */
7441 static bool
7442 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7443 tree addr, tree loaded_val, tree stored_val,
7444 int index)
7446 tree loadedi, storedi, initial, new_storedi, old_vali;
7447 tree type, itype, cmpxchg, iaddr;
7448 gimple_stmt_iterator si;
7449 basic_block loop_header = single_succ (load_bb);
7450 gimple phi, stmt;
7451 edge e;
7452 enum built_in_function fncode;
7454 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7455 order to use the RELAXED memory model effectively. */
7456 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7457 + index + 1);
7458 cmpxchg = builtin_decl_explicit (fncode);
7459 if (cmpxchg == NULL_TREE)
7460 return false;
7461 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7462 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7464 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7465 return false;
7467 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7468 si = gsi_last_bb (load_bb);
7469 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7471 /* For floating-point values, we'll need to view-convert them to integers
7472 so that we can perform the atomic compare and swap. Simplify the
7473 following code by always setting up the "i"ntegral variables. */
7474 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7476 tree iaddr_val;
7478 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7479 true), NULL);
7480 iaddr_val
7481 = force_gimple_operand_gsi (&si,
7482 fold_convert (TREE_TYPE (iaddr), addr),
7483 false, NULL_TREE, true, GSI_SAME_STMT);
7484 stmt = gimple_build_assign (iaddr, iaddr_val);
7485 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7486 loadedi = create_tmp_var (itype, NULL);
7487 if (gimple_in_ssa_p (cfun))
7488 loadedi = make_ssa_name (loadedi, NULL);
7490 else
7492 iaddr = addr;
7493 loadedi = loaded_val;
7496 initial
7497 = force_gimple_operand_gsi (&si,
7498 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
7499 iaddr,
7500 build_int_cst (TREE_TYPE (iaddr), 0)),
7501 true, NULL_TREE, true, GSI_SAME_STMT);
7503 /* Move the value to the LOADEDI temporary. */
7504 if (gimple_in_ssa_p (cfun))
7506 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7507 phi = create_phi_node (loadedi, loop_header);
7508 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7509 initial);
7511 else
7512 gsi_insert_before (&si,
7513 gimple_build_assign (loadedi, initial),
7514 GSI_SAME_STMT);
7515 if (loadedi != loaded_val)
7517 gimple_stmt_iterator gsi2;
7518 tree x;
7520 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7521 gsi2 = gsi_start_bb (loop_header);
7522 if (gimple_in_ssa_p (cfun))
7524 gimple stmt;
7525 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7526 true, GSI_SAME_STMT);
7527 stmt = gimple_build_assign (loaded_val, x);
7528 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7530 else
7532 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7533 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7534 true, GSI_SAME_STMT);
7537 gsi_remove (&si, true);
7539 si = gsi_last_bb (store_bb);
7540 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7542 if (iaddr == addr)
7543 storedi = stored_val;
7544 else
7545 storedi =
7546 force_gimple_operand_gsi (&si,
7547 build1 (VIEW_CONVERT_EXPR, itype,
7548 stored_val), true, NULL_TREE, true,
7549 GSI_SAME_STMT);
7551 /* Build the compare&swap statement. */
7552 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7553 new_storedi = force_gimple_operand_gsi (&si,
7554 fold_convert (TREE_TYPE (loadedi),
7555 new_storedi),
7556 true, NULL_TREE,
7557 true, GSI_SAME_STMT);
7559 if (gimple_in_ssa_p (cfun))
7560 old_vali = loadedi;
7561 else
7563 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7564 stmt = gimple_build_assign (old_vali, loadedi);
7565 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7567 stmt = gimple_build_assign (loadedi, new_storedi);
7568 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7571 /* Note that we always perform the comparison as an integer, even for
7572 floating point. This allows the atomic operation to properly
7573 succeed even with NaNs and -0.0. */
7574 stmt = gimple_build_cond_empty
7575 (build2 (NE_EXPR, boolean_type_node,
7576 new_storedi, old_vali));
7577 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7579 /* Update cfg. */
7580 e = single_succ_edge (store_bb);
7581 e->flags &= ~EDGE_FALLTHRU;
7582 e->flags |= EDGE_FALSE_VALUE;
7584 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7586 /* Copy the new value to loadedi (we already did that before the condition
7587 if we are not in SSA). */
7588 if (gimple_in_ssa_p (cfun))
7590 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7591 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7594 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7595 gsi_remove (&si, true);
7597 struct loop *loop = alloc_loop ();
7598 loop->header = loop_header;
7599 loop->latch = store_bb;
7600 add_loop (loop, loop_header->loop_father);
7602 if (gimple_in_ssa_p (cfun))
7603 update_ssa (TODO_update_ssa_no_phi);
7605 return true;
7608 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7610 GOMP_atomic_start ();
7611 *addr = rhs;
7612 GOMP_atomic_end ();
7614 The result is not globally atomic, but works so long as all parallel
7615 references are within #pragma omp atomic directives. According to
7616 responses received from omp@openmp.org, appears to be within spec.
7617 Which makes sense, since that's how several other compilers handle
7618 this situation as well.
7619 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7620 expanding. STORED_VAL is the operand of the matching
7621 GIMPLE_OMP_ATOMIC_STORE.
7623 We replace
7624 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7625 loaded_val = *addr;
7627 and replace
7628 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7629 *addr = stored_val;
7632 static bool
7633 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7634 tree addr, tree loaded_val, tree stored_val)
7636 gimple_stmt_iterator si;
7637 gimple stmt;
7638 tree t;
7640 si = gsi_last_bb (load_bb);
7641 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7643 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7644 t = build_call_expr (t, 0);
7645 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7647 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7648 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7649 gsi_remove (&si, true);
7651 si = gsi_last_bb (store_bb);
7652 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7654 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7655 stored_val);
7656 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7658 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7659 t = build_call_expr (t, 0);
7660 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7661 gsi_remove (&si, true);
7663 if (gimple_in_ssa_p (cfun))
7664 update_ssa (TODO_update_ssa_no_phi);
7665 return true;
7668 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7669 using expand_omp_atomic_fetch_op. If it failed, we try to
7670 call expand_omp_atomic_pipeline, and if it fails too, the
7671 ultimate fallback is wrapping the operation in a mutex
7672 (expand_omp_atomic_mutex). REGION is the atomic region built
7673 by build_omp_regions_1(). */
7675 static void
7676 expand_omp_atomic (struct omp_region *region)
7678 basic_block load_bb = region->entry, store_bb = region->exit;
7679 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7680 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7681 tree addr = gimple_omp_atomic_load_rhs (load);
7682 tree stored_val = gimple_omp_atomic_store_val (store);
7683 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7684 HOST_WIDE_INT index;
7686 /* Make sure the type is one of the supported sizes. */
7687 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7688 index = exact_log2 (index);
7689 if (index >= 0 && index <= 4)
7691 unsigned int align = TYPE_ALIGN_UNIT (type);
7693 /* __sync builtins require strict data alignment. */
7694 if (exact_log2 (align) >= index)
7696 /* Atomic load. */
7697 if (loaded_val == stored_val
7698 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7699 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7700 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7701 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7702 return;
7704 /* Atomic store. */
7705 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7706 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7707 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7708 && store_bb == single_succ (load_bb)
7709 && first_stmt (store_bb) == store
7710 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7711 stored_val, index))
7712 return;
7714 /* When possible, use specialized atomic update functions. */
7715 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7716 && store_bb == single_succ (load_bb)
7717 && expand_omp_atomic_fetch_op (load_bb, addr,
7718 loaded_val, stored_val, index))
7719 return;
7721 /* If we don't have specialized __sync builtins, try and implement
7722 as a compare and swap loop. */
7723 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7724 loaded_val, stored_val, index))
7725 return;
7729 /* The ultimate fallback is wrapping the operation in a mutex. */
7730 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7734 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7736 static void
7737 expand_omp_target (struct omp_region *region)
7739 basic_block entry_bb, exit_bb, new_bb;
7740 struct function *child_cfun = NULL;
7741 tree child_fn = NULL_TREE, block, t;
7742 gimple_stmt_iterator gsi;
7743 gimple entry_stmt, stmt;
7744 edge e;
7746 entry_stmt = last_stmt (region->entry);
7747 new_bb = region->entry;
7748 int kind = gimple_omp_target_kind (entry_stmt);
7749 if (kind == GF_OMP_TARGET_KIND_REGION)
7751 child_fn = gimple_omp_target_child_fn (entry_stmt);
7752 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7755 entry_bb = region->entry;
7756 exit_bb = region->exit;
7758 if (kind == GF_OMP_TARGET_KIND_REGION)
7760 unsigned srcidx, dstidx, num;
7762 /* If the target region needs data sent from the parent
7763 function, then the very first statement (except possible
7764 tree profile counter updates) of the parallel body
7765 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7766 &.OMP_DATA_O is passed as an argument to the child function,
7767 we need to replace it with the argument as seen by the child
7768 function.
7770 In most cases, this will end up being the identity assignment
7771 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7772 a function call that has been inlined, the original PARM_DECL
7773 .OMP_DATA_I may have been converted into a different local
7774 variable. In which case, we need to keep the assignment. */
7775 if (gimple_omp_target_data_arg (entry_stmt))
7777 basic_block entry_succ_bb = single_succ (entry_bb);
7778 gimple_stmt_iterator gsi;
7779 tree arg;
7780 gimple tgtcopy_stmt = NULL;
7781 tree sender
7782 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7784 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7786 gcc_assert (!gsi_end_p (gsi));
7787 stmt = gsi_stmt (gsi);
7788 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7789 continue;
7791 if (gimple_num_ops (stmt) == 2)
7793 tree arg = gimple_assign_rhs1 (stmt);
7795 /* We're ignoring the subcode because we're
7796 effectively doing a STRIP_NOPS. */
7798 if (TREE_CODE (arg) == ADDR_EXPR
7799 && TREE_OPERAND (arg, 0) == sender)
7801 tgtcopy_stmt = stmt;
7802 break;
7807 gcc_assert (tgtcopy_stmt != NULL);
7808 arg = DECL_ARGUMENTS (child_fn);
7810 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7811 gsi_remove (&gsi, true);
7814 /* Declare local variables needed in CHILD_CFUN. */
7815 block = DECL_INITIAL (child_fn);
7816 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7817 /* The gimplifier could record temporaries in target block
7818 rather than in containing function's local_decls chain,
7819 which would mean cgraph missed finalizing them. Do it now. */
7820 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7821 if (TREE_CODE (t) == VAR_DECL
7822 && TREE_STATIC (t)
7823 && !DECL_EXTERNAL (t))
7824 varpool_finalize_decl (t);
7825 DECL_SAVED_TREE (child_fn) = NULL;
7826 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7827 gimple_set_body (child_fn, NULL);
7828 TREE_USED (block) = 1;
7830 /* Reset DECL_CONTEXT on function arguments. */
7831 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7832 DECL_CONTEXT (t) = child_fn;
7834 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7835 so that it can be moved to the child function. */
7836 gsi = gsi_last_bb (entry_bb);
7837 stmt = gsi_stmt (gsi);
7838 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7839 && gimple_omp_target_kind (stmt)
7840 == GF_OMP_TARGET_KIND_REGION);
7841 gsi_remove (&gsi, true);
7842 e = split_block (entry_bb, stmt);
7843 entry_bb = e->dest;
7844 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7846 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7847 if (exit_bb)
7849 gsi = gsi_last_bb (exit_bb);
7850 gcc_assert (!gsi_end_p (gsi)
7851 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7852 stmt = gimple_build_return (NULL);
7853 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7854 gsi_remove (&gsi, true);
7857 /* Move the target region into CHILD_CFUN. */
7859 block = gimple_block (entry_stmt);
7861 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7862 if (exit_bb)
7863 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7864 /* When the OMP expansion process cannot guarantee an up-to-date
7865 loop tree arrange for the child function to fixup loops. */
7866 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7867 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7869 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7870 num = vec_safe_length (child_cfun->local_decls);
7871 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7873 t = (*child_cfun->local_decls)[srcidx];
7874 if (DECL_CONTEXT (t) == cfun->decl)
7875 continue;
7876 if (srcidx != dstidx)
7877 (*child_cfun->local_decls)[dstidx] = t;
7878 dstidx++;
7880 if (dstidx != num)
7881 vec_safe_truncate (child_cfun->local_decls, dstidx);
7883 /* Inform the callgraph about the new function. */
7884 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7885 cgraph_add_new_function (child_fn, true);
7887 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7888 fixed in a following pass. */
7889 push_cfun (child_cfun);
7890 rebuild_cgraph_edges ();
7892 /* Some EH regions might become dead, see PR34608. If
7893 pass_cleanup_cfg isn't the first pass to happen with the
7894 new child, these dead EH edges might cause problems.
7895 Clean them up now. */
7896 if (flag_exceptions)
7898 basic_block bb;
7899 bool changed = false;
7901 FOR_EACH_BB (bb)
7902 changed |= gimple_purge_dead_eh_edges (bb);
7903 if (changed)
7904 cleanup_tree_cfg ();
7906 pop_cfun ();
7909 /* Emit a library call to launch the target region, or do data
7910 transfers. */
7911 tree t1, t2, t3, t4, device, cond, c, clauses;
7912 enum built_in_function start_ix;
7913 location_t clause_loc;
7915 clauses = gimple_omp_target_clauses (entry_stmt);
7917 if (kind == GF_OMP_TARGET_KIND_REGION)
7918 start_ix = BUILT_IN_GOMP_TARGET;
7919 else if (kind == GF_OMP_TARGET_KIND_DATA)
7920 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7921 else
7922 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7924 /* By default, the value of DEVICE is -1 (let runtime library choose)
7925 and there is no conditional. */
7926 cond = NULL_TREE;
7927 device = build_int_cst (integer_type_node, -1);
7929 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7930 if (c)
7931 cond = OMP_CLAUSE_IF_EXPR (c);
7933 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7934 if (c)
7936 device = OMP_CLAUSE_DEVICE_ID (c);
7937 clause_loc = OMP_CLAUSE_LOCATION (c);
7939 else
7940 clause_loc = gimple_location (entry_stmt);
7942 /* Ensure 'device' is of the correct type. */
7943 device = fold_convert_loc (clause_loc, integer_type_node, device);
7945 /* If we found the clause 'if (cond)', build
7946 (cond ? device : -2). */
7947 if (cond)
7949 cond = gimple_boolify (cond);
7951 basic_block cond_bb, then_bb, else_bb;
7952 edge e;
7953 tree tmp_var;
7955 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
7956 if (kind != GF_OMP_TARGET_KIND_REGION)
7958 gsi = gsi_last_bb (new_bb);
7959 gsi_prev (&gsi);
7960 e = split_block (new_bb, gsi_stmt (gsi));
7962 else
7963 e = split_block (new_bb, NULL);
7964 cond_bb = e->src;
7965 new_bb = e->dest;
7966 remove_edge (e);
7968 then_bb = create_empty_bb (cond_bb);
7969 else_bb = create_empty_bb (then_bb);
7970 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
7971 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
7973 stmt = gimple_build_cond_empty (cond);
7974 gsi = gsi_last_bb (cond_bb);
7975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7977 gsi = gsi_start_bb (then_bb);
7978 stmt = gimple_build_assign (tmp_var, device);
7979 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7981 gsi = gsi_start_bb (else_bb);
7982 stmt = gimple_build_assign (tmp_var,
7983 build_int_cst (integer_type_node, -2));
7984 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7986 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
7987 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
7988 if (current_loops)
7990 add_bb_to_loop (then_bb, cond_bb->loop_father);
7991 add_bb_to_loop (else_bb, cond_bb->loop_father);
7993 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
7994 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
7996 device = tmp_var;
7999 gsi = gsi_last_bb (new_bb);
8000 t = gimple_omp_target_data_arg (entry_stmt);
8001 if (t == NULL)
8003 t1 = size_zero_node;
8004 t2 = build_zero_cst (ptr_type_node);
8005 t3 = t2;
8006 t4 = t2;
8008 else
8010 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8011 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8012 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8013 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8014 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8017 gimple g;
8018 /* FIXME: This will be address of
8019 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8020 symbol, as soon as the linker plugin is able to create it for us. */
8021 tree openmp_target = build_zero_cst (ptr_type_node);
8022 if (kind == GF_OMP_TARGET_KIND_REGION)
8024 tree fnaddr = build_fold_addr_expr (child_fn);
8025 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8026 device, fnaddr, openmp_target, t1, t2, t3, t4);
8028 else
8029 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8030 device, openmp_target, t1, t2, t3, t4);
8031 gimple_set_location (g, gimple_location (entry_stmt));
8032 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8033 if (kind != GF_OMP_TARGET_KIND_REGION)
8035 g = gsi_stmt (gsi);
8036 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8037 gsi_remove (&gsi, true);
8039 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8041 gsi = gsi_last_bb (region->exit);
8042 g = gsi_stmt (gsi);
8043 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8044 gsi_remove (&gsi, true);
8049 /* Expand the parallel region tree rooted at REGION. Expansion
8050 proceeds in depth-first order. Innermost regions are expanded
8051 first. This way, parallel regions that require a new function to
8052 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8053 internal dependencies in their body. */
8055 static void
8056 expand_omp (struct omp_region *region)
8058 while (region)
8060 location_t saved_location;
8061 gimple inner_stmt = NULL;
8063 /* First, determine whether this is a combined parallel+workshare
8064 region. */
8065 if (region->type == GIMPLE_OMP_PARALLEL)
8066 determine_parallel_type (region);
8068 if (region->type == GIMPLE_OMP_FOR
8069 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8070 inner_stmt = last_stmt (region->inner->entry);
8072 if (region->inner)
8073 expand_omp (region->inner);
8075 saved_location = input_location;
8076 if (gimple_has_location (last_stmt (region->entry)))
8077 input_location = gimple_location (last_stmt (region->entry));
8079 switch (region->type)
8081 case GIMPLE_OMP_PARALLEL:
8082 case GIMPLE_OMP_TASK:
8083 expand_omp_taskreg (region);
8084 break;
8086 case GIMPLE_OMP_FOR:
8087 expand_omp_for (region, inner_stmt);
8088 break;
8090 case GIMPLE_OMP_SECTIONS:
8091 expand_omp_sections (region);
8092 break;
8094 case GIMPLE_OMP_SECTION:
8095 /* Individual omp sections are handled together with their
8096 parent GIMPLE_OMP_SECTIONS region. */
8097 break;
8099 case GIMPLE_OMP_SINGLE:
8100 expand_omp_single (region);
8101 break;
8103 case GIMPLE_OMP_MASTER:
8104 case GIMPLE_OMP_TASKGROUP:
8105 case GIMPLE_OMP_ORDERED:
8106 case GIMPLE_OMP_CRITICAL:
8107 case GIMPLE_OMP_TEAMS:
8108 expand_omp_synch (region);
8109 break;
8111 case GIMPLE_OMP_ATOMIC_LOAD:
8112 expand_omp_atomic (region);
8113 break;
8115 case GIMPLE_OMP_TARGET:
8116 expand_omp_target (region);
8117 break;
8119 default:
8120 gcc_unreachable ();
8123 input_location = saved_location;
8124 region = region->next;
8129 /* Helper for build_omp_regions. Scan the dominator tree starting at
8130 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8131 true, the function ends once a single tree is built (otherwise, whole
8132 forest of OMP constructs may be built). */
8134 static void
8135 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8136 bool single_tree)
8138 gimple_stmt_iterator gsi;
8139 gimple stmt;
8140 basic_block son;
8142 gsi = gsi_last_bb (bb);
8143 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8145 struct omp_region *region;
8146 enum gimple_code code;
8148 stmt = gsi_stmt (gsi);
8149 code = gimple_code (stmt);
8150 if (code == GIMPLE_OMP_RETURN)
8152 /* STMT is the return point out of region PARENT. Mark it
8153 as the exit point and make PARENT the immediately
8154 enclosing region. */
8155 gcc_assert (parent);
8156 region = parent;
8157 region->exit = bb;
8158 parent = parent->outer;
8160 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8162 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8163 GIMPLE_OMP_RETURN, but matches with
8164 GIMPLE_OMP_ATOMIC_LOAD. */
8165 gcc_assert (parent);
8166 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8167 region = parent;
8168 region->exit = bb;
8169 parent = parent->outer;
8172 else if (code == GIMPLE_OMP_CONTINUE)
8174 gcc_assert (parent);
8175 parent->cont = bb;
8177 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8179 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8180 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8183 else if (code == GIMPLE_OMP_TARGET
8184 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8185 new_omp_region (bb, code, parent);
8186 else
8188 /* Otherwise, this directive becomes the parent for a new
8189 region. */
8190 region = new_omp_region (bb, code, parent);
8191 parent = region;
8195 if (single_tree && !parent)
8196 return;
8198 for (son = first_dom_son (CDI_DOMINATORS, bb);
8199 son;
8200 son = next_dom_son (CDI_DOMINATORS, son))
8201 build_omp_regions_1 (son, parent, single_tree);
8204 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8205 root_omp_region. */
8207 static void
8208 build_omp_regions_root (basic_block root)
8210 gcc_assert (root_omp_region == NULL);
8211 build_omp_regions_1 (root, NULL, true);
8212 gcc_assert (root_omp_region != NULL);
8215 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8217 void
8218 omp_expand_local (basic_block head)
8220 build_omp_regions_root (head);
8221 if (dump_file && (dump_flags & TDF_DETAILS))
8223 fprintf (dump_file, "\nOMP region tree\n\n");
8224 dump_omp_region (dump_file, root_omp_region, 0);
8225 fprintf (dump_file, "\n");
8228 remove_exit_barriers (root_omp_region);
8229 expand_omp (root_omp_region);
8231 free_omp_regions ();
8234 /* Scan the CFG and build a tree of OMP regions. Return the root of
8235 the OMP region tree. */
8237 static void
8238 build_omp_regions (void)
8240 gcc_assert (root_omp_region == NULL);
8241 calculate_dominance_info (CDI_DOMINATORS);
8242 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8245 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8247 static unsigned int
8248 execute_expand_omp (void)
8250 build_omp_regions ();
8252 if (!root_omp_region)
8253 return 0;
8255 if (dump_file)
8257 fprintf (dump_file, "\nOMP region tree\n\n");
8258 dump_omp_region (dump_file, root_omp_region, 0);
8259 fprintf (dump_file, "\n");
8262 remove_exit_barriers (root_omp_region);
8264 expand_omp (root_omp_region);
8266 cleanup_tree_cfg ();
8268 free_omp_regions ();
8270 return 0;
8273 /* OMP expansion -- the default pass, run before creation of SSA form. */
8275 static bool
8276 gate_expand_omp (void)
8278 return ((flag_openmp != 0 || flag_openmp_simd != 0
8279 || flag_enable_cilkplus != 0) && !seen_error ());
8282 namespace {
8284 const pass_data pass_data_expand_omp =
8286 GIMPLE_PASS, /* type */
8287 "ompexp", /* name */
8288 OPTGROUP_NONE, /* optinfo_flags */
8289 true, /* has_gate */
8290 true, /* has_execute */
8291 TV_NONE, /* tv_id */
8292 PROP_gimple_any, /* properties_required */
8293 0, /* properties_provided */
8294 0, /* properties_destroyed */
8295 0, /* todo_flags_start */
8296 0, /* todo_flags_finish */
8299 class pass_expand_omp : public gimple_opt_pass
8301 public:
8302 pass_expand_omp (gcc::context *ctxt)
8303 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8306 /* opt_pass methods: */
8307 bool gate () { return gate_expand_omp (); }
8308 unsigned int execute () { return execute_expand_omp (); }
8310 }; // class pass_expand_omp
8312 } // anon namespace
8314 gimple_opt_pass *
8315 make_pass_expand_omp (gcc::context *ctxt)
8317 return new pass_expand_omp (ctxt);
8320 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8322 /* If ctx is a worksharing context inside of a cancellable parallel
8323 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8324 and conditional branch to parallel's cancel_label to handle
8325 cancellation in the implicit barrier. */
8327 static void
8328 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8330 gimple omp_return = gimple_seq_last_stmt (*body);
8331 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8332 if (gimple_omp_return_nowait_p (omp_return))
8333 return;
8334 if (ctx->outer
8335 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8336 && ctx->outer->cancellable)
8338 tree lhs = create_tmp_var (boolean_type_node, NULL);
8339 gimple_omp_return_set_lhs (omp_return, lhs);
8340 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8341 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8342 ctx->outer->cancel_label, fallthru_label);
8343 gimple_seq_add_stmt (body, g);
8344 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8348 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8349 CTX is the enclosing OMP context for the current statement. */
8351 static void
8352 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8354 tree block, control;
8355 gimple_stmt_iterator tgsi;
8356 gimple stmt, new_stmt, bind, t;
8357 gimple_seq ilist, dlist, olist, new_body;
8359 stmt = gsi_stmt (*gsi_p);
8361 push_gimplify_context ();
8363 dlist = NULL;
8364 ilist = NULL;
8365 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8366 &ilist, &dlist, ctx, NULL);
8368 new_body = gimple_omp_body (stmt);
8369 gimple_omp_set_body (stmt, NULL);
8370 tgsi = gsi_start (new_body);
8371 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8373 omp_context *sctx;
8374 gimple sec_start;
8376 sec_start = gsi_stmt (tgsi);
8377 sctx = maybe_lookup_ctx (sec_start);
8378 gcc_assert (sctx);
8380 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8381 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8382 GSI_CONTINUE_LINKING);
8383 gimple_omp_set_body (sec_start, NULL);
8385 if (gsi_one_before_end_p (tgsi))
8387 gimple_seq l = NULL;
8388 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8389 &l, ctx);
8390 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8391 gimple_omp_section_set_last (sec_start);
8394 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8395 GSI_CONTINUE_LINKING);
8398 block = make_node (BLOCK);
8399 bind = gimple_build_bind (NULL, new_body, block);
8401 olist = NULL;
8402 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8404 block = make_node (BLOCK);
8405 new_stmt = gimple_build_bind (NULL, NULL, block);
8406 gsi_replace (gsi_p, new_stmt, true);
8408 pop_gimplify_context (new_stmt);
8409 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8410 BLOCK_VARS (block) = gimple_bind_vars (bind);
8411 if (BLOCK_VARS (block))
8412 TREE_USED (block) = 1;
8414 new_body = NULL;
8415 gimple_seq_add_seq (&new_body, ilist);
8416 gimple_seq_add_stmt (&new_body, stmt);
8417 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8418 gimple_seq_add_stmt (&new_body, bind);
8420 control = create_tmp_var (unsigned_type_node, ".section");
8421 t = gimple_build_omp_continue (control, control);
8422 gimple_omp_sections_set_control (stmt, control);
8423 gimple_seq_add_stmt (&new_body, t);
8425 gimple_seq_add_seq (&new_body, olist);
8426 if (ctx->cancellable)
8427 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8428 gimple_seq_add_seq (&new_body, dlist);
8430 new_body = maybe_catch_exception (new_body);
8432 t = gimple_build_omp_return
8433 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8434 OMP_CLAUSE_NOWAIT));
8435 gimple_seq_add_stmt (&new_body, t);
8436 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8438 gimple_bind_set_body (new_stmt, new_body);
8442 /* A subroutine of lower_omp_single. Expand the simple form of
8443 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8445 if (GOMP_single_start ())
8446 BODY;
8447 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8449 FIXME. It may be better to delay expanding the logic of this until
8450 pass_expand_omp. The expanded logic may make the job more difficult
8451 to a synchronization analysis pass. */
8453 static void
8454 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8456 location_t loc = gimple_location (single_stmt);
8457 tree tlabel = create_artificial_label (loc);
8458 tree flabel = create_artificial_label (loc);
8459 gimple call, cond;
8460 tree lhs, decl;
8462 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8463 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8464 call = gimple_build_call (decl, 0);
8465 gimple_call_set_lhs (call, lhs);
8466 gimple_seq_add_stmt (pre_p, call);
8468 cond = gimple_build_cond (EQ_EXPR, lhs,
8469 fold_convert_loc (loc, TREE_TYPE (lhs),
8470 boolean_true_node),
8471 tlabel, flabel);
8472 gimple_seq_add_stmt (pre_p, cond);
8473 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8474 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8475 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8479 /* A subroutine of lower_omp_single. Expand the simple form of
8480 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8482 #pragma omp single copyprivate (a, b, c)
8484 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8487 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8489 BODY;
8490 copyout.a = a;
8491 copyout.b = b;
8492 copyout.c = c;
8493 GOMP_single_copy_end (&copyout);
8495 else
8497 a = copyout_p->a;
8498 b = copyout_p->b;
8499 c = copyout_p->c;
8501 GOMP_barrier ();
8504 FIXME. It may be better to delay expanding the logic of this until
8505 pass_expand_omp. The expanded logic may make the job more difficult
8506 to a synchronization analysis pass. */
8508 static void
8509 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8511 tree ptr_type, t, l0, l1, l2, bfn_decl;
8512 gimple_seq copyin_seq;
8513 location_t loc = gimple_location (single_stmt);
8515 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8517 ptr_type = build_pointer_type (ctx->record_type);
8518 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8520 l0 = create_artificial_label (loc);
8521 l1 = create_artificial_label (loc);
8522 l2 = create_artificial_label (loc);
8524 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8525 t = build_call_expr_loc (loc, bfn_decl, 0);
8526 t = fold_convert_loc (loc, ptr_type, t);
8527 gimplify_assign (ctx->receiver_decl, t, pre_p);
8529 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8530 build_int_cst (ptr_type, 0));
8531 t = build3 (COND_EXPR, void_type_node, t,
8532 build_and_jump (&l0), build_and_jump (&l1));
8533 gimplify_and_add (t, pre_p);
8535 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8537 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8539 copyin_seq = NULL;
8540 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8541 &copyin_seq, ctx);
8543 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8544 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8545 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8546 gimplify_and_add (t, pre_p);
8548 t = build_and_jump (&l2);
8549 gimplify_and_add (t, pre_p);
8551 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8553 gimple_seq_add_seq (pre_p, copyin_seq);
8555 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8559 /* Expand code for an OpenMP single directive. */
8561 static void
8562 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8564 tree block;
8565 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8566 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8568 push_gimplify_context ();
8570 block = make_node (BLOCK);
8571 bind = gimple_build_bind (NULL, NULL, block);
8572 gsi_replace (gsi_p, bind, true);
8573 bind_body = NULL;
8574 dlist = NULL;
8575 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8576 &bind_body, &dlist, ctx, NULL);
8577 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8579 gimple_seq_add_stmt (&bind_body, single_stmt);
8581 if (ctx->record_type)
8582 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8583 else
8584 lower_omp_single_simple (single_stmt, &bind_body);
8586 gimple_omp_set_body (single_stmt, NULL);
8588 gimple_seq_add_seq (&bind_body, dlist);
8590 bind_body = maybe_catch_exception (bind_body);
8592 t = gimple_build_omp_return
8593 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8594 OMP_CLAUSE_NOWAIT));
8595 gimple_seq_add_stmt (&bind_body_tail, t);
8596 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8597 if (ctx->record_type)
8599 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8600 tree clobber = build_constructor (ctx->record_type, NULL);
8601 TREE_THIS_VOLATILE (clobber) = 1;
8602 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8603 clobber), GSI_SAME_STMT);
8605 gimple_seq_add_seq (&bind_body, bind_body_tail);
8606 gimple_bind_set_body (bind, bind_body);
8608 pop_gimplify_context (bind);
8610 gimple_bind_append_vars (bind, ctx->block_vars);
8611 BLOCK_VARS (block) = ctx->block_vars;
8612 if (BLOCK_VARS (block))
8613 TREE_USED (block) = 1;
8617 /* Expand code for an OpenMP master directive. */
8619 static void
8620 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8622 tree block, lab = NULL, x, bfn_decl;
8623 gimple stmt = gsi_stmt (*gsi_p), bind;
8624 location_t loc = gimple_location (stmt);
8625 gimple_seq tseq;
8627 push_gimplify_context ();
8629 block = make_node (BLOCK);
8630 bind = gimple_build_bind (NULL, NULL, block);
8631 gsi_replace (gsi_p, bind, true);
8632 gimple_bind_add_stmt (bind, stmt);
8634 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8635 x = build_call_expr_loc (loc, bfn_decl, 0);
8636 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8637 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8638 tseq = NULL;
8639 gimplify_and_add (x, &tseq);
8640 gimple_bind_add_seq (bind, tseq);
8642 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8643 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8644 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8645 gimple_omp_set_body (stmt, NULL);
8647 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8649 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8651 pop_gimplify_context (bind);
8653 gimple_bind_append_vars (bind, ctx->block_vars);
8654 BLOCK_VARS (block) = ctx->block_vars;
8658 /* Expand code for an OpenMP taskgroup directive. */
8660 static void
8661 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8663 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8664 tree block = make_node (BLOCK);
8666 bind = gimple_build_bind (NULL, NULL, block);
8667 gsi_replace (gsi_p, bind, true);
8668 gimple_bind_add_stmt (bind, stmt);
8670 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8672 gimple_bind_add_stmt (bind, x);
8674 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8675 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8676 gimple_omp_set_body (stmt, NULL);
8678 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8680 gimple_bind_append_vars (bind, ctx->block_vars);
8681 BLOCK_VARS (block) = ctx->block_vars;
8685 /* Expand code for an OpenMP ordered directive. */
8687 static void
8688 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8690 tree block;
8691 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8693 push_gimplify_context ();
8695 block = make_node (BLOCK);
8696 bind = gimple_build_bind (NULL, NULL, block);
8697 gsi_replace (gsi_p, bind, true);
8698 gimple_bind_add_stmt (bind, stmt);
8700 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8702 gimple_bind_add_stmt (bind, x);
8704 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8705 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8706 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8707 gimple_omp_set_body (stmt, NULL);
8709 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8710 gimple_bind_add_stmt (bind, x);
8712 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8714 pop_gimplify_context (bind);
8716 gimple_bind_append_vars (bind, ctx->block_vars);
8717 BLOCK_VARS (block) = gimple_bind_vars (bind);
8721 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8722 substitution of a couple of function calls. But in the NAMED case,
8723 requires that languages coordinate a symbol name. It is therefore
8724 best put here in common code. */
8726 static GTY((param1_is (tree), param2_is (tree)))
8727 splay_tree critical_name_mutexes;
8729 static void
8730 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8732 tree block;
8733 tree name, lock, unlock;
8734 gimple stmt = gsi_stmt (*gsi_p), bind;
8735 location_t loc = gimple_location (stmt);
8736 gimple_seq tbody;
8738 name = gimple_omp_critical_name (stmt);
8739 if (name)
8741 tree decl;
8742 splay_tree_node n;
8744 if (!critical_name_mutexes)
8745 critical_name_mutexes
8746 = splay_tree_new_ggc (splay_tree_compare_pointers,
8747 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8748 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8750 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8751 if (n == NULL)
8753 char *new_str;
8755 decl = create_tmp_var_raw (ptr_type_node, NULL);
8757 new_str = ACONCAT ((".gomp_critical_user_",
8758 IDENTIFIER_POINTER (name), NULL));
8759 DECL_NAME (decl) = get_identifier (new_str);
8760 TREE_PUBLIC (decl) = 1;
8761 TREE_STATIC (decl) = 1;
8762 DECL_COMMON (decl) = 1;
8763 DECL_ARTIFICIAL (decl) = 1;
8764 DECL_IGNORED_P (decl) = 1;
8765 varpool_finalize_decl (decl);
8767 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8768 (splay_tree_value) decl);
8770 else
8771 decl = (tree) n->value;
8773 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8774 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8776 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8777 unlock = build_call_expr_loc (loc, unlock, 1,
8778 build_fold_addr_expr_loc (loc, decl));
8780 else
8782 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8783 lock = build_call_expr_loc (loc, lock, 0);
8785 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8786 unlock = build_call_expr_loc (loc, unlock, 0);
8789 push_gimplify_context ();
8791 block = make_node (BLOCK);
8792 bind = gimple_build_bind (NULL, NULL, block);
8793 gsi_replace (gsi_p, bind, true);
8794 gimple_bind_add_stmt (bind, stmt);
8796 tbody = gimple_bind_body (bind);
8797 gimplify_and_add (lock, &tbody);
8798 gimple_bind_set_body (bind, tbody);
8800 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8801 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8802 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8803 gimple_omp_set_body (stmt, NULL);
8805 tbody = gimple_bind_body (bind);
8806 gimplify_and_add (unlock, &tbody);
8807 gimple_bind_set_body (bind, tbody);
8809 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8811 pop_gimplify_context (bind);
8812 gimple_bind_append_vars (bind, ctx->block_vars);
8813 BLOCK_VARS (block) = gimple_bind_vars (bind);
8817 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8818 for a lastprivate clause. Given a loop control predicate of (V
8819 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8820 is appended to *DLIST, iterator initialization is appended to
8821 *BODY_P. */
8823 static void
8824 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8825 gimple_seq *dlist, struct omp_context *ctx)
8827 tree clauses, cond, vinit;
8828 enum tree_code cond_code;
8829 gimple_seq stmts;
8831 cond_code = fd->loop.cond_code;
8832 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8834 /* When possible, use a strict equality expression. This can let VRP
8835 type optimizations deduce the value and remove a copy. */
8836 if (tree_fits_shwi_p (fd->loop.step))
8838 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8839 if (step == 1 || step == -1)
8840 cond_code = EQ_EXPR;
8843 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8845 clauses = gimple_omp_for_clauses (fd->for_stmt);
8846 stmts = NULL;
8847 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8848 if (!gimple_seq_empty_p (stmts))
8850 gimple_seq_add_seq (&stmts, *dlist);
8851 *dlist = stmts;
8853 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8854 vinit = fd->loop.n1;
8855 if (cond_code == EQ_EXPR
8856 && tree_fits_shwi_p (fd->loop.n2)
8857 && ! integer_zerop (fd->loop.n2))
8858 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8859 else
8860 vinit = unshare_expr (vinit);
8862 /* Initialize the iterator variable, so that threads that don't execute
8863 any iterations don't execute the lastprivate clauses by accident. */
8864 gimplify_assign (fd->loop.v, vinit, body_p);
8869 /* Lower code for an OpenMP loop directive. */
8871 static void
8872 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8874 tree *rhs_p, block;
8875 struct omp_for_data fd, *fdp = NULL;
8876 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8877 gimple_seq omp_for_body, body, dlist;
8878 size_t i;
8880 push_gimplify_context ();
8882 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8884 block = make_node (BLOCK);
8885 new_stmt = gimple_build_bind (NULL, NULL, block);
8886 /* Replace at gsi right away, so that 'stmt' is no member
8887 of a sequence anymore as we're going to add to to a different
8888 one below. */
8889 gsi_replace (gsi_p, new_stmt, true);
8891 /* Move declaration of temporaries in the loop body before we make
8892 it go away. */
8893 omp_for_body = gimple_omp_body (stmt);
8894 if (!gimple_seq_empty_p (omp_for_body)
8895 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8897 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
8898 gimple_bind_append_vars (new_stmt, vars);
8901 if (gimple_omp_for_combined_into_p (stmt))
8903 extract_omp_for_data (stmt, &fd, NULL);
8904 fdp = &fd;
8906 /* We need two temporaries with fd.loop.v type (istart/iend)
8907 and then (fd.collapse - 1) temporaries with the same
8908 type for count2 ... countN-1 vars if not constant. */
8909 size_t count = 2;
8910 tree type = fd.iter_type;
8911 if (fd.collapse > 1
8912 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8913 count += fd.collapse - 1;
8914 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8915 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8916 tree clauses = *pc;
8917 if (parallel_for)
8918 outerc
8919 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8920 OMP_CLAUSE__LOOPTEMP_);
8921 for (i = 0; i < count; i++)
8923 tree temp;
8924 if (parallel_for)
8926 gcc_assert (outerc);
8927 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8928 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8929 OMP_CLAUSE__LOOPTEMP_);
8931 else
8932 temp = create_tmp_var (type, NULL);
8933 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8934 OMP_CLAUSE_DECL (*pc) = temp;
8935 pc = &OMP_CLAUSE_CHAIN (*pc);
8937 *pc = clauses;
8940 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8941 dlist = NULL;
8942 body = NULL;
8943 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
8944 fdp);
8945 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
8947 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8949 /* Lower the header expressions. At this point, we can assume that
8950 the header is of the form:
8952 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
8954 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
8955 using the .omp_data_s mapping, if needed. */
8956 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
8958 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
8959 if (!is_gimple_min_invariant (*rhs_p))
8960 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8962 rhs_p = gimple_omp_for_final_ptr (stmt, i);
8963 if (!is_gimple_min_invariant (*rhs_p))
8964 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8966 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
8967 if (!is_gimple_min_invariant (*rhs_p))
8968 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8971 /* Once lowered, extract the bounds and clauses. */
8972 extract_omp_for_data (stmt, &fd, NULL);
8974 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
8976 gimple_seq_add_stmt (&body, stmt);
8977 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
8979 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
8980 fd.loop.v));
8982 /* After the loop, add exit clauses. */
8983 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
8985 if (ctx->cancellable)
8986 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
8988 gimple_seq_add_seq (&body, dlist);
8990 body = maybe_catch_exception (body);
8992 /* Region exit marker goes at the end of the loop body. */
8993 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
8994 maybe_add_implicit_barrier_cancel (ctx, &body);
8995 pop_gimplify_context (new_stmt);
8997 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8998 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
8999 if (BLOCK_VARS (block))
9000 TREE_USED (block) = 1;
9002 gimple_bind_set_body (new_stmt, body);
9003 gimple_omp_set_body (stmt, NULL);
9004 gimple_omp_for_set_pre_body (stmt, NULL);
9007 /* Callback for walk_stmts. Check if the current statement only contains
9008 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
9010 static tree
9011 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9012 bool *handled_ops_p,
9013 struct walk_stmt_info *wi)
9015 int *info = (int *) wi->info;
9016 gimple stmt = gsi_stmt (*gsi_p);
9018 *handled_ops_p = true;
9019 switch (gimple_code (stmt))
9021 WALK_SUBSTMTS;
9023 case GIMPLE_OMP_FOR:
9024 case GIMPLE_OMP_SECTIONS:
9025 *info = *info == 0 ? 1 : -1;
9026 break;
9027 default:
9028 *info = -1;
9029 break;
9031 return NULL;
9034 struct omp_taskcopy_context
9036 /* This field must be at the beginning, as we do "inheritance": Some
9037 callback functions for tree-inline.c (e.g., omp_copy_decl)
9038 receive a copy_body_data pointer that is up-casted to an
9039 omp_context pointer. */
9040 copy_body_data cb;
9041 omp_context *ctx;
9044 static tree
9045 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9047 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9049 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9050 return create_tmp_var (TREE_TYPE (var), NULL);
9052 return var;
9055 static tree
9056 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9058 tree name, new_fields = NULL, type, f;
9060 type = lang_hooks.types.make_type (RECORD_TYPE);
9061 name = DECL_NAME (TYPE_NAME (orig_type));
9062 name = build_decl (gimple_location (tcctx->ctx->stmt),
9063 TYPE_DECL, name, type);
9064 TYPE_NAME (type) = name;
9066 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9068 tree new_f = copy_node (f);
9069 DECL_CONTEXT (new_f) = type;
9070 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9071 TREE_CHAIN (new_f) = new_fields;
9072 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9073 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9074 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9075 &tcctx->cb, NULL);
9076 new_fields = new_f;
9077 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9079 TYPE_FIELDS (type) = nreverse (new_fields);
9080 layout_type (type);
9081 return type;
9084 /* Create task copyfn. */
9086 static void
9087 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9089 struct function *child_cfun;
9090 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9091 tree record_type, srecord_type, bind, list;
9092 bool record_needs_remap = false, srecord_needs_remap = false;
9093 splay_tree_node n;
9094 struct omp_taskcopy_context tcctx;
9095 location_t loc = gimple_location (task_stmt);
9097 child_fn = gimple_omp_task_copy_fn (task_stmt);
9098 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9099 gcc_assert (child_cfun->cfg == NULL);
9100 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9102 /* Reset DECL_CONTEXT on function arguments. */
9103 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9104 DECL_CONTEXT (t) = child_fn;
9106 /* Populate the function. */
9107 push_gimplify_context ();
9108 push_cfun (child_cfun);
9110 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9111 TREE_SIDE_EFFECTS (bind) = 1;
9112 list = NULL;
9113 DECL_SAVED_TREE (child_fn) = bind;
9114 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9116 /* Remap src and dst argument types if needed. */
9117 record_type = ctx->record_type;
9118 srecord_type = ctx->srecord_type;
9119 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9120 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9122 record_needs_remap = true;
9123 break;
9125 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9126 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9128 srecord_needs_remap = true;
9129 break;
9132 if (record_needs_remap || srecord_needs_remap)
9134 memset (&tcctx, '\0', sizeof (tcctx));
9135 tcctx.cb.src_fn = ctx->cb.src_fn;
9136 tcctx.cb.dst_fn = child_fn;
9137 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9138 gcc_checking_assert (tcctx.cb.src_node);
9139 tcctx.cb.dst_node = tcctx.cb.src_node;
9140 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9141 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9142 tcctx.cb.eh_lp_nr = 0;
9143 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9144 tcctx.cb.decl_map = pointer_map_create ();
9145 tcctx.ctx = ctx;
9147 if (record_needs_remap)
9148 record_type = task_copyfn_remap_type (&tcctx, record_type);
9149 if (srecord_needs_remap)
9150 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9152 else
9153 tcctx.cb.decl_map = NULL;
9155 arg = DECL_ARGUMENTS (child_fn);
9156 TREE_TYPE (arg) = build_pointer_type (record_type);
9157 sarg = DECL_CHAIN (arg);
9158 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9160 /* First pass: initialize temporaries used in record_type and srecord_type
9161 sizes and field offsets. */
9162 if (tcctx.cb.decl_map)
9163 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9164 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9166 tree *p;
9168 decl = OMP_CLAUSE_DECL (c);
9169 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9170 if (p == NULL)
9171 continue;
9172 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9173 sf = (tree) n->value;
9174 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9175 src = build_simple_mem_ref_loc (loc, sarg);
9176 src = omp_build_component_ref (src, sf);
9177 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9178 append_to_statement_list (t, &list);
9181 /* Second pass: copy shared var pointers and copy construct non-VLA
9182 firstprivate vars. */
9183 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9184 switch (OMP_CLAUSE_CODE (c))
9186 case OMP_CLAUSE_SHARED:
9187 decl = OMP_CLAUSE_DECL (c);
9188 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9189 if (n == NULL)
9190 break;
9191 f = (tree) n->value;
9192 if (tcctx.cb.decl_map)
9193 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9194 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9195 sf = (tree) n->value;
9196 if (tcctx.cb.decl_map)
9197 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9198 src = build_simple_mem_ref_loc (loc, sarg);
9199 src = omp_build_component_ref (src, sf);
9200 dst = build_simple_mem_ref_loc (loc, arg);
9201 dst = omp_build_component_ref (dst, f);
9202 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9203 append_to_statement_list (t, &list);
9204 break;
9205 case OMP_CLAUSE_FIRSTPRIVATE:
9206 decl = OMP_CLAUSE_DECL (c);
9207 if (is_variable_sized (decl))
9208 break;
9209 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9210 if (n == NULL)
9211 break;
9212 f = (tree) n->value;
9213 if (tcctx.cb.decl_map)
9214 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9215 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9216 if (n != NULL)
9218 sf = (tree) n->value;
9219 if (tcctx.cb.decl_map)
9220 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9221 src = build_simple_mem_ref_loc (loc, sarg);
9222 src = omp_build_component_ref (src, sf);
9223 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9224 src = build_simple_mem_ref_loc (loc, src);
9226 else
9227 src = decl;
9228 dst = build_simple_mem_ref_loc (loc, arg);
9229 dst = omp_build_component_ref (dst, f);
9230 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9231 append_to_statement_list (t, &list);
9232 break;
9233 case OMP_CLAUSE_PRIVATE:
9234 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9235 break;
9236 decl = OMP_CLAUSE_DECL (c);
9237 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9238 f = (tree) n->value;
9239 if (tcctx.cb.decl_map)
9240 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9241 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9242 if (n != NULL)
9244 sf = (tree) n->value;
9245 if (tcctx.cb.decl_map)
9246 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9247 src = build_simple_mem_ref_loc (loc, sarg);
9248 src = omp_build_component_ref (src, sf);
9249 if (use_pointer_for_field (decl, NULL))
9250 src = build_simple_mem_ref_loc (loc, src);
9252 else
9253 src = decl;
9254 dst = build_simple_mem_ref_loc (loc, arg);
9255 dst = omp_build_component_ref (dst, f);
9256 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9257 append_to_statement_list (t, &list);
9258 break;
9259 default:
9260 break;
9263 /* Last pass: handle VLA firstprivates. */
9264 if (tcctx.cb.decl_map)
9265 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9266 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9268 tree ind, ptr, df;
9270 decl = OMP_CLAUSE_DECL (c);
9271 if (!is_variable_sized (decl))
9272 continue;
9273 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9274 if (n == NULL)
9275 continue;
9276 f = (tree) n->value;
9277 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9278 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9279 ind = DECL_VALUE_EXPR (decl);
9280 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9281 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9282 n = splay_tree_lookup (ctx->sfield_map,
9283 (splay_tree_key) TREE_OPERAND (ind, 0));
9284 sf = (tree) n->value;
9285 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9286 src = build_simple_mem_ref_loc (loc, sarg);
9287 src = omp_build_component_ref (src, sf);
9288 src = build_simple_mem_ref_loc (loc, src);
9289 dst = build_simple_mem_ref_loc (loc, arg);
9290 dst = omp_build_component_ref (dst, f);
9291 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9292 append_to_statement_list (t, &list);
9293 n = splay_tree_lookup (ctx->field_map,
9294 (splay_tree_key) TREE_OPERAND (ind, 0));
9295 df = (tree) n->value;
9296 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9297 ptr = build_simple_mem_ref_loc (loc, arg);
9298 ptr = omp_build_component_ref (ptr, df);
9299 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9300 build_fold_addr_expr_loc (loc, dst));
9301 append_to_statement_list (t, &list);
9304 t = build1 (RETURN_EXPR, void_type_node, NULL);
9305 append_to_statement_list (t, &list);
9307 if (tcctx.cb.decl_map)
9308 pointer_map_destroy (tcctx.cb.decl_map);
9309 pop_gimplify_context (NULL);
9310 BIND_EXPR_BODY (bind) = list;
9311 pop_cfun ();
9314 static void
9315 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9317 tree c, clauses;
9318 gimple g;
9319 size_t n_in = 0, n_out = 0, idx = 2, i;
9321 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9322 OMP_CLAUSE_DEPEND);
9323 gcc_assert (clauses);
9324 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9325 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9326 switch (OMP_CLAUSE_DEPEND_KIND (c))
9328 case OMP_CLAUSE_DEPEND_IN:
9329 n_in++;
9330 break;
9331 case OMP_CLAUSE_DEPEND_OUT:
9332 case OMP_CLAUSE_DEPEND_INOUT:
9333 n_out++;
9334 break;
9335 default:
9336 gcc_unreachable ();
9338 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9339 tree array = create_tmp_var (type, NULL);
9340 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9341 NULL_TREE);
9342 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9343 gimple_seq_add_stmt (iseq, g);
9344 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9345 NULL_TREE);
9346 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9347 gimple_seq_add_stmt (iseq, g);
9348 for (i = 0; i < 2; i++)
9350 if ((i ? n_in : n_out) == 0)
9351 continue;
9352 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9353 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9354 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9356 tree t = OMP_CLAUSE_DECL (c);
9357 t = fold_convert (ptr_type_node, t);
9358 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9359 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9360 NULL_TREE, NULL_TREE);
9361 g = gimple_build_assign (r, t);
9362 gimple_seq_add_stmt (iseq, g);
9365 tree *p = gimple_omp_task_clauses_ptr (stmt);
9366 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9367 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9368 OMP_CLAUSE_CHAIN (c) = *p;
9369 *p = c;
9370 tree clobber = build_constructor (type, NULL);
9371 TREE_THIS_VOLATILE (clobber) = 1;
9372 g = gimple_build_assign (array, clobber);
9373 gimple_seq_add_stmt (oseq, g);
9376 /* Lower the OpenMP parallel or task directive in the current statement
9377 in GSI_P. CTX holds context information for the directive. */
9379 static void
9380 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9382 tree clauses;
9383 tree child_fn, t;
9384 gimple stmt = gsi_stmt (*gsi_p);
9385 gimple par_bind, bind, dep_bind = NULL;
9386 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9387 location_t loc = gimple_location (stmt);
9389 clauses = gimple_omp_taskreg_clauses (stmt);
9390 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9391 par_body = gimple_bind_body (par_bind);
9392 child_fn = ctx->cb.dst_fn;
9393 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9394 && !gimple_omp_parallel_combined_p (stmt))
9396 struct walk_stmt_info wi;
9397 int ws_num = 0;
9399 memset (&wi, 0, sizeof (wi));
9400 wi.info = &ws_num;
9401 wi.val_only = true;
9402 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9403 if (ws_num == 1)
9404 gimple_omp_parallel_set_combined_p (stmt, true);
9406 gimple_seq dep_ilist = NULL;
9407 gimple_seq dep_olist = NULL;
9408 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9409 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9411 push_gimplify_context ();
9412 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9413 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9416 if (ctx->srecord_type)
9417 create_task_copyfn (stmt, ctx);
9419 push_gimplify_context ();
9421 par_olist = NULL;
9422 par_ilist = NULL;
9423 par_rlist = NULL;
9424 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9425 lower_omp (&par_body, ctx);
9426 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9427 lower_reduction_clauses (clauses, &par_rlist, ctx);
9429 /* Declare all the variables created by mapping and the variables
9430 declared in the scope of the parallel body. */
9431 record_vars_into (ctx->block_vars, child_fn);
9432 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9434 if (ctx->record_type)
9436 ctx->sender_decl
9437 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9438 : ctx->record_type, ".omp_data_o");
9439 DECL_NAMELESS (ctx->sender_decl) = 1;
9440 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9441 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9444 olist = NULL;
9445 ilist = NULL;
9446 lower_send_clauses (clauses, &ilist, &olist, ctx);
9447 lower_send_shared_vars (&ilist, &olist, ctx);
9449 if (ctx->record_type)
9451 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9452 TREE_THIS_VOLATILE (clobber) = 1;
9453 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9454 clobber));
9457 /* Once all the expansions are done, sequence all the different
9458 fragments inside gimple_omp_body. */
9460 new_body = NULL;
9462 if (ctx->record_type)
9464 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9465 /* fixup_child_record_type might have changed receiver_decl's type. */
9466 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9467 gimple_seq_add_stmt (&new_body,
9468 gimple_build_assign (ctx->receiver_decl, t));
9471 gimple_seq_add_seq (&new_body, par_ilist);
9472 gimple_seq_add_seq (&new_body, par_body);
9473 gimple_seq_add_seq (&new_body, par_rlist);
9474 if (ctx->cancellable)
9475 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9476 gimple_seq_add_seq (&new_body, par_olist);
9477 new_body = maybe_catch_exception (new_body);
9478 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9479 gimple_omp_set_body (stmt, new_body);
9481 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9482 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9483 gimple_bind_add_seq (bind, ilist);
9484 gimple_bind_add_stmt (bind, stmt);
9485 gimple_bind_add_seq (bind, olist);
9487 pop_gimplify_context (NULL);
9489 if (dep_bind)
9491 gimple_bind_add_seq (dep_bind, dep_ilist);
9492 gimple_bind_add_stmt (dep_bind, bind);
9493 gimple_bind_add_seq (dep_bind, dep_olist);
9494 pop_gimplify_context (dep_bind);
9498 /* Lower the OpenMP target directive in the current statement
9499 in GSI_P. CTX holds context information for the directive. */
9501 static void
9502 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9504 tree clauses;
9505 tree child_fn, t, c;
9506 gimple stmt = gsi_stmt (*gsi_p);
9507 gimple tgt_bind = NULL, bind;
9508 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9509 location_t loc = gimple_location (stmt);
9510 int kind = gimple_omp_target_kind (stmt);
9511 unsigned int map_cnt = 0;
9513 clauses = gimple_omp_target_clauses (stmt);
9514 if (kind == GF_OMP_TARGET_KIND_REGION)
9516 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9517 tgt_body = gimple_bind_body (tgt_bind);
9519 else if (kind == GF_OMP_TARGET_KIND_DATA)
9520 tgt_body = gimple_omp_body (stmt);
9521 child_fn = ctx->cb.dst_fn;
9523 push_gimplify_context ();
9525 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9526 switch (OMP_CLAUSE_CODE (c))
9528 tree var, x;
9530 default:
9531 break;
9532 case OMP_CLAUSE_MAP:
9533 case OMP_CLAUSE_TO:
9534 case OMP_CLAUSE_FROM:
9535 var = OMP_CLAUSE_DECL (c);
9536 if (!DECL_P (var))
9538 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9539 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9540 map_cnt++;
9541 continue;
9544 if (DECL_SIZE (var)
9545 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9547 tree var2 = DECL_VALUE_EXPR (var);
9548 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9549 var2 = TREE_OPERAND (var2, 0);
9550 gcc_assert (DECL_P (var2));
9551 var = var2;
9554 if (!maybe_lookup_field (var, ctx))
9555 continue;
9557 if (kind == GF_OMP_TARGET_KIND_REGION)
9559 x = build_receiver_ref (var, true, ctx);
9560 tree new_var = lookup_decl (var, ctx);
9561 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9562 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9563 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9564 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9565 x = build_simple_mem_ref (x);
9566 SET_DECL_VALUE_EXPR (new_var, x);
9567 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9569 map_cnt++;
9572 if (kind == GF_OMP_TARGET_KIND_REGION)
9574 target_nesting_level++;
9575 lower_omp (&tgt_body, ctx);
9576 target_nesting_level--;
9578 else if (kind == GF_OMP_TARGET_KIND_DATA)
9579 lower_omp (&tgt_body, ctx);
9581 if (kind == GF_OMP_TARGET_KIND_REGION)
9583 /* Declare all the variables created by mapping and the variables
9584 declared in the scope of the target body. */
9585 record_vars_into (ctx->block_vars, child_fn);
9586 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9589 olist = NULL;
9590 ilist = NULL;
9591 if (ctx->record_type)
9593 ctx->sender_decl
9594 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9595 DECL_NAMELESS (ctx->sender_decl) = 1;
9596 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9597 t = make_tree_vec (3);
9598 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9599 TREE_VEC_ELT (t, 1)
9600 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9601 ".omp_data_sizes");
9602 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9603 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9604 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9605 TREE_VEC_ELT (t, 2)
9606 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9607 map_cnt),
9608 ".omp_data_kinds");
9609 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9610 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9611 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9612 gimple_omp_target_set_data_arg (stmt, t);
9614 vec<constructor_elt, va_gc> *vsize;
9615 vec<constructor_elt, va_gc> *vkind;
9616 vec_alloc (vsize, map_cnt);
9617 vec_alloc (vkind, map_cnt);
9618 unsigned int map_idx = 0;
9620 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9621 switch (OMP_CLAUSE_CODE (c))
9623 tree ovar, nc;
9625 default:
9626 break;
9627 case OMP_CLAUSE_MAP:
9628 case OMP_CLAUSE_TO:
9629 case OMP_CLAUSE_FROM:
9630 nc = c;
9631 ovar = OMP_CLAUSE_DECL (c);
9632 if (!DECL_P (ovar))
9634 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9635 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9637 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9638 == get_base_address (ovar));
9639 nc = OMP_CLAUSE_CHAIN (c);
9640 ovar = OMP_CLAUSE_DECL (nc);
9642 else
9644 tree x = build_sender_ref (ovar, ctx);
9645 tree v
9646 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9647 gimplify_assign (x, v, &ilist);
9648 nc = NULL_TREE;
9651 else
9653 if (DECL_SIZE (ovar)
9654 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9656 tree ovar2 = DECL_VALUE_EXPR (ovar);
9657 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9658 ovar2 = TREE_OPERAND (ovar2, 0);
9659 gcc_assert (DECL_P (ovar2));
9660 ovar = ovar2;
9662 if (!maybe_lookup_field (ovar, ctx))
9663 continue;
9666 if (nc)
9668 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9669 tree x = build_sender_ref (ovar, ctx);
9670 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9671 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9672 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9673 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9675 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9676 tree avar
9677 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9678 mark_addressable (avar);
9679 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9680 avar = build_fold_addr_expr (avar);
9681 gimplify_assign (x, avar, &ilist);
9683 else if (is_gimple_reg (var))
9685 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9686 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9687 mark_addressable (avar);
9688 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9689 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9690 gimplify_assign (avar, var, &ilist);
9691 avar = build_fold_addr_expr (avar);
9692 gimplify_assign (x, avar, &ilist);
9693 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9694 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9695 && !TYPE_READONLY (TREE_TYPE (var)))
9697 x = build_sender_ref (ovar, ctx);
9698 x = build_simple_mem_ref (x);
9699 gimplify_assign (var, x, &olist);
9702 else
9704 var = build_fold_addr_expr (var);
9705 gimplify_assign (x, var, &ilist);
9708 tree s = OMP_CLAUSE_SIZE (c);
9709 if (s == NULL_TREE)
9710 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9711 s = fold_convert (size_type_node, s);
9712 tree purpose = size_int (map_idx++);
9713 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9714 if (TREE_CODE (s) != INTEGER_CST)
9715 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9717 unsigned char tkind = 0;
9718 switch (OMP_CLAUSE_CODE (c))
9720 case OMP_CLAUSE_MAP:
9721 tkind = OMP_CLAUSE_MAP_KIND (c);
9722 break;
9723 case OMP_CLAUSE_TO:
9724 tkind = OMP_CLAUSE_MAP_TO;
9725 break;
9726 case OMP_CLAUSE_FROM:
9727 tkind = OMP_CLAUSE_MAP_FROM;
9728 break;
9729 default:
9730 gcc_unreachable ();
9732 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9733 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9734 talign = DECL_ALIGN_UNIT (ovar);
9735 talign = ceil_log2 (talign);
9736 tkind |= talign << 3;
9737 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9738 build_int_cst (unsigned_char_type_node,
9739 tkind));
9740 if (nc && nc != c)
9741 c = nc;
9744 gcc_assert (map_idx == map_cnt);
9746 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9747 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9748 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9749 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9750 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9752 gimple_seq initlist = NULL;
9753 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9754 TREE_VEC_ELT (t, 1)),
9755 &initlist, true, NULL_TREE);
9756 gimple_seq_add_seq (&ilist, initlist);
9759 tree clobber = build_constructor (ctx->record_type, NULL);
9760 TREE_THIS_VOLATILE (clobber) = 1;
9761 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9762 clobber));
9765 /* Once all the expansions are done, sequence all the different
9766 fragments inside gimple_omp_body. */
9768 new_body = NULL;
9770 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9772 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9773 /* fixup_child_record_type might have changed receiver_decl's type. */
9774 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9775 gimple_seq_add_stmt (&new_body,
9776 gimple_build_assign (ctx->receiver_decl, t));
9779 if (kind == GF_OMP_TARGET_KIND_REGION)
9781 gimple_seq_add_seq (&new_body, tgt_body);
9782 new_body = maybe_catch_exception (new_body);
9784 else if (kind == GF_OMP_TARGET_KIND_DATA)
9785 new_body = tgt_body;
9786 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9788 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9789 gimple_omp_set_body (stmt, new_body);
9792 bind = gimple_build_bind (NULL, NULL,
9793 tgt_bind ? gimple_bind_block (tgt_bind)
9794 : NULL_TREE);
9795 gsi_replace (gsi_p, bind, true);
9796 gimple_bind_add_seq (bind, ilist);
9797 gimple_bind_add_stmt (bind, stmt);
9798 gimple_bind_add_seq (bind, olist);
9800 pop_gimplify_context (NULL);
9803 /* Expand code for an OpenMP teams directive. */
9805 static void
9806 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9808 gimple teams_stmt = gsi_stmt (*gsi_p);
9809 push_gimplify_context ();
9811 tree block = make_node (BLOCK);
9812 gimple bind = gimple_build_bind (NULL, NULL, block);
9813 gsi_replace (gsi_p, bind, true);
9814 gimple_seq bind_body = NULL;
9815 gimple_seq dlist = NULL;
9816 gimple_seq olist = NULL;
9818 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9819 OMP_CLAUSE_NUM_TEAMS);
9820 if (num_teams == NULL_TREE)
9821 num_teams = build_int_cst (unsigned_type_node, 0);
9822 else
9824 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9825 num_teams = fold_convert (unsigned_type_node, num_teams);
9826 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9828 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9829 OMP_CLAUSE_THREAD_LIMIT);
9830 if (thread_limit == NULL_TREE)
9831 thread_limit = build_int_cst (unsigned_type_node, 0);
9832 else
9834 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9835 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9836 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9837 fb_rvalue);
9840 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9841 &bind_body, &dlist, ctx, NULL);
9842 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9843 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9844 gimple_seq_add_stmt (&bind_body, teams_stmt);
9846 location_t loc = gimple_location (teams_stmt);
9847 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9848 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9849 gimple_set_location (call, loc);
9850 gimple_seq_add_stmt (&bind_body, call);
9852 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9853 gimple_omp_set_body (teams_stmt, NULL);
9854 gimple_seq_add_seq (&bind_body, olist);
9855 gimple_seq_add_seq (&bind_body, dlist);
9856 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9857 gimple_bind_set_body (bind, bind_body);
9859 pop_gimplify_context (bind);
9861 gimple_bind_append_vars (bind, ctx->block_vars);
9862 BLOCK_VARS (block) = ctx->block_vars;
9863 if (BLOCK_VARS (block))
9864 TREE_USED (block) = 1;
9868 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9869 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9870 of OpenMP context, but with task_shared_vars set. */
9872 static tree
9873 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9874 void *data)
9876 tree t = *tp;
9878 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9879 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9880 return t;
9882 if (task_shared_vars
9883 && DECL_P (t)
9884 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9885 return t;
9887 /* If a global variable has been privatized, TREE_CONSTANT on
9888 ADDR_EXPR might be wrong. */
9889 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9890 recompute_tree_invariant_for_addr_expr (t);
9892 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9893 return NULL_TREE;
9896 static void
9897 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9899 gimple stmt = gsi_stmt (*gsi_p);
9900 struct walk_stmt_info wi;
9902 if (gimple_has_location (stmt))
9903 input_location = gimple_location (stmt);
9905 if (task_shared_vars)
9906 memset (&wi, '\0', sizeof (wi));
9908 /* If we have issued syntax errors, avoid doing any heavy lifting.
9909 Just replace the OpenMP directives with a NOP to avoid
9910 confusing RTL expansion. */
9911 if (seen_error () && is_gimple_omp (stmt))
9913 gsi_replace (gsi_p, gimple_build_nop (), true);
9914 return;
9917 switch (gimple_code (stmt))
9919 case GIMPLE_COND:
9920 if ((ctx || task_shared_vars)
9921 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9922 ctx ? NULL : &wi, NULL)
9923 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9924 ctx ? NULL : &wi, NULL)))
9925 gimple_regimplify_operands (stmt, gsi_p);
9926 break;
9927 case GIMPLE_CATCH:
9928 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9929 break;
9930 case GIMPLE_EH_FILTER:
9931 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9932 break;
9933 case GIMPLE_TRY:
9934 lower_omp (gimple_try_eval_ptr (stmt), ctx);
9935 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
9936 break;
9937 case GIMPLE_TRANSACTION:
9938 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
9939 break;
9940 case GIMPLE_BIND:
9941 lower_omp (gimple_bind_body_ptr (stmt), ctx);
9942 break;
9943 case GIMPLE_OMP_PARALLEL:
9944 case GIMPLE_OMP_TASK:
9945 ctx = maybe_lookup_ctx (stmt);
9946 gcc_assert (ctx);
9947 if (ctx->cancellable)
9948 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9949 lower_omp_taskreg (gsi_p, ctx);
9950 break;
9951 case GIMPLE_OMP_FOR:
9952 ctx = maybe_lookup_ctx (stmt);
9953 gcc_assert (ctx);
9954 if (ctx->cancellable)
9955 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9956 lower_omp_for (gsi_p, ctx);
9957 break;
9958 case GIMPLE_OMP_SECTIONS:
9959 ctx = maybe_lookup_ctx (stmt);
9960 gcc_assert (ctx);
9961 if (ctx->cancellable)
9962 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9963 lower_omp_sections (gsi_p, ctx);
9964 break;
9965 case GIMPLE_OMP_SINGLE:
9966 ctx = maybe_lookup_ctx (stmt);
9967 gcc_assert (ctx);
9968 lower_omp_single (gsi_p, ctx);
9969 break;
9970 case GIMPLE_OMP_MASTER:
9971 ctx = maybe_lookup_ctx (stmt);
9972 gcc_assert (ctx);
9973 lower_omp_master (gsi_p, ctx);
9974 break;
9975 case GIMPLE_OMP_TASKGROUP:
9976 ctx = maybe_lookup_ctx (stmt);
9977 gcc_assert (ctx);
9978 lower_omp_taskgroup (gsi_p, ctx);
9979 break;
9980 case GIMPLE_OMP_ORDERED:
9981 ctx = maybe_lookup_ctx (stmt);
9982 gcc_assert (ctx);
9983 lower_omp_ordered (gsi_p, ctx);
9984 break;
9985 case GIMPLE_OMP_CRITICAL:
9986 ctx = maybe_lookup_ctx (stmt);
9987 gcc_assert (ctx);
9988 lower_omp_critical (gsi_p, ctx);
9989 break;
9990 case GIMPLE_OMP_ATOMIC_LOAD:
9991 if ((ctx || task_shared_vars)
9992 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
9993 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
9994 gimple_regimplify_operands (stmt, gsi_p);
9995 break;
9996 case GIMPLE_OMP_TARGET:
9997 ctx = maybe_lookup_ctx (stmt);
9998 gcc_assert (ctx);
9999 lower_omp_target (gsi_p, ctx);
10000 break;
10001 case GIMPLE_OMP_TEAMS:
10002 ctx = maybe_lookup_ctx (stmt);
10003 gcc_assert (ctx);
10004 lower_omp_teams (gsi_p, ctx);
10005 break;
10006 case GIMPLE_CALL:
10007 tree fndecl;
10008 fndecl = gimple_call_fndecl (stmt);
10009 if (fndecl
10010 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10011 switch (DECL_FUNCTION_CODE (fndecl))
10013 case BUILT_IN_GOMP_BARRIER:
10014 if (ctx == NULL)
10015 break;
10016 /* FALLTHRU */
10017 case BUILT_IN_GOMP_CANCEL:
10018 case BUILT_IN_GOMP_CANCELLATION_POINT:
10019 omp_context *cctx;
10020 cctx = ctx;
10021 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10022 cctx = cctx->outer;
10023 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10024 if (!cctx->cancellable)
10026 if (DECL_FUNCTION_CODE (fndecl)
10027 == BUILT_IN_GOMP_CANCELLATION_POINT)
10029 stmt = gimple_build_nop ();
10030 gsi_replace (gsi_p, stmt, false);
10032 break;
10034 tree lhs;
10035 lhs = create_tmp_var (boolean_type_node, NULL);
10036 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10038 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10039 gimple_call_set_fndecl (stmt, fndecl);
10040 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10042 gimple_call_set_lhs (stmt, lhs);
10043 tree fallthru_label;
10044 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10045 gimple g;
10046 g = gimple_build_label (fallthru_label);
10047 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10048 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10049 cctx->cancel_label, fallthru_label);
10050 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10051 break;
10052 default:
10053 break;
10055 /* FALLTHRU */
10056 default:
10057 if ((ctx || task_shared_vars)
10058 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10059 ctx ? NULL : &wi))
10060 gimple_regimplify_operands (stmt, gsi_p);
10061 break;
10065 static void
10066 lower_omp (gimple_seq *body, omp_context *ctx)
10068 location_t saved_location = input_location;
10069 gimple_stmt_iterator gsi;
10070 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10071 lower_omp_1 (&gsi, ctx);
10072 /* Inside target region we haven't called fold_stmt during gimplification,
10073 because it can break code by adding decl references that weren't in the
10074 source. Call fold_stmt now. */
10075 if (target_nesting_level)
10076 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10077 fold_stmt (&gsi);
10078 input_location = saved_location;
10081 /* Main entry point. */
10083 static unsigned int
10084 execute_lower_omp (void)
10086 gimple_seq body;
10088 /* This pass always runs, to provide PROP_gimple_lomp.
10089 But there is nothing to do unless -fopenmp is given. */
10090 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
10091 return 0;
10093 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10094 delete_omp_context);
10096 body = gimple_body (current_function_decl);
10097 scan_omp (&body, NULL);
10098 gcc_assert (taskreg_nesting_level == 0);
10100 if (all_contexts->root)
10102 if (task_shared_vars)
10103 push_gimplify_context ();
10104 lower_omp (&body, NULL);
10105 if (task_shared_vars)
10106 pop_gimplify_context (NULL);
10109 if (all_contexts)
10111 splay_tree_delete (all_contexts);
10112 all_contexts = NULL;
10114 BITMAP_FREE (task_shared_vars);
10115 return 0;
10118 namespace {
10120 const pass_data pass_data_lower_omp =
10122 GIMPLE_PASS, /* type */
10123 "omplower", /* name */
10124 OPTGROUP_NONE, /* optinfo_flags */
10125 false, /* has_gate */
10126 true, /* has_execute */
10127 TV_NONE, /* tv_id */
10128 PROP_gimple_any, /* properties_required */
10129 PROP_gimple_lomp, /* properties_provided */
10130 0, /* properties_destroyed */
10131 0, /* todo_flags_start */
10132 0, /* todo_flags_finish */
10135 class pass_lower_omp : public gimple_opt_pass
10137 public:
10138 pass_lower_omp (gcc::context *ctxt)
10139 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10142 /* opt_pass methods: */
10143 unsigned int execute () { return execute_lower_omp (); }
10145 }; // class pass_lower_omp
10147 } // anon namespace
10149 gimple_opt_pass *
10150 make_pass_lower_omp (gcc::context *ctxt)
10152 return new pass_lower_omp (ctxt);
10155 /* The following is a utility to diagnose OpenMP structured block violations.
10156 It is not part of the "omplower" pass, as that's invoked too late. It
10157 should be invoked by the respective front ends after gimplification. */
10159 static splay_tree all_labels;
10161 /* Check for mismatched contexts and generate an error if needed. Return
10162 true if an error is detected. */
10164 static bool
10165 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10166 gimple branch_ctx, gimple label_ctx)
10168 if (label_ctx == branch_ctx)
10169 return false;
10173 Previously we kept track of the label's entire context in diagnose_sb_[12]
10174 so we could traverse it and issue a correct "exit" or "enter" error
10175 message upon a structured block violation.
10177 We built the context by building a list with tree_cons'ing, but there is
10178 no easy counterpart in gimple tuples. It seems like far too much work
10179 for issuing exit/enter error messages. If someone really misses the
10180 distinct error message... patches welcome.
10183 #if 0
10184 /* Try to avoid confusing the user by producing and error message
10185 with correct "exit" or "enter" verbiage. We prefer "exit"
10186 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10187 if (branch_ctx == NULL)
10188 exit_p = false;
10189 else
10191 while (label_ctx)
10193 if (TREE_VALUE (label_ctx) == branch_ctx)
10195 exit_p = false;
10196 break;
10198 label_ctx = TREE_CHAIN (label_ctx);
10202 if (exit_p)
10203 error ("invalid exit from OpenMP structured block");
10204 else
10205 error ("invalid entry to OpenMP structured block");
10206 #endif
10208 bool cilkplus_block = false;
10209 if (flag_enable_cilkplus)
10211 if ((branch_ctx
10212 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10213 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10214 || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
10215 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10216 cilkplus_block = true;
10219 /* If it's obvious we have an invalid entry, be specific about the error. */
10220 if (branch_ctx == NULL)
10222 if (cilkplus_block)
10223 error ("invalid entry to Cilk Plus structured block");
10224 else
10225 error ("invalid entry to OpenMP structured block");
10227 else
10229 /* Otherwise, be vague and lazy, but efficient. */
10230 if (cilkplus_block)
10231 error ("invalid branch to/from a Cilk Plus structured block");
10232 else
10233 error ("invalid branch to/from an OpenMP structured block");
10236 gsi_replace (gsi_p, gimple_build_nop (), false);
10237 return true;
10240 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10241 where each label is found. */
10243 static tree
10244 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10245 struct walk_stmt_info *wi)
10247 gimple context = (gimple) wi->info;
10248 gimple inner_context;
10249 gimple stmt = gsi_stmt (*gsi_p);
10251 *handled_ops_p = true;
10253 switch (gimple_code (stmt))
10255 WALK_SUBSTMTS;
10257 case GIMPLE_OMP_PARALLEL:
10258 case GIMPLE_OMP_TASK:
10259 case GIMPLE_OMP_SECTIONS:
10260 case GIMPLE_OMP_SINGLE:
10261 case GIMPLE_OMP_SECTION:
10262 case GIMPLE_OMP_MASTER:
10263 case GIMPLE_OMP_ORDERED:
10264 case GIMPLE_OMP_CRITICAL:
10265 case GIMPLE_OMP_TARGET:
10266 case GIMPLE_OMP_TEAMS:
10267 case GIMPLE_OMP_TASKGROUP:
10268 /* The minimal context here is just the current OMP construct. */
10269 inner_context = stmt;
10270 wi->info = inner_context;
10271 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10272 wi->info = context;
10273 break;
10275 case GIMPLE_OMP_FOR:
10276 inner_context = stmt;
10277 wi->info = inner_context;
10278 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10279 walk them. */
10280 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10281 diagnose_sb_1, NULL, wi);
10282 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10283 wi->info = context;
10284 break;
10286 case GIMPLE_LABEL:
10287 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10288 (splay_tree_value) context);
10289 break;
10291 default:
10292 break;
10295 return NULL_TREE;
10298 /* Pass 2: Check each branch and see if its context differs from that of
10299 the destination label's context. */
10301 static tree
10302 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10303 struct walk_stmt_info *wi)
10305 gimple context = (gimple) wi->info;
10306 splay_tree_node n;
10307 gimple stmt = gsi_stmt (*gsi_p);
10309 *handled_ops_p = true;
10311 switch (gimple_code (stmt))
10313 WALK_SUBSTMTS;
10315 case GIMPLE_OMP_PARALLEL:
10316 case GIMPLE_OMP_TASK:
10317 case GIMPLE_OMP_SECTIONS:
10318 case GIMPLE_OMP_SINGLE:
10319 case GIMPLE_OMP_SECTION:
10320 case GIMPLE_OMP_MASTER:
10321 case GIMPLE_OMP_ORDERED:
10322 case GIMPLE_OMP_CRITICAL:
10323 case GIMPLE_OMP_TARGET:
10324 case GIMPLE_OMP_TEAMS:
10325 case GIMPLE_OMP_TASKGROUP:
10326 wi->info = stmt;
10327 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10328 wi->info = context;
10329 break;
10331 case GIMPLE_OMP_FOR:
10332 wi->info = stmt;
10333 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10334 walk them. */
10335 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10336 diagnose_sb_2, NULL, wi);
10337 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10338 wi->info = context;
10339 break;
10341 case GIMPLE_COND:
10343 tree lab = gimple_cond_true_label (stmt);
10344 if (lab)
10346 n = splay_tree_lookup (all_labels,
10347 (splay_tree_key) lab);
10348 diagnose_sb_0 (gsi_p, context,
10349 n ? (gimple) n->value : NULL);
10351 lab = gimple_cond_false_label (stmt);
10352 if (lab)
10354 n = splay_tree_lookup (all_labels,
10355 (splay_tree_key) lab);
10356 diagnose_sb_0 (gsi_p, context,
10357 n ? (gimple) n->value : NULL);
10360 break;
10362 case GIMPLE_GOTO:
10364 tree lab = gimple_goto_dest (stmt);
10365 if (TREE_CODE (lab) != LABEL_DECL)
10366 break;
10368 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10369 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10371 break;
10373 case GIMPLE_SWITCH:
10375 unsigned int i;
10376 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10378 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10379 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10380 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10381 break;
10384 break;
10386 case GIMPLE_RETURN:
10387 diagnose_sb_0 (gsi_p, context, NULL);
10388 break;
10390 default:
10391 break;
10394 return NULL_TREE;
10397 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10398 codes. */
10399 bool
10400 make_gimple_omp_edges (basic_block bb, struct omp_region **region)
10402 gimple last = last_stmt (bb);
10403 enum gimple_code code = gimple_code (last);
10404 struct omp_region *cur_region = *region;
10405 bool fallthru = false;
10407 switch (code)
10409 case GIMPLE_OMP_PARALLEL:
10410 case GIMPLE_OMP_TASK:
10411 case GIMPLE_OMP_FOR:
10412 case GIMPLE_OMP_SINGLE:
10413 case GIMPLE_OMP_TEAMS:
10414 case GIMPLE_OMP_MASTER:
10415 case GIMPLE_OMP_TASKGROUP:
10416 case GIMPLE_OMP_ORDERED:
10417 case GIMPLE_OMP_CRITICAL:
10418 case GIMPLE_OMP_SECTION:
10419 cur_region = new_omp_region (bb, code, cur_region);
10420 fallthru = true;
10421 break;
10423 case GIMPLE_OMP_TARGET:
10424 cur_region = new_omp_region (bb, code, cur_region);
10425 fallthru = true;
10426 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10427 cur_region = cur_region->outer;
10428 break;
10430 case GIMPLE_OMP_SECTIONS:
10431 cur_region = new_omp_region (bb, code, cur_region);
10432 fallthru = true;
10433 break;
10435 case GIMPLE_OMP_SECTIONS_SWITCH:
10436 fallthru = false;
10437 break;
10439 case GIMPLE_OMP_ATOMIC_LOAD:
10440 case GIMPLE_OMP_ATOMIC_STORE:
10441 fallthru = true;
10442 break;
10444 case GIMPLE_OMP_RETURN:
10445 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10446 somewhere other than the next block. This will be
10447 created later. */
10448 cur_region->exit = bb;
10449 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10450 cur_region = cur_region->outer;
10451 break;
10453 case GIMPLE_OMP_CONTINUE:
10454 cur_region->cont = bb;
10455 switch (cur_region->type)
10457 case GIMPLE_OMP_FOR:
10458 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10459 succs edges as abnormal to prevent splitting
10460 them. */
10461 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10462 /* Make the loopback edge. */
10463 make_edge (bb, single_succ (cur_region->entry),
10464 EDGE_ABNORMAL);
10466 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10467 corresponds to the case that the body of the loop
10468 is not executed at all. */
10469 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10470 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10471 fallthru = false;
10472 break;
10474 case GIMPLE_OMP_SECTIONS:
10475 /* Wire up the edges into and out of the nested sections. */
10477 basic_block switch_bb = single_succ (cur_region->entry);
10479 struct omp_region *i;
10480 for (i = cur_region->inner; i ; i = i->next)
10482 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10483 make_edge (switch_bb, i->entry, 0);
10484 make_edge (i->exit, bb, EDGE_FALLTHRU);
10487 /* Make the loopback edge to the block with
10488 GIMPLE_OMP_SECTIONS_SWITCH. */
10489 make_edge (bb, switch_bb, 0);
10491 /* Make the edge from the switch to exit. */
10492 make_edge (switch_bb, bb->next_bb, 0);
10493 fallthru = false;
10495 break;
10497 default:
10498 gcc_unreachable ();
10500 break;
10502 default:
10503 gcc_unreachable ();
10506 if (*region != cur_region)
10507 *region = cur_region;
10509 return fallthru;
10512 static unsigned int
10513 diagnose_omp_structured_block_errors (void)
10515 struct walk_stmt_info wi;
10516 gimple_seq body = gimple_body (current_function_decl);
10518 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10520 memset (&wi, 0, sizeof (wi));
10521 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10523 memset (&wi, 0, sizeof (wi));
10524 wi.want_locations = true;
10525 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10527 gimple_set_body (current_function_decl, body);
10529 splay_tree_delete (all_labels);
10530 all_labels = NULL;
10532 return 0;
10535 static bool
10536 gate_diagnose_omp_blocks (void)
10538 return flag_openmp || flag_enable_cilkplus;
10541 namespace {
10543 const pass_data pass_data_diagnose_omp_blocks =
10545 GIMPLE_PASS, /* type */
10546 "*diagnose_omp_blocks", /* name */
10547 OPTGROUP_NONE, /* optinfo_flags */
10548 true, /* has_gate */
10549 true, /* has_execute */
10550 TV_NONE, /* tv_id */
10551 PROP_gimple_any, /* properties_required */
10552 0, /* properties_provided */
10553 0, /* properties_destroyed */
10554 0, /* todo_flags_start */
10555 0, /* todo_flags_finish */
10558 class pass_diagnose_omp_blocks : public gimple_opt_pass
10560 public:
10561 pass_diagnose_omp_blocks (gcc::context *ctxt)
10562 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10565 /* opt_pass methods: */
10566 bool gate () { return gate_diagnose_omp_blocks (); }
10567 unsigned int execute () {
10568 return diagnose_omp_structured_block_errors ();
10571 }; // class pass_diagnose_omp_blocks
10573 } // anon namespace
10575 gimple_opt_pass *
10576 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10578 return new pass_diagnose_omp_blocks (ctxt);
10581 #include "gt-omp-low.h"