Daily bump.
[official-gcc.git] / gcc / omp-low.c
blobb59d069ac144c222911d8cfebbc0a680a8d0ae5a
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-2014 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 "predict.h"
33 #include "vec.h"
34 #include "hashtab.h"
35 #include "hash-set.h"
36 #include "machmode.h"
37 #include "hard-reg-set.h"
38 #include "input.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
62 #include "cgraph.h"
63 #include "tree-cfg.h"
64 #include "tree-phinodes.h"
65 #include "ssa-iterators.h"
66 #include "tree-ssanames.h"
67 #include "tree-into-ssa.h"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
77 #include "optabs.h"
78 #include "cfgloop.h"
79 #include "target.h"
80 #include "omp-low.h"
81 #include "gimple-low.h"
82 #include "tree-cfgcleanup.h"
83 #include "pretty-print.h"
84 #include "alloc-pool.h"
85 #include "ipa-prop.h"
86 #include "tree-nested.h"
87 #include "tree-eh.h"
88 #include "cilk.h"
91 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
92 phases. The first phase scans the function looking for OMP statements
93 and then for variables that must be replaced to satisfy data sharing
94 clauses. The second phase expands code for the constructs, as well as
95 re-gimplifying things when variables have been replaced with complex
96 expressions.
98 Final code generation is done by pass_expand_omp. The flowgraph is
99 scanned for parallel regions which are then moved to a new
100 function, to be invoked by the thread library. */
102 /* Parallel region information. Every parallel and workshare
103 directive is enclosed between two markers, the OMP_* directive
104 and a corresponding OMP_RETURN statement. */
106 struct omp_region
108 /* The enclosing region. */
109 struct omp_region *outer;
111 /* First child region. */
112 struct omp_region *inner;
114 /* Next peer region. */
115 struct omp_region *next;
117 /* Block containing the omp directive as its last stmt. */
118 basic_block entry;
120 /* Block containing the OMP_RETURN as its last stmt. */
121 basic_block exit;
123 /* Block containing the OMP_CONTINUE as its last stmt. */
124 basic_block cont;
126 /* If this is a combined parallel+workshare region, this is a list
127 of additional arguments needed by the combined parallel+workshare
128 library call. */
129 vec<tree, va_gc> *ws_args;
131 /* The code for the omp directive of this region. */
132 enum gimple_code type;
134 /* Schedule kind, only used for OMP_FOR type regions. */
135 enum omp_clause_schedule_kind sched_kind;
137 /* True if this is a combined parallel+workshare region. */
138 bool is_combined_parallel;
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
144 typedef struct omp_context
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
154 gimple stmt;
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
177 tree cancel_label;
179 /* What to do with variables with implicitly determined sharing
180 attributes. */
181 enum omp_clause_default_kind default_kind;
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
186 int depth;
188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
191 /* True if this construct can be cancelled. */
192 bool cancellable;
193 } omp_context;
196 struct omp_for_data_loop
198 tree v, n1, n2, step;
199 enum tree_code cond_code;
202 /* A structure describing the main elements of a parallel loop. */
204 struct omp_for_data
206 struct omp_for_data_loop loop;
207 tree chunk_size;
208 gimple for_stmt;
209 tree pre, iter_type;
210 int collapse;
211 bool have_nowait, have_ordered;
212 enum omp_clause_schedule_kind sched_kind;
213 struct omp_for_data_loop *loops;
217 static splay_tree all_contexts;
218 static int taskreg_nesting_level;
219 static int target_nesting_level;
220 static struct omp_region *root_omp_region;
221 static bitmap task_shared_vars;
222 static vec<omp_context *> taskreg_contexts;
224 static void scan_omp (gimple_seq *, omp_context *);
225 static tree scan_omp_1_op (tree *, int *, void *);
227 #define WALK_SUBSTMTS \
228 case GIMPLE_BIND: \
229 case GIMPLE_TRY: \
230 case GIMPLE_CATCH: \
231 case GIMPLE_EH_FILTER: \
232 case GIMPLE_TRANSACTION: \
233 /* The sub-statements for these should be walked. */ \
234 *handled_ops_p = false; \
235 break;
237 /* Convenience function for calling scan_omp_1_op on tree operands. */
239 static inline tree
240 scan_omp_op (tree *tp, omp_context *ctx)
242 struct walk_stmt_info wi;
244 memset (&wi, 0, sizeof (wi));
245 wi.info = ctx;
246 wi.want_locations = true;
248 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
251 static void lower_omp (gimple_seq *, omp_context *);
252 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
253 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
255 /* Find an OpenMP clause of type KIND within CLAUSES. */
257 tree
258 find_omp_clause (tree clauses, enum omp_clause_code kind)
260 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
261 if (OMP_CLAUSE_CODE (clauses) == kind)
262 return clauses;
264 return NULL_TREE;
267 /* Return true if CTX is for an omp parallel. */
269 static inline bool
270 is_parallel_ctx (omp_context *ctx)
272 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
276 /* Return true if CTX is for an omp task. */
278 static inline bool
279 is_task_ctx (omp_context *ctx)
281 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
285 /* Return true if CTX is for an omp parallel or omp task. */
287 static inline bool
288 is_taskreg_ctx (omp_context *ctx)
290 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
291 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
295 /* Return true if REGION is a combined parallel+workshare region. */
297 static inline bool
298 is_combined_parallel (struct omp_region *region)
300 return region->is_combined_parallel;
304 /* Extract the header elements of parallel loop FOR_STMT and store
305 them into *FD. */
307 static void
308 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
309 struct omp_for_data_loop *loops)
311 tree t, var, *collapse_iter, *collapse_count;
312 tree count = NULL_TREE, iter_type = long_integer_type_node;
313 struct omp_for_data_loop *loop;
314 int i;
315 struct omp_for_data_loop dummy_loop;
316 location_t loc = gimple_location (for_stmt);
317 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
318 bool distribute = gimple_omp_for_kind (for_stmt)
319 == GF_OMP_FOR_KIND_DISTRIBUTE;
321 fd->for_stmt = for_stmt;
322 fd->pre = NULL;
323 fd->collapse = gimple_omp_for_collapse (for_stmt);
324 if (fd->collapse > 1)
325 fd->loops = loops;
326 else
327 fd->loops = &fd->loop;
329 fd->have_nowait = distribute || simd;
330 fd->have_ordered = false;
331 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
332 fd->chunk_size = NULL_TREE;
333 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
334 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
335 collapse_iter = NULL;
336 collapse_count = NULL;
338 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
339 switch (OMP_CLAUSE_CODE (t))
341 case OMP_CLAUSE_NOWAIT:
342 fd->have_nowait = true;
343 break;
344 case OMP_CLAUSE_ORDERED:
345 fd->have_ordered = true;
346 break;
347 case OMP_CLAUSE_SCHEDULE:
348 gcc_assert (!distribute);
349 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
350 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
351 break;
352 case OMP_CLAUSE_DIST_SCHEDULE:
353 gcc_assert (distribute);
354 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
355 break;
356 case OMP_CLAUSE_COLLAPSE:
357 if (fd->collapse > 1)
359 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
360 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
362 break;
363 default:
364 break;
367 /* FIXME: for now map schedule(auto) to schedule(static).
368 There should be analysis to determine whether all iterations
369 are approximately the same amount of work (then schedule(static)
370 is best) or if it varies (then schedule(dynamic,N) is better). */
371 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
373 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
374 gcc_assert (fd->chunk_size == NULL);
376 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
377 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
378 gcc_assert (fd->chunk_size == NULL);
379 else if (fd->chunk_size == NULL)
381 /* We only need to compute a default chunk size for ordered
382 static loops and dynamic loops. */
383 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
384 || fd->have_ordered)
385 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
386 ? integer_zero_node : integer_one_node;
389 for (i = 0; i < fd->collapse; i++)
391 if (fd->collapse == 1)
392 loop = &fd->loop;
393 else if (loops != NULL)
394 loop = loops + i;
395 else
396 loop = &dummy_loop;
398 loop->v = gimple_omp_for_index (for_stmt, i);
399 gcc_assert (SSA_VAR_P (loop->v));
400 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
401 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
402 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
403 loop->n1 = gimple_omp_for_initial (for_stmt, i);
405 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
406 loop->n2 = gimple_omp_for_final (for_stmt, i);
407 switch (loop->cond_code)
409 case LT_EXPR:
410 case GT_EXPR:
411 break;
412 case NE_EXPR:
413 gcc_assert (gimple_omp_for_kind (for_stmt)
414 == GF_OMP_FOR_KIND_CILKSIMD
415 || (gimple_omp_for_kind (for_stmt)
416 == GF_OMP_FOR_KIND_CILKFOR));
417 break;
418 case LE_EXPR:
419 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
420 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
421 else
422 loop->n2 = fold_build2_loc (loc,
423 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
424 build_int_cst (TREE_TYPE (loop->n2), 1));
425 loop->cond_code = LT_EXPR;
426 break;
427 case GE_EXPR:
428 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
429 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
430 else
431 loop->n2 = fold_build2_loc (loc,
432 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
433 build_int_cst (TREE_TYPE (loop->n2), 1));
434 loop->cond_code = GT_EXPR;
435 break;
436 default:
437 gcc_unreachable ();
440 t = gimple_omp_for_incr (for_stmt, i);
441 gcc_assert (TREE_OPERAND (t, 0) == var);
442 switch (TREE_CODE (t))
444 case PLUS_EXPR:
445 loop->step = TREE_OPERAND (t, 1);
446 break;
447 case POINTER_PLUS_EXPR:
448 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
449 break;
450 case MINUS_EXPR:
451 loop->step = TREE_OPERAND (t, 1);
452 loop->step = fold_build1_loc (loc,
453 NEGATE_EXPR, TREE_TYPE (loop->step),
454 loop->step);
455 break;
456 default:
457 gcc_unreachable ();
460 if (simd
461 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
462 && !fd->have_ordered))
464 if (fd->collapse == 1)
465 iter_type = TREE_TYPE (loop->v);
466 else if (i == 0
467 || TYPE_PRECISION (iter_type)
468 < TYPE_PRECISION (TREE_TYPE (loop->v)))
469 iter_type
470 = build_nonstandard_integer_type
471 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
473 else if (iter_type != long_long_unsigned_type_node)
475 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
476 iter_type = long_long_unsigned_type_node;
477 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
478 && TYPE_PRECISION (TREE_TYPE (loop->v))
479 >= TYPE_PRECISION (iter_type))
481 tree n;
483 if (loop->cond_code == LT_EXPR)
484 n = fold_build2_loc (loc,
485 PLUS_EXPR, TREE_TYPE (loop->v),
486 loop->n2, loop->step);
487 else
488 n = loop->n1;
489 if (TREE_CODE (n) != INTEGER_CST
490 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
491 iter_type = long_long_unsigned_type_node;
493 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
494 > TYPE_PRECISION (iter_type))
496 tree n1, n2;
498 if (loop->cond_code == LT_EXPR)
500 n1 = loop->n1;
501 n2 = fold_build2_loc (loc,
502 PLUS_EXPR, TREE_TYPE (loop->v),
503 loop->n2, loop->step);
505 else
507 n1 = fold_build2_loc (loc,
508 MINUS_EXPR, TREE_TYPE (loop->v),
509 loop->n2, loop->step);
510 n2 = loop->n1;
512 if (TREE_CODE (n1) != INTEGER_CST
513 || TREE_CODE (n2) != INTEGER_CST
514 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
515 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
516 iter_type = long_long_unsigned_type_node;
520 if (collapse_count && *collapse_count == NULL)
522 t = fold_binary (loop->cond_code, boolean_type_node,
523 fold_convert (TREE_TYPE (loop->v), loop->n1),
524 fold_convert (TREE_TYPE (loop->v), loop->n2));
525 if (t && integer_zerop (t))
526 count = build_zero_cst (long_long_unsigned_type_node);
527 else if ((i == 0 || count != NULL_TREE)
528 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
529 && TREE_CONSTANT (loop->n1)
530 && TREE_CONSTANT (loop->n2)
531 && TREE_CODE (loop->step) == INTEGER_CST)
533 tree itype = TREE_TYPE (loop->v);
535 if (POINTER_TYPE_P (itype))
536 itype = signed_type_for (itype);
537 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
538 t = fold_build2_loc (loc,
539 PLUS_EXPR, itype,
540 fold_convert_loc (loc, itype, loop->step), t);
541 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
542 fold_convert_loc (loc, itype, loop->n2));
543 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
544 fold_convert_loc (loc, itype, loop->n1));
545 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
546 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
547 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
548 fold_build1_loc (loc, NEGATE_EXPR, itype,
549 fold_convert_loc (loc, itype,
550 loop->step)));
551 else
552 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
553 fold_convert_loc (loc, itype, loop->step));
554 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
555 if (count != NULL_TREE)
556 count = fold_build2_loc (loc,
557 MULT_EXPR, long_long_unsigned_type_node,
558 count, t);
559 else
560 count = t;
561 if (TREE_CODE (count) != INTEGER_CST)
562 count = NULL_TREE;
564 else if (count && !integer_zerop (count))
565 count = NULL_TREE;
569 if (count
570 && !simd
571 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
572 || fd->have_ordered))
574 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
575 iter_type = long_long_unsigned_type_node;
576 else
577 iter_type = long_integer_type_node;
579 else if (collapse_iter && *collapse_iter != NULL)
580 iter_type = TREE_TYPE (*collapse_iter);
581 fd->iter_type = iter_type;
582 if (collapse_iter && *collapse_iter == NULL)
583 *collapse_iter = create_tmp_var (iter_type, ".iter");
584 if (collapse_count && *collapse_count == NULL)
586 if (count)
587 *collapse_count = fold_convert_loc (loc, iter_type, count);
588 else
589 *collapse_count = create_tmp_var (iter_type, ".count");
592 if (fd->collapse > 1)
594 fd->loop.v = *collapse_iter;
595 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
596 fd->loop.n2 = *collapse_count;
597 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
598 fd->loop.cond_code = LT_EXPR;
603 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
604 is the immediate dominator of PAR_ENTRY_BB, return true if there
605 are no data dependencies that would prevent expanding the parallel
606 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
608 When expanding a combined parallel+workshare region, the call to
609 the child function may need additional arguments in the case of
610 GIMPLE_OMP_FOR regions. In some cases, these arguments are
611 computed out of variables passed in from the parent to the child
612 via 'struct .omp_data_s'. For instance:
614 #pragma omp parallel for schedule (guided, i * 4)
615 for (j ...)
617 Is lowered into:
619 # BLOCK 2 (PAR_ENTRY_BB)
620 .omp_data_o.i = i;
621 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
623 # BLOCK 3 (WS_ENTRY_BB)
624 .omp_data_i = &.omp_data_o;
625 D.1667 = .omp_data_i->i;
626 D.1598 = D.1667 * 4;
627 #pragma omp for schedule (guided, D.1598)
629 When we outline the parallel region, the call to the child function
630 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
631 that value is computed *after* the call site. So, in principle we
632 cannot do the transformation.
634 To see whether the code in WS_ENTRY_BB blocks the combined
635 parallel+workshare call, we collect all the variables used in the
636 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
637 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
638 call.
640 FIXME. If we had the SSA form built at this point, we could merely
641 hoist the code in block 3 into block 2 and be done with it. But at
642 this point we don't have dataflow information and though we could
643 hack something up here, it is really not worth the aggravation. */
645 static bool
646 workshare_safe_to_combine_p (basic_block ws_entry_bb)
648 struct omp_for_data fd;
649 gimple ws_stmt = last_stmt (ws_entry_bb);
651 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
652 return true;
654 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
656 extract_omp_for_data (ws_stmt, &fd, NULL);
658 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
659 return false;
660 if (fd.iter_type != long_integer_type_node)
661 return false;
663 /* FIXME. We give up too easily here. If any of these arguments
664 are not constants, they will likely involve variables that have
665 been mapped into fields of .omp_data_s for sharing with the child
666 function. With appropriate data flow, it would be possible to
667 see through this. */
668 if (!is_gimple_min_invariant (fd.loop.n1)
669 || !is_gimple_min_invariant (fd.loop.n2)
670 || !is_gimple_min_invariant (fd.loop.step)
671 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
672 return false;
674 return true;
678 /* Collect additional arguments needed to emit a combined
679 parallel+workshare call. WS_STMT is the workshare directive being
680 expanded. */
682 static vec<tree, va_gc> *
683 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
685 tree t;
686 location_t loc = gimple_location (ws_stmt);
687 vec<tree, va_gc> *ws_args;
689 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
691 struct omp_for_data fd;
692 tree n1, n2;
694 extract_omp_for_data (ws_stmt, &fd, NULL);
695 n1 = fd.loop.n1;
696 n2 = fd.loop.n2;
698 if (gimple_omp_for_combined_into_p (ws_stmt))
700 tree innerc
701 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
702 OMP_CLAUSE__LOOPTEMP_);
703 gcc_assert (innerc);
704 n1 = OMP_CLAUSE_DECL (innerc);
705 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
706 OMP_CLAUSE__LOOPTEMP_);
707 gcc_assert (innerc);
708 n2 = OMP_CLAUSE_DECL (innerc);
711 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
713 t = fold_convert_loc (loc, long_integer_type_node, n1);
714 ws_args->quick_push (t);
716 t = fold_convert_loc (loc, long_integer_type_node, n2);
717 ws_args->quick_push (t);
719 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
720 ws_args->quick_push (t);
722 if (fd.chunk_size)
724 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
725 ws_args->quick_push (t);
728 return ws_args;
730 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
732 /* Number of sections is equal to the number of edges from the
733 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
734 the exit of the sections region. */
735 basic_block bb = single_succ (gimple_bb (ws_stmt));
736 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
737 vec_alloc (ws_args, 1);
738 ws_args->quick_push (t);
739 return ws_args;
742 gcc_unreachable ();
746 /* Discover whether REGION is a combined parallel+workshare region. */
748 static void
749 determine_parallel_type (struct omp_region *region)
751 basic_block par_entry_bb, par_exit_bb;
752 basic_block ws_entry_bb, ws_exit_bb;
754 if (region == NULL || region->inner == NULL
755 || region->exit == NULL || region->inner->exit == NULL
756 || region->inner->cont == NULL)
757 return;
759 /* We only support parallel+for and parallel+sections. */
760 if (region->type != GIMPLE_OMP_PARALLEL
761 || (region->inner->type != GIMPLE_OMP_FOR
762 && region->inner->type != GIMPLE_OMP_SECTIONS))
763 return;
765 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
766 WS_EXIT_BB -> PAR_EXIT_BB. */
767 par_entry_bb = region->entry;
768 par_exit_bb = region->exit;
769 ws_entry_bb = region->inner->entry;
770 ws_exit_bb = region->inner->exit;
772 if (single_succ (par_entry_bb) == ws_entry_bb
773 && single_succ (ws_exit_bb) == par_exit_bb
774 && workshare_safe_to_combine_p (ws_entry_bb)
775 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
776 || (last_and_only_stmt (ws_entry_bb)
777 && last_and_only_stmt (par_exit_bb))))
779 gimple par_stmt = last_stmt (par_entry_bb);
780 gimple ws_stmt = last_stmt (ws_entry_bb);
782 if (region->inner->type == GIMPLE_OMP_FOR)
784 /* If this is a combined parallel loop, we need to determine
785 whether or not to use the combined library calls. There
786 are two cases where we do not apply the transformation:
787 static loops and any kind of ordered loop. In the first
788 case, we already open code the loop so there is no need
789 to do anything else. In the latter case, the combined
790 parallel loop call would still need extra synchronization
791 to implement ordered semantics, so there would not be any
792 gain in using the combined call. */
793 tree clauses = gimple_omp_for_clauses (ws_stmt);
794 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
795 if (c == NULL
796 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
797 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
799 region->is_combined_parallel = false;
800 region->inner->is_combined_parallel = false;
801 return;
805 region->is_combined_parallel = true;
806 region->inner->is_combined_parallel = true;
807 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
812 /* Return true if EXPR is variable sized. */
814 static inline bool
815 is_variable_sized (const_tree expr)
817 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
820 /* Return true if DECL is a reference type. */
822 static inline bool
823 is_reference (tree decl)
825 return lang_hooks.decls.omp_privatize_by_reference (decl);
828 /* Lookup variables in the decl or field splay trees. The "maybe" form
829 allows for the variable form to not have been entered, otherwise we
830 assert that the variable must have been entered. */
832 static inline tree
833 lookup_decl (tree var, omp_context *ctx)
835 tree *n = ctx->cb.decl_map->get (var);
836 return *n;
839 static inline tree
840 maybe_lookup_decl (const_tree var, omp_context *ctx)
842 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
843 return n ? *n : NULL_TREE;
846 static inline tree
847 lookup_field (tree var, omp_context *ctx)
849 splay_tree_node n;
850 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
851 return (tree) n->value;
854 static inline tree
855 lookup_sfield (tree var, omp_context *ctx)
857 splay_tree_node n;
858 n = splay_tree_lookup (ctx->sfield_map
859 ? ctx->sfield_map : ctx->field_map,
860 (splay_tree_key) var);
861 return (tree) n->value;
864 static inline tree
865 maybe_lookup_field (tree var, omp_context *ctx)
867 splay_tree_node n;
868 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
869 return n ? (tree) n->value : NULL_TREE;
872 /* Return true if DECL should be copied by pointer. SHARED_CTX is
873 the parallel context if DECL is to be shared. */
875 static bool
876 use_pointer_for_field (tree decl, omp_context *shared_ctx)
878 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
879 return true;
881 /* We can only use copy-in/copy-out semantics for shared variables
882 when we know the value is not accessible from an outer scope. */
883 if (shared_ctx)
885 /* ??? Trivially accessible from anywhere. But why would we even
886 be passing an address in this case? Should we simply assert
887 this to be false, or should we have a cleanup pass that removes
888 these from the list of mappings? */
889 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
890 return true;
892 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
893 without analyzing the expression whether or not its location
894 is accessible to anyone else. In the case of nested parallel
895 regions it certainly may be. */
896 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
897 return true;
899 /* Do not use copy-in/copy-out for variables that have their
900 address taken. */
901 if (TREE_ADDRESSABLE (decl))
902 return true;
904 /* lower_send_shared_vars only uses copy-in, but not copy-out
905 for these. */
906 if (TREE_READONLY (decl)
907 || ((TREE_CODE (decl) == RESULT_DECL
908 || TREE_CODE (decl) == PARM_DECL)
909 && DECL_BY_REFERENCE (decl)))
910 return false;
912 /* Disallow copy-in/out in nested parallel if
913 decl is shared in outer parallel, otherwise
914 each thread could store the shared variable
915 in its own copy-in location, making the
916 variable no longer really shared. */
917 if (shared_ctx->is_nested)
919 omp_context *up;
921 for (up = shared_ctx->outer; up; up = up->outer)
922 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
923 break;
925 if (up)
927 tree c;
929 for (c = gimple_omp_taskreg_clauses (up->stmt);
930 c; c = OMP_CLAUSE_CHAIN (c))
931 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
932 && OMP_CLAUSE_DECL (c) == decl)
933 break;
935 if (c)
936 goto maybe_mark_addressable_and_ret;
940 /* For tasks avoid using copy-in/out. As tasks can be
941 deferred or executed in different thread, when GOMP_task
942 returns, the task hasn't necessarily terminated. */
943 if (is_task_ctx (shared_ctx))
945 tree outer;
946 maybe_mark_addressable_and_ret:
947 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
948 if (is_gimple_reg (outer))
950 /* Taking address of OUTER in lower_send_shared_vars
951 might need regimplification of everything that uses the
952 variable. */
953 if (!task_shared_vars)
954 task_shared_vars = BITMAP_ALLOC (NULL);
955 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
956 TREE_ADDRESSABLE (outer) = 1;
958 return true;
962 return false;
965 /* Construct a new automatic decl similar to VAR. */
967 static tree
968 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
970 tree copy = copy_var_decl (var, name, type);
972 DECL_CONTEXT (copy) = current_function_decl;
973 DECL_CHAIN (copy) = ctx->block_vars;
974 ctx->block_vars = copy;
976 return copy;
979 static tree
980 omp_copy_decl_1 (tree var, omp_context *ctx)
982 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
985 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
986 as appropriate. */
987 static tree
988 omp_build_component_ref (tree obj, tree field)
990 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
991 if (TREE_THIS_VOLATILE (field))
992 TREE_THIS_VOLATILE (ret) |= 1;
993 if (TREE_READONLY (field))
994 TREE_READONLY (ret) |= 1;
995 return ret;
998 /* Build tree nodes to access the field for VAR on the receiver side. */
1000 static tree
1001 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1003 tree x, field = lookup_field (var, ctx);
1005 /* If the receiver record type was remapped in the child function,
1006 remap the field into the new record type. */
1007 x = maybe_lookup_field (field, ctx);
1008 if (x != NULL)
1009 field = x;
1011 x = build_simple_mem_ref (ctx->receiver_decl);
1012 x = omp_build_component_ref (x, field);
1013 if (by_ref)
1014 x = build_simple_mem_ref (x);
1016 return x;
1019 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1020 of a parallel, this is a component reference; for workshare constructs
1021 this is some variable. */
1023 static tree
1024 build_outer_var_ref (tree var, omp_context *ctx)
1026 tree x;
1028 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1029 x = var;
1030 else if (is_variable_sized (var))
1032 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1033 x = build_outer_var_ref (x, ctx);
1034 x = build_simple_mem_ref (x);
1036 else if (is_taskreg_ctx (ctx))
1038 bool by_ref = use_pointer_for_field (var, NULL);
1039 x = build_receiver_ref (var, by_ref, ctx);
1041 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1042 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1044 /* #pragma omp simd isn't a worksharing construct, and can reference even
1045 private vars in its linear etc. clauses. */
1046 x = NULL_TREE;
1047 if (ctx->outer && is_taskreg_ctx (ctx))
1048 x = lookup_decl (var, ctx->outer);
1049 else if (ctx->outer)
1050 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1051 if (x == NULL_TREE)
1052 x = var;
1054 else if (ctx->outer)
1055 x = lookup_decl (var, ctx->outer);
1056 else if (is_reference (var))
1057 /* This can happen with orphaned constructs. If var is reference, it is
1058 possible it is shared and as such valid. */
1059 x = var;
1060 else
1061 gcc_unreachable ();
1063 if (is_reference (var))
1064 x = build_simple_mem_ref (x);
1066 return x;
1069 /* Build tree nodes to access the field for VAR on the sender side. */
1071 static tree
1072 build_sender_ref (tree var, omp_context *ctx)
1074 tree field = lookup_sfield (var, ctx);
1075 return omp_build_component_ref (ctx->sender_decl, field);
1078 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1080 static void
1081 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1083 tree field, type, sfield = NULL_TREE;
1085 gcc_assert ((mask & 1) == 0
1086 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1087 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1088 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1090 type = TREE_TYPE (var);
1091 if (mask & 4)
1093 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1094 type = build_pointer_type (build_pointer_type (type));
1096 else if (by_ref)
1097 type = build_pointer_type (type);
1098 else if ((mask & 3) == 1 && is_reference (var))
1099 type = TREE_TYPE (type);
1101 field = build_decl (DECL_SOURCE_LOCATION (var),
1102 FIELD_DECL, DECL_NAME (var), type);
1104 /* Remember what variable this field was created for. This does have a
1105 side effect of making dwarf2out ignore this member, so for helpful
1106 debugging we clear it later in delete_omp_context. */
1107 DECL_ABSTRACT_ORIGIN (field) = var;
1108 if (type == TREE_TYPE (var))
1110 DECL_ALIGN (field) = DECL_ALIGN (var);
1111 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1112 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1114 else
1115 DECL_ALIGN (field) = TYPE_ALIGN (type);
1117 if ((mask & 3) == 3)
1119 insert_field_into_struct (ctx->record_type, field);
1120 if (ctx->srecord_type)
1122 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1123 FIELD_DECL, DECL_NAME (var), type);
1124 DECL_ABSTRACT_ORIGIN (sfield) = var;
1125 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1126 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1127 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1128 insert_field_into_struct (ctx->srecord_type, sfield);
1131 else
1133 if (ctx->srecord_type == NULL_TREE)
1135 tree t;
1137 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1138 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1139 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1141 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1142 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1143 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1144 insert_field_into_struct (ctx->srecord_type, sfield);
1145 splay_tree_insert (ctx->sfield_map,
1146 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1147 (splay_tree_value) sfield);
1150 sfield = field;
1151 insert_field_into_struct ((mask & 1) ? ctx->record_type
1152 : ctx->srecord_type, field);
1155 if (mask & 1)
1156 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1157 (splay_tree_value) field);
1158 if ((mask & 2) && ctx->sfield_map)
1159 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1160 (splay_tree_value) sfield);
1163 static tree
1164 install_var_local (tree var, omp_context *ctx)
1166 tree new_var = omp_copy_decl_1 (var, ctx);
1167 insert_decl_map (&ctx->cb, var, new_var);
1168 return new_var;
1171 /* Adjust the replacement for DECL in CTX for the new context. This means
1172 copying the DECL_VALUE_EXPR, and fixing up the type. */
1174 static void
1175 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1177 tree new_decl, size;
1179 new_decl = lookup_decl (decl, ctx);
1181 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1183 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1184 && DECL_HAS_VALUE_EXPR_P (decl))
1186 tree ve = DECL_VALUE_EXPR (decl);
1187 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1188 SET_DECL_VALUE_EXPR (new_decl, ve);
1189 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1192 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1194 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1195 if (size == error_mark_node)
1196 size = TYPE_SIZE (TREE_TYPE (new_decl));
1197 DECL_SIZE (new_decl) = size;
1199 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1200 if (size == error_mark_node)
1201 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1202 DECL_SIZE_UNIT (new_decl) = size;
1206 /* The callback for remap_decl. Search all containing contexts for a
1207 mapping of the variable; this avoids having to duplicate the splay
1208 tree ahead of time. We know a mapping doesn't already exist in the
1209 given context. Create new mappings to implement default semantics. */
1211 static tree
1212 omp_copy_decl (tree var, copy_body_data *cb)
1214 omp_context *ctx = (omp_context *) cb;
1215 tree new_var;
1217 if (TREE_CODE (var) == LABEL_DECL)
1219 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1220 DECL_CONTEXT (new_var) = current_function_decl;
1221 insert_decl_map (&ctx->cb, var, new_var);
1222 return new_var;
1225 while (!is_taskreg_ctx (ctx))
1227 ctx = ctx->outer;
1228 if (ctx == NULL)
1229 return var;
1230 new_var = maybe_lookup_decl (var, ctx);
1231 if (new_var)
1232 return new_var;
1235 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1236 return var;
1238 return error_mark_node;
1242 /* Debugging dumps for parallel regions. */
1243 void dump_omp_region (FILE *, struct omp_region *, int);
1244 void debug_omp_region (struct omp_region *);
1245 void debug_all_omp_regions (void);
1247 /* Dump the parallel region tree rooted at REGION. */
1249 void
1250 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1252 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1253 gimple_code_name[region->type]);
1255 if (region->inner)
1256 dump_omp_region (file, region->inner, indent + 4);
1258 if (region->cont)
1260 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1261 region->cont->index);
1264 if (region->exit)
1265 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1266 region->exit->index);
1267 else
1268 fprintf (file, "%*s[no exit marker]\n", indent, "");
1270 if (region->next)
1271 dump_omp_region (file, region->next, indent);
1274 DEBUG_FUNCTION void
1275 debug_omp_region (struct omp_region *region)
1277 dump_omp_region (stderr, region, 0);
1280 DEBUG_FUNCTION void
1281 debug_all_omp_regions (void)
1283 dump_omp_region (stderr, root_omp_region, 0);
1287 /* Create a new parallel region starting at STMT inside region PARENT. */
1289 static struct omp_region *
1290 new_omp_region (basic_block bb, enum gimple_code type,
1291 struct omp_region *parent)
1293 struct omp_region *region = XCNEW (struct omp_region);
1295 region->outer = parent;
1296 region->entry = bb;
1297 region->type = type;
1299 if (parent)
1301 /* This is a nested region. Add it to the list of inner
1302 regions in PARENT. */
1303 region->next = parent->inner;
1304 parent->inner = region;
1306 else
1308 /* This is a toplevel region. Add it to the list of toplevel
1309 regions in ROOT_OMP_REGION. */
1310 region->next = root_omp_region;
1311 root_omp_region = region;
1314 return region;
1317 /* Release the memory associated with the region tree rooted at REGION. */
1319 static void
1320 free_omp_region_1 (struct omp_region *region)
1322 struct omp_region *i, *n;
1324 for (i = region->inner; i ; i = n)
1326 n = i->next;
1327 free_omp_region_1 (i);
1330 free (region);
1333 /* Release the memory for the entire omp region tree. */
1335 void
1336 free_omp_regions (void)
1338 struct omp_region *r, *n;
1339 for (r = root_omp_region; r ; r = n)
1341 n = r->next;
1342 free_omp_region_1 (r);
1344 root_omp_region = NULL;
1348 /* Create a new context, with OUTER_CTX being the surrounding context. */
1350 static omp_context *
1351 new_omp_context (gimple stmt, omp_context *outer_ctx)
1353 omp_context *ctx = XCNEW (omp_context);
1355 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1356 (splay_tree_value) ctx);
1357 ctx->stmt = stmt;
1359 if (outer_ctx)
1361 ctx->outer = outer_ctx;
1362 ctx->cb = outer_ctx->cb;
1363 ctx->cb.block = NULL;
1364 ctx->depth = outer_ctx->depth + 1;
1366 else
1368 ctx->cb.src_fn = current_function_decl;
1369 ctx->cb.dst_fn = current_function_decl;
1370 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1371 gcc_checking_assert (ctx->cb.src_node);
1372 ctx->cb.dst_node = ctx->cb.src_node;
1373 ctx->cb.src_cfun = cfun;
1374 ctx->cb.copy_decl = omp_copy_decl;
1375 ctx->cb.eh_lp_nr = 0;
1376 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1377 ctx->depth = 1;
1380 ctx->cb.decl_map = new hash_map<tree, tree>;
1382 return ctx;
1385 static gimple_seq maybe_catch_exception (gimple_seq);
1387 /* Finalize task copyfn. */
1389 static void
1390 finalize_task_copyfn (gimple task_stmt)
1392 struct function *child_cfun;
1393 tree child_fn;
1394 gimple_seq seq = NULL, new_seq;
1395 gimple bind;
1397 child_fn = gimple_omp_task_copy_fn (task_stmt);
1398 if (child_fn == NULL_TREE)
1399 return;
1401 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1402 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1404 push_cfun (child_cfun);
1405 bind = gimplify_body (child_fn, false);
1406 gimple_seq_add_stmt (&seq, bind);
1407 new_seq = maybe_catch_exception (seq);
1408 if (new_seq != seq)
1410 bind = gimple_build_bind (NULL, new_seq, NULL);
1411 seq = NULL;
1412 gimple_seq_add_stmt (&seq, bind);
1414 gimple_set_body (child_fn, seq);
1415 pop_cfun ();
1417 /* Inform the callgraph about the new function. */
1418 cgraph_node::add_new_function (child_fn, false);
1421 /* Destroy a omp_context data structures. Called through the splay tree
1422 value delete callback. */
1424 static void
1425 delete_omp_context (splay_tree_value value)
1427 omp_context *ctx = (omp_context *) value;
1429 delete ctx->cb.decl_map;
1431 if (ctx->field_map)
1432 splay_tree_delete (ctx->field_map);
1433 if (ctx->sfield_map)
1434 splay_tree_delete (ctx->sfield_map);
1436 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1437 it produces corrupt debug information. */
1438 if (ctx->record_type)
1440 tree t;
1441 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1442 DECL_ABSTRACT_ORIGIN (t) = NULL;
1444 if (ctx->srecord_type)
1446 tree t;
1447 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1448 DECL_ABSTRACT_ORIGIN (t) = NULL;
1451 if (is_task_ctx (ctx))
1452 finalize_task_copyfn (ctx->stmt);
1454 XDELETE (ctx);
1457 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1458 context. */
1460 static void
1461 fixup_child_record_type (omp_context *ctx)
1463 tree f, type = ctx->record_type;
1465 /* ??? It isn't sufficient to just call remap_type here, because
1466 variably_modified_type_p doesn't work the way we expect for
1467 record types. Testing each field for whether it needs remapping
1468 and creating a new record by hand works, however. */
1469 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1470 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1471 break;
1472 if (f)
1474 tree name, new_fields = NULL;
1476 type = lang_hooks.types.make_type (RECORD_TYPE);
1477 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1478 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1479 TYPE_DECL, name, type);
1480 TYPE_NAME (type) = name;
1482 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1484 tree new_f = copy_node (f);
1485 DECL_CONTEXT (new_f) = type;
1486 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1487 DECL_CHAIN (new_f) = new_fields;
1488 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1489 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1490 &ctx->cb, NULL);
1491 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1492 &ctx->cb, NULL);
1493 new_fields = new_f;
1495 /* Arrange to be able to look up the receiver field
1496 given the sender field. */
1497 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1498 (splay_tree_value) new_f);
1500 TYPE_FIELDS (type) = nreverse (new_fields);
1501 layout_type (type);
1504 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1507 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1508 specified by CLAUSES. */
1510 static void
1511 scan_sharing_clauses (tree clauses, omp_context *ctx)
1513 tree c, decl;
1514 bool scan_array_reductions = false;
1516 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1518 bool by_ref;
1520 switch (OMP_CLAUSE_CODE (c))
1522 case OMP_CLAUSE_PRIVATE:
1523 decl = OMP_CLAUSE_DECL (c);
1524 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1525 goto do_private;
1526 else if (!is_variable_sized (decl))
1527 install_var_local (decl, ctx);
1528 break;
1530 case OMP_CLAUSE_SHARED:
1531 decl = OMP_CLAUSE_DECL (c);
1532 /* Ignore shared directives in teams construct. */
1533 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1535 /* Global variables don't need to be copied,
1536 the receiver side will use them directly. */
1537 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1538 if (is_global_var (odecl))
1539 break;
1540 insert_decl_map (&ctx->cb, decl, odecl);
1541 break;
1543 gcc_assert (is_taskreg_ctx (ctx));
1544 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1545 || !is_variable_sized (decl));
1546 /* Global variables don't need to be copied,
1547 the receiver side will use them directly. */
1548 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1549 break;
1550 by_ref = use_pointer_for_field (decl, ctx);
1551 if (! TREE_READONLY (decl)
1552 || TREE_ADDRESSABLE (decl)
1553 || by_ref
1554 || is_reference (decl))
1556 install_var_field (decl, by_ref, 3, ctx);
1557 install_var_local (decl, ctx);
1558 break;
1560 /* We don't need to copy const scalar vars back. */
1561 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1562 goto do_private;
1564 case OMP_CLAUSE_LASTPRIVATE:
1565 /* Let the corresponding firstprivate clause create
1566 the variable. */
1567 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1568 break;
1569 /* FALLTHRU */
1571 case OMP_CLAUSE_FIRSTPRIVATE:
1572 case OMP_CLAUSE_REDUCTION:
1573 case OMP_CLAUSE_LINEAR:
1574 decl = OMP_CLAUSE_DECL (c);
1575 do_private:
1576 if (is_variable_sized (decl))
1578 if (is_task_ctx (ctx))
1579 install_var_field (decl, false, 1, ctx);
1580 break;
1582 else if (is_taskreg_ctx (ctx))
1584 bool global
1585 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1586 by_ref = use_pointer_for_field (decl, NULL);
1588 if (is_task_ctx (ctx)
1589 && (global || by_ref || is_reference (decl)))
1591 install_var_field (decl, false, 1, ctx);
1592 if (!global)
1593 install_var_field (decl, by_ref, 2, ctx);
1595 else if (!global)
1596 install_var_field (decl, by_ref, 3, ctx);
1598 install_var_local (decl, ctx);
1599 break;
1601 case OMP_CLAUSE__LOOPTEMP_:
1602 gcc_assert (is_parallel_ctx (ctx));
1603 decl = OMP_CLAUSE_DECL (c);
1604 install_var_field (decl, false, 3, ctx);
1605 install_var_local (decl, ctx);
1606 break;
1608 case OMP_CLAUSE_COPYPRIVATE:
1609 case OMP_CLAUSE_COPYIN:
1610 decl = OMP_CLAUSE_DECL (c);
1611 by_ref = use_pointer_for_field (decl, NULL);
1612 install_var_field (decl, by_ref, 3, ctx);
1613 break;
1615 case OMP_CLAUSE_DEFAULT:
1616 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1617 break;
1619 case OMP_CLAUSE_FINAL:
1620 case OMP_CLAUSE_IF:
1621 case OMP_CLAUSE_NUM_THREADS:
1622 case OMP_CLAUSE_NUM_TEAMS:
1623 case OMP_CLAUSE_THREAD_LIMIT:
1624 case OMP_CLAUSE_DEVICE:
1625 case OMP_CLAUSE_SCHEDULE:
1626 case OMP_CLAUSE_DIST_SCHEDULE:
1627 case OMP_CLAUSE_DEPEND:
1628 case OMP_CLAUSE__CILK_FOR_COUNT_:
1629 if (ctx->outer)
1630 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1631 break;
1633 case OMP_CLAUSE_TO:
1634 case OMP_CLAUSE_FROM:
1635 case OMP_CLAUSE_MAP:
1636 if (ctx->outer)
1637 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1638 decl = OMP_CLAUSE_DECL (c);
1639 /* Global variables with "omp declare target" attribute
1640 don't need to be copied, the receiver side will use them
1641 directly. */
1642 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1643 && DECL_P (decl)
1644 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1645 && lookup_attribute ("omp declare target",
1646 DECL_ATTRIBUTES (decl)))
1647 break;
1648 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1649 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1651 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1652 #pragma omp target data, there is nothing to map for
1653 those. */
1654 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1655 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1656 break;
1658 if (DECL_P (decl))
1660 if (DECL_SIZE (decl)
1661 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1663 tree decl2 = DECL_VALUE_EXPR (decl);
1664 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1665 decl2 = TREE_OPERAND (decl2, 0);
1666 gcc_assert (DECL_P (decl2));
1667 install_var_field (decl2, true, 3, ctx);
1668 install_var_local (decl2, ctx);
1669 install_var_local (decl, ctx);
1671 else
1673 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1674 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1675 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1676 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1677 install_var_field (decl, true, 7, ctx);
1678 else
1679 install_var_field (decl, true, 3, ctx);
1680 if (gimple_omp_target_kind (ctx->stmt)
1681 == GF_OMP_TARGET_KIND_REGION)
1682 install_var_local (decl, ctx);
1685 else
1687 tree base = get_base_address (decl);
1688 tree nc = OMP_CLAUSE_CHAIN (c);
1689 if (DECL_P (base)
1690 && nc != NULL_TREE
1691 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1692 && OMP_CLAUSE_DECL (nc) == base
1693 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1694 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1696 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1697 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1699 else
1701 if (ctx->outer)
1703 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1704 decl = OMP_CLAUSE_DECL (c);
1706 gcc_assert (!splay_tree_lookup (ctx->field_map,
1707 (splay_tree_key) decl));
1708 tree field
1709 = build_decl (OMP_CLAUSE_LOCATION (c),
1710 FIELD_DECL, NULL_TREE, ptr_type_node);
1711 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1712 insert_field_into_struct (ctx->record_type, field);
1713 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1714 (splay_tree_value) field);
1717 break;
1719 case OMP_CLAUSE_NOWAIT:
1720 case OMP_CLAUSE_ORDERED:
1721 case OMP_CLAUSE_COLLAPSE:
1722 case OMP_CLAUSE_UNTIED:
1723 case OMP_CLAUSE_MERGEABLE:
1724 case OMP_CLAUSE_PROC_BIND:
1725 case OMP_CLAUSE_SAFELEN:
1726 break;
1728 case OMP_CLAUSE_ALIGNED:
1729 decl = OMP_CLAUSE_DECL (c);
1730 if (is_global_var (decl)
1731 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1732 install_var_local (decl, ctx);
1733 break;
1735 default:
1736 gcc_unreachable ();
1740 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1742 switch (OMP_CLAUSE_CODE (c))
1744 case OMP_CLAUSE_LASTPRIVATE:
1745 /* Let the corresponding firstprivate clause create
1746 the variable. */
1747 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1748 scan_array_reductions = true;
1749 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1750 break;
1751 /* FALLTHRU */
1753 case OMP_CLAUSE_PRIVATE:
1754 case OMP_CLAUSE_FIRSTPRIVATE:
1755 case OMP_CLAUSE_REDUCTION:
1756 case OMP_CLAUSE_LINEAR:
1757 decl = OMP_CLAUSE_DECL (c);
1758 if (is_variable_sized (decl))
1759 install_var_local (decl, ctx);
1760 fixup_remapped_decl (decl, ctx,
1761 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1762 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1763 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1764 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1765 scan_array_reductions = true;
1766 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1767 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1768 scan_array_reductions = true;
1769 break;
1771 case OMP_CLAUSE_SHARED:
1772 /* Ignore shared directives in teams construct. */
1773 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1774 break;
1775 decl = OMP_CLAUSE_DECL (c);
1776 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1777 fixup_remapped_decl (decl, ctx, false);
1778 break;
1780 case OMP_CLAUSE_MAP:
1781 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1782 break;
1783 decl = OMP_CLAUSE_DECL (c);
1784 if (DECL_P (decl)
1785 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1786 && lookup_attribute ("omp declare target",
1787 DECL_ATTRIBUTES (decl)))
1788 break;
1789 if (DECL_P (decl))
1791 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1792 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1793 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1795 tree new_decl = lookup_decl (decl, ctx);
1796 TREE_TYPE (new_decl)
1797 = remap_type (TREE_TYPE (decl), &ctx->cb);
1799 else if (DECL_SIZE (decl)
1800 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1802 tree decl2 = DECL_VALUE_EXPR (decl);
1803 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1804 decl2 = TREE_OPERAND (decl2, 0);
1805 gcc_assert (DECL_P (decl2));
1806 fixup_remapped_decl (decl2, ctx, false);
1807 fixup_remapped_decl (decl, ctx, true);
1809 else
1810 fixup_remapped_decl (decl, ctx, false);
1812 break;
1814 case OMP_CLAUSE_COPYPRIVATE:
1815 case OMP_CLAUSE_COPYIN:
1816 case OMP_CLAUSE_DEFAULT:
1817 case OMP_CLAUSE_IF:
1818 case OMP_CLAUSE_NUM_THREADS:
1819 case OMP_CLAUSE_NUM_TEAMS:
1820 case OMP_CLAUSE_THREAD_LIMIT:
1821 case OMP_CLAUSE_DEVICE:
1822 case OMP_CLAUSE_SCHEDULE:
1823 case OMP_CLAUSE_DIST_SCHEDULE:
1824 case OMP_CLAUSE_NOWAIT:
1825 case OMP_CLAUSE_ORDERED:
1826 case OMP_CLAUSE_COLLAPSE:
1827 case OMP_CLAUSE_UNTIED:
1828 case OMP_CLAUSE_FINAL:
1829 case OMP_CLAUSE_MERGEABLE:
1830 case OMP_CLAUSE_PROC_BIND:
1831 case OMP_CLAUSE_SAFELEN:
1832 case OMP_CLAUSE_ALIGNED:
1833 case OMP_CLAUSE_DEPEND:
1834 case OMP_CLAUSE__LOOPTEMP_:
1835 case OMP_CLAUSE_TO:
1836 case OMP_CLAUSE_FROM:
1837 case OMP_CLAUSE__CILK_FOR_COUNT_:
1838 break;
1840 default:
1841 gcc_unreachable ();
1845 if (scan_array_reductions)
1846 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1847 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1848 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1850 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1851 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1853 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1854 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1855 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1856 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1857 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1858 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1861 /* Create a new name for omp child function. Returns an identifier. If
1862 IS_CILK_FOR is true then the suffix for the child function is
1863 "_cilk_for_fn." */
1865 static tree
1866 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1868 if (is_cilk_for)
1869 return clone_function_name (current_function_decl, "_cilk_for_fn");
1870 return clone_function_name (current_function_decl,
1871 task_copy ? "_omp_cpyfn" : "_omp_fn");
1874 /* Returns the type of the induction variable for the child function for
1875 _Cilk_for and the types for _high and _low variables based on TYPE. */
1877 static tree
1878 cilk_for_check_loop_diff_type (tree type)
1880 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1882 if (TYPE_UNSIGNED (type))
1883 return uint32_type_node;
1884 else
1885 return integer_type_node;
1887 else
1889 if (TYPE_UNSIGNED (type))
1890 return uint64_type_node;
1891 else
1892 return long_long_integer_type_node;
1896 /* Build a decl for the omp child function. It'll not contain a body
1897 yet, just the bare decl. */
1899 static void
1900 create_omp_child_function (omp_context *ctx, bool task_copy)
1902 tree decl, type, name, t;
1904 tree cilk_for_count
1905 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1906 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1907 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1908 tree cilk_var_type = NULL_TREE;
1910 name = create_omp_child_function_name (task_copy,
1911 cilk_for_count != NULL_TREE);
1912 if (task_copy)
1913 type = build_function_type_list (void_type_node, ptr_type_node,
1914 ptr_type_node, NULL_TREE);
1915 else if (cilk_for_count)
1917 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1918 cilk_var_type = cilk_for_check_loop_diff_type (type);
1919 type = build_function_type_list (void_type_node, ptr_type_node,
1920 cilk_var_type, cilk_var_type, NULL_TREE);
1922 else
1923 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1925 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1927 if (!task_copy)
1928 ctx->cb.dst_fn = decl;
1929 else
1930 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1932 TREE_STATIC (decl) = 1;
1933 TREE_USED (decl) = 1;
1934 DECL_ARTIFICIAL (decl) = 1;
1935 DECL_IGNORED_P (decl) = 0;
1936 TREE_PUBLIC (decl) = 0;
1937 DECL_UNINLINABLE (decl) = 1;
1938 DECL_EXTERNAL (decl) = 0;
1939 DECL_CONTEXT (decl) = NULL_TREE;
1940 DECL_INITIAL (decl) = make_node (BLOCK);
1941 bool target_p = false;
1942 if (lookup_attribute ("omp declare target",
1943 DECL_ATTRIBUTES (current_function_decl)))
1944 target_p = true;
1945 else
1947 omp_context *octx;
1948 for (octx = ctx; octx; octx = octx->outer)
1949 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1950 && gimple_omp_target_kind (octx->stmt)
1951 == GF_OMP_TARGET_KIND_REGION)
1953 target_p = true;
1954 break;
1957 if (target_p)
1958 DECL_ATTRIBUTES (decl)
1959 = tree_cons (get_identifier ("omp declare target"),
1960 NULL_TREE, DECL_ATTRIBUTES (decl));
1962 t = build_decl (DECL_SOURCE_LOCATION (decl),
1963 RESULT_DECL, NULL_TREE, void_type_node);
1964 DECL_ARTIFICIAL (t) = 1;
1965 DECL_IGNORED_P (t) = 1;
1966 DECL_CONTEXT (t) = decl;
1967 DECL_RESULT (decl) = t;
1969 /* _Cilk_for's child function requires two extra parameters called
1970 __low and __high that are set the by Cilk runtime when it calls this
1971 function. */
1972 if (cilk_for_count)
1974 t = build_decl (DECL_SOURCE_LOCATION (decl),
1975 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1976 DECL_ARTIFICIAL (t) = 1;
1977 DECL_NAMELESS (t) = 1;
1978 DECL_ARG_TYPE (t) = ptr_type_node;
1979 DECL_CONTEXT (t) = current_function_decl;
1980 TREE_USED (t) = 1;
1981 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1982 DECL_ARGUMENTS (decl) = t;
1984 t = build_decl (DECL_SOURCE_LOCATION (decl),
1985 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1986 DECL_ARTIFICIAL (t) = 1;
1987 DECL_NAMELESS (t) = 1;
1988 DECL_ARG_TYPE (t) = ptr_type_node;
1989 DECL_CONTEXT (t) = current_function_decl;
1990 TREE_USED (t) = 1;
1991 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1992 DECL_ARGUMENTS (decl) = t;
1995 tree data_name = get_identifier (".omp_data_i");
1996 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
1997 ptr_type_node);
1998 DECL_ARTIFICIAL (t) = 1;
1999 DECL_NAMELESS (t) = 1;
2000 DECL_ARG_TYPE (t) = ptr_type_node;
2001 DECL_CONTEXT (t) = current_function_decl;
2002 TREE_USED (t) = 1;
2003 if (cilk_for_count)
2004 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2005 DECL_ARGUMENTS (decl) = t;
2006 if (!task_copy)
2007 ctx->receiver_decl = t;
2008 else
2010 t = build_decl (DECL_SOURCE_LOCATION (decl),
2011 PARM_DECL, get_identifier (".omp_data_o"),
2012 ptr_type_node);
2013 DECL_ARTIFICIAL (t) = 1;
2014 DECL_NAMELESS (t) = 1;
2015 DECL_ARG_TYPE (t) = ptr_type_node;
2016 DECL_CONTEXT (t) = current_function_decl;
2017 TREE_USED (t) = 1;
2018 TREE_ADDRESSABLE (t) = 1;
2019 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2020 DECL_ARGUMENTS (decl) = t;
2023 /* Allocate memory for the function structure. The call to
2024 allocate_struct_function clobbers CFUN, so we need to restore
2025 it afterward. */
2026 push_struct_function (decl);
2027 cfun->function_end_locus = gimple_location (ctx->stmt);
2028 pop_cfun ();
2031 /* Callback for walk_gimple_seq. Check if combined parallel
2032 contains gimple_omp_for_combined_into_p OMP_FOR. */
2034 static tree
2035 find_combined_for (gimple_stmt_iterator *gsi_p,
2036 bool *handled_ops_p,
2037 struct walk_stmt_info *wi)
2039 gimple stmt = gsi_stmt (*gsi_p);
2041 *handled_ops_p = true;
2042 switch (gimple_code (stmt))
2044 WALK_SUBSTMTS;
2046 case GIMPLE_OMP_FOR:
2047 if (gimple_omp_for_combined_into_p (stmt)
2048 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2050 wi->info = stmt;
2051 return integer_zero_node;
2053 break;
2054 default:
2055 break;
2057 return NULL;
2060 /* Scan an OpenMP parallel directive. */
2062 static void
2063 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2065 omp_context *ctx;
2066 tree name;
2067 gimple stmt = gsi_stmt (*gsi);
2069 /* Ignore parallel directives with empty bodies, unless there
2070 are copyin clauses. */
2071 if (optimize > 0
2072 && empty_body_p (gimple_omp_body (stmt))
2073 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2074 OMP_CLAUSE_COPYIN) == NULL)
2076 gsi_replace (gsi, gimple_build_nop (), false);
2077 return;
2080 if (gimple_omp_parallel_combined_p (stmt))
2082 gimple for_stmt;
2083 struct walk_stmt_info wi;
2085 memset (&wi, 0, sizeof (wi));
2086 wi.val_only = true;
2087 walk_gimple_seq (gimple_omp_body (stmt),
2088 find_combined_for, NULL, &wi);
2089 for_stmt = (gimple) wi.info;
2090 if (for_stmt)
2092 struct omp_for_data fd;
2093 extract_omp_for_data (for_stmt, &fd, NULL);
2094 /* We need two temporaries with fd.loop.v type (istart/iend)
2095 and then (fd.collapse - 1) temporaries with the same
2096 type for count2 ... countN-1 vars if not constant. */
2097 size_t count = 2, i;
2098 tree type = fd.iter_type;
2099 if (fd.collapse > 1
2100 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2101 count += fd.collapse - 1;
2102 for (i = 0; i < count; i++)
2104 tree temp = create_tmp_var (type, NULL);
2105 tree c = build_omp_clause (UNKNOWN_LOCATION,
2106 OMP_CLAUSE__LOOPTEMP_);
2107 insert_decl_map (&outer_ctx->cb, temp, temp);
2108 OMP_CLAUSE_DECL (c) = temp;
2109 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2110 gimple_omp_parallel_set_clauses (stmt, c);
2115 ctx = new_omp_context (stmt, outer_ctx);
2116 taskreg_contexts.safe_push (ctx);
2117 if (taskreg_nesting_level > 1)
2118 ctx->is_nested = true;
2119 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2120 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2121 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2122 name = create_tmp_var_name (".omp_data_s");
2123 name = build_decl (gimple_location (stmt),
2124 TYPE_DECL, name, ctx->record_type);
2125 DECL_ARTIFICIAL (name) = 1;
2126 DECL_NAMELESS (name) = 1;
2127 TYPE_NAME (ctx->record_type) = name;
2128 create_omp_child_function (ctx, false);
2129 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2131 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2132 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2134 if (TYPE_FIELDS (ctx->record_type) == NULL)
2135 ctx->record_type = ctx->receiver_decl = NULL;
2138 /* Scan an OpenMP task directive. */
2140 static void
2141 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2143 omp_context *ctx;
2144 tree name, t;
2145 gimple stmt = gsi_stmt (*gsi);
2147 /* Ignore task directives with empty bodies. */
2148 if (optimize > 0
2149 && empty_body_p (gimple_omp_body (stmt)))
2151 gsi_replace (gsi, gimple_build_nop (), false);
2152 return;
2155 ctx = new_omp_context (stmt, outer_ctx);
2156 taskreg_contexts.safe_push (ctx);
2157 if (taskreg_nesting_level > 1)
2158 ctx->is_nested = true;
2159 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2160 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2161 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2162 name = create_tmp_var_name (".omp_data_s");
2163 name = build_decl (gimple_location (stmt),
2164 TYPE_DECL, name, ctx->record_type);
2165 DECL_ARTIFICIAL (name) = 1;
2166 DECL_NAMELESS (name) = 1;
2167 TYPE_NAME (ctx->record_type) = name;
2168 create_omp_child_function (ctx, false);
2169 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2171 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2173 if (ctx->srecord_type)
2175 name = create_tmp_var_name (".omp_data_a");
2176 name = build_decl (gimple_location (stmt),
2177 TYPE_DECL, name, ctx->srecord_type);
2178 DECL_ARTIFICIAL (name) = 1;
2179 DECL_NAMELESS (name) = 1;
2180 TYPE_NAME (ctx->srecord_type) = name;
2181 create_omp_child_function (ctx, true);
2184 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2186 if (TYPE_FIELDS (ctx->record_type) == NULL)
2188 ctx->record_type = ctx->receiver_decl = NULL;
2189 t = build_int_cst (long_integer_type_node, 0);
2190 gimple_omp_task_set_arg_size (stmt, t);
2191 t = build_int_cst (long_integer_type_node, 1);
2192 gimple_omp_task_set_arg_align (stmt, t);
2197 /* If any decls have been made addressable during scan_omp,
2198 adjust their fields if needed, and layout record types
2199 of parallel/task constructs. */
2201 static void
2202 finish_taskreg_scan (omp_context *ctx)
2204 if (ctx->record_type == NULL_TREE)
2205 return;
2207 /* If any task_shared_vars were needed, verify all
2208 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2209 statements if use_pointer_for_field hasn't changed
2210 because of that. If it did, update field types now. */
2211 if (task_shared_vars)
2213 tree c;
2215 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2216 c; c = OMP_CLAUSE_CHAIN (c))
2217 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2219 tree decl = OMP_CLAUSE_DECL (c);
2221 /* Global variables don't need to be copied,
2222 the receiver side will use them directly. */
2223 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2224 continue;
2225 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2226 || !use_pointer_for_field (decl, ctx))
2227 continue;
2228 tree field = lookup_field (decl, ctx);
2229 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2230 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2231 continue;
2232 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2233 TREE_THIS_VOLATILE (field) = 0;
2234 DECL_USER_ALIGN (field) = 0;
2235 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2236 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2237 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2238 if (ctx->srecord_type)
2240 tree sfield = lookup_sfield (decl, ctx);
2241 TREE_TYPE (sfield) = TREE_TYPE (field);
2242 TREE_THIS_VOLATILE (sfield) = 0;
2243 DECL_USER_ALIGN (sfield) = 0;
2244 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2245 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2246 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2251 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2253 layout_type (ctx->record_type);
2254 fixup_child_record_type (ctx);
2256 else
2258 location_t loc = gimple_location (ctx->stmt);
2259 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2260 /* Move VLA fields to the end. */
2261 p = &TYPE_FIELDS (ctx->record_type);
2262 while (*p)
2263 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2264 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2266 *q = *p;
2267 *p = TREE_CHAIN (*p);
2268 TREE_CHAIN (*q) = NULL_TREE;
2269 q = &TREE_CHAIN (*q);
2271 else
2272 p = &DECL_CHAIN (*p);
2273 *p = vla_fields;
2274 layout_type (ctx->record_type);
2275 fixup_child_record_type (ctx);
2276 if (ctx->srecord_type)
2277 layout_type (ctx->srecord_type);
2278 tree t = fold_convert_loc (loc, long_integer_type_node,
2279 TYPE_SIZE_UNIT (ctx->record_type));
2280 gimple_omp_task_set_arg_size (ctx->stmt, t);
2281 t = build_int_cst (long_integer_type_node,
2282 TYPE_ALIGN_UNIT (ctx->record_type));
2283 gimple_omp_task_set_arg_align (ctx->stmt, t);
2288 /* Scan an OpenMP loop directive. */
2290 static void
2291 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2293 omp_context *ctx;
2294 size_t i;
2296 ctx = new_omp_context (stmt, outer_ctx);
2298 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2300 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2301 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2303 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2304 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2305 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2306 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2308 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2311 /* Scan an OpenMP sections directive. */
2313 static void
2314 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2316 omp_context *ctx;
2318 ctx = new_omp_context (stmt, outer_ctx);
2319 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2320 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2323 /* Scan an OpenMP single directive. */
2325 static void
2326 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2328 omp_context *ctx;
2329 tree name;
2331 ctx = new_omp_context (stmt, outer_ctx);
2332 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2333 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2334 name = create_tmp_var_name (".omp_copy_s");
2335 name = build_decl (gimple_location (stmt),
2336 TYPE_DECL, name, ctx->record_type);
2337 TYPE_NAME (ctx->record_type) = name;
2339 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2340 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2342 if (TYPE_FIELDS (ctx->record_type) == NULL)
2343 ctx->record_type = NULL;
2344 else
2345 layout_type (ctx->record_type);
2348 /* Scan an OpenMP target{, data, update} directive. */
2350 static void
2351 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2353 omp_context *ctx;
2354 tree name;
2355 int kind = gimple_omp_target_kind (stmt);
2357 ctx = new_omp_context (stmt, outer_ctx);
2358 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2359 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2360 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2361 name = create_tmp_var_name (".omp_data_t");
2362 name = build_decl (gimple_location (stmt),
2363 TYPE_DECL, name, ctx->record_type);
2364 DECL_ARTIFICIAL (name) = 1;
2365 DECL_NAMELESS (name) = 1;
2366 TYPE_NAME (ctx->record_type) = name;
2367 if (kind == GF_OMP_TARGET_KIND_REGION)
2369 create_omp_child_function (ctx, false);
2370 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2373 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2374 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2376 if (TYPE_FIELDS (ctx->record_type) == NULL)
2377 ctx->record_type = ctx->receiver_decl = NULL;
2378 else
2380 TYPE_FIELDS (ctx->record_type)
2381 = nreverse (TYPE_FIELDS (ctx->record_type));
2382 #ifdef ENABLE_CHECKING
2383 tree field;
2384 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2385 for (field = TYPE_FIELDS (ctx->record_type);
2386 field;
2387 field = DECL_CHAIN (field))
2388 gcc_assert (DECL_ALIGN (field) == align);
2389 #endif
2390 layout_type (ctx->record_type);
2391 if (kind == GF_OMP_TARGET_KIND_REGION)
2392 fixup_child_record_type (ctx);
2396 /* Scan an OpenMP teams directive. */
2398 static void
2399 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2401 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2402 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2403 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2406 /* Check OpenMP nesting restrictions. */
2407 static bool
2408 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2410 if (ctx != NULL)
2412 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2413 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2415 error_at (gimple_location (stmt),
2416 "OpenMP constructs may not be nested inside simd region");
2417 return false;
2419 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2421 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2422 || (gimple_omp_for_kind (stmt)
2423 != GF_OMP_FOR_KIND_DISTRIBUTE))
2424 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2426 error_at (gimple_location (stmt),
2427 "only distribute or parallel constructs are allowed to "
2428 "be closely nested inside teams construct");
2429 return false;
2433 switch (gimple_code (stmt))
2435 case GIMPLE_OMP_FOR:
2436 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2437 return true;
2438 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2440 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2442 error_at (gimple_location (stmt),
2443 "distribute construct must be closely nested inside "
2444 "teams construct");
2445 return false;
2447 return true;
2449 /* FALLTHRU */
2450 case GIMPLE_CALL:
2451 if (is_gimple_call (stmt)
2452 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2453 == BUILT_IN_GOMP_CANCEL
2454 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2455 == BUILT_IN_GOMP_CANCELLATION_POINT))
2457 const char *bad = NULL;
2458 const char *kind = NULL;
2459 if (ctx == NULL)
2461 error_at (gimple_location (stmt), "orphaned %qs construct",
2462 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2463 == BUILT_IN_GOMP_CANCEL
2464 ? "#pragma omp cancel"
2465 : "#pragma omp cancellation point");
2466 return false;
2468 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2469 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2470 : 0)
2472 case 1:
2473 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2474 bad = "#pragma omp parallel";
2475 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2476 == BUILT_IN_GOMP_CANCEL
2477 && !integer_zerop (gimple_call_arg (stmt, 1)))
2478 ctx->cancellable = true;
2479 kind = "parallel";
2480 break;
2481 case 2:
2482 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2483 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2484 bad = "#pragma omp for";
2485 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2486 == BUILT_IN_GOMP_CANCEL
2487 && !integer_zerop (gimple_call_arg (stmt, 1)))
2489 ctx->cancellable = true;
2490 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2491 OMP_CLAUSE_NOWAIT))
2492 warning_at (gimple_location (stmt), 0,
2493 "%<#pragma omp cancel for%> inside "
2494 "%<nowait%> for construct");
2495 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2496 OMP_CLAUSE_ORDERED))
2497 warning_at (gimple_location (stmt), 0,
2498 "%<#pragma omp cancel for%> inside "
2499 "%<ordered%> for construct");
2501 kind = "for";
2502 break;
2503 case 4:
2504 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2505 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2506 bad = "#pragma omp sections";
2507 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2508 == BUILT_IN_GOMP_CANCEL
2509 && !integer_zerop (gimple_call_arg (stmt, 1)))
2511 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2513 ctx->cancellable = true;
2514 if (find_omp_clause (gimple_omp_sections_clauses
2515 (ctx->stmt),
2516 OMP_CLAUSE_NOWAIT))
2517 warning_at (gimple_location (stmt), 0,
2518 "%<#pragma omp cancel sections%> inside "
2519 "%<nowait%> sections construct");
2521 else
2523 gcc_assert (ctx->outer
2524 && gimple_code (ctx->outer->stmt)
2525 == GIMPLE_OMP_SECTIONS);
2526 ctx->outer->cancellable = true;
2527 if (find_omp_clause (gimple_omp_sections_clauses
2528 (ctx->outer->stmt),
2529 OMP_CLAUSE_NOWAIT))
2530 warning_at (gimple_location (stmt), 0,
2531 "%<#pragma omp cancel sections%> inside "
2532 "%<nowait%> sections construct");
2535 kind = "sections";
2536 break;
2537 case 8:
2538 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2539 bad = "#pragma omp task";
2540 else
2541 ctx->cancellable = true;
2542 kind = "taskgroup";
2543 break;
2544 default:
2545 error_at (gimple_location (stmt), "invalid arguments");
2546 return false;
2548 if (bad)
2550 error_at (gimple_location (stmt),
2551 "%<%s %s%> construct not closely nested inside of %qs",
2552 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2553 == BUILT_IN_GOMP_CANCEL
2554 ? "#pragma omp cancel"
2555 : "#pragma omp cancellation point", kind, bad);
2556 return false;
2559 /* FALLTHRU */
2560 case GIMPLE_OMP_SECTIONS:
2561 case GIMPLE_OMP_SINGLE:
2562 for (; ctx != NULL; ctx = ctx->outer)
2563 switch (gimple_code (ctx->stmt))
2565 case GIMPLE_OMP_FOR:
2566 case GIMPLE_OMP_SECTIONS:
2567 case GIMPLE_OMP_SINGLE:
2568 case GIMPLE_OMP_ORDERED:
2569 case GIMPLE_OMP_MASTER:
2570 case GIMPLE_OMP_TASK:
2571 case GIMPLE_OMP_CRITICAL:
2572 if (is_gimple_call (stmt))
2574 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2575 != BUILT_IN_GOMP_BARRIER)
2576 return true;
2577 error_at (gimple_location (stmt),
2578 "barrier region may not be closely nested inside "
2579 "of work-sharing, critical, ordered, master or "
2580 "explicit task region");
2581 return false;
2583 error_at (gimple_location (stmt),
2584 "work-sharing region may not be closely nested inside "
2585 "of work-sharing, critical, ordered, master or explicit "
2586 "task region");
2587 return false;
2588 case GIMPLE_OMP_PARALLEL:
2589 return true;
2590 default:
2591 break;
2593 break;
2594 case GIMPLE_OMP_MASTER:
2595 for (; ctx != NULL; ctx = ctx->outer)
2596 switch (gimple_code (ctx->stmt))
2598 case GIMPLE_OMP_FOR:
2599 case GIMPLE_OMP_SECTIONS:
2600 case GIMPLE_OMP_SINGLE:
2601 case GIMPLE_OMP_TASK:
2602 error_at (gimple_location (stmt),
2603 "master region may not be closely nested inside "
2604 "of work-sharing or explicit task region");
2605 return false;
2606 case GIMPLE_OMP_PARALLEL:
2607 return true;
2608 default:
2609 break;
2611 break;
2612 case GIMPLE_OMP_ORDERED:
2613 for (; ctx != NULL; ctx = ctx->outer)
2614 switch (gimple_code (ctx->stmt))
2616 case GIMPLE_OMP_CRITICAL:
2617 case GIMPLE_OMP_TASK:
2618 error_at (gimple_location (stmt),
2619 "ordered region may not be closely nested inside "
2620 "of critical or explicit task region");
2621 return false;
2622 case GIMPLE_OMP_FOR:
2623 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2624 OMP_CLAUSE_ORDERED) == NULL)
2626 error_at (gimple_location (stmt),
2627 "ordered region must be closely nested inside "
2628 "a loop region with an ordered clause");
2629 return false;
2631 return true;
2632 case GIMPLE_OMP_PARALLEL:
2633 error_at (gimple_location (stmt),
2634 "ordered region must be closely nested inside "
2635 "a loop region with an ordered clause");
2636 return false;
2637 default:
2638 break;
2640 break;
2641 case GIMPLE_OMP_CRITICAL:
2642 for (; ctx != NULL; ctx = ctx->outer)
2643 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2644 && (gimple_omp_critical_name (stmt)
2645 == gimple_omp_critical_name (ctx->stmt)))
2647 error_at (gimple_location (stmt),
2648 "critical region may not be nested inside a critical "
2649 "region with the same name");
2650 return false;
2652 break;
2653 case GIMPLE_OMP_TEAMS:
2654 if (ctx == NULL
2655 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2656 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2658 error_at (gimple_location (stmt),
2659 "teams construct not closely nested inside of target "
2660 "region");
2661 return false;
2663 break;
2664 case GIMPLE_OMP_TARGET:
2665 for (; ctx != NULL; ctx = ctx->outer)
2666 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
2667 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
2669 const char *name;
2670 switch (gimple_omp_target_kind (stmt))
2672 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2673 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2674 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2675 default: gcc_unreachable ();
2677 warning_at (gimple_location (stmt), 0,
2678 "%s construct inside of target region", name);
2680 break;
2681 default:
2682 break;
2684 return true;
2688 /* Helper function scan_omp.
2690 Callback for walk_tree or operators in walk_gimple_stmt used to
2691 scan for OpenMP directives in TP. */
2693 static tree
2694 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2696 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2697 omp_context *ctx = (omp_context *) wi->info;
2698 tree t = *tp;
2700 switch (TREE_CODE (t))
2702 case VAR_DECL:
2703 case PARM_DECL:
2704 case LABEL_DECL:
2705 case RESULT_DECL:
2706 if (ctx)
2707 *tp = remap_decl (t, &ctx->cb);
2708 break;
2710 default:
2711 if (ctx && TYPE_P (t))
2712 *tp = remap_type (t, &ctx->cb);
2713 else if (!DECL_P (t))
2715 *walk_subtrees = 1;
2716 if (ctx)
2718 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2719 if (tem != TREE_TYPE (t))
2721 if (TREE_CODE (t) == INTEGER_CST)
2722 *tp = wide_int_to_tree (tem, t);
2723 else
2724 TREE_TYPE (t) = tem;
2728 break;
2731 return NULL_TREE;
2734 /* Return true if FNDECL is a setjmp or a longjmp. */
2736 static bool
2737 setjmp_or_longjmp_p (const_tree fndecl)
2739 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2740 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2741 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2742 return true;
2744 tree declname = DECL_NAME (fndecl);
2745 if (!declname)
2746 return false;
2747 const char *name = IDENTIFIER_POINTER (declname);
2748 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2752 /* Helper function for scan_omp.
2754 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2755 the current statement in GSI. */
2757 static tree
2758 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2759 struct walk_stmt_info *wi)
2761 gimple stmt = gsi_stmt (*gsi);
2762 omp_context *ctx = (omp_context *) wi->info;
2764 if (gimple_has_location (stmt))
2765 input_location = gimple_location (stmt);
2767 /* Check the OpenMP nesting restrictions. */
2768 bool remove = false;
2769 if (is_gimple_omp (stmt))
2770 remove = !check_omp_nesting_restrictions (stmt, ctx);
2771 else if (is_gimple_call (stmt))
2773 tree fndecl = gimple_call_fndecl (stmt);
2774 if (fndecl)
2776 if (setjmp_or_longjmp_p (fndecl)
2777 && ctx
2778 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2779 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2781 remove = true;
2782 error_at (gimple_location (stmt),
2783 "setjmp/longjmp inside simd construct");
2785 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2786 switch (DECL_FUNCTION_CODE (fndecl))
2788 case BUILT_IN_GOMP_BARRIER:
2789 case BUILT_IN_GOMP_CANCEL:
2790 case BUILT_IN_GOMP_CANCELLATION_POINT:
2791 case BUILT_IN_GOMP_TASKYIELD:
2792 case BUILT_IN_GOMP_TASKWAIT:
2793 case BUILT_IN_GOMP_TASKGROUP_START:
2794 case BUILT_IN_GOMP_TASKGROUP_END:
2795 remove = !check_omp_nesting_restrictions (stmt, ctx);
2796 break;
2797 default:
2798 break;
2802 if (remove)
2804 stmt = gimple_build_nop ();
2805 gsi_replace (gsi, stmt, false);
2808 *handled_ops_p = true;
2810 switch (gimple_code (stmt))
2812 case GIMPLE_OMP_PARALLEL:
2813 taskreg_nesting_level++;
2814 scan_omp_parallel (gsi, ctx);
2815 taskreg_nesting_level--;
2816 break;
2818 case GIMPLE_OMP_TASK:
2819 taskreg_nesting_level++;
2820 scan_omp_task (gsi, ctx);
2821 taskreg_nesting_level--;
2822 break;
2824 case GIMPLE_OMP_FOR:
2825 scan_omp_for (stmt, ctx);
2826 break;
2828 case GIMPLE_OMP_SECTIONS:
2829 scan_omp_sections (stmt, ctx);
2830 break;
2832 case GIMPLE_OMP_SINGLE:
2833 scan_omp_single (stmt, ctx);
2834 break;
2836 case GIMPLE_OMP_SECTION:
2837 case GIMPLE_OMP_MASTER:
2838 case GIMPLE_OMP_TASKGROUP:
2839 case GIMPLE_OMP_ORDERED:
2840 case GIMPLE_OMP_CRITICAL:
2841 ctx = new_omp_context (stmt, ctx);
2842 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2843 break;
2845 case GIMPLE_OMP_TARGET:
2846 scan_omp_target (stmt, ctx);
2847 break;
2849 case GIMPLE_OMP_TEAMS:
2850 scan_omp_teams (stmt, ctx);
2851 break;
2853 case GIMPLE_BIND:
2855 tree var;
2857 *handled_ops_p = false;
2858 if (ctx)
2859 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2860 insert_decl_map (&ctx->cb, var, var);
2862 break;
2863 default:
2864 *handled_ops_p = false;
2865 break;
2868 return NULL_TREE;
2872 /* Scan all the statements starting at the current statement. CTX
2873 contains context information about the OpenMP directives and
2874 clauses found during the scan. */
2876 static void
2877 scan_omp (gimple_seq *body_p, omp_context *ctx)
2879 location_t saved_location;
2880 struct walk_stmt_info wi;
2882 memset (&wi, 0, sizeof (wi));
2883 wi.info = ctx;
2884 wi.want_locations = true;
2886 saved_location = input_location;
2887 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2888 input_location = saved_location;
2891 /* Re-gimplification and code generation routines. */
2893 /* Build a call to GOMP_barrier. */
2895 static gimple
2896 build_omp_barrier (tree lhs)
2898 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2899 : BUILT_IN_GOMP_BARRIER);
2900 gimple g = gimple_build_call (fndecl, 0);
2901 if (lhs)
2902 gimple_call_set_lhs (g, lhs);
2903 return g;
2906 /* If a context was created for STMT when it was scanned, return it. */
2908 static omp_context *
2909 maybe_lookup_ctx (gimple stmt)
2911 splay_tree_node n;
2912 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2913 return n ? (omp_context *) n->value : NULL;
2917 /* Find the mapping for DECL in CTX or the immediately enclosing
2918 context that has a mapping for DECL.
2920 If CTX is a nested parallel directive, we may have to use the decl
2921 mappings created in CTX's parent context. Suppose that we have the
2922 following parallel nesting (variable UIDs showed for clarity):
2924 iD.1562 = 0;
2925 #omp parallel shared(iD.1562) -> outer parallel
2926 iD.1562 = iD.1562 + 1;
2928 #omp parallel shared (iD.1562) -> inner parallel
2929 iD.1562 = iD.1562 - 1;
2931 Each parallel structure will create a distinct .omp_data_s structure
2932 for copying iD.1562 in/out of the directive:
2934 outer parallel .omp_data_s.1.i -> iD.1562
2935 inner parallel .omp_data_s.2.i -> iD.1562
2937 A shared variable mapping will produce a copy-out operation before
2938 the parallel directive and a copy-in operation after it. So, in
2939 this case we would have:
2941 iD.1562 = 0;
2942 .omp_data_o.1.i = iD.1562;
2943 #omp parallel shared(iD.1562) -> outer parallel
2944 .omp_data_i.1 = &.omp_data_o.1
2945 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2947 .omp_data_o.2.i = iD.1562; -> **
2948 #omp parallel shared(iD.1562) -> inner parallel
2949 .omp_data_i.2 = &.omp_data_o.2
2950 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2953 ** This is a problem. The symbol iD.1562 cannot be referenced
2954 inside the body of the outer parallel region. But since we are
2955 emitting this copy operation while expanding the inner parallel
2956 directive, we need to access the CTX structure of the outer
2957 parallel directive to get the correct mapping:
2959 .omp_data_o.2.i = .omp_data_i.1->i
2961 Since there may be other workshare or parallel directives enclosing
2962 the parallel directive, it may be necessary to walk up the context
2963 parent chain. This is not a problem in general because nested
2964 parallelism happens only rarely. */
2966 static tree
2967 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2969 tree t;
2970 omp_context *up;
2972 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2973 t = maybe_lookup_decl (decl, up);
2975 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2977 return t ? t : decl;
2981 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2982 in outer contexts. */
2984 static tree
2985 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2987 tree t = NULL;
2988 omp_context *up;
2990 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2991 t = maybe_lookup_decl (decl, up);
2993 return t ? t : decl;
2997 /* Construct the initialization value for reduction CLAUSE. */
2999 tree
3000 omp_reduction_init (tree clause, tree type)
3002 location_t loc = OMP_CLAUSE_LOCATION (clause);
3003 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3005 case PLUS_EXPR:
3006 case MINUS_EXPR:
3007 case BIT_IOR_EXPR:
3008 case BIT_XOR_EXPR:
3009 case TRUTH_OR_EXPR:
3010 case TRUTH_ORIF_EXPR:
3011 case TRUTH_XOR_EXPR:
3012 case NE_EXPR:
3013 return build_zero_cst (type);
3015 case MULT_EXPR:
3016 case TRUTH_AND_EXPR:
3017 case TRUTH_ANDIF_EXPR:
3018 case EQ_EXPR:
3019 return fold_convert_loc (loc, type, integer_one_node);
3021 case BIT_AND_EXPR:
3022 return fold_convert_loc (loc, type, integer_minus_one_node);
3024 case MAX_EXPR:
3025 if (SCALAR_FLOAT_TYPE_P (type))
3027 REAL_VALUE_TYPE max, min;
3028 if (HONOR_INFINITIES (TYPE_MODE (type)))
3030 real_inf (&max);
3031 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3033 else
3034 real_maxval (&min, 1, TYPE_MODE (type));
3035 return build_real (type, min);
3037 else
3039 gcc_assert (INTEGRAL_TYPE_P (type));
3040 return TYPE_MIN_VALUE (type);
3043 case MIN_EXPR:
3044 if (SCALAR_FLOAT_TYPE_P (type))
3046 REAL_VALUE_TYPE max;
3047 if (HONOR_INFINITIES (TYPE_MODE (type)))
3048 real_inf (&max);
3049 else
3050 real_maxval (&max, 0, TYPE_MODE (type));
3051 return build_real (type, max);
3053 else
3055 gcc_assert (INTEGRAL_TYPE_P (type));
3056 return TYPE_MAX_VALUE (type);
3059 default:
3060 gcc_unreachable ();
3064 /* Return alignment to be assumed for var in CLAUSE, which should be
3065 OMP_CLAUSE_ALIGNED. */
3067 static tree
3068 omp_clause_aligned_alignment (tree clause)
3070 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3071 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3073 /* Otherwise return implementation defined alignment. */
3074 unsigned int al = 1;
3075 machine_mode mode, vmode;
3076 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3077 if (vs)
3078 vs = 1 << floor_log2 (vs);
3079 static enum mode_class classes[]
3080 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3081 for (int i = 0; i < 4; i += 2)
3082 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3083 mode != VOIDmode;
3084 mode = GET_MODE_WIDER_MODE (mode))
3086 vmode = targetm.vectorize.preferred_simd_mode (mode);
3087 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3088 continue;
3089 while (vs
3090 && GET_MODE_SIZE (vmode) < vs
3091 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3092 vmode = GET_MODE_2XWIDER_MODE (vmode);
3094 tree type = lang_hooks.types.type_for_mode (mode, 1);
3095 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3096 continue;
3097 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3098 / GET_MODE_SIZE (mode));
3099 if (TYPE_MODE (type) != vmode)
3100 continue;
3101 if (TYPE_ALIGN_UNIT (type) > al)
3102 al = TYPE_ALIGN_UNIT (type);
3104 return build_int_cst (integer_type_node, al);
3107 /* Return maximum possible vectorization factor for the target. */
3109 static int
3110 omp_max_vf (void)
3112 if (!optimize
3113 || optimize_debug
3114 || !flag_tree_loop_optimize
3115 || (!flag_tree_loop_vectorize
3116 && (global_options_set.x_flag_tree_loop_vectorize
3117 || global_options_set.x_flag_tree_vectorize)))
3118 return 1;
3120 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3121 if (vs)
3123 vs = 1 << floor_log2 (vs);
3124 return vs;
3126 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3127 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3128 return GET_MODE_NUNITS (vqimode);
3129 return 1;
3132 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3133 privatization. */
3135 static bool
3136 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3137 tree &idx, tree &lane, tree &ivar, tree &lvar)
3139 if (max_vf == 0)
3141 max_vf = omp_max_vf ();
3142 if (max_vf > 1)
3144 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3145 OMP_CLAUSE_SAFELEN);
3146 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3147 max_vf = 1;
3148 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3149 max_vf) == -1)
3150 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3152 if (max_vf > 1)
3154 idx = create_tmp_var (unsigned_type_node, NULL);
3155 lane = create_tmp_var (unsigned_type_node, NULL);
3158 if (max_vf == 1)
3159 return false;
3161 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3162 tree avar = create_tmp_var_raw (atype, NULL);
3163 if (TREE_ADDRESSABLE (new_var))
3164 TREE_ADDRESSABLE (avar) = 1;
3165 DECL_ATTRIBUTES (avar)
3166 = tree_cons (get_identifier ("omp simd array"), NULL,
3167 DECL_ATTRIBUTES (avar));
3168 gimple_add_tmp_var (avar);
3169 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3170 NULL_TREE, NULL_TREE);
3171 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3172 NULL_TREE, NULL_TREE);
3173 if (DECL_P (new_var))
3175 SET_DECL_VALUE_EXPR (new_var, lvar);
3176 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3178 return true;
3181 /* Helper function of lower_rec_input_clauses. For a reference
3182 in simd reduction, add an underlying variable it will reference. */
3184 static void
3185 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3187 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3188 if (TREE_CONSTANT (z))
3190 const char *name = NULL;
3191 if (DECL_NAME (new_vard))
3192 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3194 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3195 gimple_add_tmp_var (z);
3196 TREE_ADDRESSABLE (z) = 1;
3197 z = build_fold_addr_expr_loc (loc, z);
3198 gimplify_assign (new_vard, z, ilist);
3202 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3203 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3204 private variables. Initialization statements go in ILIST, while calls
3205 to destructors go in DLIST. */
3207 static void
3208 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3209 omp_context *ctx, struct omp_for_data *fd)
3211 tree c, dtor, copyin_seq, x, ptr;
3212 bool copyin_by_ref = false;
3213 bool lastprivate_firstprivate = false;
3214 bool reduction_omp_orig_ref = false;
3215 int pass;
3216 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3217 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3218 int max_vf = 0;
3219 tree lane = NULL_TREE, idx = NULL_TREE;
3220 tree ivar = NULL_TREE, lvar = NULL_TREE;
3221 gimple_seq llist[2] = { NULL, NULL };
3223 copyin_seq = NULL;
3225 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3226 with data sharing clauses referencing variable sized vars. That
3227 is unnecessarily hard to support and very unlikely to result in
3228 vectorized code anyway. */
3229 if (is_simd)
3230 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3231 switch (OMP_CLAUSE_CODE (c))
3233 case OMP_CLAUSE_LINEAR:
3234 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3235 max_vf = 1;
3236 /* FALLTHRU */
3237 case OMP_CLAUSE_REDUCTION:
3238 case OMP_CLAUSE_PRIVATE:
3239 case OMP_CLAUSE_FIRSTPRIVATE:
3240 case OMP_CLAUSE_LASTPRIVATE:
3241 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3242 max_vf = 1;
3243 break;
3244 default:
3245 continue;
3248 /* Do all the fixed sized types in the first pass, and the variable sized
3249 types in the second pass. This makes sure that the scalar arguments to
3250 the variable sized types are processed before we use them in the
3251 variable sized operations. */
3252 for (pass = 0; pass < 2; ++pass)
3254 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3256 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3257 tree var, new_var;
3258 bool by_ref;
3259 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3261 switch (c_kind)
3263 case OMP_CLAUSE_PRIVATE:
3264 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3265 continue;
3266 break;
3267 case OMP_CLAUSE_SHARED:
3268 /* Ignore shared directives in teams construct. */
3269 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3270 continue;
3271 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3273 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3274 continue;
3276 case OMP_CLAUSE_FIRSTPRIVATE:
3277 case OMP_CLAUSE_COPYIN:
3278 case OMP_CLAUSE_LINEAR:
3279 break;
3280 case OMP_CLAUSE_REDUCTION:
3281 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3282 reduction_omp_orig_ref = true;
3283 break;
3284 case OMP_CLAUSE__LOOPTEMP_:
3285 /* Handle _looptemp_ clauses only on parallel. */
3286 if (fd)
3287 continue;
3288 break;
3289 case OMP_CLAUSE_LASTPRIVATE:
3290 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3292 lastprivate_firstprivate = true;
3293 if (pass != 0)
3294 continue;
3296 /* Even without corresponding firstprivate, if
3297 decl is Fortran allocatable, it needs outer var
3298 reference. */
3299 else if (pass == 0
3300 && lang_hooks.decls.omp_private_outer_ref
3301 (OMP_CLAUSE_DECL (c)))
3302 lastprivate_firstprivate = true;
3303 break;
3304 case OMP_CLAUSE_ALIGNED:
3305 if (pass == 0)
3306 continue;
3307 var = OMP_CLAUSE_DECL (c);
3308 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3309 && !is_global_var (var))
3311 new_var = maybe_lookup_decl (var, ctx);
3312 if (new_var == NULL_TREE)
3313 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3314 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3315 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3316 omp_clause_aligned_alignment (c));
3317 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3318 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3319 gimplify_and_add (x, ilist);
3321 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3322 && is_global_var (var))
3324 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3325 new_var = lookup_decl (var, ctx);
3326 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3327 t = build_fold_addr_expr_loc (clause_loc, t);
3328 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3329 t = build_call_expr_loc (clause_loc, t2, 2, t,
3330 omp_clause_aligned_alignment (c));
3331 t = fold_convert_loc (clause_loc, ptype, t);
3332 x = create_tmp_var (ptype, NULL);
3333 t = build2 (MODIFY_EXPR, ptype, x, t);
3334 gimplify_and_add (t, ilist);
3335 t = build_simple_mem_ref_loc (clause_loc, x);
3336 SET_DECL_VALUE_EXPR (new_var, t);
3337 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3339 continue;
3340 default:
3341 continue;
3344 new_var = var = OMP_CLAUSE_DECL (c);
3345 if (c_kind != OMP_CLAUSE_COPYIN)
3346 new_var = lookup_decl (var, ctx);
3348 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3350 if (pass != 0)
3351 continue;
3353 else if (is_variable_sized (var))
3355 /* For variable sized types, we need to allocate the
3356 actual storage here. Call alloca and store the
3357 result in the pointer decl that we created elsewhere. */
3358 if (pass == 0)
3359 continue;
3361 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3363 gimple stmt;
3364 tree tmp, atmp;
3366 ptr = DECL_VALUE_EXPR (new_var);
3367 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3368 ptr = TREE_OPERAND (ptr, 0);
3369 gcc_assert (DECL_P (ptr));
3370 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3372 /* void *tmp = __builtin_alloca */
3373 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3374 stmt = gimple_build_call (atmp, 1, x);
3375 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3376 gimple_add_tmp_var (tmp);
3377 gimple_call_set_lhs (stmt, tmp);
3379 gimple_seq_add_stmt (ilist, stmt);
3381 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3382 gimplify_assign (ptr, x, ilist);
3385 else if (is_reference (var))
3387 /* For references that are being privatized for Fortran,
3388 allocate new backing storage for the new pointer
3389 variable. This allows us to avoid changing all the
3390 code that expects a pointer to something that expects
3391 a direct variable. */
3392 if (pass == 0)
3393 continue;
3395 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3396 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3398 x = build_receiver_ref (var, false, ctx);
3399 x = build_fold_addr_expr_loc (clause_loc, x);
3401 else if (TREE_CONSTANT (x))
3403 /* For reduction in SIMD loop, defer adding the
3404 initialization of the reference, because if we decide
3405 to use SIMD array for it, the initilization could cause
3406 expansion ICE. */
3407 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3408 x = NULL_TREE;
3409 else
3411 const char *name = NULL;
3412 if (DECL_NAME (var))
3413 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3415 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3416 name);
3417 gimple_add_tmp_var (x);
3418 TREE_ADDRESSABLE (x) = 1;
3419 x = build_fold_addr_expr_loc (clause_loc, x);
3422 else
3424 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3425 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3428 if (x)
3430 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3431 gimplify_assign (new_var, x, ilist);
3434 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3436 else if (c_kind == OMP_CLAUSE_REDUCTION
3437 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3439 if (pass == 0)
3440 continue;
3442 else if (pass != 0)
3443 continue;
3445 switch (OMP_CLAUSE_CODE (c))
3447 case OMP_CLAUSE_SHARED:
3448 /* Ignore shared directives in teams construct. */
3449 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3450 continue;
3451 /* Shared global vars are just accessed directly. */
3452 if (is_global_var (new_var))
3453 break;
3454 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3455 needs to be delayed until after fixup_child_record_type so
3456 that we get the correct type during the dereference. */
3457 by_ref = use_pointer_for_field (var, ctx);
3458 x = build_receiver_ref (var, by_ref, ctx);
3459 SET_DECL_VALUE_EXPR (new_var, x);
3460 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3462 /* ??? If VAR is not passed by reference, and the variable
3463 hasn't been initialized yet, then we'll get a warning for
3464 the store into the omp_data_s structure. Ideally, we'd be
3465 able to notice this and not store anything at all, but
3466 we're generating code too early. Suppress the warning. */
3467 if (!by_ref)
3468 TREE_NO_WARNING (var) = 1;
3469 break;
3471 case OMP_CLAUSE_LASTPRIVATE:
3472 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3473 break;
3474 /* FALLTHRU */
3476 case OMP_CLAUSE_PRIVATE:
3477 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3478 x = build_outer_var_ref (var, ctx);
3479 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3481 if (is_task_ctx (ctx))
3482 x = build_receiver_ref (var, false, ctx);
3483 else
3484 x = build_outer_var_ref (var, ctx);
3486 else
3487 x = NULL;
3488 do_private:
3489 tree nx;
3490 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3491 if (is_simd)
3493 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3494 if ((TREE_ADDRESSABLE (new_var) || nx || y
3495 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3496 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3497 idx, lane, ivar, lvar))
3499 if (nx)
3500 x = lang_hooks.decls.omp_clause_default_ctor
3501 (c, unshare_expr (ivar), x);
3502 if (nx && x)
3503 gimplify_and_add (x, &llist[0]);
3504 if (y)
3506 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3507 if (y)
3509 gimple_seq tseq = NULL;
3511 dtor = y;
3512 gimplify_stmt (&dtor, &tseq);
3513 gimple_seq_add_seq (&llist[1], tseq);
3516 break;
3519 if (nx)
3520 gimplify_and_add (nx, ilist);
3521 /* FALLTHRU */
3523 do_dtor:
3524 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3525 if (x)
3527 gimple_seq tseq = NULL;
3529 dtor = x;
3530 gimplify_stmt (&dtor, &tseq);
3531 gimple_seq_add_seq (dlist, tseq);
3533 break;
3535 case OMP_CLAUSE_LINEAR:
3536 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3537 goto do_firstprivate;
3538 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3539 x = NULL;
3540 else
3541 x = build_outer_var_ref (var, ctx);
3542 goto do_private;
3544 case OMP_CLAUSE_FIRSTPRIVATE:
3545 if (is_task_ctx (ctx))
3547 if (is_reference (var) || is_variable_sized (var))
3548 goto do_dtor;
3549 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3550 ctx))
3551 || use_pointer_for_field (var, NULL))
3553 x = build_receiver_ref (var, false, ctx);
3554 SET_DECL_VALUE_EXPR (new_var, x);
3555 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3556 goto do_dtor;
3559 do_firstprivate:
3560 x = build_outer_var_ref (var, ctx);
3561 if (is_simd)
3563 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3564 && gimple_omp_for_combined_into_p (ctx->stmt))
3566 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3567 tree stept = TREE_TYPE (t);
3568 tree ct = find_omp_clause (clauses,
3569 OMP_CLAUSE__LOOPTEMP_);
3570 gcc_assert (ct);
3571 tree l = OMP_CLAUSE_DECL (ct);
3572 tree n1 = fd->loop.n1;
3573 tree step = fd->loop.step;
3574 tree itype = TREE_TYPE (l);
3575 if (POINTER_TYPE_P (itype))
3576 itype = signed_type_for (itype);
3577 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3578 if (TYPE_UNSIGNED (itype)
3579 && fd->loop.cond_code == GT_EXPR)
3580 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3581 fold_build1 (NEGATE_EXPR, itype, l),
3582 fold_build1 (NEGATE_EXPR,
3583 itype, step));
3584 else
3585 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3586 t = fold_build2 (MULT_EXPR, stept,
3587 fold_convert (stept, l), t);
3589 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3591 x = lang_hooks.decls.omp_clause_linear_ctor
3592 (c, new_var, x, t);
3593 gimplify_and_add (x, ilist);
3594 goto do_dtor;
3597 if (POINTER_TYPE_P (TREE_TYPE (x)))
3598 x = fold_build2 (POINTER_PLUS_EXPR,
3599 TREE_TYPE (x), x, t);
3600 else
3601 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3604 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3605 || TREE_ADDRESSABLE (new_var))
3606 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3607 idx, lane, ivar, lvar))
3609 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3611 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3612 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3613 gimplify_and_add (x, ilist);
3614 gimple_stmt_iterator gsi
3615 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3616 gimple g
3617 = gimple_build_assign (unshare_expr (lvar), iv);
3618 gsi_insert_before_without_update (&gsi, g,
3619 GSI_SAME_STMT);
3620 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3621 enum tree_code code = PLUS_EXPR;
3622 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3623 code = POINTER_PLUS_EXPR;
3624 g = gimple_build_assign_with_ops (code, iv, iv, t);
3625 gsi_insert_before_without_update (&gsi, g,
3626 GSI_SAME_STMT);
3627 break;
3629 x = lang_hooks.decls.omp_clause_copy_ctor
3630 (c, unshare_expr (ivar), x);
3631 gimplify_and_add (x, &llist[0]);
3632 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3633 if (x)
3635 gimple_seq tseq = NULL;
3637 dtor = x;
3638 gimplify_stmt (&dtor, &tseq);
3639 gimple_seq_add_seq (&llist[1], tseq);
3641 break;
3644 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3645 gimplify_and_add (x, ilist);
3646 goto do_dtor;
3648 case OMP_CLAUSE__LOOPTEMP_:
3649 gcc_assert (is_parallel_ctx (ctx));
3650 x = build_outer_var_ref (var, ctx);
3651 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3652 gimplify_and_add (x, ilist);
3653 break;
3655 case OMP_CLAUSE_COPYIN:
3656 by_ref = use_pointer_for_field (var, NULL);
3657 x = build_receiver_ref (var, by_ref, ctx);
3658 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3659 append_to_statement_list (x, &copyin_seq);
3660 copyin_by_ref |= by_ref;
3661 break;
3663 case OMP_CLAUSE_REDUCTION:
3664 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3666 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3667 gimple tseq;
3668 x = build_outer_var_ref (var, ctx);
3670 if (is_reference (var)
3671 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3672 TREE_TYPE (x)))
3673 x = build_fold_addr_expr_loc (clause_loc, x);
3674 SET_DECL_VALUE_EXPR (placeholder, x);
3675 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3676 tree new_vard = new_var;
3677 if (is_reference (var))
3679 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3680 new_vard = TREE_OPERAND (new_var, 0);
3681 gcc_assert (DECL_P (new_vard));
3683 if (is_simd
3684 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3685 idx, lane, ivar, lvar))
3687 if (new_vard == new_var)
3689 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3690 SET_DECL_VALUE_EXPR (new_var, ivar);
3692 else
3694 SET_DECL_VALUE_EXPR (new_vard,
3695 build_fold_addr_expr (ivar));
3696 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3698 x = lang_hooks.decls.omp_clause_default_ctor
3699 (c, unshare_expr (ivar),
3700 build_outer_var_ref (var, ctx));
3701 if (x)
3702 gimplify_and_add (x, &llist[0]);
3703 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3705 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3706 lower_omp (&tseq, ctx);
3707 gimple_seq_add_seq (&llist[0], tseq);
3709 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3710 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3711 lower_omp (&tseq, ctx);
3712 gimple_seq_add_seq (&llist[1], tseq);
3713 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3714 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3715 if (new_vard == new_var)
3716 SET_DECL_VALUE_EXPR (new_var, lvar);
3717 else
3718 SET_DECL_VALUE_EXPR (new_vard,
3719 build_fold_addr_expr (lvar));
3720 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3721 if (x)
3723 tseq = NULL;
3724 dtor = x;
3725 gimplify_stmt (&dtor, &tseq);
3726 gimple_seq_add_seq (&llist[1], tseq);
3728 break;
3730 /* If this is a reference to constant size reduction var
3731 with placeholder, we haven't emitted the initializer
3732 for it because it is undesirable if SIMD arrays are used.
3733 But if they aren't used, we need to emit the deferred
3734 initialization now. */
3735 else if (is_reference (var) && is_simd)
3736 handle_simd_reference (clause_loc, new_vard, ilist);
3737 x = lang_hooks.decls.omp_clause_default_ctor
3738 (c, unshare_expr (new_var),
3739 build_outer_var_ref (var, ctx));
3740 if (x)
3741 gimplify_and_add (x, ilist);
3742 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3744 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3745 lower_omp (&tseq, ctx);
3746 gimple_seq_add_seq (ilist, tseq);
3748 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3749 if (is_simd)
3751 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3752 lower_omp (&tseq, ctx);
3753 gimple_seq_add_seq (dlist, tseq);
3754 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3756 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3757 goto do_dtor;
3759 else
3761 x = omp_reduction_init (c, TREE_TYPE (new_var));
3762 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3763 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3765 /* reduction(-:var) sums up the partial results, so it
3766 acts identically to reduction(+:var). */
3767 if (code == MINUS_EXPR)
3768 code = PLUS_EXPR;
3770 tree new_vard = new_var;
3771 if (is_simd && is_reference (var))
3773 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3774 new_vard = TREE_OPERAND (new_var, 0);
3775 gcc_assert (DECL_P (new_vard));
3777 if (is_simd
3778 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3779 idx, lane, ivar, lvar))
3781 tree ref = build_outer_var_ref (var, ctx);
3783 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3785 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3786 ref = build_outer_var_ref (var, ctx);
3787 gimplify_assign (ref, x, &llist[1]);
3789 if (new_vard != new_var)
3791 SET_DECL_VALUE_EXPR (new_vard,
3792 build_fold_addr_expr (lvar));
3793 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3796 else
3798 if (is_reference (var) && is_simd)
3799 handle_simd_reference (clause_loc, new_vard, ilist);
3800 gimplify_assign (new_var, x, ilist);
3801 if (is_simd)
3803 tree ref = build_outer_var_ref (var, ctx);
3805 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3806 ref = build_outer_var_ref (var, ctx);
3807 gimplify_assign (ref, x, dlist);
3811 break;
3813 default:
3814 gcc_unreachable ();
3819 if (lane)
3821 tree uid = create_tmp_var (ptr_type_node, "simduid");
3822 /* Don't want uninit warnings on simduid, it is always uninitialized,
3823 but we use it not for the value, but for the DECL_UID only. */
3824 TREE_NO_WARNING (uid) = 1;
3825 gimple g
3826 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3827 gimple_call_set_lhs (g, lane);
3828 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3829 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3830 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3831 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3832 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3833 gimple_omp_for_set_clauses (ctx->stmt, c);
3834 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3835 build_int_cst (unsigned_type_node, 0),
3836 NULL_TREE);
3837 gimple_seq_add_stmt (ilist, g);
3838 for (int i = 0; i < 2; i++)
3839 if (llist[i])
3841 tree vf = create_tmp_var (unsigned_type_node, NULL);
3842 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3843 gimple_call_set_lhs (g, vf);
3844 gimple_seq *seq = i == 0 ? ilist : dlist;
3845 gimple_seq_add_stmt (seq, g);
3846 tree t = build_int_cst (unsigned_type_node, 0);
3847 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3848 gimple_seq_add_stmt (seq, g);
3849 tree body = create_artificial_label (UNKNOWN_LOCATION);
3850 tree header = create_artificial_label (UNKNOWN_LOCATION);
3851 tree end = create_artificial_label (UNKNOWN_LOCATION);
3852 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3853 gimple_seq_add_stmt (seq, gimple_build_label (body));
3854 gimple_seq_add_seq (seq, llist[i]);
3855 t = build_int_cst (unsigned_type_node, 1);
3856 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3857 gimple_seq_add_stmt (seq, g);
3858 gimple_seq_add_stmt (seq, gimple_build_label (header));
3859 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3860 gimple_seq_add_stmt (seq, g);
3861 gimple_seq_add_stmt (seq, gimple_build_label (end));
3865 /* The copyin sequence is not to be executed by the main thread, since
3866 that would result in self-copies. Perhaps not visible to scalars,
3867 but it certainly is to C++ operator=. */
3868 if (copyin_seq)
3870 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3872 x = build2 (NE_EXPR, boolean_type_node, x,
3873 build_int_cst (TREE_TYPE (x), 0));
3874 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3875 gimplify_and_add (x, ilist);
3878 /* If any copyin variable is passed by reference, we must ensure the
3879 master thread doesn't modify it before it is copied over in all
3880 threads. Similarly for variables in both firstprivate and
3881 lastprivate clauses we need to ensure the lastprivate copying
3882 happens after firstprivate copying in all threads. And similarly
3883 for UDRs if initializer expression refers to omp_orig. */
3884 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3886 /* Don't add any barrier for #pragma omp simd or
3887 #pragma omp distribute. */
3888 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3889 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3890 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3893 /* If max_vf is non-zero, then we can use only a vectorization factor
3894 up to the max_vf we chose. So stick it into the safelen clause. */
3895 if (max_vf)
3897 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3898 OMP_CLAUSE_SAFELEN);
3899 if (c == NULL_TREE
3900 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3901 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3902 max_vf) == 1))
3904 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3905 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3906 max_vf);
3907 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3908 gimple_omp_for_set_clauses (ctx->stmt, c);
3914 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3915 both parallel and workshare constructs. PREDICATE may be NULL if it's
3916 always true. */
3918 static void
3919 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3920 omp_context *ctx)
3922 tree x, c, label = NULL, orig_clauses = clauses;
3923 bool par_clauses = false;
3924 tree simduid = NULL, lastlane = NULL;
3926 /* Early exit if there are no lastprivate or linear clauses. */
3927 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3928 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3929 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3930 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3931 break;
3932 if (clauses == NULL)
3934 /* If this was a workshare clause, see if it had been combined
3935 with its parallel. In that case, look for the clauses on the
3936 parallel statement itself. */
3937 if (is_parallel_ctx (ctx))
3938 return;
3940 ctx = ctx->outer;
3941 if (ctx == NULL || !is_parallel_ctx (ctx))
3942 return;
3944 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3945 OMP_CLAUSE_LASTPRIVATE);
3946 if (clauses == NULL)
3947 return;
3948 par_clauses = true;
3951 if (predicate)
3953 gimple stmt;
3954 tree label_true, arm1, arm2;
3956 label = create_artificial_label (UNKNOWN_LOCATION);
3957 label_true = create_artificial_label (UNKNOWN_LOCATION);
3958 arm1 = TREE_OPERAND (predicate, 0);
3959 arm2 = TREE_OPERAND (predicate, 1);
3960 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3961 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3962 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3963 label_true, label);
3964 gimple_seq_add_stmt (stmt_list, stmt);
3965 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3968 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3969 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3971 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3972 if (simduid)
3973 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3976 for (c = clauses; c ;)
3978 tree var, new_var;
3979 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3982 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3983 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3985 var = OMP_CLAUSE_DECL (c);
3986 new_var = lookup_decl (var, ctx);
3988 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3990 tree val = DECL_VALUE_EXPR (new_var);
3991 if (TREE_CODE (val) == ARRAY_REF
3992 && VAR_P (TREE_OPERAND (val, 0))
3993 && lookup_attribute ("omp simd array",
3994 DECL_ATTRIBUTES (TREE_OPERAND (val,
3995 0))))
3997 if (lastlane == NULL)
3999 lastlane = create_tmp_var (unsigned_type_node, NULL);
4000 gimple g
4001 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4002 2, simduid,
4003 TREE_OPERAND (val, 1));
4004 gimple_call_set_lhs (g, lastlane);
4005 gimple_seq_add_stmt (stmt_list, g);
4007 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4008 TREE_OPERAND (val, 0), lastlane,
4009 NULL_TREE, NULL_TREE);
4013 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4014 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4016 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4017 gimple_seq_add_seq (stmt_list,
4018 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4019 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4021 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4022 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4024 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4025 gimple_seq_add_seq (stmt_list,
4026 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4027 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4030 x = build_outer_var_ref (var, ctx);
4031 if (is_reference (var))
4032 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4033 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4034 gimplify_and_add (x, stmt_list);
4036 c = OMP_CLAUSE_CHAIN (c);
4037 if (c == NULL && !par_clauses)
4039 /* If this was a workshare clause, see if it had been combined
4040 with its parallel. In that case, continue looking for the
4041 clauses also on the parallel statement itself. */
4042 if (is_parallel_ctx (ctx))
4043 break;
4045 ctx = ctx->outer;
4046 if (ctx == NULL || !is_parallel_ctx (ctx))
4047 break;
4049 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4050 OMP_CLAUSE_LASTPRIVATE);
4051 par_clauses = true;
4055 if (label)
4056 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4060 /* Generate code to implement the REDUCTION clauses. */
4062 static void
4063 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4065 gimple_seq sub_seq = NULL;
4066 gimple stmt;
4067 tree x, c;
4068 int count = 0;
4070 /* SIMD reductions are handled in lower_rec_input_clauses. */
4071 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4072 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4073 return;
4075 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4076 update in that case, otherwise use a lock. */
4077 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4078 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4080 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4082 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4083 count = -1;
4084 break;
4086 count++;
4089 if (count == 0)
4090 return;
4092 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4094 tree var, ref, new_var;
4095 enum tree_code code;
4096 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4098 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4099 continue;
4101 var = OMP_CLAUSE_DECL (c);
4102 new_var = lookup_decl (var, ctx);
4103 if (is_reference (var))
4104 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4105 ref = build_outer_var_ref (var, ctx);
4106 code = OMP_CLAUSE_REDUCTION_CODE (c);
4108 /* reduction(-:var) sums up the partial results, so it acts
4109 identically to reduction(+:var). */
4110 if (code == MINUS_EXPR)
4111 code = PLUS_EXPR;
4113 if (count == 1)
4115 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4117 addr = save_expr (addr);
4118 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4119 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4120 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4121 gimplify_and_add (x, stmt_seqp);
4122 return;
4125 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4127 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4129 if (is_reference (var)
4130 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4131 TREE_TYPE (ref)))
4132 ref = build_fold_addr_expr_loc (clause_loc, ref);
4133 SET_DECL_VALUE_EXPR (placeholder, ref);
4134 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4135 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4136 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4137 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4138 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4140 else
4142 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4143 ref = build_outer_var_ref (var, ctx);
4144 gimplify_assign (ref, x, &sub_seq);
4148 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4150 gimple_seq_add_stmt (stmt_seqp, stmt);
4152 gimple_seq_add_seq (stmt_seqp, sub_seq);
4154 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4156 gimple_seq_add_stmt (stmt_seqp, stmt);
4160 /* Generate code to implement the COPYPRIVATE clauses. */
4162 static void
4163 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4164 omp_context *ctx)
4166 tree c;
4168 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4170 tree var, new_var, ref, x;
4171 bool by_ref;
4172 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4174 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4175 continue;
4177 var = OMP_CLAUSE_DECL (c);
4178 by_ref = use_pointer_for_field (var, NULL);
4180 ref = build_sender_ref (var, ctx);
4181 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4182 if (by_ref)
4184 x = build_fold_addr_expr_loc (clause_loc, new_var);
4185 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4187 gimplify_assign (ref, x, slist);
4189 ref = build_receiver_ref (var, false, ctx);
4190 if (by_ref)
4192 ref = fold_convert_loc (clause_loc,
4193 build_pointer_type (TREE_TYPE (new_var)),
4194 ref);
4195 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4197 if (is_reference (var))
4199 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4200 ref = build_simple_mem_ref_loc (clause_loc, ref);
4201 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4203 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4204 gimplify_and_add (x, rlist);
4209 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4210 and REDUCTION from the sender (aka parent) side. */
4212 static void
4213 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4214 omp_context *ctx)
4216 tree c;
4218 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4220 tree val, ref, x, var;
4221 bool by_ref, do_in = false, do_out = false;
4222 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4224 switch (OMP_CLAUSE_CODE (c))
4226 case OMP_CLAUSE_PRIVATE:
4227 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4228 break;
4229 continue;
4230 case OMP_CLAUSE_FIRSTPRIVATE:
4231 case OMP_CLAUSE_COPYIN:
4232 case OMP_CLAUSE_LASTPRIVATE:
4233 case OMP_CLAUSE_REDUCTION:
4234 case OMP_CLAUSE__LOOPTEMP_:
4235 break;
4236 default:
4237 continue;
4240 val = OMP_CLAUSE_DECL (c);
4241 var = lookup_decl_in_outer_ctx (val, ctx);
4243 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4244 && is_global_var (var))
4245 continue;
4246 if (is_variable_sized (val))
4247 continue;
4248 by_ref = use_pointer_for_field (val, NULL);
4250 switch (OMP_CLAUSE_CODE (c))
4252 case OMP_CLAUSE_PRIVATE:
4253 case OMP_CLAUSE_FIRSTPRIVATE:
4254 case OMP_CLAUSE_COPYIN:
4255 case OMP_CLAUSE__LOOPTEMP_:
4256 do_in = true;
4257 break;
4259 case OMP_CLAUSE_LASTPRIVATE:
4260 if (by_ref || is_reference (val))
4262 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4263 continue;
4264 do_in = true;
4266 else
4268 do_out = true;
4269 if (lang_hooks.decls.omp_private_outer_ref (val))
4270 do_in = true;
4272 break;
4274 case OMP_CLAUSE_REDUCTION:
4275 do_in = true;
4276 do_out = !(by_ref || is_reference (val));
4277 break;
4279 default:
4280 gcc_unreachable ();
4283 if (do_in)
4285 ref = build_sender_ref (val, ctx);
4286 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4287 gimplify_assign (ref, x, ilist);
4288 if (is_task_ctx (ctx))
4289 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4292 if (do_out)
4294 ref = build_sender_ref (val, ctx);
4295 gimplify_assign (var, ref, olist);
4300 /* Generate code to implement SHARED from the sender (aka parent)
4301 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4302 list things that got automatically shared. */
4304 static void
4305 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4307 tree var, ovar, nvar, f, x, record_type;
4309 if (ctx->record_type == NULL)
4310 return;
4312 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4313 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4315 ovar = DECL_ABSTRACT_ORIGIN (f);
4316 nvar = maybe_lookup_decl (ovar, ctx);
4317 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4318 continue;
4320 /* If CTX is a nested parallel directive. Find the immediately
4321 enclosing parallel or workshare construct that contains a
4322 mapping for OVAR. */
4323 var = lookup_decl_in_outer_ctx (ovar, ctx);
4325 if (use_pointer_for_field (ovar, ctx))
4327 x = build_sender_ref (ovar, ctx);
4328 var = build_fold_addr_expr (var);
4329 gimplify_assign (x, var, ilist);
4331 else
4333 x = build_sender_ref (ovar, ctx);
4334 gimplify_assign (x, var, ilist);
4336 if (!TREE_READONLY (var)
4337 /* We don't need to receive a new reference to a result
4338 or parm decl. In fact we may not store to it as we will
4339 invalidate any pending RSO and generate wrong gimple
4340 during inlining. */
4341 && !((TREE_CODE (var) == RESULT_DECL
4342 || TREE_CODE (var) == PARM_DECL)
4343 && DECL_BY_REFERENCE (var)))
4345 x = build_sender_ref (ovar, ctx);
4346 gimplify_assign (var, x, olist);
4353 /* A convenience function to build an empty GIMPLE_COND with just the
4354 condition. */
4356 static gimple
4357 gimple_build_cond_empty (tree cond)
4359 enum tree_code pred_code;
4360 tree lhs, rhs;
4362 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4363 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4367 /* Build the function calls to GOMP_parallel_start etc to actually
4368 generate the parallel operation. REGION is the parallel region
4369 being expanded. BB is the block where to insert the code. WS_ARGS
4370 will be set if this is a call to a combined parallel+workshare
4371 construct, it contains the list of additional arguments needed by
4372 the workshare construct. */
4374 static void
4375 expand_parallel_call (struct omp_region *region, basic_block bb,
4376 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4378 tree t, t1, t2, val, cond, c, clauses, flags;
4379 gimple_stmt_iterator gsi;
4380 gimple stmt;
4381 enum built_in_function start_ix;
4382 int start_ix2;
4383 location_t clause_loc;
4384 vec<tree, va_gc> *args;
4386 clauses = gimple_omp_parallel_clauses (entry_stmt);
4388 /* Determine what flavor of GOMP_parallel we will be
4389 emitting. */
4390 start_ix = BUILT_IN_GOMP_PARALLEL;
4391 if (is_combined_parallel (region))
4393 switch (region->inner->type)
4395 case GIMPLE_OMP_FOR:
4396 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4397 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4398 + (region->inner->sched_kind
4399 == OMP_CLAUSE_SCHEDULE_RUNTIME
4400 ? 3 : region->inner->sched_kind));
4401 start_ix = (enum built_in_function)start_ix2;
4402 break;
4403 case GIMPLE_OMP_SECTIONS:
4404 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4405 break;
4406 default:
4407 gcc_unreachable ();
4411 /* By default, the value of NUM_THREADS is zero (selected at run time)
4412 and there is no conditional. */
4413 cond = NULL_TREE;
4414 val = build_int_cst (unsigned_type_node, 0);
4415 flags = build_int_cst (unsigned_type_node, 0);
4417 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4418 if (c)
4419 cond = OMP_CLAUSE_IF_EXPR (c);
4421 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4422 if (c)
4424 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4425 clause_loc = OMP_CLAUSE_LOCATION (c);
4427 else
4428 clause_loc = gimple_location (entry_stmt);
4430 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4431 if (c)
4432 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4434 /* Ensure 'val' is of the correct type. */
4435 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4437 /* If we found the clause 'if (cond)', build either
4438 (cond != 0) or (cond ? val : 1u). */
4439 if (cond)
4441 cond = gimple_boolify (cond);
4443 if (integer_zerop (val))
4444 val = fold_build2_loc (clause_loc,
4445 EQ_EXPR, unsigned_type_node, cond,
4446 build_int_cst (TREE_TYPE (cond), 0));
4447 else
4449 basic_block cond_bb, then_bb, else_bb;
4450 edge e, e_then, e_else;
4451 tree tmp_then, tmp_else, tmp_join, tmp_var;
4453 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4454 if (gimple_in_ssa_p (cfun))
4456 tmp_then = make_ssa_name (tmp_var, NULL);
4457 tmp_else = make_ssa_name (tmp_var, NULL);
4458 tmp_join = make_ssa_name (tmp_var, NULL);
4460 else
4462 tmp_then = tmp_var;
4463 tmp_else = tmp_var;
4464 tmp_join = tmp_var;
4467 e = split_block (bb, NULL);
4468 cond_bb = e->src;
4469 bb = e->dest;
4470 remove_edge (e);
4472 then_bb = create_empty_bb (cond_bb);
4473 else_bb = create_empty_bb (then_bb);
4474 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4475 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4477 stmt = gimple_build_cond_empty (cond);
4478 gsi = gsi_start_bb (cond_bb);
4479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4481 gsi = gsi_start_bb (then_bb);
4482 stmt = gimple_build_assign (tmp_then, val);
4483 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4485 gsi = gsi_start_bb (else_bb);
4486 stmt = gimple_build_assign
4487 (tmp_else, build_int_cst (unsigned_type_node, 1));
4488 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4490 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4491 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4492 add_bb_to_loop (then_bb, cond_bb->loop_father);
4493 add_bb_to_loop (else_bb, cond_bb->loop_father);
4494 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4495 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4497 if (gimple_in_ssa_p (cfun))
4499 gimple phi = create_phi_node (tmp_join, bb);
4500 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4501 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4504 val = tmp_join;
4507 gsi = gsi_start_bb (bb);
4508 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4509 false, GSI_CONTINUE_LINKING);
4512 gsi = gsi_last_bb (bb);
4513 t = gimple_omp_parallel_data_arg (entry_stmt);
4514 if (t == NULL)
4515 t1 = null_pointer_node;
4516 else
4517 t1 = build_fold_addr_expr (t);
4518 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4520 vec_alloc (args, 4 + vec_safe_length (ws_args));
4521 args->quick_push (t2);
4522 args->quick_push (t1);
4523 args->quick_push (val);
4524 if (ws_args)
4525 args->splice (*ws_args);
4526 args->quick_push (flags);
4528 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4529 builtin_decl_explicit (start_ix), args);
4531 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4532 false, GSI_CONTINUE_LINKING);
4535 /* Insert a function call whose name is FUNC_NAME with the information from
4536 ENTRY_STMT into the basic_block BB. */
4538 static void
4539 expand_cilk_for_call (basic_block bb, gimple entry_stmt,
4540 vec <tree, va_gc> *ws_args)
4542 tree t, t1, t2;
4543 gimple_stmt_iterator gsi;
4544 vec <tree, va_gc> *args;
4546 gcc_assert (vec_safe_length (ws_args) == 2);
4547 tree func_name = (*ws_args)[0];
4548 tree grain = (*ws_args)[1];
4550 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4551 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4552 gcc_assert (count != NULL_TREE);
4553 count = OMP_CLAUSE_OPERAND (count, 0);
4555 gsi = gsi_last_bb (bb);
4556 t = gimple_omp_parallel_data_arg (entry_stmt);
4557 if (t == NULL)
4558 t1 = null_pointer_node;
4559 else
4560 t1 = build_fold_addr_expr (t);
4561 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4563 vec_alloc (args, 4);
4564 args->quick_push (t2);
4565 args->quick_push (t1);
4566 args->quick_push (count);
4567 args->quick_push (grain);
4568 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4570 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4571 GSI_CONTINUE_LINKING);
4574 /* Build the function call to GOMP_task to actually
4575 generate the task operation. BB is the block where to insert the code. */
4577 static void
4578 expand_task_call (basic_block bb, gimple entry_stmt)
4580 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4581 gimple_stmt_iterator gsi;
4582 location_t loc = gimple_location (entry_stmt);
4584 clauses = gimple_omp_task_clauses (entry_stmt);
4586 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4587 if (c)
4588 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4589 else
4590 cond = boolean_true_node;
4592 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4593 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4594 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4595 flags = build_int_cst (unsigned_type_node,
4596 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4598 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4599 if (c)
4601 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4602 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4603 build_int_cst (unsigned_type_node, 2),
4604 build_int_cst (unsigned_type_node, 0));
4605 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4607 if (depend)
4608 depend = OMP_CLAUSE_DECL (depend);
4609 else
4610 depend = build_int_cst (ptr_type_node, 0);
4612 gsi = gsi_last_bb (bb);
4613 t = gimple_omp_task_data_arg (entry_stmt);
4614 if (t == NULL)
4615 t2 = null_pointer_node;
4616 else
4617 t2 = build_fold_addr_expr_loc (loc, t);
4618 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4619 t = gimple_omp_task_copy_fn (entry_stmt);
4620 if (t == NULL)
4621 t3 = null_pointer_node;
4622 else
4623 t3 = build_fold_addr_expr_loc (loc, t);
4625 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4626 8, t1, t2, t3,
4627 gimple_omp_task_arg_size (entry_stmt),
4628 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4629 depend);
4631 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4632 false, GSI_CONTINUE_LINKING);
4636 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4637 catch handler and return it. This prevents programs from violating the
4638 structured block semantics with throws. */
4640 static gimple_seq
4641 maybe_catch_exception (gimple_seq body)
4643 gimple g;
4644 tree decl;
4646 if (!flag_exceptions)
4647 return body;
4649 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4650 decl = lang_hooks.eh_protect_cleanup_actions ();
4651 else
4652 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4654 g = gimple_build_eh_must_not_throw (decl);
4655 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4656 GIMPLE_TRY_CATCH);
4658 return gimple_seq_alloc_with_stmt (g);
4661 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4663 static tree
4664 vec2chain (vec<tree, va_gc> *v)
4666 tree chain = NULL_TREE, t;
4667 unsigned ix;
4669 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4671 DECL_CHAIN (t) = chain;
4672 chain = t;
4675 return chain;
4679 /* Remove barriers in REGION->EXIT's block. Note that this is only
4680 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4681 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4682 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4683 removed. */
4685 static void
4686 remove_exit_barrier (struct omp_region *region)
4688 gimple_stmt_iterator gsi;
4689 basic_block exit_bb;
4690 edge_iterator ei;
4691 edge e;
4692 gimple stmt;
4693 int any_addressable_vars = -1;
4695 exit_bb = region->exit;
4697 /* If the parallel region doesn't return, we don't have REGION->EXIT
4698 block at all. */
4699 if (! exit_bb)
4700 return;
4702 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4703 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4704 statements that can appear in between are extremely limited -- no
4705 memory operations at all. Here, we allow nothing at all, so the
4706 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4707 gsi = gsi_last_bb (exit_bb);
4708 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4709 gsi_prev (&gsi);
4710 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4711 return;
4713 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4715 gsi = gsi_last_bb (e->src);
4716 if (gsi_end_p (gsi))
4717 continue;
4718 stmt = gsi_stmt (gsi);
4719 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4720 && !gimple_omp_return_nowait_p (stmt))
4722 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4723 in many cases. If there could be tasks queued, the barrier
4724 might be needed to let the tasks run before some local
4725 variable of the parallel that the task uses as shared
4726 runs out of scope. The task can be spawned either
4727 from within current function (this would be easy to check)
4728 or from some function it calls and gets passed an address
4729 of such a variable. */
4730 if (any_addressable_vars < 0)
4732 gimple parallel_stmt = last_stmt (region->entry);
4733 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4734 tree local_decls, block, decl;
4735 unsigned ix;
4737 any_addressable_vars = 0;
4738 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4739 if (TREE_ADDRESSABLE (decl))
4741 any_addressable_vars = 1;
4742 break;
4744 for (block = gimple_block (stmt);
4745 !any_addressable_vars
4746 && block
4747 && TREE_CODE (block) == BLOCK;
4748 block = BLOCK_SUPERCONTEXT (block))
4750 for (local_decls = BLOCK_VARS (block);
4751 local_decls;
4752 local_decls = DECL_CHAIN (local_decls))
4753 if (TREE_ADDRESSABLE (local_decls))
4755 any_addressable_vars = 1;
4756 break;
4758 if (block == gimple_block (parallel_stmt))
4759 break;
4762 if (!any_addressable_vars)
4763 gimple_omp_return_set_nowait (stmt);
4768 static void
4769 remove_exit_barriers (struct omp_region *region)
4771 if (region->type == GIMPLE_OMP_PARALLEL)
4772 remove_exit_barrier (region);
4774 if (region->inner)
4776 region = region->inner;
4777 remove_exit_barriers (region);
4778 while (region->next)
4780 region = region->next;
4781 remove_exit_barriers (region);
4786 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4787 calls. These can't be declared as const functions, but
4788 within one parallel body they are constant, so they can be
4789 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4790 which are declared const. Similarly for task body, except
4791 that in untied task omp_get_thread_num () can change at any task
4792 scheduling point. */
4794 static void
4795 optimize_omp_library_calls (gimple entry_stmt)
4797 basic_block bb;
4798 gimple_stmt_iterator gsi;
4799 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4800 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4801 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4802 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4803 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4804 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4805 OMP_CLAUSE_UNTIED) != NULL);
4807 FOR_EACH_BB_FN (bb, cfun)
4808 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4810 gimple call = gsi_stmt (gsi);
4811 tree decl;
4813 if (is_gimple_call (call)
4814 && (decl = gimple_call_fndecl (call))
4815 && DECL_EXTERNAL (decl)
4816 && TREE_PUBLIC (decl)
4817 && DECL_INITIAL (decl) == NULL)
4819 tree built_in;
4821 if (DECL_NAME (decl) == thr_num_id)
4823 /* In #pragma omp task untied omp_get_thread_num () can change
4824 during the execution of the task region. */
4825 if (untied_task)
4826 continue;
4827 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4829 else if (DECL_NAME (decl) == num_thr_id)
4830 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4831 else
4832 continue;
4834 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4835 || gimple_call_num_args (call) != 0)
4836 continue;
4838 if (flag_exceptions && !TREE_NOTHROW (decl))
4839 continue;
4841 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4842 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4843 TREE_TYPE (TREE_TYPE (built_in))))
4844 continue;
4846 gimple_call_set_fndecl (call, built_in);
4851 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4852 regimplified. */
4854 static tree
4855 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4857 tree t = *tp;
4859 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4860 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4861 return t;
4863 if (TREE_CODE (t) == ADDR_EXPR)
4864 recompute_tree_invariant_for_addr_expr (t);
4866 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4867 return NULL_TREE;
4870 /* Prepend TO = FROM assignment before *GSI_P. */
4872 static void
4873 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4875 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4876 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4877 true, GSI_SAME_STMT);
4878 gimple stmt = gimple_build_assign (to, from);
4879 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4880 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4881 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4883 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4884 gimple_regimplify_operands (stmt, &gsi);
4888 /* Expand the OpenMP parallel or task directive starting at REGION. */
4890 static void
4891 expand_omp_taskreg (struct omp_region *region)
4893 basic_block entry_bb, exit_bb, new_bb;
4894 struct function *child_cfun;
4895 tree child_fn, block, t;
4896 gimple_stmt_iterator gsi;
4897 gimple entry_stmt, stmt;
4898 edge e;
4899 vec<tree, va_gc> *ws_args;
4901 entry_stmt = last_stmt (region->entry);
4902 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4903 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4905 entry_bb = region->entry;
4906 exit_bb = region->exit;
4908 bool is_cilk_for
4909 = (flag_cilkplus
4910 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4911 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4912 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4914 if (is_cilk_for)
4915 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4916 and the inner statement contains the name of the built-in function
4917 and grain. */
4918 ws_args = region->inner->ws_args;
4919 else if (is_combined_parallel (region))
4920 ws_args = region->ws_args;
4921 else
4922 ws_args = NULL;
4924 if (child_cfun->cfg)
4926 /* Due to inlining, it may happen that we have already outlined
4927 the region, in which case all we need to do is make the
4928 sub-graph unreachable and emit the parallel call. */
4929 edge entry_succ_e, exit_succ_e;
4931 entry_succ_e = single_succ_edge (entry_bb);
4933 gsi = gsi_last_bb (entry_bb);
4934 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4935 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4936 gsi_remove (&gsi, true);
4938 new_bb = entry_bb;
4939 if (exit_bb)
4941 exit_succ_e = single_succ_edge (exit_bb);
4942 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4944 remove_edge_and_dominated_blocks (entry_succ_e);
4946 else
4948 unsigned srcidx, dstidx, num;
4950 /* If the parallel region needs data sent from the parent
4951 function, then the very first statement (except possible
4952 tree profile counter updates) of the parallel body
4953 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4954 &.OMP_DATA_O is passed as an argument to the child function,
4955 we need to replace it with the argument as seen by the child
4956 function.
4958 In most cases, this will end up being the identity assignment
4959 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4960 a function call that has been inlined, the original PARM_DECL
4961 .OMP_DATA_I may have been converted into a different local
4962 variable. In which case, we need to keep the assignment. */
4963 if (gimple_omp_taskreg_data_arg (entry_stmt))
4965 basic_block entry_succ_bb = single_succ (entry_bb);
4966 tree arg, narg;
4967 gimple parcopy_stmt = NULL;
4969 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4971 gimple stmt;
4973 gcc_assert (!gsi_end_p (gsi));
4974 stmt = gsi_stmt (gsi);
4975 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4976 continue;
4978 if (gimple_num_ops (stmt) == 2)
4980 tree arg = gimple_assign_rhs1 (stmt);
4982 /* We're ignore the subcode because we're
4983 effectively doing a STRIP_NOPS. */
4985 if (TREE_CODE (arg) == ADDR_EXPR
4986 && TREE_OPERAND (arg, 0)
4987 == gimple_omp_taskreg_data_arg (entry_stmt))
4989 parcopy_stmt = stmt;
4990 break;
4995 gcc_assert (parcopy_stmt != NULL);
4996 arg = DECL_ARGUMENTS (child_fn);
4998 if (!gimple_in_ssa_p (cfun))
5000 if (gimple_assign_lhs (parcopy_stmt) == arg)
5001 gsi_remove (&gsi, true);
5002 else
5004 /* ?? Is setting the subcode really necessary ?? */
5005 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5006 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5009 else
5011 /* If we are in ssa form, we must load the value from the default
5012 definition of the argument. That should not be defined now,
5013 since the argument is not used uninitialized. */
5014 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5015 narg = make_ssa_name (arg, gimple_build_nop ());
5016 set_ssa_default_def (cfun, arg, narg);
5017 /* ?? Is setting the subcode really necessary ?? */
5018 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5019 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5020 update_stmt (parcopy_stmt);
5024 /* Declare local variables needed in CHILD_CFUN. */
5025 block = DECL_INITIAL (child_fn);
5026 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5027 /* The gimplifier could record temporaries in parallel/task block
5028 rather than in containing function's local_decls chain,
5029 which would mean cgraph missed finalizing them. Do it now. */
5030 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5031 if (TREE_CODE (t) == VAR_DECL
5032 && TREE_STATIC (t)
5033 && !DECL_EXTERNAL (t))
5034 varpool_node::finalize_decl (t);
5035 DECL_SAVED_TREE (child_fn) = NULL;
5036 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5037 gimple_set_body (child_fn, NULL);
5038 TREE_USED (block) = 1;
5040 /* Reset DECL_CONTEXT on function arguments. */
5041 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5042 DECL_CONTEXT (t) = child_fn;
5044 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5045 so that it can be moved to the child function. */
5046 gsi = gsi_last_bb (entry_bb);
5047 stmt = gsi_stmt (gsi);
5048 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5049 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5050 gsi_remove (&gsi, true);
5051 e = split_block (entry_bb, stmt);
5052 entry_bb = e->dest;
5053 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5055 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5056 if (exit_bb)
5058 gsi = gsi_last_bb (exit_bb);
5059 gcc_assert (!gsi_end_p (gsi)
5060 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5061 stmt = gimple_build_return (NULL);
5062 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5063 gsi_remove (&gsi, true);
5066 /* Move the parallel region into CHILD_CFUN. */
5068 if (gimple_in_ssa_p (cfun))
5070 init_tree_ssa (child_cfun);
5071 init_ssa_operands (child_cfun);
5072 child_cfun->gimple_df->in_ssa_p = true;
5073 block = NULL_TREE;
5075 else
5076 block = gimple_block (entry_stmt);
5078 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5079 if (exit_bb)
5080 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5081 /* When the OMP expansion process cannot guarantee an up-to-date
5082 loop tree arrange for the child function to fixup loops. */
5083 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5084 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5086 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5087 num = vec_safe_length (child_cfun->local_decls);
5088 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5090 t = (*child_cfun->local_decls)[srcidx];
5091 if (DECL_CONTEXT (t) == cfun->decl)
5092 continue;
5093 if (srcidx != dstidx)
5094 (*child_cfun->local_decls)[dstidx] = t;
5095 dstidx++;
5097 if (dstidx != num)
5098 vec_safe_truncate (child_cfun->local_decls, dstidx);
5100 /* Inform the callgraph about the new function. */
5101 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5102 cgraph_node::add_new_function (child_fn, true);
5104 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5105 fixed in a following pass. */
5106 push_cfun (child_cfun);
5107 if (optimize)
5108 optimize_omp_library_calls (entry_stmt);
5109 cgraph_edge::rebuild_edges ();
5111 /* Some EH regions might become dead, see PR34608. If
5112 pass_cleanup_cfg isn't the first pass to happen with the
5113 new child, these dead EH edges might cause problems.
5114 Clean them up now. */
5115 if (flag_exceptions)
5117 basic_block bb;
5118 bool changed = false;
5120 FOR_EACH_BB_FN (bb, cfun)
5121 changed |= gimple_purge_dead_eh_edges (bb);
5122 if (changed)
5123 cleanup_tree_cfg ();
5125 if (gimple_in_ssa_p (cfun))
5126 update_ssa (TODO_update_ssa);
5127 pop_cfun ();
5130 /* Emit a library call to launch the children threads. */
5131 if (is_cilk_for)
5132 expand_cilk_for_call (new_bb, entry_stmt, ws_args);
5133 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5134 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5135 else
5136 expand_task_call (new_bb, entry_stmt);
5137 if (gimple_in_ssa_p (cfun))
5138 update_ssa (TODO_update_ssa_only_virtuals);
5142 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5143 of the combined collapse > 1 loop constructs, generate code like:
5144 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5145 if (cond3 is <)
5146 adj = STEP3 - 1;
5147 else
5148 adj = STEP3 + 1;
5149 count3 = (adj + N32 - N31) / STEP3;
5150 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5151 if (cond2 is <)
5152 adj = STEP2 - 1;
5153 else
5154 adj = STEP2 + 1;
5155 count2 = (adj + N22 - N21) / STEP2;
5156 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5157 if (cond1 is <)
5158 adj = STEP1 - 1;
5159 else
5160 adj = STEP1 + 1;
5161 count1 = (adj + N12 - N11) / STEP1;
5162 count = count1 * count2 * count3;
5163 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5164 count = 0;
5165 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5166 of the combined loop constructs, just initialize COUNTS array
5167 from the _looptemp_ clauses. */
5169 /* NOTE: It *could* be better to moosh all of the BBs together,
5170 creating one larger BB with all the computation and the unexpected
5171 jump at the end. I.e.
5173 bool zero3, zero2, zero1, zero;
5175 zero3 = N32 c3 N31;
5176 count3 = (N32 - N31) /[cl] STEP3;
5177 zero2 = N22 c2 N21;
5178 count2 = (N22 - N21) /[cl] STEP2;
5179 zero1 = N12 c1 N11;
5180 count1 = (N12 - N11) /[cl] STEP1;
5181 zero = zero3 || zero2 || zero1;
5182 count = count1 * count2 * count3;
5183 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5185 After all, we expect the zero=false, and thus we expect to have to
5186 evaluate all of the comparison expressions, so short-circuiting
5187 oughtn't be a win. Since the condition isn't protecting a
5188 denominator, we're not concerned about divide-by-zero, so we can
5189 fully evaluate count even if a numerator turned out to be wrong.
5191 It seems like putting this all together would create much better
5192 scheduling opportunities, and less pressure on the chip's branch
5193 predictor. */
5195 static void
5196 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5197 basic_block &entry_bb, tree *counts,
5198 basic_block &zero_iter_bb, int &first_zero_iter,
5199 basic_block &l2_dom_bb)
5201 tree t, type = TREE_TYPE (fd->loop.v);
5202 gimple stmt;
5203 edge e, ne;
5204 int i;
5206 /* Collapsed loops need work for expansion into SSA form. */
5207 gcc_assert (!gimple_in_ssa_p (cfun));
5209 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5210 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5212 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5213 isn't supposed to be handled, as the inner loop doesn't
5214 use it. */
5215 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5216 OMP_CLAUSE__LOOPTEMP_);
5217 gcc_assert (innerc);
5218 for (i = 0; i < fd->collapse; i++)
5220 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5221 OMP_CLAUSE__LOOPTEMP_);
5222 gcc_assert (innerc);
5223 if (i)
5224 counts[i] = OMP_CLAUSE_DECL (innerc);
5225 else
5226 counts[0] = NULL_TREE;
5228 return;
5231 for (i = 0; i < fd->collapse; i++)
5233 tree itype = TREE_TYPE (fd->loops[i].v);
5235 if (SSA_VAR_P (fd->loop.n2)
5236 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5237 fold_convert (itype, fd->loops[i].n1),
5238 fold_convert (itype, fd->loops[i].n2)))
5239 == NULL_TREE || !integer_onep (t)))
5241 tree n1, n2;
5242 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5243 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5244 true, GSI_SAME_STMT);
5245 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5246 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5247 true, GSI_SAME_STMT);
5248 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5249 NULL_TREE, NULL_TREE);
5250 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5251 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5252 expand_omp_regimplify_p, NULL, NULL)
5253 || walk_tree (gimple_cond_rhs_ptr (stmt),
5254 expand_omp_regimplify_p, NULL, NULL))
5256 *gsi = gsi_for_stmt (stmt);
5257 gimple_regimplify_operands (stmt, gsi);
5259 e = split_block (entry_bb, stmt);
5260 if (zero_iter_bb == NULL)
5262 first_zero_iter = i;
5263 zero_iter_bb = create_empty_bb (entry_bb);
5264 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5265 *gsi = gsi_after_labels (zero_iter_bb);
5266 stmt = gimple_build_assign (fd->loop.n2,
5267 build_zero_cst (type));
5268 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
5269 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5270 entry_bb);
5272 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5273 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5274 e->flags = EDGE_TRUE_VALUE;
5275 e->probability = REG_BR_PROB_BASE - ne->probability;
5276 if (l2_dom_bb == NULL)
5277 l2_dom_bb = entry_bb;
5278 entry_bb = e->dest;
5279 *gsi = gsi_last_bb (entry_bb);
5282 if (POINTER_TYPE_P (itype))
5283 itype = signed_type_for (itype);
5284 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5285 ? -1 : 1));
5286 t = fold_build2 (PLUS_EXPR, itype,
5287 fold_convert (itype, fd->loops[i].step), t);
5288 t = fold_build2 (PLUS_EXPR, itype, t,
5289 fold_convert (itype, fd->loops[i].n2));
5290 t = fold_build2 (MINUS_EXPR, itype, t,
5291 fold_convert (itype, fd->loops[i].n1));
5292 /* ?? We could probably use CEIL_DIV_EXPR instead of
5293 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5294 generate the same code in the end because generically we
5295 don't know that the values involved must be negative for
5296 GT?? */
5297 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5298 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5299 fold_build1 (NEGATE_EXPR, itype, t),
5300 fold_build1 (NEGATE_EXPR, itype,
5301 fold_convert (itype,
5302 fd->loops[i].step)));
5303 else
5304 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5305 fold_convert (itype, fd->loops[i].step));
5306 t = fold_convert (type, t);
5307 if (TREE_CODE (t) == INTEGER_CST)
5308 counts[i] = t;
5309 else
5311 counts[i] = create_tmp_reg (type, ".count");
5312 expand_omp_build_assign (gsi, counts[i], t);
5314 if (SSA_VAR_P (fd->loop.n2))
5316 if (i == 0)
5317 t = counts[0];
5318 else
5319 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5320 expand_omp_build_assign (gsi, fd->loop.n2, t);
5326 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5327 T = V;
5328 V3 = N31 + (T % count3) * STEP3;
5329 T = T / count3;
5330 V2 = N21 + (T % count2) * STEP2;
5331 T = T / count2;
5332 V1 = N11 + T * STEP1;
5333 if this loop doesn't have an inner loop construct combined with it.
5334 If it does have an inner loop construct combined with it and the
5335 iteration count isn't known constant, store values from counts array
5336 into its _looptemp_ temporaries instead. */
5338 static void
5339 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5340 tree *counts, gimple inner_stmt, tree startvar)
5342 int i;
5343 if (gimple_omp_for_combined_p (fd->for_stmt))
5345 /* If fd->loop.n2 is constant, then no propagation of the counts
5346 is needed, they are constant. */
5347 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5348 return;
5350 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5351 ? gimple_omp_parallel_clauses (inner_stmt)
5352 : gimple_omp_for_clauses (inner_stmt);
5353 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5354 isn't supposed to be handled, as the inner loop doesn't
5355 use it. */
5356 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5357 gcc_assert (innerc);
5358 for (i = 0; i < fd->collapse; i++)
5360 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5361 OMP_CLAUSE__LOOPTEMP_);
5362 gcc_assert (innerc);
5363 if (i)
5365 tree tem = OMP_CLAUSE_DECL (innerc);
5366 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5367 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5368 false, GSI_CONTINUE_LINKING);
5369 gimple stmt = gimple_build_assign (tem, t);
5370 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5373 return;
5376 tree type = TREE_TYPE (fd->loop.v);
5377 tree tem = create_tmp_reg (type, ".tem");
5378 gimple stmt = gimple_build_assign (tem, startvar);
5379 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5381 for (i = fd->collapse - 1; i >= 0; i--)
5383 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5384 itype = vtype;
5385 if (POINTER_TYPE_P (vtype))
5386 itype = signed_type_for (vtype);
5387 if (i != 0)
5388 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5389 else
5390 t = tem;
5391 t = fold_convert (itype, t);
5392 t = fold_build2 (MULT_EXPR, itype, t,
5393 fold_convert (itype, fd->loops[i].step));
5394 if (POINTER_TYPE_P (vtype))
5395 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5396 else
5397 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5398 t = force_gimple_operand_gsi (gsi, t,
5399 DECL_P (fd->loops[i].v)
5400 && TREE_ADDRESSABLE (fd->loops[i].v),
5401 NULL_TREE, false,
5402 GSI_CONTINUE_LINKING);
5403 stmt = gimple_build_assign (fd->loops[i].v, t);
5404 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5405 if (i != 0)
5407 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5408 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5409 false, GSI_CONTINUE_LINKING);
5410 stmt = gimple_build_assign (tem, t);
5411 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5417 /* Helper function for expand_omp_for_*. Generate code like:
5418 L10:
5419 V3 += STEP3;
5420 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5421 L11:
5422 V3 = N31;
5423 V2 += STEP2;
5424 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5425 L12:
5426 V2 = N21;
5427 V1 += STEP1;
5428 goto BODY_BB; */
5430 static basic_block
5431 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5432 basic_block body_bb)
5434 basic_block last_bb, bb, collapse_bb = NULL;
5435 int i;
5436 gimple_stmt_iterator gsi;
5437 edge e;
5438 tree t;
5439 gimple stmt;
5441 last_bb = cont_bb;
5442 for (i = fd->collapse - 1; i >= 0; i--)
5444 tree vtype = TREE_TYPE (fd->loops[i].v);
5446 bb = create_empty_bb (last_bb);
5447 add_bb_to_loop (bb, last_bb->loop_father);
5448 gsi = gsi_start_bb (bb);
5450 if (i < fd->collapse - 1)
5452 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5453 e->probability = REG_BR_PROB_BASE / 8;
5455 t = fd->loops[i + 1].n1;
5456 t = force_gimple_operand_gsi (&gsi, t,
5457 DECL_P (fd->loops[i + 1].v)
5458 && TREE_ADDRESSABLE (fd->loops[i
5459 + 1].v),
5460 NULL_TREE, false,
5461 GSI_CONTINUE_LINKING);
5462 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5463 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5465 else
5466 collapse_bb = bb;
5468 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5470 if (POINTER_TYPE_P (vtype))
5471 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5472 else
5473 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5474 t = force_gimple_operand_gsi (&gsi, t,
5475 DECL_P (fd->loops[i].v)
5476 && TREE_ADDRESSABLE (fd->loops[i].v),
5477 NULL_TREE, false, GSI_CONTINUE_LINKING);
5478 stmt = gimple_build_assign (fd->loops[i].v, t);
5479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5481 if (i > 0)
5483 t = fd->loops[i].n2;
5484 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5485 false, GSI_CONTINUE_LINKING);
5486 tree v = fd->loops[i].v;
5487 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5488 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5489 false, GSI_CONTINUE_LINKING);
5490 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5491 stmt = gimple_build_cond_empty (t);
5492 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5493 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5494 e->probability = REG_BR_PROB_BASE * 7 / 8;
5496 else
5497 make_edge (bb, body_bb, EDGE_FALLTHRU);
5498 last_bb = bb;
5501 return collapse_bb;
5505 /* A subroutine of expand_omp_for. Generate code for a parallel
5506 loop with any schedule. Given parameters:
5508 for (V = N1; V cond N2; V += STEP) BODY;
5510 where COND is "<" or ">", we generate pseudocode
5512 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5513 if (more) goto L0; else goto L3;
5515 V = istart0;
5516 iend = iend0;
5518 BODY;
5519 V += STEP;
5520 if (V cond iend) goto L1; else goto L2;
5522 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5525 If this is a combined omp parallel loop, instead of the call to
5526 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5527 If this is gimple_omp_for_combined_p loop, then instead of assigning
5528 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5529 inner GIMPLE_OMP_FOR and V += STEP; and
5530 if (V cond iend) goto L1; else goto L2; are removed.
5532 For collapsed loops, given parameters:
5533 collapse(3)
5534 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5535 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5536 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5537 BODY;
5539 we generate pseudocode
5541 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5542 if (cond3 is <)
5543 adj = STEP3 - 1;
5544 else
5545 adj = STEP3 + 1;
5546 count3 = (adj + N32 - N31) / STEP3;
5547 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5548 if (cond2 is <)
5549 adj = STEP2 - 1;
5550 else
5551 adj = STEP2 + 1;
5552 count2 = (adj + N22 - N21) / STEP2;
5553 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5554 if (cond1 is <)
5555 adj = STEP1 - 1;
5556 else
5557 adj = STEP1 + 1;
5558 count1 = (adj + N12 - N11) / STEP1;
5559 count = count1 * count2 * count3;
5560 goto Z1;
5562 count = 0;
5564 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5565 if (more) goto L0; else goto L3;
5567 V = istart0;
5568 T = V;
5569 V3 = N31 + (T % count3) * STEP3;
5570 T = T / count3;
5571 V2 = N21 + (T % count2) * STEP2;
5572 T = T / count2;
5573 V1 = N11 + T * STEP1;
5574 iend = iend0;
5576 BODY;
5577 V += 1;
5578 if (V < iend) goto L10; else goto L2;
5579 L10:
5580 V3 += STEP3;
5581 if (V3 cond3 N32) goto L1; else goto L11;
5582 L11:
5583 V3 = N31;
5584 V2 += STEP2;
5585 if (V2 cond2 N22) goto L1; else goto L12;
5586 L12:
5587 V2 = N21;
5588 V1 += STEP1;
5589 goto L1;
5591 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5596 static void
5597 expand_omp_for_generic (struct omp_region *region,
5598 struct omp_for_data *fd,
5599 enum built_in_function start_fn,
5600 enum built_in_function next_fn,
5601 gimple inner_stmt)
5603 tree type, istart0, iend0, iend;
5604 tree t, vmain, vback, bias = NULL_TREE;
5605 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5606 basic_block l2_bb = NULL, l3_bb = NULL;
5607 gimple_stmt_iterator gsi;
5608 gimple stmt;
5609 bool in_combined_parallel = is_combined_parallel (region);
5610 bool broken_loop = region->cont == NULL;
5611 edge e, ne;
5612 tree *counts = NULL;
5613 int i;
5615 gcc_assert (!broken_loop || !in_combined_parallel);
5616 gcc_assert (fd->iter_type == long_integer_type_node
5617 || !in_combined_parallel);
5619 type = TREE_TYPE (fd->loop.v);
5620 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5621 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5622 TREE_ADDRESSABLE (istart0) = 1;
5623 TREE_ADDRESSABLE (iend0) = 1;
5625 /* See if we need to bias by LLONG_MIN. */
5626 if (fd->iter_type == long_long_unsigned_type_node
5627 && TREE_CODE (type) == INTEGER_TYPE
5628 && !TYPE_UNSIGNED (type))
5630 tree n1, n2;
5632 if (fd->loop.cond_code == LT_EXPR)
5634 n1 = fd->loop.n1;
5635 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5637 else
5639 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5640 n2 = fd->loop.n1;
5642 if (TREE_CODE (n1) != INTEGER_CST
5643 || TREE_CODE (n2) != INTEGER_CST
5644 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5645 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5648 entry_bb = region->entry;
5649 cont_bb = region->cont;
5650 collapse_bb = NULL;
5651 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5652 gcc_assert (broken_loop
5653 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5654 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5655 l1_bb = single_succ (l0_bb);
5656 if (!broken_loop)
5658 l2_bb = create_empty_bb (cont_bb);
5659 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5660 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5662 else
5663 l2_bb = NULL;
5664 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5665 exit_bb = region->exit;
5667 gsi = gsi_last_bb (entry_bb);
5669 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5670 if (fd->collapse > 1)
5672 int first_zero_iter = -1;
5673 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5675 counts = XALLOCAVEC (tree, fd->collapse);
5676 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5677 zero_iter_bb, first_zero_iter,
5678 l2_dom_bb);
5680 if (zero_iter_bb)
5682 /* Some counts[i] vars might be uninitialized if
5683 some loop has zero iterations. But the body shouldn't
5684 be executed in that case, so just avoid uninit warnings. */
5685 for (i = first_zero_iter; i < fd->collapse; i++)
5686 if (SSA_VAR_P (counts[i]))
5687 TREE_NO_WARNING (counts[i]) = 1;
5688 gsi_prev (&gsi);
5689 e = split_block (entry_bb, gsi_stmt (gsi));
5690 entry_bb = e->dest;
5691 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5692 gsi = gsi_last_bb (entry_bb);
5693 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5694 get_immediate_dominator (CDI_DOMINATORS,
5695 zero_iter_bb));
5698 if (in_combined_parallel)
5700 /* In a combined parallel loop, emit a call to
5701 GOMP_loop_foo_next. */
5702 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5703 build_fold_addr_expr (istart0),
5704 build_fold_addr_expr (iend0));
5706 else
5708 tree t0, t1, t2, t3, t4;
5709 /* If this is not a combined parallel loop, emit a call to
5710 GOMP_loop_foo_start in ENTRY_BB. */
5711 t4 = build_fold_addr_expr (iend0);
5712 t3 = build_fold_addr_expr (istart0);
5713 t2 = fold_convert (fd->iter_type, fd->loop.step);
5714 t1 = fd->loop.n2;
5715 t0 = fd->loop.n1;
5716 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5718 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5719 OMP_CLAUSE__LOOPTEMP_);
5720 gcc_assert (innerc);
5721 t0 = OMP_CLAUSE_DECL (innerc);
5722 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5723 OMP_CLAUSE__LOOPTEMP_);
5724 gcc_assert (innerc);
5725 t1 = OMP_CLAUSE_DECL (innerc);
5727 if (POINTER_TYPE_P (TREE_TYPE (t0))
5728 && TYPE_PRECISION (TREE_TYPE (t0))
5729 != TYPE_PRECISION (fd->iter_type))
5731 /* Avoid casting pointers to integer of a different size. */
5732 tree itype = signed_type_for (type);
5733 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5734 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5736 else
5738 t1 = fold_convert (fd->iter_type, t1);
5739 t0 = fold_convert (fd->iter_type, t0);
5741 if (bias)
5743 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5744 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5746 if (fd->iter_type == long_integer_type_node)
5748 if (fd->chunk_size)
5750 t = fold_convert (fd->iter_type, fd->chunk_size);
5751 t = build_call_expr (builtin_decl_explicit (start_fn),
5752 6, t0, t1, t2, t, t3, t4);
5754 else
5755 t = build_call_expr (builtin_decl_explicit (start_fn),
5756 5, t0, t1, t2, t3, t4);
5758 else
5760 tree t5;
5761 tree c_bool_type;
5762 tree bfn_decl;
5764 /* The GOMP_loop_ull_*start functions have additional boolean
5765 argument, true for < loops and false for > loops.
5766 In Fortran, the C bool type can be different from
5767 boolean_type_node. */
5768 bfn_decl = builtin_decl_explicit (start_fn);
5769 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5770 t5 = build_int_cst (c_bool_type,
5771 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5772 if (fd->chunk_size)
5774 tree bfn_decl = builtin_decl_explicit (start_fn);
5775 t = fold_convert (fd->iter_type, fd->chunk_size);
5776 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5778 else
5779 t = build_call_expr (builtin_decl_explicit (start_fn),
5780 6, t5, t0, t1, t2, t3, t4);
5783 if (TREE_TYPE (t) != boolean_type_node)
5784 t = fold_build2 (NE_EXPR, boolean_type_node,
5785 t, build_int_cst (TREE_TYPE (t), 0));
5786 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5787 true, GSI_SAME_STMT);
5788 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5790 /* Remove the GIMPLE_OMP_FOR statement. */
5791 gsi_remove (&gsi, true);
5793 /* Iteration setup for sequential loop goes in L0_BB. */
5794 tree startvar = fd->loop.v;
5795 tree endvar = NULL_TREE;
5797 if (gimple_omp_for_combined_p (fd->for_stmt))
5799 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5800 && gimple_omp_for_kind (inner_stmt)
5801 == GF_OMP_FOR_KIND_SIMD);
5802 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5803 OMP_CLAUSE__LOOPTEMP_);
5804 gcc_assert (innerc);
5805 startvar = OMP_CLAUSE_DECL (innerc);
5806 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5807 OMP_CLAUSE__LOOPTEMP_);
5808 gcc_assert (innerc);
5809 endvar = OMP_CLAUSE_DECL (innerc);
5812 gsi = gsi_start_bb (l0_bb);
5813 t = istart0;
5814 if (bias)
5815 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5816 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5817 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5818 t = fold_convert (TREE_TYPE (startvar), t);
5819 t = force_gimple_operand_gsi (&gsi, t,
5820 DECL_P (startvar)
5821 && TREE_ADDRESSABLE (startvar),
5822 NULL_TREE, false, GSI_CONTINUE_LINKING);
5823 stmt = gimple_build_assign (startvar, t);
5824 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5826 t = iend0;
5827 if (bias)
5828 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5829 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5830 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5831 t = fold_convert (TREE_TYPE (startvar), t);
5832 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5833 false, GSI_CONTINUE_LINKING);
5834 if (endvar)
5836 stmt = gimple_build_assign (endvar, iend);
5837 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5838 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
5839 stmt = gimple_build_assign (fd->loop.v, iend);
5840 else
5841 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend,
5842 NULL_TREE);
5843 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5845 if (fd->collapse > 1)
5846 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5848 if (!broken_loop)
5850 /* Code to control the increment and predicate for the sequential
5851 loop goes in the CONT_BB. */
5852 gsi = gsi_last_bb (cont_bb);
5853 stmt = gsi_stmt (gsi);
5854 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5855 vmain = gimple_omp_continue_control_use (stmt);
5856 vback = gimple_omp_continue_control_def (stmt);
5858 if (!gimple_omp_for_combined_p (fd->for_stmt))
5860 if (POINTER_TYPE_P (type))
5861 t = fold_build_pointer_plus (vmain, fd->loop.step);
5862 else
5863 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5864 t = force_gimple_operand_gsi (&gsi, t,
5865 DECL_P (vback)
5866 && TREE_ADDRESSABLE (vback),
5867 NULL_TREE, true, GSI_SAME_STMT);
5868 stmt = gimple_build_assign (vback, t);
5869 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5871 t = build2 (fd->loop.cond_code, boolean_type_node,
5872 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5873 iend);
5874 stmt = gimple_build_cond_empty (t);
5875 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5878 /* Remove GIMPLE_OMP_CONTINUE. */
5879 gsi_remove (&gsi, true);
5881 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5882 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5884 /* Emit code to get the next parallel iteration in L2_BB. */
5885 gsi = gsi_start_bb (l2_bb);
5887 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5888 build_fold_addr_expr (istart0),
5889 build_fold_addr_expr (iend0));
5890 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5891 false, GSI_CONTINUE_LINKING);
5892 if (TREE_TYPE (t) != boolean_type_node)
5893 t = fold_build2 (NE_EXPR, boolean_type_node,
5894 t, build_int_cst (TREE_TYPE (t), 0));
5895 stmt = gimple_build_cond_empty (t);
5896 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5899 /* Add the loop cleanup function. */
5900 gsi = gsi_last_bb (exit_bb);
5901 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5902 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5903 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5904 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5905 else
5906 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5907 stmt = gimple_build_call (t, 0);
5908 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5909 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5910 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5911 gsi_remove (&gsi, true);
5913 /* Connect the new blocks. */
5914 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5915 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5917 if (!broken_loop)
5919 gimple_seq phis;
5921 e = find_edge (cont_bb, l3_bb);
5922 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5924 phis = phi_nodes (l3_bb);
5925 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5927 gimple phi = gsi_stmt (gsi);
5928 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5929 PHI_ARG_DEF_FROM_EDGE (phi, e));
5931 remove_edge (e);
5933 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5934 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5935 e = find_edge (cont_bb, l1_bb);
5936 if (gimple_omp_for_combined_p (fd->for_stmt))
5938 remove_edge (e);
5939 e = NULL;
5941 else if (fd->collapse > 1)
5943 remove_edge (e);
5944 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5946 else
5947 e->flags = EDGE_TRUE_VALUE;
5948 if (e)
5950 e->probability = REG_BR_PROB_BASE * 7 / 8;
5951 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5953 else
5955 e = find_edge (cont_bb, l2_bb);
5956 e->flags = EDGE_FALLTHRU;
5958 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5960 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5961 recompute_dominator (CDI_DOMINATORS, l2_bb));
5962 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5963 recompute_dominator (CDI_DOMINATORS, l3_bb));
5964 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5965 recompute_dominator (CDI_DOMINATORS, l0_bb));
5966 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5967 recompute_dominator (CDI_DOMINATORS, l1_bb));
5969 struct loop *outer_loop = alloc_loop ();
5970 outer_loop->header = l0_bb;
5971 outer_loop->latch = l2_bb;
5972 add_loop (outer_loop, l0_bb->loop_father);
5974 if (!gimple_omp_for_combined_p (fd->for_stmt))
5976 struct loop *loop = alloc_loop ();
5977 loop->header = l1_bb;
5978 /* The loop may have multiple latches. */
5979 add_loop (loop, outer_loop);
5985 /* A subroutine of expand_omp_for. Generate code for a parallel
5986 loop with static schedule and no specified chunk size. Given
5987 parameters:
5989 for (V = N1; V cond N2; V += STEP) BODY;
5991 where COND is "<" or ">", we generate pseudocode
5993 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5994 if (cond is <)
5995 adj = STEP - 1;
5996 else
5997 adj = STEP + 1;
5998 if ((__typeof (V)) -1 > 0 && cond is >)
5999 n = -(adj + N2 - N1) / -STEP;
6000 else
6001 n = (adj + N2 - N1) / STEP;
6002 q = n / nthreads;
6003 tt = n % nthreads;
6004 if (threadid < tt) goto L3; else goto L4;
6006 tt = 0;
6007 q = q + 1;
6009 s0 = q * threadid + tt;
6010 e0 = s0 + q;
6011 V = s0 * STEP + N1;
6012 if (s0 >= e0) goto L2; else goto L0;
6014 e = e0 * STEP + N1;
6016 BODY;
6017 V += STEP;
6018 if (V cond e) goto L1;
6022 static void
6023 expand_omp_for_static_nochunk (struct omp_region *region,
6024 struct omp_for_data *fd,
6025 gimple inner_stmt)
6027 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6028 tree type, itype, vmain, vback;
6029 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6030 basic_block body_bb, cont_bb, collapse_bb = NULL;
6031 basic_block fin_bb;
6032 gimple_stmt_iterator gsi;
6033 gimple stmt;
6034 edge ep;
6035 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6036 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6037 bool broken_loop = region->cont == NULL;
6038 tree *counts = NULL;
6039 tree n1, n2, step;
6041 itype = type = TREE_TYPE (fd->loop.v);
6042 if (POINTER_TYPE_P (type))
6043 itype = signed_type_for (type);
6045 entry_bb = region->entry;
6046 cont_bb = region->cont;
6047 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6048 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6049 gcc_assert (broken_loop
6050 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6051 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6052 body_bb = single_succ (seq_start_bb);
6053 if (!broken_loop)
6055 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6056 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6058 exit_bb = region->exit;
6060 /* Iteration space partitioning goes in ENTRY_BB. */
6061 gsi = gsi_last_bb (entry_bb);
6062 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6064 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6066 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6067 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6070 if (fd->collapse > 1)
6072 int first_zero_iter = -1;
6073 basic_block l2_dom_bb = NULL;
6075 counts = XALLOCAVEC (tree, fd->collapse);
6076 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6077 fin_bb, first_zero_iter,
6078 l2_dom_bb);
6079 t = NULL_TREE;
6081 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6082 t = integer_one_node;
6083 else
6084 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6085 fold_convert (type, fd->loop.n1),
6086 fold_convert (type, fd->loop.n2));
6087 if (fd->collapse == 1
6088 && TYPE_UNSIGNED (type)
6089 && (t == NULL_TREE || !integer_onep (t)))
6091 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6092 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6093 true, GSI_SAME_STMT);
6094 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6095 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6096 true, GSI_SAME_STMT);
6097 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6098 NULL_TREE, NULL_TREE);
6099 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6100 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6101 expand_omp_regimplify_p, NULL, NULL)
6102 || walk_tree (gimple_cond_rhs_ptr (stmt),
6103 expand_omp_regimplify_p, NULL, NULL))
6105 gsi = gsi_for_stmt (stmt);
6106 gimple_regimplify_operands (stmt, &gsi);
6108 ep = split_block (entry_bb, stmt);
6109 ep->flags = EDGE_TRUE_VALUE;
6110 entry_bb = ep->dest;
6111 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6112 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6113 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6114 if (gimple_in_ssa_p (cfun))
6116 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6117 for (gsi = gsi_start_phis (fin_bb);
6118 !gsi_end_p (gsi); gsi_next (&gsi))
6120 gimple phi = gsi_stmt (gsi);
6121 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6122 ep, UNKNOWN_LOCATION);
6125 gsi = gsi_last_bb (entry_bb);
6128 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6129 t = fold_convert (itype, t);
6130 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6131 true, GSI_SAME_STMT);
6133 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6134 t = fold_convert (itype, t);
6135 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6136 true, GSI_SAME_STMT);
6138 n1 = fd->loop.n1;
6139 n2 = fd->loop.n2;
6140 step = fd->loop.step;
6141 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6143 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6144 OMP_CLAUSE__LOOPTEMP_);
6145 gcc_assert (innerc);
6146 n1 = OMP_CLAUSE_DECL (innerc);
6147 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6148 OMP_CLAUSE__LOOPTEMP_);
6149 gcc_assert (innerc);
6150 n2 = OMP_CLAUSE_DECL (innerc);
6152 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6153 true, NULL_TREE, true, GSI_SAME_STMT);
6154 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6155 true, NULL_TREE, true, GSI_SAME_STMT);
6156 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6157 true, NULL_TREE, true, GSI_SAME_STMT);
6159 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6160 t = fold_build2 (PLUS_EXPR, itype, step, t);
6161 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6162 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6163 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6164 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6165 fold_build1 (NEGATE_EXPR, itype, t),
6166 fold_build1 (NEGATE_EXPR, itype, step));
6167 else
6168 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6169 t = fold_convert (itype, t);
6170 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6172 q = create_tmp_reg (itype, "q");
6173 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6174 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6175 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6177 tt = create_tmp_reg (itype, "tt");
6178 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6179 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6180 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6182 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6183 stmt = gimple_build_cond_empty (t);
6184 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6186 second_bb = split_block (entry_bb, stmt)->dest;
6187 gsi = gsi_last_bb (second_bb);
6188 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6190 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6191 GSI_SAME_STMT);
6192 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6193 build_int_cst (itype, 1));
6194 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6196 third_bb = split_block (second_bb, stmt)->dest;
6197 gsi = gsi_last_bb (third_bb);
6198 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6200 t = build2 (MULT_EXPR, itype, q, threadid);
6201 t = build2 (PLUS_EXPR, itype, t, tt);
6202 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6204 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6205 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6207 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6208 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6210 /* Remove the GIMPLE_OMP_FOR statement. */
6211 gsi_remove (&gsi, true);
6213 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6214 gsi = gsi_start_bb (seq_start_bb);
6216 tree startvar = fd->loop.v;
6217 tree endvar = NULL_TREE;
6219 if (gimple_omp_for_combined_p (fd->for_stmt))
6221 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6222 ? gimple_omp_parallel_clauses (inner_stmt)
6223 : gimple_omp_for_clauses (inner_stmt);
6224 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6225 gcc_assert (innerc);
6226 startvar = OMP_CLAUSE_DECL (innerc);
6227 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6228 OMP_CLAUSE__LOOPTEMP_);
6229 gcc_assert (innerc);
6230 endvar = OMP_CLAUSE_DECL (innerc);
6232 t = fold_convert (itype, s0);
6233 t = fold_build2 (MULT_EXPR, itype, t, step);
6234 if (POINTER_TYPE_P (type))
6235 t = fold_build_pointer_plus (n1, t);
6236 else
6237 t = fold_build2 (PLUS_EXPR, type, t, n1);
6238 t = fold_convert (TREE_TYPE (startvar), t);
6239 t = force_gimple_operand_gsi (&gsi, t,
6240 DECL_P (startvar)
6241 && TREE_ADDRESSABLE (startvar),
6242 NULL_TREE, false, GSI_CONTINUE_LINKING);
6243 stmt = gimple_build_assign (startvar, t);
6244 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6246 t = fold_convert (itype, e0);
6247 t = fold_build2 (MULT_EXPR, itype, t, step);
6248 if (POINTER_TYPE_P (type))
6249 t = fold_build_pointer_plus (n1, t);
6250 else
6251 t = fold_build2 (PLUS_EXPR, type, t, n1);
6252 t = fold_convert (TREE_TYPE (startvar), t);
6253 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6254 false, GSI_CONTINUE_LINKING);
6255 if (endvar)
6257 stmt = gimple_build_assign (endvar, e);
6258 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6259 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6260 stmt = gimple_build_assign (fd->loop.v, e);
6261 else
6262 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6263 NULL_TREE);
6264 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6266 if (fd->collapse > 1)
6267 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6269 if (!broken_loop)
6271 /* The code controlling the sequential loop replaces the
6272 GIMPLE_OMP_CONTINUE. */
6273 gsi = gsi_last_bb (cont_bb);
6274 stmt = gsi_stmt (gsi);
6275 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6276 vmain = gimple_omp_continue_control_use (stmt);
6277 vback = gimple_omp_continue_control_def (stmt);
6279 if (!gimple_omp_for_combined_p (fd->for_stmt))
6281 if (POINTER_TYPE_P (type))
6282 t = fold_build_pointer_plus (vmain, step);
6283 else
6284 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6285 t = force_gimple_operand_gsi (&gsi, t,
6286 DECL_P (vback)
6287 && TREE_ADDRESSABLE (vback),
6288 NULL_TREE, true, GSI_SAME_STMT);
6289 stmt = gimple_build_assign (vback, t);
6290 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6292 t = build2 (fd->loop.cond_code, boolean_type_node,
6293 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6294 ? t : vback, e);
6295 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6298 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6299 gsi_remove (&gsi, true);
6301 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6302 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6305 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6306 gsi = gsi_last_bb (exit_bb);
6307 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6309 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6310 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6312 gsi_remove (&gsi, true);
6314 /* Connect all the blocks. */
6315 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6316 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6317 ep = find_edge (entry_bb, second_bb);
6318 ep->flags = EDGE_TRUE_VALUE;
6319 ep->probability = REG_BR_PROB_BASE / 4;
6320 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6321 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6323 if (!broken_loop)
6325 ep = find_edge (cont_bb, body_bb);
6326 if (gimple_omp_for_combined_p (fd->for_stmt))
6328 remove_edge (ep);
6329 ep = NULL;
6331 else if (fd->collapse > 1)
6333 remove_edge (ep);
6334 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6336 else
6337 ep->flags = EDGE_TRUE_VALUE;
6338 find_edge (cont_bb, fin_bb)->flags
6339 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6342 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6343 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6344 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6346 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6347 recompute_dominator (CDI_DOMINATORS, body_bb));
6348 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6349 recompute_dominator (CDI_DOMINATORS, fin_bb));
6351 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6353 struct loop *loop = alloc_loop ();
6354 loop->header = body_bb;
6355 if (collapse_bb == NULL)
6356 loop->latch = cont_bb;
6357 add_loop (loop, body_bb->loop_father);
6362 /* A subroutine of expand_omp_for. Generate code for a parallel
6363 loop with static schedule and a specified chunk size. Given
6364 parameters:
6366 for (V = N1; V cond N2; V += STEP) BODY;
6368 where COND is "<" or ">", we generate pseudocode
6370 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6371 if (cond is <)
6372 adj = STEP - 1;
6373 else
6374 adj = STEP + 1;
6375 if ((__typeof (V)) -1 > 0 && cond is >)
6376 n = -(adj + N2 - N1) / -STEP;
6377 else
6378 n = (adj + N2 - N1) / STEP;
6379 trip = 0;
6380 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6381 here so that V is defined
6382 if the loop is not entered
6384 s0 = (trip * nthreads + threadid) * CHUNK;
6385 e0 = min(s0 + CHUNK, n);
6386 if (s0 < n) goto L1; else goto L4;
6388 V = s0 * STEP + N1;
6389 e = e0 * STEP + N1;
6391 BODY;
6392 V += STEP;
6393 if (V cond e) goto L2; else goto L3;
6395 trip += 1;
6396 goto L0;
6400 static void
6401 expand_omp_for_static_chunk (struct omp_region *region,
6402 struct omp_for_data *fd, gimple inner_stmt)
6404 tree n, s0, e0, e, t;
6405 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6406 tree type, itype, vmain, vback, vextra;
6407 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6408 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6409 gimple_stmt_iterator gsi;
6410 gimple stmt;
6411 edge se;
6412 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6413 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6414 bool broken_loop = region->cont == NULL;
6415 tree *counts = NULL;
6416 tree n1, n2, step;
6418 itype = type = TREE_TYPE (fd->loop.v);
6419 if (POINTER_TYPE_P (type))
6420 itype = signed_type_for (type);
6422 entry_bb = region->entry;
6423 se = split_block (entry_bb, last_stmt (entry_bb));
6424 entry_bb = se->src;
6425 iter_part_bb = se->dest;
6426 cont_bb = region->cont;
6427 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6428 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6429 gcc_assert (broken_loop
6430 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6431 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6432 body_bb = single_succ (seq_start_bb);
6433 if (!broken_loop)
6435 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6436 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6437 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6439 exit_bb = region->exit;
6441 /* Trip and adjustment setup goes in ENTRY_BB. */
6442 gsi = gsi_last_bb (entry_bb);
6443 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6445 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6447 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6448 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6451 if (fd->collapse > 1)
6453 int first_zero_iter = -1;
6454 basic_block l2_dom_bb = NULL;
6456 counts = XALLOCAVEC (tree, fd->collapse);
6457 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6458 fin_bb, first_zero_iter,
6459 l2_dom_bb);
6460 t = NULL_TREE;
6462 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6463 t = integer_one_node;
6464 else
6465 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6466 fold_convert (type, fd->loop.n1),
6467 fold_convert (type, fd->loop.n2));
6468 if (fd->collapse == 1
6469 && TYPE_UNSIGNED (type)
6470 && (t == NULL_TREE || !integer_onep (t)))
6472 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6473 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6474 true, GSI_SAME_STMT);
6475 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6476 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6477 true, GSI_SAME_STMT);
6478 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6479 NULL_TREE, NULL_TREE);
6480 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6481 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6482 expand_omp_regimplify_p, NULL, NULL)
6483 || walk_tree (gimple_cond_rhs_ptr (stmt),
6484 expand_omp_regimplify_p, NULL, NULL))
6486 gsi = gsi_for_stmt (stmt);
6487 gimple_regimplify_operands (stmt, &gsi);
6489 se = split_block (entry_bb, stmt);
6490 se->flags = EDGE_TRUE_VALUE;
6491 entry_bb = se->dest;
6492 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6493 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6494 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6495 if (gimple_in_ssa_p (cfun))
6497 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6498 for (gsi = gsi_start_phis (fin_bb);
6499 !gsi_end_p (gsi); gsi_next (&gsi))
6501 gimple phi = gsi_stmt (gsi);
6502 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6503 se, UNKNOWN_LOCATION);
6506 gsi = gsi_last_bb (entry_bb);
6509 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6510 t = fold_convert (itype, t);
6511 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6512 true, GSI_SAME_STMT);
6514 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6515 t = fold_convert (itype, t);
6516 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6517 true, GSI_SAME_STMT);
6519 n1 = fd->loop.n1;
6520 n2 = fd->loop.n2;
6521 step = fd->loop.step;
6522 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6524 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6525 OMP_CLAUSE__LOOPTEMP_);
6526 gcc_assert (innerc);
6527 n1 = OMP_CLAUSE_DECL (innerc);
6528 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6529 OMP_CLAUSE__LOOPTEMP_);
6530 gcc_assert (innerc);
6531 n2 = OMP_CLAUSE_DECL (innerc);
6533 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6534 true, NULL_TREE, true, GSI_SAME_STMT);
6535 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6536 true, NULL_TREE, true, GSI_SAME_STMT);
6537 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6538 true, NULL_TREE, true, GSI_SAME_STMT);
6539 fd->chunk_size
6540 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6541 true, NULL_TREE, true, GSI_SAME_STMT);
6543 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6544 t = fold_build2 (PLUS_EXPR, itype, step, t);
6545 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6546 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6547 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6548 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6549 fold_build1 (NEGATE_EXPR, itype, t),
6550 fold_build1 (NEGATE_EXPR, itype, step));
6551 else
6552 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6553 t = fold_convert (itype, t);
6554 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6555 true, GSI_SAME_STMT);
6557 trip_var = create_tmp_reg (itype, ".trip");
6558 if (gimple_in_ssa_p (cfun))
6560 trip_init = make_ssa_name (trip_var, NULL);
6561 trip_main = make_ssa_name (trip_var, NULL);
6562 trip_back = make_ssa_name (trip_var, NULL);
6564 else
6566 trip_init = trip_var;
6567 trip_main = trip_var;
6568 trip_back = trip_var;
6571 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6572 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6574 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6575 t = fold_build2 (MULT_EXPR, itype, t, step);
6576 if (POINTER_TYPE_P (type))
6577 t = fold_build_pointer_plus (n1, t);
6578 else
6579 t = fold_build2 (PLUS_EXPR, type, t, n1);
6580 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6581 true, GSI_SAME_STMT);
6583 /* Remove the GIMPLE_OMP_FOR. */
6584 gsi_remove (&gsi, true);
6586 /* Iteration space partitioning goes in ITER_PART_BB. */
6587 gsi = gsi_last_bb (iter_part_bb);
6589 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6590 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6591 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6592 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6593 false, GSI_CONTINUE_LINKING);
6595 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6596 t = fold_build2 (MIN_EXPR, itype, t, n);
6597 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6598 false, GSI_CONTINUE_LINKING);
6600 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6601 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6603 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6604 gsi = gsi_start_bb (seq_start_bb);
6606 tree startvar = fd->loop.v;
6607 tree endvar = NULL_TREE;
6609 if (gimple_omp_for_combined_p (fd->for_stmt))
6611 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6612 ? gimple_omp_parallel_clauses (inner_stmt)
6613 : gimple_omp_for_clauses (inner_stmt);
6614 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6615 gcc_assert (innerc);
6616 startvar = OMP_CLAUSE_DECL (innerc);
6617 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6618 OMP_CLAUSE__LOOPTEMP_);
6619 gcc_assert (innerc);
6620 endvar = OMP_CLAUSE_DECL (innerc);
6623 t = fold_convert (itype, s0);
6624 t = fold_build2 (MULT_EXPR, itype, t, step);
6625 if (POINTER_TYPE_P (type))
6626 t = fold_build_pointer_plus (n1, t);
6627 else
6628 t = fold_build2 (PLUS_EXPR, type, t, n1);
6629 t = fold_convert (TREE_TYPE (startvar), t);
6630 t = force_gimple_operand_gsi (&gsi, t,
6631 DECL_P (startvar)
6632 && TREE_ADDRESSABLE (startvar),
6633 NULL_TREE, false, GSI_CONTINUE_LINKING);
6634 stmt = gimple_build_assign (startvar, t);
6635 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6637 t = fold_convert (itype, e0);
6638 t = fold_build2 (MULT_EXPR, itype, t, step);
6639 if (POINTER_TYPE_P (type))
6640 t = fold_build_pointer_plus (n1, t);
6641 else
6642 t = fold_build2 (PLUS_EXPR, type, t, n1);
6643 t = fold_convert (TREE_TYPE (startvar), t);
6644 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6645 false, GSI_CONTINUE_LINKING);
6646 if (endvar)
6648 stmt = gimple_build_assign (endvar, e);
6649 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6650 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6651 stmt = gimple_build_assign (fd->loop.v, e);
6652 else
6653 stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
6654 NULL_TREE);
6655 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6657 if (fd->collapse > 1)
6658 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6660 if (!broken_loop)
6662 /* The code controlling the sequential loop goes in CONT_BB,
6663 replacing the GIMPLE_OMP_CONTINUE. */
6664 gsi = gsi_last_bb (cont_bb);
6665 stmt = gsi_stmt (gsi);
6666 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6667 vmain = gimple_omp_continue_control_use (stmt);
6668 vback = gimple_omp_continue_control_def (stmt);
6670 if (!gimple_omp_for_combined_p (fd->for_stmt))
6672 if (POINTER_TYPE_P (type))
6673 t = fold_build_pointer_plus (vmain, step);
6674 else
6675 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6676 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6677 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6678 true, GSI_SAME_STMT);
6679 stmt = gimple_build_assign (vback, t);
6680 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6682 t = build2 (fd->loop.cond_code, boolean_type_node,
6683 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6684 ? t : vback, e);
6685 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6688 /* Remove GIMPLE_OMP_CONTINUE. */
6689 gsi_remove (&gsi, true);
6691 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6692 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6694 /* Trip update code goes into TRIP_UPDATE_BB. */
6695 gsi = gsi_start_bb (trip_update_bb);
6697 t = build_int_cst (itype, 1);
6698 t = build2 (PLUS_EXPR, itype, trip_main, t);
6699 stmt = gimple_build_assign (trip_back, t);
6700 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6703 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6704 gsi = gsi_last_bb (exit_bb);
6705 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6707 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6708 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6710 gsi_remove (&gsi, true);
6712 /* Connect the new blocks. */
6713 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6714 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6716 if (!broken_loop)
6718 se = find_edge (cont_bb, body_bb);
6719 if (gimple_omp_for_combined_p (fd->for_stmt))
6721 remove_edge (se);
6722 se = NULL;
6724 else if (fd->collapse > 1)
6726 remove_edge (se);
6727 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6729 else
6730 se->flags = EDGE_TRUE_VALUE;
6731 find_edge (cont_bb, trip_update_bb)->flags
6732 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6734 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6737 if (gimple_in_ssa_p (cfun))
6739 gimple_stmt_iterator psi;
6740 gimple phi;
6741 edge re, ene;
6742 edge_var_map *vm;
6743 size_t i;
6745 gcc_assert (fd->collapse == 1 && !broken_loop);
6747 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6748 remove arguments of the phi nodes in fin_bb. We need to create
6749 appropriate phi nodes in iter_part_bb instead. */
6750 se = single_pred_edge (fin_bb);
6751 re = single_succ_edge (trip_update_bb);
6752 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6753 ene = single_succ_edge (entry_bb);
6755 psi = gsi_start_phis (fin_bb);
6756 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6757 gsi_next (&psi), ++i)
6759 gimple nphi;
6760 source_location locus;
6762 phi = gsi_stmt (psi);
6763 t = gimple_phi_result (phi);
6764 gcc_assert (t == redirect_edge_var_map_result (vm));
6765 nphi = create_phi_node (t, iter_part_bb);
6767 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6768 locus = gimple_phi_arg_location_from_edge (phi, se);
6770 /* A special case -- fd->loop.v is not yet computed in
6771 iter_part_bb, we need to use vextra instead. */
6772 if (t == fd->loop.v)
6773 t = vextra;
6774 add_phi_arg (nphi, t, ene, locus);
6775 locus = redirect_edge_var_map_location (vm);
6776 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6778 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6779 redirect_edge_var_map_clear (re);
6780 while (1)
6782 psi = gsi_start_phis (fin_bb);
6783 if (gsi_end_p (psi))
6784 break;
6785 remove_phi_node (&psi, false);
6788 /* Make phi node for trip. */
6789 phi = create_phi_node (trip_main, iter_part_bb);
6790 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6791 UNKNOWN_LOCATION);
6792 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6793 UNKNOWN_LOCATION);
6796 if (!broken_loop)
6797 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6798 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6799 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6800 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6801 recompute_dominator (CDI_DOMINATORS, fin_bb));
6802 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6803 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6804 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6805 recompute_dominator (CDI_DOMINATORS, body_bb));
6807 if (!broken_loop)
6809 struct loop *trip_loop = alloc_loop ();
6810 trip_loop->header = iter_part_bb;
6811 trip_loop->latch = trip_update_bb;
6812 add_loop (trip_loop, iter_part_bb->loop_father);
6814 if (!gimple_omp_for_combined_p (fd->for_stmt))
6816 struct loop *loop = alloc_loop ();
6817 loop->header = body_bb;
6818 if (collapse_bb == NULL)
6819 loop->latch = cont_bb;
6820 add_loop (loop, trip_loop);
6825 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6826 Given parameters:
6827 for (V = N1; V cond N2; V += STEP) BODY;
6829 where COND is "<" or ">" or "!=", we generate pseudocode
6831 for (ind_var = low; ind_var < high; ind_var++)
6833 V = n1 + (ind_var * STEP)
6835 <BODY>
6838 In the above pseudocode, low and high are function parameters of the
6839 child function. In the function below, we are inserting a temp.
6840 variable that will be making a call to two OMP functions that will not be
6841 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6842 with _Cilk_for). These functions are replaced with low and high
6843 by the function that handles taskreg. */
6846 static void
6847 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6849 bool broken_loop = region->cont == NULL;
6850 basic_block entry_bb = region->entry;
6851 basic_block cont_bb = region->cont;
6853 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6854 gcc_assert (broken_loop
6855 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6856 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6857 basic_block l1_bb, l2_bb;
6859 if (!broken_loop)
6861 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6862 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6863 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6864 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6866 else
6868 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6869 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6870 l2_bb = single_succ (l1_bb);
6872 basic_block exit_bb = region->exit;
6873 basic_block l2_dom_bb = NULL;
6875 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6877 /* Below statements until the "tree high_val = ..." are pseudo statements
6878 used to pass information to be used by expand_omp_taskreg.
6879 low_val and high_val will be replaced by the __low and __high
6880 parameter from the child function.
6882 The call_exprs part is a place-holder, it is mainly used
6883 to distinctly identify to the top-level part that this is
6884 where we should put low and high (reasoning given in header
6885 comment). */
6887 tree child_fndecl
6888 = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry));
6889 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6890 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6892 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6893 high_val = t;
6894 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6895 low_val = t;
6897 gcc_assert (low_val && high_val);
6899 tree type = TREE_TYPE (low_val);
6900 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6901 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6903 /* Not needed in SSA form right now. */
6904 gcc_assert (!gimple_in_ssa_p (cfun));
6905 if (l2_dom_bb == NULL)
6906 l2_dom_bb = l1_bb;
6908 tree n1 = low_val;
6909 tree n2 = high_val;
6911 gimple stmt = gimple_build_assign (ind_var, n1);
6913 /* Replace the GIMPLE_OMP_FOR statement. */
6914 gsi_replace (&gsi, stmt, true);
6916 if (!broken_loop)
6918 /* Code to control the increment goes in the CONT_BB. */
6919 gsi = gsi_last_bb (cont_bb);
6920 stmt = gsi_stmt (gsi);
6921 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6922 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6923 build_one_cst (type));
6925 /* Replace GIMPLE_OMP_CONTINUE. */
6926 gsi_replace (&gsi, stmt, true);
6929 /* Emit the condition in L1_BB. */
6930 gsi = gsi_after_labels (l1_bb);
6931 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6932 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6933 fd->loop.step);
6934 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6935 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6936 fd->loop.n1, fold_convert (sizetype, t));
6937 else
6938 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6939 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6940 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6941 expand_omp_build_assign (&gsi, fd->loop.v, t);
6943 /* The condition is always '<' since the runtime will fill in the low
6944 and high values. */
6945 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6946 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6948 /* Remove GIMPLE_OMP_RETURN. */
6949 gsi = gsi_last_bb (exit_bb);
6950 gsi_remove (&gsi, true);
6952 /* Connect the new blocks. */
6953 remove_edge (FALLTHRU_EDGE (entry_bb));
6955 edge e, ne;
6956 if (!broken_loop)
6958 remove_edge (BRANCH_EDGE (entry_bb));
6959 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6961 e = BRANCH_EDGE (l1_bb);
6962 ne = FALLTHRU_EDGE (l1_bb);
6963 e->flags = EDGE_TRUE_VALUE;
6965 else
6967 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6969 ne = single_succ_edge (l1_bb);
6970 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6973 ne->flags = EDGE_FALSE_VALUE;
6974 e->probability = REG_BR_PROB_BASE * 7 / 8;
6975 ne->probability = REG_BR_PROB_BASE / 8;
6977 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6978 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6979 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6981 if (!broken_loop)
6983 struct loop *loop = alloc_loop ();
6984 loop->header = l1_bb;
6985 loop->latch = cont_bb;
6986 add_loop (loop, l1_bb->loop_father);
6987 loop->safelen = INT_MAX;
6990 /* Pick the correct library function based on the precision of the
6991 induction variable type. */
6992 tree lib_fun = NULL_TREE;
6993 if (TYPE_PRECISION (type) == 32)
6994 lib_fun = cilk_for_32_fndecl;
6995 else if (TYPE_PRECISION (type) == 64)
6996 lib_fun = cilk_for_64_fndecl;
6997 else
6998 gcc_unreachable ();
7000 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7002 /* WS_ARGS contains the library function flavor to call:
7003 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7004 user-defined grain value. If the user does not define one, then zero
7005 is passed in by the parser. */
7006 vec_alloc (region->ws_args, 2);
7007 region->ws_args->quick_push (lib_fun);
7008 region->ws_args->quick_push (fd->chunk_size);
7011 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7012 loop. Given parameters:
7014 for (V = N1; V cond N2; V += STEP) BODY;
7016 where COND is "<" or ">", we generate pseudocode
7018 V = N1;
7019 goto L1;
7021 BODY;
7022 V += STEP;
7024 if (V cond N2) goto L0; else goto L2;
7027 For collapsed loops, given parameters:
7028 collapse(3)
7029 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7030 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7031 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7032 BODY;
7034 we generate pseudocode
7036 if (cond3 is <)
7037 adj = STEP3 - 1;
7038 else
7039 adj = STEP3 + 1;
7040 count3 = (adj + N32 - N31) / STEP3;
7041 if (cond2 is <)
7042 adj = STEP2 - 1;
7043 else
7044 adj = STEP2 + 1;
7045 count2 = (adj + N22 - N21) / STEP2;
7046 if (cond1 is <)
7047 adj = STEP1 - 1;
7048 else
7049 adj = STEP1 + 1;
7050 count1 = (adj + N12 - N11) / STEP1;
7051 count = count1 * count2 * count3;
7052 V = 0;
7053 V1 = N11;
7054 V2 = N21;
7055 V3 = N31;
7056 goto L1;
7058 BODY;
7059 V += 1;
7060 V3 += STEP3;
7061 V2 += (V3 cond3 N32) ? 0 : STEP2;
7062 V3 = (V3 cond3 N32) ? V3 : N31;
7063 V1 += (V2 cond2 N22) ? 0 : STEP1;
7064 V2 = (V2 cond2 N22) ? V2 : N21;
7066 if (V < count) goto L0; else goto L2;
7071 static void
7072 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7074 tree type, t;
7075 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7076 gimple_stmt_iterator gsi;
7077 gimple stmt;
7078 bool broken_loop = region->cont == NULL;
7079 edge e, ne;
7080 tree *counts = NULL;
7081 int i;
7082 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7083 OMP_CLAUSE_SAFELEN);
7084 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7085 OMP_CLAUSE__SIMDUID_);
7086 tree n1, n2;
7088 type = TREE_TYPE (fd->loop.v);
7089 entry_bb = region->entry;
7090 cont_bb = region->cont;
7091 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7092 gcc_assert (broken_loop
7093 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7094 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7095 if (!broken_loop)
7097 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7098 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7099 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7100 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7102 else
7104 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7105 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7106 l2_bb = single_succ (l1_bb);
7108 exit_bb = region->exit;
7109 l2_dom_bb = NULL;
7111 gsi = gsi_last_bb (entry_bb);
7113 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7114 /* Not needed in SSA form right now. */
7115 gcc_assert (!gimple_in_ssa_p (cfun));
7116 if (fd->collapse > 1)
7118 int first_zero_iter = -1;
7119 basic_block zero_iter_bb = l2_bb;
7121 counts = XALLOCAVEC (tree, fd->collapse);
7122 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7123 zero_iter_bb, first_zero_iter,
7124 l2_dom_bb);
7126 if (l2_dom_bb == NULL)
7127 l2_dom_bb = l1_bb;
7129 n1 = fd->loop.n1;
7130 n2 = fd->loop.n2;
7131 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7133 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7134 OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 n1 = OMP_CLAUSE_DECL (innerc);
7137 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7138 OMP_CLAUSE__LOOPTEMP_);
7139 gcc_assert (innerc);
7140 n2 = OMP_CLAUSE_DECL (innerc);
7141 expand_omp_build_assign (&gsi, fd->loop.v,
7142 fold_convert (type, n1));
7143 if (fd->collapse > 1)
7145 gsi_prev (&gsi);
7146 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7147 gsi_next (&gsi);
7150 else
7152 expand_omp_build_assign (&gsi, fd->loop.v,
7153 fold_convert (type, fd->loop.n1));
7154 if (fd->collapse > 1)
7155 for (i = 0; i < fd->collapse; i++)
7157 tree itype = TREE_TYPE (fd->loops[i].v);
7158 if (POINTER_TYPE_P (itype))
7159 itype = signed_type_for (itype);
7160 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7161 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7165 /* Remove the GIMPLE_OMP_FOR statement. */
7166 gsi_remove (&gsi, true);
7168 if (!broken_loop)
7170 /* Code to control the increment goes in the CONT_BB. */
7171 gsi = gsi_last_bb (cont_bb);
7172 stmt = gsi_stmt (gsi);
7173 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7175 if (POINTER_TYPE_P (type))
7176 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7177 else
7178 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7179 expand_omp_build_assign (&gsi, fd->loop.v, t);
7181 if (fd->collapse > 1)
7183 i = fd->collapse - 1;
7184 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7186 t = fold_convert (sizetype, fd->loops[i].step);
7187 t = fold_build_pointer_plus (fd->loops[i].v, t);
7189 else
7191 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7192 fd->loops[i].step);
7193 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7194 fd->loops[i].v, t);
7196 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7198 for (i = fd->collapse - 1; i > 0; i--)
7200 tree itype = TREE_TYPE (fd->loops[i].v);
7201 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7202 if (POINTER_TYPE_P (itype2))
7203 itype2 = signed_type_for (itype2);
7204 t = build3 (COND_EXPR, itype2,
7205 build2 (fd->loops[i].cond_code, boolean_type_node,
7206 fd->loops[i].v,
7207 fold_convert (itype, fd->loops[i].n2)),
7208 build_int_cst (itype2, 0),
7209 fold_convert (itype2, fd->loops[i - 1].step));
7210 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7211 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7212 else
7213 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7214 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7216 t = build3 (COND_EXPR, itype,
7217 build2 (fd->loops[i].cond_code, boolean_type_node,
7218 fd->loops[i].v,
7219 fold_convert (itype, fd->loops[i].n2)),
7220 fd->loops[i].v,
7221 fold_convert (itype, fd->loops[i].n1));
7222 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7226 /* Remove GIMPLE_OMP_CONTINUE. */
7227 gsi_remove (&gsi, true);
7230 /* Emit the condition in L1_BB. */
7231 gsi = gsi_start_bb (l1_bb);
7233 t = fold_convert (type, n2);
7234 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7235 false, GSI_CONTINUE_LINKING);
7236 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7237 stmt = gimple_build_cond_empty (t);
7238 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7239 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
7240 NULL, NULL)
7241 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
7242 NULL, NULL))
7244 gsi = gsi_for_stmt (stmt);
7245 gimple_regimplify_operands (stmt, &gsi);
7248 /* Remove GIMPLE_OMP_RETURN. */
7249 gsi = gsi_last_bb (exit_bb);
7250 gsi_remove (&gsi, true);
7252 /* Connect the new blocks. */
7253 remove_edge (FALLTHRU_EDGE (entry_bb));
7255 if (!broken_loop)
7257 remove_edge (BRANCH_EDGE (entry_bb));
7258 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7260 e = BRANCH_EDGE (l1_bb);
7261 ne = FALLTHRU_EDGE (l1_bb);
7262 e->flags = EDGE_TRUE_VALUE;
7264 else
7266 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7268 ne = single_succ_edge (l1_bb);
7269 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7272 ne->flags = EDGE_FALSE_VALUE;
7273 e->probability = REG_BR_PROB_BASE * 7 / 8;
7274 ne->probability = REG_BR_PROB_BASE / 8;
7276 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7277 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7278 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7280 if (!broken_loop)
7282 struct loop *loop = alloc_loop ();
7283 loop->header = l1_bb;
7284 loop->latch = cont_bb;
7285 add_loop (loop, l1_bb->loop_father);
7286 if (safelen == NULL_TREE)
7287 loop->safelen = INT_MAX;
7288 else
7290 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7291 if (TREE_CODE (safelen) != INTEGER_CST)
7292 loop->safelen = 0;
7293 else if (!tree_fits_uhwi_p (safelen)
7294 || tree_to_uhwi (safelen) > INT_MAX)
7295 loop->safelen = INT_MAX;
7296 else
7297 loop->safelen = tree_to_uhwi (safelen);
7298 if (loop->safelen == 1)
7299 loop->safelen = 0;
7301 if (simduid)
7303 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7304 cfun->has_simduid_loops = true;
7306 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7307 the loop. */
7308 if ((flag_tree_loop_vectorize
7309 || (!global_options_set.x_flag_tree_loop_vectorize
7310 && !global_options_set.x_flag_tree_vectorize))
7311 && flag_tree_loop_optimize
7312 && loop->safelen > 1)
7314 loop->force_vectorize = true;
7315 cfun->has_force_vectorize_loops = true;
7321 /* Expand the OpenMP loop defined by REGION. */
7323 static void
7324 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7326 struct omp_for_data fd;
7327 struct omp_for_data_loop *loops;
7329 loops
7330 = (struct omp_for_data_loop *)
7331 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7332 * sizeof (struct omp_for_data_loop));
7333 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7334 region->sched_kind = fd.sched_kind;
7336 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7337 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7338 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7339 if (region->cont)
7341 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7342 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7343 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7345 else
7346 /* If there isn't a continue then this is a degerate case where
7347 the introduction of abnormal edges during lowering will prevent
7348 original loops from being detected. Fix that up. */
7349 loops_state_set (LOOPS_NEED_FIXUP);
7351 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7352 expand_omp_simd (region, &fd);
7353 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7354 expand_cilk_for (region, &fd);
7355 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7356 && !fd.have_ordered)
7358 if (fd.chunk_size == NULL)
7359 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7360 else
7361 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7363 else
7365 int fn_index, start_ix, next_ix;
7367 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7368 == GF_OMP_FOR_KIND_FOR);
7369 if (fd.chunk_size == NULL
7370 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7371 fd.chunk_size = integer_zero_node;
7372 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7373 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7374 ? 3 : fd.sched_kind;
7375 fn_index += fd.have_ordered * 4;
7376 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7377 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7378 if (fd.iter_type == long_long_unsigned_type_node)
7380 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7381 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7382 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7383 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7385 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7386 (enum built_in_function) next_ix, inner_stmt);
7389 if (gimple_in_ssa_p (cfun))
7390 update_ssa (TODO_update_ssa_only_virtuals);
7394 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7396 v = GOMP_sections_start (n);
7398 switch (v)
7400 case 0:
7401 goto L2;
7402 case 1:
7403 section 1;
7404 goto L1;
7405 case 2:
7407 case n:
7409 default:
7410 abort ();
7413 v = GOMP_sections_next ();
7414 goto L0;
7416 reduction;
7418 If this is a combined parallel sections, replace the call to
7419 GOMP_sections_start with call to GOMP_sections_next. */
7421 static void
7422 expand_omp_sections (struct omp_region *region)
7424 tree t, u, vin = NULL, vmain, vnext, l2;
7425 unsigned len;
7426 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7427 gimple_stmt_iterator si, switch_si;
7428 gimple sections_stmt, stmt, cont;
7429 edge_iterator ei;
7430 edge e;
7431 struct omp_region *inner;
7432 unsigned i, casei;
7433 bool exit_reachable = region->cont != NULL;
7435 gcc_assert (region->exit != NULL);
7436 entry_bb = region->entry;
7437 l0_bb = single_succ (entry_bb);
7438 l1_bb = region->cont;
7439 l2_bb = region->exit;
7440 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7441 l2 = gimple_block_label (l2_bb);
7442 else
7444 /* This can happen if there are reductions. */
7445 len = EDGE_COUNT (l0_bb->succs);
7446 gcc_assert (len > 0);
7447 e = EDGE_SUCC (l0_bb, len - 1);
7448 si = gsi_last_bb (e->dest);
7449 l2 = NULL_TREE;
7450 if (gsi_end_p (si)
7451 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7452 l2 = gimple_block_label (e->dest);
7453 else
7454 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7456 si = gsi_last_bb (e->dest);
7457 if (gsi_end_p (si)
7458 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7460 l2 = gimple_block_label (e->dest);
7461 break;
7465 if (exit_reachable)
7466 default_bb = create_empty_bb (l1_bb->prev_bb);
7467 else
7468 default_bb = create_empty_bb (l0_bb);
7470 /* We will build a switch() with enough cases for all the
7471 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7472 and a default case to abort if something goes wrong. */
7473 len = EDGE_COUNT (l0_bb->succs);
7475 /* Use vec::quick_push on label_vec throughout, since we know the size
7476 in advance. */
7477 auto_vec<tree> label_vec (len);
7479 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7480 GIMPLE_OMP_SECTIONS statement. */
7481 si = gsi_last_bb (entry_bb);
7482 sections_stmt = gsi_stmt (si);
7483 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7484 vin = gimple_omp_sections_control (sections_stmt);
7485 if (!is_combined_parallel (region))
7487 /* If we are not inside a combined parallel+sections region,
7488 call GOMP_sections_start. */
7489 t = build_int_cst (unsigned_type_node, len - 1);
7490 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7491 stmt = gimple_build_call (u, 1, t);
7493 else
7495 /* Otherwise, call GOMP_sections_next. */
7496 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7497 stmt = gimple_build_call (u, 0);
7499 gimple_call_set_lhs (stmt, vin);
7500 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7501 gsi_remove (&si, true);
7503 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7504 L0_BB. */
7505 switch_si = gsi_last_bb (l0_bb);
7506 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7507 if (exit_reachable)
7509 cont = last_stmt (l1_bb);
7510 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7511 vmain = gimple_omp_continue_control_use (cont);
7512 vnext = gimple_omp_continue_control_def (cont);
7514 else
7516 vmain = vin;
7517 vnext = NULL_TREE;
7520 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7521 label_vec.quick_push (t);
7522 i = 1;
7524 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7525 for (inner = region->inner, casei = 1;
7526 inner;
7527 inner = inner->next, i++, casei++)
7529 basic_block s_entry_bb, s_exit_bb;
7531 /* Skip optional reduction region. */
7532 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7534 --i;
7535 --casei;
7536 continue;
7539 s_entry_bb = inner->entry;
7540 s_exit_bb = inner->exit;
7542 t = gimple_block_label (s_entry_bb);
7543 u = build_int_cst (unsigned_type_node, casei);
7544 u = build_case_label (u, NULL, t);
7545 label_vec.quick_push (u);
7547 si = gsi_last_bb (s_entry_bb);
7548 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7549 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7550 gsi_remove (&si, true);
7551 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7553 if (s_exit_bb == NULL)
7554 continue;
7556 si = gsi_last_bb (s_exit_bb);
7557 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7558 gsi_remove (&si, true);
7560 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7563 /* Error handling code goes in DEFAULT_BB. */
7564 t = gimple_block_label (default_bb);
7565 u = build_case_label (NULL, NULL, t);
7566 make_edge (l0_bb, default_bb, 0);
7567 add_bb_to_loop (default_bb, current_loops->tree_root);
7569 stmt = gimple_build_switch (vmain, u, label_vec);
7570 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7571 gsi_remove (&switch_si, true);
7573 si = gsi_start_bb (default_bb);
7574 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7575 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7577 if (exit_reachable)
7579 tree bfn_decl;
7581 /* Code to get the next section goes in L1_BB. */
7582 si = gsi_last_bb (l1_bb);
7583 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7585 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7586 stmt = gimple_build_call (bfn_decl, 0);
7587 gimple_call_set_lhs (stmt, vnext);
7588 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7589 gsi_remove (&si, true);
7591 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7594 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7595 si = gsi_last_bb (l2_bb);
7596 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7597 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7598 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7599 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7600 else
7601 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7602 stmt = gimple_build_call (t, 0);
7603 if (gimple_omp_return_lhs (gsi_stmt (si)))
7604 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7605 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7606 gsi_remove (&si, true);
7608 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7612 /* Expand code for an OpenMP single directive. We've already expanded
7613 much of the code, here we simply place the GOMP_barrier call. */
7615 static void
7616 expand_omp_single (struct omp_region *region)
7618 basic_block entry_bb, exit_bb;
7619 gimple_stmt_iterator si;
7621 entry_bb = region->entry;
7622 exit_bb = region->exit;
7624 si = gsi_last_bb (entry_bb);
7625 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7626 gsi_remove (&si, true);
7627 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7629 si = gsi_last_bb (exit_bb);
7630 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7632 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7633 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7635 gsi_remove (&si, true);
7636 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7640 /* Generic expansion for OpenMP synchronization directives: master,
7641 ordered and critical. All we need to do here is remove the entry
7642 and exit markers for REGION. */
7644 static void
7645 expand_omp_synch (struct omp_region *region)
7647 basic_block entry_bb, exit_bb;
7648 gimple_stmt_iterator si;
7650 entry_bb = region->entry;
7651 exit_bb = region->exit;
7653 si = gsi_last_bb (entry_bb);
7654 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7655 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7656 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7657 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7658 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7659 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7660 gsi_remove (&si, true);
7661 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7663 if (exit_bb)
7665 si = gsi_last_bb (exit_bb);
7666 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7667 gsi_remove (&si, true);
7668 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7672 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7673 operation as a normal volatile load. */
7675 static bool
7676 expand_omp_atomic_load (basic_block load_bb, tree addr,
7677 tree loaded_val, int index)
7679 enum built_in_function tmpbase;
7680 gimple_stmt_iterator gsi;
7681 basic_block store_bb;
7682 location_t loc;
7683 gimple stmt;
7684 tree decl, call, type, itype;
7686 gsi = gsi_last_bb (load_bb);
7687 stmt = gsi_stmt (gsi);
7688 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7689 loc = gimple_location (stmt);
7691 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7692 is smaller than word size, then expand_atomic_load assumes that the load
7693 is atomic. We could avoid the builtin entirely in this case. */
7695 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7696 decl = builtin_decl_explicit (tmpbase);
7697 if (decl == NULL_TREE)
7698 return false;
7700 type = TREE_TYPE (loaded_val);
7701 itype = TREE_TYPE (TREE_TYPE (decl));
7703 call = build_call_expr_loc (loc, decl, 2, addr,
7704 build_int_cst (NULL,
7705 gimple_omp_atomic_seq_cst_p (stmt)
7706 ? MEMMODEL_SEQ_CST
7707 : MEMMODEL_RELAXED));
7708 if (!useless_type_conversion_p (type, itype))
7709 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7710 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7712 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7713 gsi_remove (&gsi, true);
7715 store_bb = single_succ (load_bb);
7716 gsi = gsi_last_bb (store_bb);
7717 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7718 gsi_remove (&gsi, true);
7720 if (gimple_in_ssa_p (cfun))
7721 update_ssa (TODO_update_ssa_no_phi);
7723 return true;
7726 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7727 operation as a normal volatile store. */
7729 static bool
7730 expand_omp_atomic_store (basic_block load_bb, tree addr,
7731 tree loaded_val, tree stored_val, int index)
7733 enum built_in_function tmpbase;
7734 gimple_stmt_iterator gsi;
7735 basic_block store_bb = single_succ (load_bb);
7736 location_t loc;
7737 gimple stmt;
7738 tree decl, call, type, itype;
7739 machine_mode imode;
7740 bool exchange;
7742 gsi = gsi_last_bb (load_bb);
7743 stmt = gsi_stmt (gsi);
7744 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7746 /* If the load value is needed, then this isn't a store but an exchange. */
7747 exchange = gimple_omp_atomic_need_value_p (stmt);
7749 gsi = gsi_last_bb (store_bb);
7750 stmt = gsi_stmt (gsi);
7751 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7752 loc = gimple_location (stmt);
7754 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7755 is smaller than word size, then expand_atomic_store assumes that the store
7756 is atomic. We could avoid the builtin entirely in this case. */
7758 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7759 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7760 decl = builtin_decl_explicit (tmpbase);
7761 if (decl == NULL_TREE)
7762 return false;
7764 type = TREE_TYPE (stored_val);
7766 /* Dig out the type of the function's second argument. */
7767 itype = TREE_TYPE (decl);
7768 itype = TYPE_ARG_TYPES (itype);
7769 itype = TREE_CHAIN (itype);
7770 itype = TREE_VALUE (itype);
7771 imode = TYPE_MODE (itype);
7773 if (exchange && !can_atomic_exchange_p (imode, true))
7774 return false;
7776 if (!useless_type_conversion_p (itype, type))
7777 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7778 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7779 build_int_cst (NULL,
7780 gimple_omp_atomic_seq_cst_p (stmt)
7781 ? MEMMODEL_SEQ_CST
7782 : MEMMODEL_RELAXED));
7783 if (exchange)
7785 if (!useless_type_conversion_p (type, itype))
7786 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7787 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7790 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7791 gsi_remove (&gsi, true);
7793 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7794 gsi = gsi_last_bb (load_bb);
7795 gsi_remove (&gsi, true);
7797 if (gimple_in_ssa_p (cfun))
7798 update_ssa (TODO_update_ssa_no_phi);
7800 return true;
7803 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7804 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7805 size of the data type, and thus usable to find the index of the builtin
7806 decl. Returns false if the expression is not of the proper form. */
7808 static bool
7809 expand_omp_atomic_fetch_op (basic_block load_bb,
7810 tree addr, tree loaded_val,
7811 tree stored_val, int index)
7813 enum built_in_function oldbase, newbase, tmpbase;
7814 tree decl, itype, call;
7815 tree lhs, rhs;
7816 basic_block store_bb = single_succ (load_bb);
7817 gimple_stmt_iterator gsi;
7818 gimple stmt;
7819 location_t loc;
7820 enum tree_code code;
7821 bool need_old, need_new;
7822 machine_mode imode;
7823 bool seq_cst;
7825 /* We expect to find the following sequences:
7827 load_bb:
7828 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7830 store_bb:
7831 val = tmp OP something; (or: something OP tmp)
7832 GIMPLE_OMP_STORE (val)
7834 ???FIXME: Allow a more flexible sequence.
7835 Perhaps use data flow to pick the statements.
7839 gsi = gsi_after_labels (store_bb);
7840 stmt = gsi_stmt (gsi);
7841 loc = gimple_location (stmt);
7842 if (!is_gimple_assign (stmt))
7843 return false;
7844 gsi_next (&gsi);
7845 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7846 return false;
7847 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7848 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7849 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7850 gcc_checking_assert (!need_old || !need_new);
7852 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7853 return false;
7855 /* Check for one of the supported fetch-op operations. */
7856 code = gimple_assign_rhs_code (stmt);
7857 switch (code)
7859 case PLUS_EXPR:
7860 case POINTER_PLUS_EXPR:
7861 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7862 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7863 break;
7864 case MINUS_EXPR:
7865 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7866 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7867 break;
7868 case BIT_AND_EXPR:
7869 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7870 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7871 break;
7872 case BIT_IOR_EXPR:
7873 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7874 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7875 break;
7876 case BIT_XOR_EXPR:
7877 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7878 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7879 break;
7880 default:
7881 return false;
7884 /* Make sure the expression is of the proper form. */
7885 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7886 rhs = gimple_assign_rhs2 (stmt);
7887 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7888 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7889 rhs = gimple_assign_rhs1 (stmt);
7890 else
7891 return false;
7893 tmpbase = ((enum built_in_function)
7894 ((need_new ? newbase : oldbase) + index + 1));
7895 decl = builtin_decl_explicit (tmpbase);
7896 if (decl == NULL_TREE)
7897 return false;
7898 itype = TREE_TYPE (TREE_TYPE (decl));
7899 imode = TYPE_MODE (itype);
7901 /* We could test all of the various optabs involved, but the fact of the
7902 matter is that (with the exception of i486 vs i586 and xadd) all targets
7903 that support any atomic operaton optab also implements compare-and-swap.
7904 Let optabs.c take care of expanding any compare-and-swap loop. */
7905 if (!can_compare_and_swap_p (imode, true))
7906 return false;
7908 gsi = gsi_last_bb (load_bb);
7909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7911 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7912 It only requires that the operation happen atomically. Thus we can
7913 use the RELAXED memory model. */
7914 call = build_call_expr_loc (loc, decl, 3, addr,
7915 fold_convert_loc (loc, itype, rhs),
7916 build_int_cst (NULL,
7917 seq_cst ? MEMMODEL_SEQ_CST
7918 : MEMMODEL_RELAXED));
7920 if (need_old || need_new)
7922 lhs = need_old ? loaded_val : stored_val;
7923 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7924 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7926 else
7927 call = fold_convert_loc (loc, void_type_node, call);
7928 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7929 gsi_remove (&gsi, true);
7931 gsi = gsi_last_bb (store_bb);
7932 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7933 gsi_remove (&gsi, true);
7934 gsi = gsi_last_bb (store_bb);
7935 gsi_remove (&gsi, true);
7937 if (gimple_in_ssa_p (cfun))
7938 update_ssa (TODO_update_ssa_no_phi);
7940 return true;
7943 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7945 oldval = *addr;
7946 repeat:
7947 newval = rhs; // with oldval replacing *addr in rhs
7948 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7949 if (oldval != newval)
7950 goto repeat;
7952 INDEX is log2 of the size of the data type, and thus usable to find the
7953 index of the builtin decl. */
7955 static bool
7956 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7957 tree addr, tree loaded_val, tree stored_val,
7958 int index)
7960 tree loadedi, storedi, initial, new_storedi, old_vali;
7961 tree type, itype, cmpxchg, iaddr;
7962 gimple_stmt_iterator si;
7963 basic_block loop_header = single_succ (load_bb);
7964 gimple phi, stmt;
7965 edge e;
7966 enum built_in_function fncode;
7968 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7969 order to use the RELAXED memory model effectively. */
7970 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7971 + index + 1);
7972 cmpxchg = builtin_decl_explicit (fncode);
7973 if (cmpxchg == NULL_TREE)
7974 return false;
7975 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7976 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7978 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7979 return false;
7981 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7982 si = gsi_last_bb (load_bb);
7983 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7985 /* For floating-point values, we'll need to view-convert them to integers
7986 so that we can perform the atomic compare and swap. Simplify the
7987 following code by always setting up the "i"ntegral variables. */
7988 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7990 tree iaddr_val;
7992 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7993 true), NULL);
7994 iaddr_val
7995 = force_gimple_operand_gsi (&si,
7996 fold_convert (TREE_TYPE (iaddr), addr),
7997 false, NULL_TREE, true, GSI_SAME_STMT);
7998 stmt = gimple_build_assign (iaddr, iaddr_val);
7999 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8000 loadedi = create_tmp_var (itype, NULL);
8001 if (gimple_in_ssa_p (cfun))
8002 loadedi = make_ssa_name (loadedi, NULL);
8004 else
8006 iaddr = addr;
8007 loadedi = loaded_val;
8010 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8011 tree loaddecl = builtin_decl_explicit (fncode);
8012 if (loaddecl)
8013 initial
8014 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8015 build_call_expr (loaddecl, 2, iaddr,
8016 build_int_cst (NULL_TREE,
8017 MEMMODEL_RELAXED)));
8018 else
8019 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8020 build_int_cst (TREE_TYPE (iaddr), 0));
8022 initial
8023 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8024 GSI_SAME_STMT);
8026 /* Move the value to the LOADEDI temporary. */
8027 if (gimple_in_ssa_p (cfun))
8029 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8030 phi = create_phi_node (loadedi, loop_header);
8031 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8032 initial);
8034 else
8035 gsi_insert_before (&si,
8036 gimple_build_assign (loadedi, initial),
8037 GSI_SAME_STMT);
8038 if (loadedi != loaded_val)
8040 gimple_stmt_iterator gsi2;
8041 tree x;
8043 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8044 gsi2 = gsi_start_bb (loop_header);
8045 if (gimple_in_ssa_p (cfun))
8047 gimple stmt;
8048 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8049 true, GSI_SAME_STMT);
8050 stmt = gimple_build_assign (loaded_val, x);
8051 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8053 else
8055 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8056 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8057 true, GSI_SAME_STMT);
8060 gsi_remove (&si, true);
8062 si = gsi_last_bb (store_bb);
8063 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8065 if (iaddr == addr)
8066 storedi = stored_val;
8067 else
8068 storedi =
8069 force_gimple_operand_gsi (&si,
8070 build1 (VIEW_CONVERT_EXPR, itype,
8071 stored_val), true, NULL_TREE, true,
8072 GSI_SAME_STMT);
8074 /* Build the compare&swap statement. */
8075 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8076 new_storedi = force_gimple_operand_gsi (&si,
8077 fold_convert (TREE_TYPE (loadedi),
8078 new_storedi),
8079 true, NULL_TREE,
8080 true, GSI_SAME_STMT);
8082 if (gimple_in_ssa_p (cfun))
8083 old_vali = loadedi;
8084 else
8086 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8087 stmt = gimple_build_assign (old_vali, loadedi);
8088 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8090 stmt = gimple_build_assign (loadedi, new_storedi);
8091 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8094 /* Note that we always perform the comparison as an integer, even for
8095 floating point. This allows the atomic operation to properly
8096 succeed even with NaNs and -0.0. */
8097 stmt = gimple_build_cond_empty
8098 (build2 (NE_EXPR, boolean_type_node,
8099 new_storedi, old_vali));
8100 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8102 /* Update cfg. */
8103 e = single_succ_edge (store_bb);
8104 e->flags &= ~EDGE_FALLTHRU;
8105 e->flags |= EDGE_FALSE_VALUE;
8107 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8109 /* Copy the new value to loadedi (we already did that before the condition
8110 if we are not in SSA). */
8111 if (gimple_in_ssa_p (cfun))
8113 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8114 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8117 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8118 gsi_remove (&si, true);
8120 struct loop *loop = alloc_loop ();
8121 loop->header = loop_header;
8122 loop->latch = store_bb;
8123 add_loop (loop, loop_header->loop_father);
8125 if (gimple_in_ssa_p (cfun))
8126 update_ssa (TODO_update_ssa_no_phi);
8128 return true;
8131 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8133 GOMP_atomic_start ();
8134 *addr = rhs;
8135 GOMP_atomic_end ();
8137 The result is not globally atomic, but works so long as all parallel
8138 references are within #pragma omp atomic directives. According to
8139 responses received from omp@openmp.org, appears to be within spec.
8140 Which makes sense, since that's how several other compilers handle
8141 this situation as well.
8142 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8143 expanding. STORED_VAL is the operand of the matching
8144 GIMPLE_OMP_ATOMIC_STORE.
8146 We replace
8147 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8148 loaded_val = *addr;
8150 and replace
8151 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8152 *addr = stored_val;
8155 static bool
8156 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8157 tree addr, tree loaded_val, tree stored_val)
8159 gimple_stmt_iterator si;
8160 gimple stmt;
8161 tree t;
8163 si = gsi_last_bb (load_bb);
8164 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8166 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8167 t = build_call_expr (t, 0);
8168 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8170 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8171 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8172 gsi_remove (&si, true);
8174 si = gsi_last_bb (store_bb);
8175 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8177 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8178 stored_val);
8179 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8181 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8182 t = build_call_expr (t, 0);
8183 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8184 gsi_remove (&si, true);
8186 if (gimple_in_ssa_p (cfun))
8187 update_ssa (TODO_update_ssa_no_phi);
8188 return true;
8191 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8192 using expand_omp_atomic_fetch_op. If it failed, we try to
8193 call expand_omp_atomic_pipeline, and if it fails too, the
8194 ultimate fallback is wrapping the operation in a mutex
8195 (expand_omp_atomic_mutex). REGION is the atomic region built
8196 by build_omp_regions_1(). */
8198 static void
8199 expand_omp_atomic (struct omp_region *region)
8201 basic_block load_bb = region->entry, store_bb = region->exit;
8202 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
8203 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8204 tree addr = gimple_omp_atomic_load_rhs (load);
8205 tree stored_val = gimple_omp_atomic_store_val (store);
8206 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8207 HOST_WIDE_INT index;
8209 /* Make sure the type is one of the supported sizes. */
8210 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8211 index = exact_log2 (index);
8212 if (index >= 0 && index <= 4)
8214 unsigned int align = TYPE_ALIGN_UNIT (type);
8216 /* __sync builtins require strict data alignment. */
8217 if (exact_log2 (align) >= index)
8219 /* Atomic load. */
8220 if (loaded_val == stored_val
8221 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8222 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8223 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8224 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8225 return;
8227 /* Atomic store. */
8228 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8229 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8230 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8231 && store_bb == single_succ (load_bb)
8232 && first_stmt (store_bb) == store
8233 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8234 stored_val, index))
8235 return;
8237 /* When possible, use specialized atomic update functions. */
8238 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8239 && store_bb == single_succ (load_bb)
8240 && expand_omp_atomic_fetch_op (load_bb, addr,
8241 loaded_val, stored_val, index))
8242 return;
8244 /* If we don't have specialized __sync builtins, try and implement
8245 as a compare and swap loop. */
8246 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8247 loaded_val, stored_val, index))
8248 return;
8252 /* The ultimate fallback is wrapping the operation in a mutex. */
8253 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8257 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8259 static void
8260 expand_omp_target (struct omp_region *region)
8262 basic_block entry_bb, exit_bb, new_bb;
8263 struct function *child_cfun = NULL;
8264 tree child_fn = NULL_TREE, block, t;
8265 gimple_stmt_iterator gsi;
8266 gimple entry_stmt, stmt;
8267 edge e;
8269 entry_stmt = last_stmt (region->entry);
8270 new_bb = region->entry;
8271 int kind = gimple_omp_target_kind (entry_stmt);
8272 if (kind == GF_OMP_TARGET_KIND_REGION)
8274 child_fn = gimple_omp_target_child_fn (entry_stmt);
8275 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8278 entry_bb = region->entry;
8279 exit_bb = region->exit;
8281 if (kind == GF_OMP_TARGET_KIND_REGION)
8283 unsigned srcidx, dstidx, num;
8285 /* If the target region needs data sent from the parent
8286 function, then the very first statement (except possible
8287 tree profile counter updates) of the parallel body
8288 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8289 &.OMP_DATA_O is passed as an argument to the child function,
8290 we need to replace it with the argument as seen by the child
8291 function.
8293 In most cases, this will end up being the identity assignment
8294 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8295 a function call that has been inlined, the original PARM_DECL
8296 .OMP_DATA_I may have been converted into a different local
8297 variable. In which case, we need to keep the assignment. */
8298 if (gimple_omp_target_data_arg (entry_stmt))
8300 basic_block entry_succ_bb = single_succ (entry_bb);
8301 gimple_stmt_iterator gsi;
8302 tree arg;
8303 gimple tgtcopy_stmt = NULL;
8304 tree sender
8305 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8307 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8309 gcc_assert (!gsi_end_p (gsi));
8310 stmt = gsi_stmt (gsi);
8311 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8312 continue;
8314 if (gimple_num_ops (stmt) == 2)
8316 tree arg = gimple_assign_rhs1 (stmt);
8318 /* We're ignoring the subcode because we're
8319 effectively doing a STRIP_NOPS. */
8321 if (TREE_CODE (arg) == ADDR_EXPR
8322 && TREE_OPERAND (arg, 0) == sender)
8324 tgtcopy_stmt = stmt;
8325 break;
8330 gcc_assert (tgtcopy_stmt != NULL);
8331 arg = DECL_ARGUMENTS (child_fn);
8333 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8334 gsi_remove (&gsi, true);
8337 /* Declare local variables needed in CHILD_CFUN. */
8338 block = DECL_INITIAL (child_fn);
8339 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8340 /* The gimplifier could record temporaries in target block
8341 rather than in containing function's local_decls chain,
8342 which would mean cgraph missed finalizing them. Do it now. */
8343 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8344 if (TREE_CODE (t) == VAR_DECL
8345 && TREE_STATIC (t)
8346 && !DECL_EXTERNAL (t))
8347 varpool_node::finalize_decl (t);
8348 DECL_SAVED_TREE (child_fn) = NULL;
8349 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8350 gimple_set_body (child_fn, NULL);
8351 TREE_USED (block) = 1;
8353 /* Reset DECL_CONTEXT on function arguments. */
8354 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8355 DECL_CONTEXT (t) = child_fn;
8357 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8358 so that it can be moved to the child function. */
8359 gsi = gsi_last_bb (entry_bb);
8360 stmt = gsi_stmt (gsi);
8361 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8362 && gimple_omp_target_kind (stmt)
8363 == GF_OMP_TARGET_KIND_REGION);
8364 gsi_remove (&gsi, true);
8365 e = split_block (entry_bb, stmt);
8366 entry_bb = e->dest;
8367 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8369 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8370 if (exit_bb)
8372 gsi = gsi_last_bb (exit_bb);
8373 gcc_assert (!gsi_end_p (gsi)
8374 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8375 stmt = gimple_build_return (NULL);
8376 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8377 gsi_remove (&gsi, true);
8380 /* Move the target region into CHILD_CFUN. */
8382 block = gimple_block (entry_stmt);
8384 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8385 if (exit_bb)
8386 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8387 /* When the OMP expansion process cannot guarantee an up-to-date
8388 loop tree arrange for the child function to fixup loops. */
8389 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8390 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8392 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8393 num = vec_safe_length (child_cfun->local_decls);
8394 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8396 t = (*child_cfun->local_decls)[srcidx];
8397 if (DECL_CONTEXT (t) == cfun->decl)
8398 continue;
8399 if (srcidx != dstidx)
8400 (*child_cfun->local_decls)[dstidx] = t;
8401 dstidx++;
8403 if (dstidx != num)
8404 vec_safe_truncate (child_cfun->local_decls, dstidx);
8406 /* Inform the callgraph about the new function. */
8407 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8408 cgraph_node::add_new_function (child_fn, true);
8410 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8411 fixed in a following pass. */
8412 push_cfun (child_cfun);
8413 cgraph_edge::rebuild_edges ();
8415 /* Some EH regions might become dead, see PR34608. If
8416 pass_cleanup_cfg isn't the first pass to happen with the
8417 new child, these dead EH edges might cause problems.
8418 Clean them up now. */
8419 if (flag_exceptions)
8421 basic_block bb;
8422 bool changed = false;
8424 FOR_EACH_BB_FN (bb, cfun)
8425 changed |= gimple_purge_dead_eh_edges (bb);
8426 if (changed)
8427 cleanup_tree_cfg ();
8429 pop_cfun ();
8432 /* Emit a library call to launch the target region, or do data
8433 transfers. */
8434 tree t1, t2, t3, t4, device, cond, c, clauses;
8435 enum built_in_function start_ix;
8436 location_t clause_loc;
8438 clauses = gimple_omp_target_clauses (entry_stmt);
8440 if (kind == GF_OMP_TARGET_KIND_REGION)
8441 start_ix = BUILT_IN_GOMP_TARGET;
8442 else if (kind == GF_OMP_TARGET_KIND_DATA)
8443 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8444 else
8445 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8447 /* By default, the value of DEVICE is -1 (let runtime library choose)
8448 and there is no conditional. */
8449 cond = NULL_TREE;
8450 device = build_int_cst (integer_type_node, -1);
8452 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8453 if (c)
8454 cond = OMP_CLAUSE_IF_EXPR (c);
8456 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8457 if (c)
8459 device = OMP_CLAUSE_DEVICE_ID (c);
8460 clause_loc = OMP_CLAUSE_LOCATION (c);
8462 else
8463 clause_loc = gimple_location (entry_stmt);
8465 /* Ensure 'device' is of the correct type. */
8466 device = fold_convert_loc (clause_loc, integer_type_node, device);
8468 /* If we found the clause 'if (cond)', build
8469 (cond ? device : -2). */
8470 if (cond)
8472 cond = gimple_boolify (cond);
8474 basic_block cond_bb, then_bb, else_bb;
8475 edge e;
8476 tree tmp_var;
8478 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8479 if (kind != GF_OMP_TARGET_KIND_REGION)
8481 gsi = gsi_last_bb (new_bb);
8482 gsi_prev (&gsi);
8483 e = split_block (new_bb, gsi_stmt (gsi));
8485 else
8486 e = split_block (new_bb, NULL);
8487 cond_bb = e->src;
8488 new_bb = e->dest;
8489 remove_edge (e);
8491 then_bb = create_empty_bb (cond_bb);
8492 else_bb = create_empty_bb (then_bb);
8493 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8494 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8496 stmt = gimple_build_cond_empty (cond);
8497 gsi = gsi_last_bb (cond_bb);
8498 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8500 gsi = gsi_start_bb (then_bb);
8501 stmt = gimple_build_assign (tmp_var, device);
8502 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8504 gsi = gsi_start_bb (else_bb);
8505 stmt = gimple_build_assign (tmp_var,
8506 build_int_cst (integer_type_node, -2));
8507 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8509 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8510 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
8511 add_bb_to_loop (then_bb, cond_bb->loop_father);
8512 add_bb_to_loop (else_bb, cond_bb->loop_father);
8513 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8514 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8516 device = tmp_var;
8519 gsi = gsi_last_bb (new_bb);
8520 t = gimple_omp_target_data_arg (entry_stmt);
8521 if (t == NULL)
8523 t1 = size_zero_node;
8524 t2 = build_zero_cst (ptr_type_node);
8525 t3 = t2;
8526 t4 = t2;
8528 else
8530 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8531 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8532 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8533 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8534 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8537 gimple g;
8538 /* FIXME: This will be address of
8539 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8540 symbol, as soon as the linker plugin is able to create it for us. */
8541 tree openmp_target = build_zero_cst (ptr_type_node);
8542 if (kind == GF_OMP_TARGET_KIND_REGION)
8544 tree fnaddr = build_fold_addr_expr (child_fn);
8545 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8546 device, fnaddr, openmp_target, t1, t2, t3, t4);
8548 else
8549 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8550 device, openmp_target, t1, t2, t3, t4);
8551 gimple_set_location (g, gimple_location (entry_stmt));
8552 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8553 if (kind != GF_OMP_TARGET_KIND_REGION)
8555 g = gsi_stmt (gsi);
8556 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8557 gsi_remove (&gsi, true);
8559 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8561 gsi = gsi_last_bb (region->exit);
8562 g = gsi_stmt (gsi);
8563 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8564 gsi_remove (&gsi, true);
8569 /* Expand the parallel region tree rooted at REGION. Expansion
8570 proceeds in depth-first order. Innermost regions are expanded
8571 first. This way, parallel regions that require a new function to
8572 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8573 internal dependencies in their body. */
8575 static void
8576 expand_omp (struct omp_region *region)
8578 while (region)
8580 location_t saved_location;
8581 gimple inner_stmt = NULL;
8583 /* First, determine whether this is a combined parallel+workshare
8584 region. */
8585 if (region->type == GIMPLE_OMP_PARALLEL)
8586 determine_parallel_type (region);
8588 if (region->type == GIMPLE_OMP_FOR
8589 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8590 inner_stmt = last_stmt (region->inner->entry);
8592 if (region->inner)
8593 expand_omp (region->inner);
8595 saved_location = input_location;
8596 if (gimple_has_location (last_stmt (region->entry)))
8597 input_location = gimple_location (last_stmt (region->entry));
8599 switch (region->type)
8601 case GIMPLE_OMP_PARALLEL:
8602 case GIMPLE_OMP_TASK:
8603 expand_omp_taskreg (region);
8604 break;
8606 case GIMPLE_OMP_FOR:
8607 expand_omp_for (region, inner_stmt);
8608 break;
8610 case GIMPLE_OMP_SECTIONS:
8611 expand_omp_sections (region);
8612 break;
8614 case GIMPLE_OMP_SECTION:
8615 /* Individual omp sections are handled together with their
8616 parent GIMPLE_OMP_SECTIONS region. */
8617 break;
8619 case GIMPLE_OMP_SINGLE:
8620 expand_omp_single (region);
8621 break;
8623 case GIMPLE_OMP_MASTER:
8624 case GIMPLE_OMP_TASKGROUP:
8625 case GIMPLE_OMP_ORDERED:
8626 case GIMPLE_OMP_CRITICAL:
8627 case GIMPLE_OMP_TEAMS:
8628 expand_omp_synch (region);
8629 break;
8631 case GIMPLE_OMP_ATOMIC_LOAD:
8632 expand_omp_atomic (region);
8633 break;
8635 case GIMPLE_OMP_TARGET:
8636 expand_omp_target (region);
8637 break;
8639 default:
8640 gcc_unreachable ();
8643 input_location = saved_location;
8644 region = region->next;
8649 /* Helper for build_omp_regions. Scan the dominator tree starting at
8650 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8651 true, the function ends once a single tree is built (otherwise, whole
8652 forest of OMP constructs may be built). */
8654 static void
8655 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8656 bool single_tree)
8658 gimple_stmt_iterator gsi;
8659 gimple stmt;
8660 basic_block son;
8662 gsi = gsi_last_bb (bb);
8663 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8665 struct omp_region *region;
8666 enum gimple_code code;
8668 stmt = gsi_stmt (gsi);
8669 code = gimple_code (stmt);
8670 if (code == GIMPLE_OMP_RETURN)
8672 /* STMT is the return point out of region PARENT. Mark it
8673 as the exit point and make PARENT the immediately
8674 enclosing region. */
8675 gcc_assert (parent);
8676 region = parent;
8677 region->exit = bb;
8678 parent = parent->outer;
8680 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8682 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8683 GIMPLE_OMP_RETURN, but matches with
8684 GIMPLE_OMP_ATOMIC_LOAD. */
8685 gcc_assert (parent);
8686 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8687 region = parent;
8688 region->exit = bb;
8689 parent = parent->outer;
8692 else if (code == GIMPLE_OMP_CONTINUE)
8694 gcc_assert (parent);
8695 parent->cont = bb;
8697 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8699 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8700 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8703 else if (code == GIMPLE_OMP_TARGET
8704 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8705 new_omp_region (bb, code, parent);
8706 else
8708 /* Otherwise, this directive becomes the parent for a new
8709 region. */
8710 region = new_omp_region (bb, code, parent);
8711 parent = region;
8715 if (single_tree && !parent)
8716 return;
8718 for (son = first_dom_son (CDI_DOMINATORS, bb);
8719 son;
8720 son = next_dom_son (CDI_DOMINATORS, son))
8721 build_omp_regions_1 (son, parent, single_tree);
8724 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8725 root_omp_region. */
8727 static void
8728 build_omp_regions_root (basic_block root)
8730 gcc_assert (root_omp_region == NULL);
8731 build_omp_regions_1 (root, NULL, true);
8732 gcc_assert (root_omp_region != NULL);
8735 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8737 void
8738 omp_expand_local (basic_block head)
8740 build_omp_regions_root (head);
8741 if (dump_file && (dump_flags & TDF_DETAILS))
8743 fprintf (dump_file, "\nOMP region tree\n\n");
8744 dump_omp_region (dump_file, root_omp_region, 0);
8745 fprintf (dump_file, "\n");
8748 remove_exit_barriers (root_omp_region);
8749 expand_omp (root_omp_region);
8751 free_omp_regions ();
8754 /* Scan the CFG and build a tree of OMP regions. Return the root of
8755 the OMP region tree. */
8757 static void
8758 build_omp_regions (void)
8760 gcc_assert (root_omp_region == NULL);
8761 calculate_dominance_info (CDI_DOMINATORS);
8762 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8765 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8767 static unsigned int
8768 execute_expand_omp (void)
8770 build_omp_regions ();
8772 if (!root_omp_region)
8773 return 0;
8775 if (dump_file)
8777 fprintf (dump_file, "\nOMP region tree\n\n");
8778 dump_omp_region (dump_file, root_omp_region, 0);
8779 fprintf (dump_file, "\n");
8782 remove_exit_barriers (root_omp_region);
8784 expand_omp (root_omp_region);
8786 cleanup_tree_cfg ();
8788 free_omp_regions ();
8790 return 0;
8793 /* OMP expansion -- the default pass, run before creation of SSA form. */
8795 namespace {
8797 const pass_data pass_data_expand_omp =
8799 GIMPLE_PASS, /* type */
8800 "ompexp", /* name */
8801 OPTGROUP_NONE, /* optinfo_flags */
8802 TV_NONE, /* tv_id */
8803 PROP_gimple_any, /* properties_required */
8804 0, /* properties_provided */
8805 0, /* properties_destroyed */
8806 0, /* todo_flags_start */
8807 0, /* todo_flags_finish */
8810 class pass_expand_omp : public gimple_opt_pass
8812 public:
8813 pass_expand_omp (gcc::context *ctxt)
8814 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8817 /* opt_pass methods: */
8818 virtual bool gate (function *)
8820 return ((flag_openmp != 0 || flag_openmp_simd != 0
8821 || flag_cilkplus != 0) && !seen_error ());
8824 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8826 }; // class pass_expand_omp
8828 } // anon namespace
8830 gimple_opt_pass *
8831 make_pass_expand_omp (gcc::context *ctxt)
8833 return new pass_expand_omp (ctxt);
8836 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8838 /* If ctx is a worksharing context inside of a cancellable parallel
8839 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8840 and conditional branch to parallel's cancel_label to handle
8841 cancellation in the implicit barrier. */
8843 static void
8844 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8846 gimple omp_return = gimple_seq_last_stmt (*body);
8847 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8848 if (gimple_omp_return_nowait_p (omp_return))
8849 return;
8850 if (ctx->outer
8851 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8852 && ctx->outer->cancellable)
8854 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8855 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8856 tree lhs = create_tmp_var (c_bool_type, NULL);
8857 gimple_omp_return_set_lhs (omp_return, lhs);
8858 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8859 gimple g = gimple_build_cond (NE_EXPR, lhs,
8860 fold_convert (c_bool_type,
8861 boolean_false_node),
8862 ctx->outer->cancel_label, fallthru_label);
8863 gimple_seq_add_stmt (body, g);
8864 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8868 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8869 CTX is the enclosing OMP context for the current statement. */
8871 static void
8872 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8874 tree block, control;
8875 gimple_stmt_iterator tgsi;
8876 gimple stmt, new_stmt, bind, t;
8877 gimple_seq ilist, dlist, olist, new_body;
8879 stmt = gsi_stmt (*gsi_p);
8881 push_gimplify_context ();
8883 dlist = NULL;
8884 ilist = NULL;
8885 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8886 &ilist, &dlist, ctx, NULL);
8888 new_body = gimple_omp_body (stmt);
8889 gimple_omp_set_body (stmt, NULL);
8890 tgsi = gsi_start (new_body);
8891 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8893 omp_context *sctx;
8894 gimple sec_start;
8896 sec_start = gsi_stmt (tgsi);
8897 sctx = maybe_lookup_ctx (sec_start);
8898 gcc_assert (sctx);
8900 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8901 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8902 GSI_CONTINUE_LINKING);
8903 gimple_omp_set_body (sec_start, NULL);
8905 if (gsi_one_before_end_p (tgsi))
8907 gimple_seq l = NULL;
8908 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8909 &l, ctx);
8910 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8911 gimple_omp_section_set_last (sec_start);
8914 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8915 GSI_CONTINUE_LINKING);
8918 block = make_node (BLOCK);
8919 bind = gimple_build_bind (NULL, new_body, block);
8921 olist = NULL;
8922 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8924 block = make_node (BLOCK);
8925 new_stmt = gimple_build_bind (NULL, NULL, block);
8926 gsi_replace (gsi_p, new_stmt, true);
8928 pop_gimplify_context (new_stmt);
8929 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8930 BLOCK_VARS (block) = gimple_bind_vars (bind);
8931 if (BLOCK_VARS (block))
8932 TREE_USED (block) = 1;
8934 new_body = NULL;
8935 gimple_seq_add_seq (&new_body, ilist);
8936 gimple_seq_add_stmt (&new_body, stmt);
8937 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8938 gimple_seq_add_stmt (&new_body, bind);
8940 control = create_tmp_var (unsigned_type_node, ".section");
8941 t = gimple_build_omp_continue (control, control);
8942 gimple_omp_sections_set_control (stmt, control);
8943 gimple_seq_add_stmt (&new_body, t);
8945 gimple_seq_add_seq (&new_body, olist);
8946 if (ctx->cancellable)
8947 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8948 gimple_seq_add_seq (&new_body, dlist);
8950 new_body = maybe_catch_exception (new_body);
8952 t = gimple_build_omp_return
8953 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8954 OMP_CLAUSE_NOWAIT));
8955 gimple_seq_add_stmt (&new_body, t);
8956 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8958 gimple_bind_set_body (new_stmt, new_body);
8962 /* A subroutine of lower_omp_single. Expand the simple form of
8963 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8965 if (GOMP_single_start ())
8966 BODY;
8967 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8969 FIXME. It may be better to delay expanding the logic of this until
8970 pass_expand_omp. The expanded logic may make the job more difficult
8971 to a synchronization analysis pass. */
8973 static void
8974 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8976 location_t loc = gimple_location (single_stmt);
8977 tree tlabel = create_artificial_label (loc);
8978 tree flabel = create_artificial_label (loc);
8979 gimple call, cond;
8980 tree lhs, decl;
8982 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8983 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8984 call = gimple_build_call (decl, 0);
8985 gimple_call_set_lhs (call, lhs);
8986 gimple_seq_add_stmt (pre_p, call);
8988 cond = gimple_build_cond (EQ_EXPR, lhs,
8989 fold_convert_loc (loc, TREE_TYPE (lhs),
8990 boolean_true_node),
8991 tlabel, flabel);
8992 gimple_seq_add_stmt (pre_p, cond);
8993 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8994 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8995 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8999 /* A subroutine of lower_omp_single. Expand the simple form of
9000 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9002 #pragma omp single copyprivate (a, b, c)
9004 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9007 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9009 BODY;
9010 copyout.a = a;
9011 copyout.b = b;
9012 copyout.c = c;
9013 GOMP_single_copy_end (&copyout);
9015 else
9017 a = copyout_p->a;
9018 b = copyout_p->b;
9019 c = copyout_p->c;
9021 GOMP_barrier ();
9024 FIXME. It may be better to delay expanding the logic of this until
9025 pass_expand_omp. The expanded logic may make the job more difficult
9026 to a synchronization analysis pass. */
9028 static void
9029 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9031 tree ptr_type, t, l0, l1, l2, bfn_decl;
9032 gimple_seq copyin_seq;
9033 location_t loc = gimple_location (single_stmt);
9035 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9037 ptr_type = build_pointer_type (ctx->record_type);
9038 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9040 l0 = create_artificial_label (loc);
9041 l1 = create_artificial_label (loc);
9042 l2 = create_artificial_label (loc);
9044 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9045 t = build_call_expr_loc (loc, bfn_decl, 0);
9046 t = fold_convert_loc (loc, ptr_type, t);
9047 gimplify_assign (ctx->receiver_decl, t, pre_p);
9049 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9050 build_int_cst (ptr_type, 0));
9051 t = build3 (COND_EXPR, void_type_node, t,
9052 build_and_jump (&l0), build_and_jump (&l1));
9053 gimplify_and_add (t, pre_p);
9055 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9057 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9059 copyin_seq = NULL;
9060 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9061 &copyin_seq, ctx);
9063 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9064 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9065 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9066 gimplify_and_add (t, pre_p);
9068 t = build_and_jump (&l2);
9069 gimplify_and_add (t, pre_p);
9071 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9073 gimple_seq_add_seq (pre_p, copyin_seq);
9075 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9079 /* Expand code for an OpenMP single directive. */
9081 static void
9082 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9084 tree block;
9085 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9086 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9088 push_gimplify_context ();
9090 block = make_node (BLOCK);
9091 bind = gimple_build_bind (NULL, NULL, block);
9092 gsi_replace (gsi_p, bind, true);
9093 bind_body = NULL;
9094 dlist = NULL;
9095 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9096 &bind_body, &dlist, ctx, NULL);
9097 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9099 gimple_seq_add_stmt (&bind_body, single_stmt);
9101 if (ctx->record_type)
9102 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9103 else
9104 lower_omp_single_simple (single_stmt, &bind_body);
9106 gimple_omp_set_body (single_stmt, NULL);
9108 gimple_seq_add_seq (&bind_body, dlist);
9110 bind_body = maybe_catch_exception (bind_body);
9112 t = gimple_build_omp_return
9113 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9114 OMP_CLAUSE_NOWAIT));
9115 gimple_seq_add_stmt (&bind_body_tail, t);
9116 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9117 if (ctx->record_type)
9119 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9120 tree clobber = build_constructor (ctx->record_type, NULL);
9121 TREE_THIS_VOLATILE (clobber) = 1;
9122 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9123 clobber), GSI_SAME_STMT);
9125 gimple_seq_add_seq (&bind_body, bind_body_tail);
9126 gimple_bind_set_body (bind, bind_body);
9128 pop_gimplify_context (bind);
9130 gimple_bind_append_vars (bind, ctx->block_vars);
9131 BLOCK_VARS (block) = ctx->block_vars;
9132 if (BLOCK_VARS (block))
9133 TREE_USED (block) = 1;
9137 /* Expand code for an OpenMP master directive. */
9139 static void
9140 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9142 tree block, lab = NULL, x, bfn_decl;
9143 gimple stmt = gsi_stmt (*gsi_p), bind;
9144 location_t loc = gimple_location (stmt);
9145 gimple_seq tseq;
9147 push_gimplify_context ();
9149 block = make_node (BLOCK);
9150 bind = gimple_build_bind (NULL, NULL, block);
9151 gsi_replace (gsi_p, bind, true);
9152 gimple_bind_add_stmt (bind, stmt);
9154 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9155 x = build_call_expr_loc (loc, bfn_decl, 0);
9156 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9157 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9158 tseq = NULL;
9159 gimplify_and_add (x, &tseq);
9160 gimple_bind_add_seq (bind, tseq);
9162 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9163 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9164 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9165 gimple_omp_set_body (stmt, NULL);
9167 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9169 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9171 pop_gimplify_context (bind);
9173 gimple_bind_append_vars (bind, ctx->block_vars);
9174 BLOCK_VARS (block) = ctx->block_vars;
9178 /* Expand code for an OpenMP taskgroup directive. */
9180 static void
9181 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9183 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9184 tree block = make_node (BLOCK);
9186 bind = gimple_build_bind (NULL, NULL, block);
9187 gsi_replace (gsi_p, bind, true);
9188 gimple_bind_add_stmt (bind, stmt);
9190 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9192 gimple_bind_add_stmt (bind, x);
9194 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9195 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9196 gimple_omp_set_body (stmt, NULL);
9198 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9200 gimple_bind_append_vars (bind, ctx->block_vars);
9201 BLOCK_VARS (block) = ctx->block_vars;
9205 /* Expand code for an OpenMP ordered directive. */
9207 static void
9208 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9210 tree block;
9211 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9213 push_gimplify_context ();
9215 block = make_node (BLOCK);
9216 bind = gimple_build_bind (NULL, NULL, block);
9217 gsi_replace (gsi_p, bind, true);
9218 gimple_bind_add_stmt (bind, stmt);
9220 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9222 gimple_bind_add_stmt (bind, x);
9224 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9225 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9226 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9227 gimple_omp_set_body (stmt, NULL);
9229 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9230 gimple_bind_add_stmt (bind, x);
9232 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9234 pop_gimplify_context (bind);
9236 gimple_bind_append_vars (bind, ctx->block_vars);
9237 BLOCK_VARS (block) = gimple_bind_vars (bind);
9241 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9242 substitution of a couple of function calls. But in the NAMED case,
9243 requires that languages coordinate a symbol name. It is therefore
9244 best put here in common code. */
9246 static GTY((param1_is (tree), param2_is (tree)))
9247 splay_tree critical_name_mutexes;
9249 static void
9250 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9252 tree block;
9253 tree name, lock, unlock;
9254 gimple stmt = gsi_stmt (*gsi_p), bind;
9255 location_t loc = gimple_location (stmt);
9256 gimple_seq tbody;
9258 name = gimple_omp_critical_name (stmt);
9259 if (name)
9261 tree decl;
9262 splay_tree_node n;
9264 if (!critical_name_mutexes)
9265 critical_name_mutexes
9266 = splay_tree_new_ggc (splay_tree_compare_pointers,
9267 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9268 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9270 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9271 if (n == NULL)
9273 char *new_str;
9275 decl = create_tmp_var_raw (ptr_type_node, NULL);
9277 new_str = ACONCAT ((".gomp_critical_user_",
9278 IDENTIFIER_POINTER (name), NULL));
9279 DECL_NAME (decl) = get_identifier (new_str);
9280 TREE_PUBLIC (decl) = 1;
9281 TREE_STATIC (decl) = 1;
9282 DECL_COMMON (decl) = 1;
9283 DECL_ARTIFICIAL (decl) = 1;
9284 DECL_IGNORED_P (decl) = 1;
9285 varpool_node::finalize_decl (decl);
9287 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9288 (splay_tree_value) decl);
9290 else
9291 decl = (tree) n->value;
9293 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9294 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9296 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9297 unlock = build_call_expr_loc (loc, unlock, 1,
9298 build_fold_addr_expr_loc (loc, decl));
9300 else
9302 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9303 lock = build_call_expr_loc (loc, lock, 0);
9305 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9306 unlock = build_call_expr_loc (loc, unlock, 0);
9309 push_gimplify_context ();
9311 block = make_node (BLOCK);
9312 bind = gimple_build_bind (NULL, NULL, block);
9313 gsi_replace (gsi_p, bind, true);
9314 gimple_bind_add_stmt (bind, stmt);
9316 tbody = gimple_bind_body (bind);
9317 gimplify_and_add (lock, &tbody);
9318 gimple_bind_set_body (bind, tbody);
9320 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9321 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9322 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9323 gimple_omp_set_body (stmt, NULL);
9325 tbody = gimple_bind_body (bind);
9326 gimplify_and_add (unlock, &tbody);
9327 gimple_bind_set_body (bind, tbody);
9329 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9331 pop_gimplify_context (bind);
9332 gimple_bind_append_vars (bind, ctx->block_vars);
9333 BLOCK_VARS (block) = gimple_bind_vars (bind);
9337 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9338 for a lastprivate clause. Given a loop control predicate of (V
9339 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9340 is appended to *DLIST, iterator initialization is appended to
9341 *BODY_P. */
9343 static void
9344 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9345 gimple_seq *dlist, struct omp_context *ctx)
9347 tree clauses, cond, vinit;
9348 enum tree_code cond_code;
9349 gimple_seq stmts;
9351 cond_code = fd->loop.cond_code;
9352 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9354 /* When possible, use a strict equality expression. This can let VRP
9355 type optimizations deduce the value and remove a copy. */
9356 if (tree_fits_shwi_p (fd->loop.step))
9358 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9359 if (step == 1 || step == -1)
9360 cond_code = EQ_EXPR;
9363 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9365 clauses = gimple_omp_for_clauses (fd->for_stmt);
9366 stmts = NULL;
9367 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9368 if (!gimple_seq_empty_p (stmts))
9370 gimple_seq_add_seq (&stmts, *dlist);
9371 *dlist = stmts;
9373 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9374 vinit = fd->loop.n1;
9375 if (cond_code == EQ_EXPR
9376 && tree_fits_shwi_p (fd->loop.n2)
9377 && ! integer_zerop (fd->loop.n2))
9378 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9379 else
9380 vinit = unshare_expr (vinit);
9382 /* Initialize the iterator variable, so that threads that don't execute
9383 any iterations don't execute the lastprivate clauses by accident. */
9384 gimplify_assign (fd->loop.v, vinit, body_p);
9389 /* Lower code for an OpenMP loop directive. */
9391 static void
9392 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9394 tree *rhs_p, block;
9395 struct omp_for_data fd, *fdp = NULL;
9396 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9397 gimple_seq omp_for_body, body, dlist;
9398 size_t i;
9400 push_gimplify_context ();
9402 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9404 block = make_node (BLOCK);
9405 new_stmt = gimple_build_bind (NULL, NULL, block);
9406 /* Replace at gsi right away, so that 'stmt' is no member
9407 of a sequence anymore as we're going to add to to a different
9408 one below. */
9409 gsi_replace (gsi_p, new_stmt, true);
9411 /* Move declaration of temporaries in the loop body before we make
9412 it go away. */
9413 omp_for_body = gimple_omp_body (stmt);
9414 if (!gimple_seq_empty_p (omp_for_body)
9415 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9417 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9418 tree vars = gimple_bind_vars (inner_bind);
9419 gimple_bind_append_vars (new_stmt, vars);
9420 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9421 keep them on the inner_bind and it's block. */
9422 gimple_bind_set_vars (inner_bind, NULL_TREE);
9423 if (gimple_bind_block (inner_bind))
9424 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9427 if (gimple_omp_for_combined_into_p (stmt))
9429 extract_omp_for_data (stmt, &fd, NULL);
9430 fdp = &fd;
9432 /* We need two temporaries with fd.loop.v type (istart/iend)
9433 and then (fd.collapse - 1) temporaries with the same
9434 type for count2 ... countN-1 vars if not constant. */
9435 size_t count = 2;
9436 tree type = fd.iter_type;
9437 if (fd.collapse > 1
9438 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9439 count += fd.collapse - 1;
9440 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9441 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9442 tree clauses = *pc;
9443 if (parallel_for)
9444 outerc
9445 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9446 OMP_CLAUSE__LOOPTEMP_);
9447 for (i = 0; i < count; i++)
9449 tree temp;
9450 if (parallel_for)
9452 gcc_assert (outerc);
9453 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9454 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9455 OMP_CLAUSE__LOOPTEMP_);
9457 else
9459 temp = create_tmp_var (type, NULL);
9460 insert_decl_map (&ctx->outer->cb, temp, temp);
9462 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9463 OMP_CLAUSE_DECL (*pc) = temp;
9464 pc = &OMP_CLAUSE_CHAIN (*pc);
9466 *pc = clauses;
9469 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9470 dlist = NULL;
9471 body = NULL;
9472 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9473 fdp);
9474 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9476 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9478 /* Lower the header expressions. At this point, we can assume that
9479 the header is of the form:
9481 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9483 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9484 using the .omp_data_s mapping, if needed. */
9485 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9487 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9488 if (!is_gimple_min_invariant (*rhs_p))
9489 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9491 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9492 if (!is_gimple_min_invariant (*rhs_p))
9493 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9495 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9496 if (!is_gimple_min_invariant (*rhs_p))
9497 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9500 /* Once lowered, extract the bounds and clauses. */
9501 extract_omp_for_data (stmt, &fd, NULL);
9503 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9505 gimple_seq_add_stmt (&body, stmt);
9506 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9508 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9509 fd.loop.v));
9511 /* After the loop, add exit clauses. */
9512 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9514 if (ctx->cancellable)
9515 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9517 gimple_seq_add_seq (&body, dlist);
9519 body = maybe_catch_exception (body);
9521 /* Region exit marker goes at the end of the loop body. */
9522 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9523 maybe_add_implicit_barrier_cancel (ctx, &body);
9524 pop_gimplify_context (new_stmt);
9526 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9527 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9528 if (BLOCK_VARS (block))
9529 TREE_USED (block) = 1;
9531 gimple_bind_set_body (new_stmt, body);
9532 gimple_omp_set_body (stmt, NULL);
9533 gimple_omp_for_set_pre_body (stmt, NULL);
9536 /* Callback for walk_stmts. Check if the current statement only contains
9537 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9539 static tree
9540 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9541 bool *handled_ops_p,
9542 struct walk_stmt_info *wi)
9544 int *info = (int *) wi->info;
9545 gimple stmt = gsi_stmt (*gsi_p);
9547 *handled_ops_p = true;
9548 switch (gimple_code (stmt))
9550 WALK_SUBSTMTS;
9552 case GIMPLE_OMP_FOR:
9553 case GIMPLE_OMP_SECTIONS:
9554 *info = *info == 0 ? 1 : -1;
9555 break;
9556 default:
9557 *info = -1;
9558 break;
9560 return NULL;
9563 struct omp_taskcopy_context
9565 /* This field must be at the beginning, as we do "inheritance": Some
9566 callback functions for tree-inline.c (e.g., omp_copy_decl)
9567 receive a copy_body_data pointer that is up-casted to an
9568 omp_context pointer. */
9569 copy_body_data cb;
9570 omp_context *ctx;
9573 static tree
9574 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9576 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9578 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9579 return create_tmp_var (TREE_TYPE (var), NULL);
9581 return var;
9584 static tree
9585 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9587 tree name, new_fields = NULL, type, f;
9589 type = lang_hooks.types.make_type (RECORD_TYPE);
9590 name = DECL_NAME (TYPE_NAME (orig_type));
9591 name = build_decl (gimple_location (tcctx->ctx->stmt),
9592 TYPE_DECL, name, type);
9593 TYPE_NAME (type) = name;
9595 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9597 tree new_f = copy_node (f);
9598 DECL_CONTEXT (new_f) = type;
9599 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9600 TREE_CHAIN (new_f) = new_fields;
9601 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9602 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9603 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9604 &tcctx->cb, NULL);
9605 new_fields = new_f;
9606 tcctx->cb.decl_map->put (f, new_f);
9608 TYPE_FIELDS (type) = nreverse (new_fields);
9609 layout_type (type);
9610 return type;
9613 /* Create task copyfn. */
9615 static void
9616 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9618 struct function *child_cfun;
9619 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9620 tree record_type, srecord_type, bind, list;
9621 bool record_needs_remap = false, srecord_needs_remap = false;
9622 splay_tree_node n;
9623 struct omp_taskcopy_context tcctx;
9624 location_t loc = gimple_location (task_stmt);
9626 child_fn = gimple_omp_task_copy_fn (task_stmt);
9627 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9628 gcc_assert (child_cfun->cfg == NULL);
9629 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9631 /* Reset DECL_CONTEXT on function arguments. */
9632 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9633 DECL_CONTEXT (t) = child_fn;
9635 /* Populate the function. */
9636 push_gimplify_context ();
9637 push_cfun (child_cfun);
9639 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9640 TREE_SIDE_EFFECTS (bind) = 1;
9641 list = NULL;
9642 DECL_SAVED_TREE (child_fn) = bind;
9643 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9645 /* Remap src and dst argument types if needed. */
9646 record_type = ctx->record_type;
9647 srecord_type = ctx->srecord_type;
9648 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9649 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9651 record_needs_remap = true;
9652 break;
9654 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9655 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9657 srecord_needs_remap = true;
9658 break;
9661 if (record_needs_remap || srecord_needs_remap)
9663 memset (&tcctx, '\0', sizeof (tcctx));
9664 tcctx.cb.src_fn = ctx->cb.src_fn;
9665 tcctx.cb.dst_fn = child_fn;
9666 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9667 gcc_checking_assert (tcctx.cb.src_node);
9668 tcctx.cb.dst_node = tcctx.cb.src_node;
9669 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9670 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9671 tcctx.cb.eh_lp_nr = 0;
9672 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9673 tcctx.cb.decl_map = new hash_map<tree, tree>;
9674 tcctx.ctx = ctx;
9676 if (record_needs_remap)
9677 record_type = task_copyfn_remap_type (&tcctx, record_type);
9678 if (srecord_needs_remap)
9679 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9681 else
9682 tcctx.cb.decl_map = NULL;
9684 arg = DECL_ARGUMENTS (child_fn);
9685 TREE_TYPE (arg) = build_pointer_type (record_type);
9686 sarg = DECL_CHAIN (arg);
9687 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9689 /* First pass: initialize temporaries used in record_type and srecord_type
9690 sizes and field offsets. */
9691 if (tcctx.cb.decl_map)
9692 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9693 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9695 tree *p;
9697 decl = OMP_CLAUSE_DECL (c);
9698 p = tcctx.cb.decl_map->get (decl);
9699 if (p == NULL)
9700 continue;
9701 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9702 sf = (tree) n->value;
9703 sf = *tcctx.cb.decl_map->get (sf);
9704 src = build_simple_mem_ref_loc (loc, sarg);
9705 src = omp_build_component_ref (src, sf);
9706 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9707 append_to_statement_list (t, &list);
9710 /* Second pass: copy shared var pointers and copy construct non-VLA
9711 firstprivate vars. */
9712 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9713 switch (OMP_CLAUSE_CODE (c))
9715 case OMP_CLAUSE_SHARED:
9716 decl = OMP_CLAUSE_DECL (c);
9717 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9718 if (n == NULL)
9719 break;
9720 f = (tree) n->value;
9721 if (tcctx.cb.decl_map)
9722 f = *tcctx.cb.decl_map->get (f);
9723 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9724 sf = (tree) n->value;
9725 if (tcctx.cb.decl_map)
9726 sf = *tcctx.cb.decl_map->get (sf);
9727 src = build_simple_mem_ref_loc (loc, sarg);
9728 src = omp_build_component_ref (src, sf);
9729 dst = build_simple_mem_ref_loc (loc, arg);
9730 dst = omp_build_component_ref (dst, f);
9731 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9732 append_to_statement_list (t, &list);
9733 break;
9734 case OMP_CLAUSE_FIRSTPRIVATE:
9735 decl = OMP_CLAUSE_DECL (c);
9736 if (is_variable_sized (decl))
9737 break;
9738 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9739 if (n == NULL)
9740 break;
9741 f = (tree) n->value;
9742 if (tcctx.cb.decl_map)
9743 f = *tcctx.cb.decl_map->get (f);
9744 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9745 if (n != NULL)
9747 sf = (tree) n->value;
9748 if (tcctx.cb.decl_map)
9749 sf = *tcctx.cb.decl_map->get (sf);
9750 src = build_simple_mem_ref_loc (loc, sarg);
9751 src = omp_build_component_ref (src, sf);
9752 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9753 src = build_simple_mem_ref_loc (loc, src);
9755 else
9756 src = decl;
9757 dst = build_simple_mem_ref_loc (loc, arg);
9758 dst = omp_build_component_ref (dst, f);
9759 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9760 append_to_statement_list (t, &list);
9761 break;
9762 case OMP_CLAUSE_PRIVATE:
9763 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9764 break;
9765 decl = OMP_CLAUSE_DECL (c);
9766 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9767 f = (tree) n->value;
9768 if (tcctx.cb.decl_map)
9769 f = *tcctx.cb.decl_map->get (f);
9770 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9771 if (n != NULL)
9773 sf = (tree) n->value;
9774 if (tcctx.cb.decl_map)
9775 sf = *tcctx.cb.decl_map->get (sf);
9776 src = build_simple_mem_ref_loc (loc, sarg);
9777 src = omp_build_component_ref (src, sf);
9778 if (use_pointer_for_field (decl, NULL))
9779 src = build_simple_mem_ref_loc (loc, src);
9781 else
9782 src = decl;
9783 dst = build_simple_mem_ref_loc (loc, arg);
9784 dst = omp_build_component_ref (dst, f);
9785 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9786 append_to_statement_list (t, &list);
9787 break;
9788 default:
9789 break;
9792 /* Last pass: handle VLA firstprivates. */
9793 if (tcctx.cb.decl_map)
9794 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9795 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9797 tree ind, ptr, df;
9799 decl = OMP_CLAUSE_DECL (c);
9800 if (!is_variable_sized (decl))
9801 continue;
9802 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9803 if (n == NULL)
9804 continue;
9805 f = (tree) n->value;
9806 f = *tcctx.cb.decl_map->get (f);
9807 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9808 ind = DECL_VALUE_EXPR (decl);
9809 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9810 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9811 n = splay_tree_lookup (ctx->sfield_map,
9812 (splay_tree_key) TREE_OPERAND (ind, 0));
9813 sf = (tree) n->value;
9814 sf = *tcctx.cb.decl_map->get (sf);
9815 src = build_simple_mem_ref_loc (loc, sarg);
9816 src = omp_build_component_ref (src, sf);
9817 src = build_simple_mem_ref_loc (loc, src);
9818 dst = build_simple_mem_ref_loc (loc, arg);
9819 dst = omp_build_component_ref (dst, f);
9820 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9821 append_to_statement_list (t, &list);
9822 n = splay_tree_lookup (ctx->field_map,
9823 (splay_tree_key) TREE_OPERAND (ind, 0));
9824 df = (tree) n->value;
9825 df = *tcctx.cb.decl_map->get (df);
9826 ptr = build_simple_mem_ref_loc (loc, arg);
9827 ptr = omp_build_component_ref (ptr, df);
9828 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9829 build_fold_addr_expr_loc (loc, dst));
9830 append_to_statement_list (t, &list);
9833 t = build1 (RETURN_EXPR, void_type_node, NULL);
9834 append_to_statement_list (t, &list);
9836 if (tcctx.cb.decl_map)
9837 delete tcctx.cb.decl_map;
9838 pop_gimplify_context (NULL);
9839 BIND_EXPR_BODY (bind) = list;
9840 pop_cfun ();
9843 static void
9844 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9846 tree c, clauses;
9847 gimple g;
9848 size_t n_in = 0, n_out = 0, idx = 2, i;
9850 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9851 OMP_CLAUSE_DEPEND);
9852 gcc_assert (clauses);
9853 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9854 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9855 switch (OMP_CLAUSE_DEPEND_KIND (c))
9857 case OMP_CLAUSE_DEPEND_IN:
9858 n_in++;
9859 break;
9860 case OMP_CLAUSE_DEPEND_OUT:
9861 case OMP_CLAUSE_DEPEND_INOUT:
9862 n_out++;
9863 break;
9864 default:
9865 gcc_unreachable ();
9867 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9868 tree array = create_tmp_var (type, NULL);
9869 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9870 NULL_TREE);
9871 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9872 gimple_seq_add_stmt (iseq, g);
9873 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9874 NULL_TREE);
9875 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9876 gimple_seq_add_stmt (iseq, g);
9877 for (i = 0; i < 2; i++)
9879 if ((i ? n_in : n_out) == 0)
9880 continue;
9881 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9882 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9883 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9885 tree t = OMP_CLAUSE_DECL (c);
9886 t = fold_convert (ptr_type_node, t);
9887 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9888 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9889 NULL_TREE, NULL_TREE);
9890 g = gimple_build_assign (r, t);
9891 gimple_seq_add_stmt (iseq, g);
9894 tree *p = gimple_omp_task_clauses_ptr (stmt);
9895 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9896 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9897 OMP_CLAUSE_CHAIN (c) = *p;
9898 *p = c;
9899 tree clobber = build_constructor (type, NULL);
9900 TREE_THIS_VOLATILE (clobber) = 1;
9901 g = gimple_build_assign (array, clobber);
9902 gimple_seq_add_stmt (oseq, g);
9905 /* Lower the OpenMP parallel or task directive in the current statement
9906 in GSI_P. CTX holds context information for the directive. */
9908 static void
9909 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9911 tree clauses;
9912 tree child_fn, t;
9913 gimple stmt = gsi_stmt (*gsi_p);
9914 gimple par_bind, bind, dep_bind = NULL;
9915 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9916 location_t loc = gimple_location (stmt);
9918 clauses = gimple_omp_taskreg_clauses (stmt);
9919 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9920 par_body = gimple_bind_body (par_bind);
9921 child_fn = ctx->cb.dst_fn;
9922 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9923 && !gimple_omp_parallel_combined_p (stmt))
9925 struct walk_stmt_info wi;
9926 int ws_num = 0;
9928 memset (&wi, 0, sizeof (wi));
9929 wi.info = &ws_num;
9930 wi.val_only = true;
9931 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9932 if (ws_num == 1)
9933 gimple_omp_parallel_set_combined_p (stmt, true);
9935 gimple_seq dep_ilist = NULL;
9936 gimple_seq dep_olist = NULL;
9937 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9938 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9940 push_gimplify_context ();
9941 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9942 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9945 if (ctx->srecord_type)
9946 create_task_copyfn (stmt, ctx);
9948 push_gimplify_context ();
9950 par_olist = NULL;
9951 par_ilist = NULL;
9952 par_rlist = NULL;
9953 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9954 lower_omp (&par_body, ctx);
9955 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9956 lower_reduction_clauses (clauses, &par_rlist, ctx);
9958 /* Declare all the variables created by mapping and the variables
9959 declared in the scope of the parallel body. */
9960 record_vars_into (ctx->block_vars, child_fn);
9961 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9963 if (ctx->record_type)
9965 ctx->sender_decl
9966 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9967 : ctx->record_type, ".omp_data_o");
9968 DECL_NAMELESS (ctx->sender_decl) = 1;
9969 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9970 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9973 olist = NULL;
9974 ilist = NULL;
9975 lower_send_clauses (clauses, &ilist, &olist, ctx);
9976 lower_send_shared_vars (&ilist, &olist, ctx);
9978 if (ctx->record_type)
9980 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9981 TREE_THIS_VOLATILE (clobber) = 1;
9982 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9983 clobber));
9986 /* Once all the expansions are done, sequence all the different
9987 fragments inside gimple_omp_body. */
9989 new_body = NULL;
9991 if (ctx->record_type)
9993 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9994 /* fixup_child_record_type might have changed receiver_decl's type. */
9995 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9996 gimple_seq_add_stmt (&new_body,
9997 gimple_build_assign (ctx->receiver_decl, t));
10000 gimple_seq_add_seq (&new_body, par_ilist);
10001 gimple_seq_add_seq (&new_body, par_body);
10002 gimple_seq_add_seq (&new_body, par_rlist);
10003 if (ctx->cancellable)
10004 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10005 gimple_seq_add_seq (&new_body, par_olist);
10006 new_body = maybe_catch_exception (new_body);
10007 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10008 gimple_omp_set_body (stmt, new_body);
10010 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10011 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10012 gimple_bind_add_seq (bind, ilist);
10013 gimple_bind_add_stmt (bind, stmt);
10014 gimple_bind_add_seq (bind, olist);
10016 pop_gimplify_context (NULL);
10018 if (dep_bind)
10020 gimple_bind_add_seq (dep_bind, dep_ilist);
10021 gimple_bind_add_stmt (dep_bind, bind);
10022 gimple_bind_add_seq (dep_bind, dep_olist);
10023 pop_gimplify_context (dep_bind);
10027 /* Lower the OpenMP target directive in the current statement
10028 in GSI_P. CTX holds context information for the directive. */
10030 static void
10031 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10033 tree clauses;
10034 tree child_fn, t, c;
10035 gimple stmt = gsi_stmt (*gsi_p);
10036 gimple tgt_bind = NULL, bind;
10037 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10038 location_t loc = gimple_location (stmt);
10039 int kind = gimple_omp_target_kind (stmt);
10040 unsigned int map_cnt = 0;
10042 clauses = gimple_omp_target_clauses (stmt);
10043 if (kind == GF_OMP_TARGET_KIND_REGION)
10045 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10046 tgt_body = gimple_bind_body (tgt_bind);
10048 else if (kind == GF_OMP_TARGET_KIND_DATA)
10049 tgt_body = gimple_omp_body (stmt);
10050 child_fn = ctx->cb.dst_fn;
10052 push_gimplify_context ();
10054 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10055 switch (OMP_CLAUSE_CODE (c))
10057 tree var, x;
10059 default:
10060 break;
10061 case OMP_CLAUSE_MAP:
10062 case OMP_CLAUSE_TO:
10063 case OMP_CLAUSE_FROM:
10064 var = OMP_CLAUSE_DECL (c);
10065 if (!DECL_P (var))
10067 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10068 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10069 map_cnt++;
10070 continue;
10073 if (DECL_SIZE (var)
10074 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10076 tree var2 = DECL_VALUE_EXPR (var);
10077 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10078 var2 = TREE_OPERAND (var2, 0);
10079 gcc_assert (DECL_P (var2));
10080 var = var2;
10083 if (!maybe_lookup_field (var, ctx))
10084 continue;
10086 if (kind == GF_OMP_TARGET_KIND_REGION)
10088 x = build_receiver_ref (var, true, ctx);
10089 tree new_var = lookup_decl (var, ctx);
10090 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10091 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10092 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10093 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10094 x = build_simple_mem_ref (x);
10095 SET_DECL_VALUE_EXPR (new_var, x);
10096 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10098 map_cnt++;
10101 if (kind == GF_OMP_TARGET_KIND_REGION)
10103 target_nesting_level++;
10104 lower_omp (&tgt_body, ctx);
10105 target_nesting_level--;
10107 else if (kind == GF_OMP_TARGET_KIND_DATA)
10108 lower_omp (&tgt_body, ctx);
10110 if (kind == GF_OMP_TARGET_KIND_REGION)
10112 /* Declare all the variables created by mapping and the variables
10113 declared in the scope of the target body. */
10114 record_vars_into (ctx->block_vars, child_fn);
10115 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10118 olist = NULL;
10119 ilist = NULL;
10120 if (ctx->record_type)
10122 ctx->sender_decl
10123 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10124 DECL_NAMELESS (ctx->sender_decl) = 1;
10125 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10126 t = make_tree_vec (3);
10127 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10128 TREE_VEC_ELT (t, 1)
10129 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10130 ".omp_data_sizes");
10131 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10132 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10133 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10134 TREE_VEC_ELT (t, 2)
10135 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10136 map_cnt),
10137 ".omp_data_kinds");
10138 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10139 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10140 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10141 gimple_omp_target_set_data_arg (stmt, t);
10143 vec<constructor_elt, va_gc> *vsize;
10144 vec<constructor_elt, va_gc> *vkind;
10145 vec_alloc (vsize, map_cnt);
10146 vec_alloc (vkind, map_cnt);
10147 unsigned int map_idx = 0;
10149 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10150 switch (OMP_CLAUSE_CODE (c))
10152 tree ovar, nc;
10154 default:
10155 break;
10156 case OMP_CLAUSE_MAP:
10157 case OMP_CLAUSE_TO:
10158 case OMP_CLAUSE_FROM:
10159 nc = c;
10160 ovar = OMP_CLAUSE_DECL (c);
10161 if (!DECL_P (ovar))
10163 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10164 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10166 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10167 == get_base_address (ovar));
10168 nc = OMP_CLAUSE_CHAIN (c);
10169 ovar = OMP_CLAUSE_DECL (nc);
10171 else
10173 tree x = build_sender_ref (ovar, ctx);
10174 tree v
10175 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10176 gimplify_assign (x, v, &ilist);
10177 nc = NULL_TREE;
10180 else
10182 if (DECL_SIZE (ovar)
10183 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10185 tree ovar2 = DECL_VALUE_EXPR (ovar);
10186 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10187 ovar2 = TREE_OPERAND (ovar2, 0);
10188 gcc_assert (DECL_P (ovar2));
10189 ovar = ovar2;
10191 if (!maybe_lookup_field (ovar, ctx))
10192 continue;
10195 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10196 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10197 talign = DECL_ALIGN_UNIT (ovar);
10198 if (nc)
10200 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10201 tree x = build_sender_ref (ovar, ctx);
10202 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10203 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10204 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10205 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10207 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10208 tree avar
10209 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10210 mark_addressable (avar);
10211 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10212 talign = DECL_ALIGN_UNIT (avar);
10213 avar = build_fold_addr_expr (avar);
10214 gimplify_assign (x, avar, &ilist);
10216 else if (is_gimple_reg (var))
10218 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10219 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10220 mark_addressable (avar);
10221 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10222 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10223 gimplify_assign (avar, var, &ilist);
10224 avar = build_fold_addr_expr (avar);
10225 gimplify_assign (x, avar, &ilist);
10226 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10227 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10228 && !TYPE_READONLY (TREE_TYPE (var)))
10230 x = build_sender_ref (ovar, ctx);
10231 x = build_simple_mem_ref (x);
10232 gimplify_assign (var, x, &olist);
10235 else
10237 var = build_fold_addr_expr (var);
10238 gimplify_assign (x, var, &ilist);
10241 tree s = OMP_CLAUSE_SIZE (c);
10242 if (s == NULL_TREE)
10243 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10244 s = fold_convert (size_type_node, s);
10245 tree purpose = size_int (map_idx++);
10246 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10247 if (TREE_CODE (s) != INTEGER_CST)
10248 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10250 unsigned char tkind = 0;
10251 switch (OMP_CLAUSE_CODE (c))
10253 case OMP_CLAUSE_MAP:
10254 tkind = OMP_CLAUSE_MAP_KIND (c);
10255 break;
10256 case OMP_CLAUSE_TO:
10257 tkind = OMP_CLAUSE_MAP_TO;
10258 break;
10259 case OMP_CLAUSE_FROM:
10260 tkind = OMP_CLAUSE_MAP_FROM;
10261 break;
10262 default:
10263 gcc_unreachable ();
10265 talign = ceil_log2 (talign);
10266 tkind |= talign << 3;
10267 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10268 build_int_cst (unsigned_char_type_node,
10269 tkind));
10270 if (nc && nc != c)
10271 c = nc;
10274 gcc_assert (map_idx == map_cnt);
10276 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10277 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10278 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10279 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10280 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10282 gimple_seq initlist = NULL;
10283 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10284 TREE_VEC_ELT (t, 1)),
10285 &initlist, true, NULL_TREE);
10286 gimple_seq_add_seq (&ilist, initlist);
10288 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10289 NULL);
10290 TREE_THIS_VOLATILE (clobber) = 1;
10291 gimple_seq_add_stmt (&olist,
10292 gimple_build_assign (TREE_VEC_ELT (t, 1),
10293 clobber));
10296 tree clobber = build_constructor (ctx->record_type, NULL);
10297 TREE_THIS_VOLATILE (clobber) = 1;
10298 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10299 clobber));
10302 /* Once all the expansions are done, sequence all the different
10303 fragments inside gimple_omp_body. */
10305 new_body = NULL;
10307 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10309 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10310 /* fixup_child_record_type might have changed receiver_decl's type. */
10311 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10312 gimple_seq_add_stmt (&new_body,
10313 gimple_build_assign (ctx->receiver_decl, t));
10316 if (kind == GF_OMP_TARGET_KIND_REGION)
10318 gimple_seq_add_seq (&new_body, tgt_body);
10319 new_body = maybe_catch_exception (new_body);
10321 else if (kind == GF_OMP_TARGET_KIND_DATA)
10322 new_body = tgt_body;
10323 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10325 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10326 gimple_omp_set_body (stmt, new_body);
10329 bind = gimple_build_bind (NULL, NULL,
10330 tgt_bind ? gimple_bind_block (tgt_bind)
10331 : NULL_TREE);
10332 gsi_replace (gsi_p, bind, true);
10333 gimple_bind_add_seq (bind, ilist);
10334 gimple_bind_add_stmt (bind, stmt);
10335 gimple_bind_add_seq (bind, olist);
10337 pop_gimplify_context (NULL);
10340 /* Expand code for an OpenMP teams directive. */
10342 static void
10343 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10345 gimple teams_stmt = gsi_stmt (*gsi_p);
10346 push_gimplify_context ();
10348 tree block = make_node (BLOCK);
10349 gimple bind = gimple_build_bind (NULL, NULL, block);
10350 gsi_replace (gsi_p, bind, true);
10351 gimple_seq bind_body = NULL;
10352 gimple_seq dlist = NULL;
10353 gimple_seq olist = NULL;
10355 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10356 OMP_CLAUSE_NUM_TEAMS);
10357 if (num_teams == NULL_TREE)
10358 num_teams = build_int_cst (unsigned_type_node, 0);
10359 else
10361 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10362 num_teams = fold_convert (unsigned_type_node, num_teams);
10363 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10365 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10366 OMP_CLAUSE_THREAD_LIMIT);
10367 if (thread_limit == NULL_TREE)
10368 thread_limit = build_int_cst (unsigned_type_node, 0);
10369 else
10371 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10372 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10373 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10374 fb_rvalue);
10377 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10378 &bind_body, &dlist, ctx, NULL);
10379 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10380 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10381 gimple_seq_add_stmt (&bind_body, teams_stmt);
10383 location_t loc = gimple_location (teams_stmt);
10384 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10385 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10386 gimple_set_location (call, loc);
10387 gimple_seq_add_stmt (&bind_body, call);
10389 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10390 gimple_omp_set_body (teams_stmt, NULL);
10391 gimple_seq_add_seq (&bind_body, olist);
10392 gimple_seq_add_seq (&bind_body, dlist);
10393 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10394 gimple_bind_set_body (bind, bind_body);
10396 pop_gimplify_context (bind);
10398 gimple_bind_append_vars (bind, ctx->block_vars);
10399 BLOCK_VARS (block) = ctx->block_vars;
10400 if (BLOCK_VARS (block))
10401 TREE_USED (block) = 1;
10405 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10406 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10407 of OpenMP context, but with task_shared_vars set. */
10409 static tree
10410 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10411 void *data)
10413 tree t = *tp;
10415 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10416 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10417 return t;
10419 if (task_shared_vars
10420 && DECL_P (t)
10421 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10422 return t;
10424 /* If a global variable has been privatized, TREE_CONSTANT on
10425 ADDR_EXPR might be wrong. */
10426 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10427 recompute_tree_invariant_for_addr_expr (t);
10429 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10430 return NULL_TREE;
10433 static void
10434 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10436 gimple stmt = gsi_stmt (*gsi_p);
10437 struct walk_stmt_info wi;
10439 if (gimple_has_location (stmt))
10440 input_location = gimple_location (stmt);
10442 if (task_shared_vars)
10443 memset (&wi, '\0', sizeof (wi));
10445 /* If we have issued syntax errors, avoid doing any heavy lifting.
10446 Just replace the OpenMP directives with a NOP to avoid
10447 confusing RTL expansion. */
10448 if (seen_error () && is_gimple_omp (stmt))
10450 gsi_replace (gsi_p, gimple_build_nop (), true);
10451 return;
10454 switch (gimple_code (stmt))
10456 case GIMPLE_COND:
10457 if ((ctx || task_shared_vars)
10458 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10459 ctx ? NULL : &wi, NULL)
10460 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10461 ctx ? NULL : &wi, NULL)))
10462 gimple_regimplify_operands (stmt, gsi_p);
10463 break;
10464 case GIMPLE_CATCH:
10465 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10466 break;
10467 case GIMPLE_EH_FILTER:
10468 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10469 break;
10470 case GIMPLE_TRY:
10471 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10472 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10473 break;
10474 case GIMPLE_TRANSACTION:
10475 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10476 break;
10477 case GIMPLE_BIND:
10478 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10479 break;
10480 case GIMPLE_OMP_PARALLEL:
10481 case GIMPLE_OMP_TASK:
10482 ctx = maybe_lookup_ctx (stmt);
10483 gcc_assert (ctx);
10484 if (ctx->cancellable)
10485 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10486 lower_omp_taskreg (gsi_p, ctx);
10487 break;
10488 case GIMPLE_OMP_FOR:
10489 ctx = maybe_lookup_ctx (stmt);
10490 gcc_assert (ctx);
10491 if (ctx->cancellable)
10492 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10493 lower_omp_for (gsi_p, ctx);
10494 break;
10495 case GIMPLE_OMP_SECTIONS:
10496 ctx = maybe_lookup_ctx (stmt);
10497 gcc_assert (ctx);
10498 if (ctx->cancellable)
10499 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10500 lower_omp_sections (gsi_p, ctx);
10501 break;
10502 case GIMPLE_OMP_SINGLE:
10503 ctx = maybe_lookup_ctx (stmt);
10504 gcc_assert (ctx);
10505 lower_omp_single (gsi_p, ctx);
10506 break;
10507 case GIMPLE_OMP_MASTER:
10508 ctx = maybe_lookup_ctx (stmt);
10509 gcc_assert (ctx);
10510 lower_omp_master (gsi_p, ctx);
10511 break;
10512 case GIMPLE_OMP_TASKGROUP:
10513 ctx = maybe_lookup_ctx (stmt);
10514 gcc_assert (ctx);
10515 lower_omp_taskgroup (gsi_p, ctx);
10516 break;
10517 case GIMPLE_OMP_ORDERED:
10518 ctx = maybe_lookup_ctx (stmt);
10519 gcc_assert (ctx);
10520 lower_omp_ordered (gsi_p, ctx);
10521 break;
10522 case GIMPLE_OMP_CRITICAL:
10523 ctx = maybe_lookup_ctx (stmt);
10524 gcc_assert (ctx);
10525 lower_omp_critical (gsi_p, ctx);
10526 break;
10527 case GIMPLE_OMP_ATOMIC_LOAD:
10528 if ((ctx || task_shared_vars)
10529 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10530 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10531 gimple_regimplify_operands (stmt, gsi_p);
10532 break;
10533 case GIMPLE_OMP_TARGET:
10534 ctx = maybe_lookup_ctx (stmt);
10535 gcc_assert (ctx);
10536 lower_omp_target (gsi_p, ctx);
10537 break;
10538 case GIMPLE_OMP_TEAMS:
10539 ctx = maybe_lookup_ctx (stmt);
10540 gcc_assert (ctx);
10541 lower_omp_teams (gsi_p, ctx);
10542 break;
10543 case GIMPLE_CALL:
10544 tree fndecl;
10545 fndecl = gimple_call_fndecl (stmt);
10546 if (fndecl
10547 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10548 switch (DECL_FUNCTION_CODE (fndecl))
10550 case BUILT_IN_GOMP_BARRIER:
10551 if (ctx == NULL)
10552 break;
10553 /* FALLTHRU */
10554 case BUILT_IN_GOMP_CANCEL:
10555 case BUILT_IN_GOMP_CANCELLATION_POINT:
10556 omp_context *cctx;
10557 cctx = ctx;
10558 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10559 cctx = cctx->outer;
10560 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10561 if (!cctx->cancellable)
10563 if (DECL_FUNCTION_CODE (fndecl)
10564 == BUILT_IN_GOMP_CANCELLATION_POINT)
10566 stmt = gimple_build_nop ();
10567 gsi_replace (gsi_p, stmt, false);
10569 break;
10571 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10573 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10574 gimple_call_set_fndecl (stmt, fndecl);
10575 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10577 tree lhs;
10578 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10579 gimple_call_set_lhs (stmt, lhs);
10580 tree fallthru_label;
10581 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10582 gimple g;
10583 g = gimple_build_label (fallthru_label);
10584 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10585 g = gimple_build_cond (NE_EXPR, lhs,
10586 fold_convert (TREE_TYPE (lhs),
10587 boolean_false_node),
10588 cctx->cancel_label, fallthru_label);
10589 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10590 break;
10591 default:
10592 break;
10594 /* FALLTHRU */
10595 default:
10596 if ((ctx || task_shared_vars)
10597 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10598 ctx ? NULL : &wi))
10600 /* Just remove clobbers, this should happen only if we have
10601 "privatized" local addressable variables in SIMD regions,
10602 the clobber isn't needed in that case and gimplifying address
10603 of the ARRAY_REF into a pointer and creating MEM_REF based
10604 clobber would create worse code than we get with the clobber
10605 dropped. */
10606 if (gimple_clobber_p (stmt))
10608 gsi_replace (gsi_p, gimple_build_nop (), true);
10609 break;
10611 gimple_regimplify_operands (stmt, gsi_p);
10613 break;
10617 static void
10618 lower_omp (gimple_seq *body, omp_context *ctx)
10620 location_t saved_location = input_location;
10621 gimple_stmt_iterator gsi;
10622 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10623 lower_omp_1 (&gsi, ctx);
10624 /* During gimplification, we have not always invoked fold_stmt
10625 (gimplify.c:maybe_fold_stmt); call it now. */
10626 if (target_nesting_level)
10627 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10628 fold_stmt (&gsi);
10629 input_location = saved_location;
10632 /* Main entry point. */
10634 static unsigned int
10635 execute_lower_omp (void)
10637 gimple_seq body;
10638 int i;
10639 omp_context *ctx;
10641 /* This pass always runs, to provide PROP_gimple_lomp.
10642 But there is nothing to do unless -fopenmp is given. */
10643 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10644 return 0;
10646 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10647 delete_omp_context);
10649 body = gimple_body (current_function_decl);
10650 scan_omp (&body, NULL);
10651 gcc_assert (taskreg_nesting_level == 0);
10652 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10653 finish_taskreg_scan (ctx);
10654 taskreg_contexts.release ();
10656 if (all_contexts->root)
10658 if (task_shared_vars)
10659 push_gimplify_context ();
10660 lower_omp (&body, NULL);
10661 if (task_shared_vars)
10662 pop_gimplify_context (NULL);
10665 if (all_contexts)
10667 splay_tree_delete (all_contexts);
10668 all_contexts = NULL;
10670 BITMAP_FREE (task_shared_vars);
10671 return 0;
10674 namespace {
10676 const pass_data pass_data_lower_omp =
10678 GIMPLE_PASS, /* type */
10679 "omplower", /* name */
10680 OPTGROUP_NONE, /* optinfo_flags */
10681 TV_NONE, /* tv_id */
10682 PROP_gimple_any, /* properties_required */
10683 PROP_gimple_lomp, /* properties_provided */
10684 0, /* properties_destroyed */
10685 0, /* todo_flags_start */
10686 0, /* todo_flags_finish */
10689 class pass_lower_omp : public gimple_opt_pass
10691 public:
10692 pass_lower_omp (gcc::context *ctxt)
10693 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10696 /* opt_pass methods: */
10697 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10699 }; // class pass_lower_omp
10701 } // anon namespace
10703 gimple_opt_pass *
10704 make_pass_lower_omp (gcc::context *ctxt)
10706 return new pass_lower_omp (ctxt);
10709 /* The following is a utility to diagnose OpenMP structured block violations.
10710 It is not part of the "omplower" pass, as that's invoked too late. It
10711 should be invoked by the respective front ends after gimplification. */
10713 static splay_tree all_labels;
10715 /* Check for mismatched contexts and generate an error if needed. Return
10716 true if an error is detected. */
10718 static bool
10719 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10720 gimple branch_ctx, gimple label_ctx)
10722 if (label_ctx == branch_ctx)
10723 return false;
10727 Previously we kept track of the label's entire context in diagnose_sb_[12]
10728 so we could traverse it and issue a correct "exit" or "enter" error
10729 message upon a structured block violation.
10731 We built the context by building a list with tree_cons'ing, but there is
10732 no easy counterpart in gimple tuples. It seems like far too much work
10733 for issuing exit/enter error messages. If someone really misses the
10734 distinct error message... patches welcome.
10737 #if 0
10738 /* Try to avoid confusing the user by producing and error message
10739 with correct "exit" or "enter" verbiage. We prefer "exit"
10740 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10741 if (branch_ctx == NULL)
10742 exit_p = false;
10743 else
10745 while (label_ctx)
10747 if (TREE_VALUE (label_ctx) == branch_ctx)
10749 exit_p = false;
10750 break;
10752 label_ctx = TREE_CHAIN (label_ctx);
10756 if (exit_p)
10757 error ("invalid exit from OpenMP structured block");
10758 else
10759 error ("invalid entry to OpenMP structured block");
10760 #endif
10762 bool cilkplus_block = false;
10763 if (flag_cilkplus)
10765 if ((branch_ctx
10766 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10767 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10768 || (label_ctx
10769 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10770 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10771 cilkplus_block = true;
10774 /* If it's obvious we have an invalid entry, be specific about the error. */
10775 if (branch_ctx == NULL)
10777 if (cilkplus_block)
10778 error ("invalid entry to Cilk Plus structured block");
10779 else
10780 error ("invalid entry to OpenMP structured block");
10782 else
10784 /* Otherwise, be vague and lazy, but efficient. */
10785 if (cilkplus_block)
10786 error ("invalid branch to/from a Cilk Plus structured block");
10787 else
10788 error ("invalid branch to/from an OpenMP structured block");
10791 gsi_replace (gsi_p, gimple_build_nop (), false);
10792 return true;
10795 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10796 where each label is found. */
10798 static tree
10799 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10800 struct walk_stmt_info *wi)
10802 gimple context = (gimple) wi->info;
10803 gimple inner_context;
10804 gimple stmt = gsi_stmt (*gsi_p);
10806 *handled_ops_p = true;
10808 switch (gimple_code (stmt))
10810 WALK_SUBSTMTS;
10812 case GIMPLE_OMP_PARALLEL:
10813 case GIMPLE_OMP_TASK:
10814 case GIMPLE_OMP_SECTIONS:
10815 case GIMPLE_OMP_SINGLE:
10816 case GIMPLE_OMP_SECTION:
10817 case GIMPLE_OMP_MASTER:
10818 case GIMPLE_OMP_ORDERED:
10819 case GIMPLE_OMP_CRITICAL:
10820 case GIMPLE_OMP_TARGET:
10821 case GIMPLE_OMP_TEAMS:
10822 case GIMPLE_OMP_TASKGROUP:
10823 /* The minimal context here is just the current OMP construct. */
10824 inner_context = stmt;
10825 wi->info = inner_context;
10826 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10827 wi->info = context;
10828 break;
10830 case GIMPLE_OMP_FOR:
10831 inner_context = stmt;
10832 wi->info = inner_context;
10833 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10834 walk them. */
10835 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10836 diagnose_sb_1, NULL, wi);
10837 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10838 wi->info = context;
10839 break;
10841 case GIMPLE_LABEL:
10842 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10843 (splay_tree_value) context);
10844 break;
10846 default:
10847 break;
10850 return NULL_TREE;
10853 /* Pass 2: Check each branch and see if its context differs from that of
10854 the destination label's context. */
10856 static tree
10857 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10858 struct walk_stmt_info *wi)
10860 gimple context = (gimple) wi->info;
10861 splay_tree_node n;
10862 gimple stmt = gsi_stmt (*gsi_p);
10864 *handled_ops_p = true;
10866 switch (gimple_code (stmt))
10868 WALK_SUBSTMTS;
10870 case GIMPLE_OMP_PARALLEL:
10871 case GIMPLE_OMP_TASK:
10872 case GIMPLE_OMP_SECTIONS:
10873 case GIMPLE_OMP_SINGLE:
10874 case GIMPLE_OMP_SECTION:
10875 case GIMPLE_OMP_MASTER:
10876 case GIMPLE_OMP_ORDERED:
10877 case GIMPLE_OMP_CRITICAL:
10878 case GIMPLE_OMP_TARGET:
10879 case GIMPLE_OMP_TEAMS:
10880 case GIMPLE_OMP_TASKGROUP:
10881 wi->info = stmt;
10882 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10883 wi->info = context;
10884 break;
10886 case GIMPLE_OMP_FOR:
10887 wi->info = stmt;
10888 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10889 walk them. */
10890 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10891 diagnose_sb_2, NULL, wi);
10892 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10893 wi->info = context;
10894 break;
10896 case GIMPLE_COND:
10898 tree lab = gimple_cond_true_label (stmt);
10899 if (lab)
10901 n = splay_tree_lookup (all_labels,
10902 (splay_tree_key) lab);
10903 diagnose_sb_0 (gsi_p, context,
10904 n ? (gimple) n->value : NULL);
10906 lab = gimple_cond_false_label (stmt);
10907 if (lab)
10909 n = splay_tree_lookup (all_labels,
10910 (splay_tree_key) lab);
10911 diagnose_sb_0 (gsi_p, context,
10912 n ? (gimple) n->value : NULL);
10915 break;
10917 case GIMPLE_GOTO:
10919 tree lab = gimple_goto_dest (stmt);
10920 if (TREE_CODE (lab) != LABEL_DECL)
10921 break;
10923 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10924 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10926 break;
10928 case GIMPLE_SWITCH:
10930 unsigned int i;
10931 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10933 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10934 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10935 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10936 break;
10939 break;
10941 case GIMPLE_RETURN:
10942 diagnose_sb_0 (gsi_p, context, NULL);
10943 break;
10945 default:
10946 break;
10949 return NULL_TREE;
10952 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10953 codes. */
10954 bool
10955 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10956 int *region_idx)
10958 gimple last = last_stmt (bb);
10959 enum gimple_code code = gimple_code (last);
10960 struct omp_region *cur_region = *region;
10961 bool fallthru = false;
10963 switch (code)
10965 case GIMPLE_OMP_PARALLEL:
10966 case GIMPLE_OMP_TASK:
10967 case GIMPLE_OMP_FOR:
10968 case GIMPLE_OMP_SINGLE:
10969 case GIMPLE_OMP_TEAMS:
10970 case GIMPLE_OMP_MASTER:
10971 case GIMPLE_OMP_TASKGROUP:
10972 case GIMPLE_OMP_ORDERED:
10973 case GIMPLE_OMP_CRITICAL:
10974 case GIMPLE_OMP_SECTION:
10975 cur_region = new_omp_region (bb, code, cur_region);
10976 fallthru = true;
10977 break;
10979 case GIMPLE_OMP_TARGET:
10980 cur_region = new_omp_region (bb, code, cur_region);
10981 fallthru = true;
10982 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10983 cur_region = cur_region->outer;
10984 break;
10986 case GIMPLE_OMP_SECTIONS:
10987 cur_region = new_omp_region (bb, code, cur_region);
10988 fallthru = true;
10989 break;
10991 case GIMPLE_OMP_SECTIONS_SWITCH:
10992 fallthru = false;
10993 break;
10995 case GIMPLE_OMP_ATOMIC_LOAD:
10996 case GIMPLE_OMP_ATOMIC_STORE:
10997 fallthru = true;
10998 break;
11000 case GIMPLE_OMP_RETURN:
11001 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11002 somewhere other than the next block. This will be
11003 created later. */
11004 cur_region->exit = bb;
11005 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11006 cur_region = cur_region->outer;
11007 break;
11009 case GIMPLE_OMP_CONTINUE:
11010 cur_region->cont = bb;
11011 switch (cur_region->type)
11013 case GIMPLE_OMP_FOR:
11014 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11015 succs edges as abnormal to prevent splitting
11016 them. */
11017 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11018 /* Make the loopback edge. */
11019 make_edge (bb, single_succ (cur_region->entry),
11020 EDGE_ABNORMAL);
11022 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11023 corresponds to the case that the body of the loop
11024 is not executed at all. */
11025 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11026 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11027 fallthru = false;
11028 break;
11030 case GIMPLE_OMP_SECTIONS:
11031 /* Wire up the edges into and out of the nested sections. */
11033 basic_block switch_bb = single_succ (cur_region->entry);
11035 struct omp_region *i;
11036 for (i = cur_region->inner; i ; i = i->next)
11038 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11039 make_edge (switch_bb, i->entry, 0);
11040 make_edge (i->exit, bb, EDGE_FALLTHRU);
11043 /* Make the loopback edge to the block with
11044 GIMPLE_OMP_SECTIONS_SWITCH. */
11045 make_edge (bb, switch_bb, 0);
11047 /* Make the edge from the switch to exit. */
11048 make_edge (switch_bb, bb->next_bb, 0);
11049 fallthru = false;
11051 break;
11053 default:
11054 gcc_unreachable ();
11056 break;
11058 default:
11059 gcc_unreachable ();
11062 if (*region != cur_region)
11064 *region = cur_region;
11065 if (cur_region)
11066 *region_idx = cur_region->entry->index;
11067 else
11068 *region_idx = 0;
11071 return fallthru;
11074 static unsigned int
11075 diagnose_omp_structured_block_errors (void)
11077 struct walk_stmt_info wi;
11078 gimple_seq body = gimple_body (current_function_decl);
11080 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11082 memset (&wi, 0, sizeof (wi));
11083 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11085 memset (&wi, 0, sizeof (wi));
11086 wi.want_locations = true;
11087 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11089 gimple_set_body (current_function_decl, body);
11091 splay_tree_delete (all_labels);
11092 all_labels = NULL;
11094 return 0;
11097 namespace {
11099 const pass_data pass_data_diagnose_omp_blocks =
11101 GIMPLE_PASS, /* type */
11102 "*diagnose_omp_blocks", /* name */
11103 OPTGROUP_NONE, /* optinfo_flags */
11104 TV_NONE, /* tv_id */
11105 PROP_gimple_any, /* properties_required */
11106 0, /* properties_provided */
11107 0, /* properties_destroyed */
11108 0, /* todo_flags_start */
11109 0, /* todo_flags_finish */
11112 class pass_diagnose_omp_blocks : public gimple_opt_pass
11114 public:
11115 pass_diagnose_omp_blocks (gcc::context *ctxt)
11116 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11119 /* opt_pass methods: */
11120 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11121 virtual unsigned int execute (function *)
11123 return diagnose_omp_structured_block_errors ();
11126 }; // class pass_diagnose_omp_blocks
11128 } // anon namespace
11130 gimple_opt_pass *
11131 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11133 return new pass_diagnose_omp_blocks (ctxt);
11136 /* SIMD clone supporting code. */
11138 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11139 of arguments to reserve space for. */
11141 static struct cgraph_simd_clone *
11142 simd_clone_struct_alloc (int nargs)
11144 struct cgraph_simd_clone *clone_info;
11145 size_t len = (sizeof (struct cgraph_simd_clone)
11146 + nargs * sizeof (struct cgraph_simd_clone_arg));
11147 clone_info = (struct cgraph_simd_clone *)
11148 ggc_internal_cleared_alloc (len);
11149 return clone_info;
11152 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11154 static inline void
11155 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11156 struct cgraph_simd_clone *from)
11158 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11159 + ((from->nargs - from->inbranch)
11160 * sizeof (struct cgraph_simd_clone_arg))));
11163 /* Return vector of parameter types of function FNDECL. This uses
11164 TYPE_ARG_TYPES if available, otherwise falls back to types of
11165 DECL_ARGUMENTS types. */
11167 vec<tree>
11168 simd_clone_vector_of_formal_parm_types (tree fndecl)
11170 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11171 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11172 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11173 unsigned int i;
11174 tree arg;
11175 FOR_EACH_VEC_ELT (args, i, arg)
11176 args[i] = TREE_TYPE (args[i]);
11177 return args;
11180 /* Given a simd function in NODE, extract the simd specific
11181 information from the OMP clauses passed in CLAUSES, and return
11182 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11183 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11184 otherwise set to FALSE. */
11186 static struct cgraph_simd_clone *
11187 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11188 bool *inbranch_specified)
11190 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11191 tree t;
11192 int n;
11193 *inbranch_specified = false;
11195 n = args.length ();
11196 if (n > 0 && args.last () == void_type_node)
11197 n--;
11199 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11200 be cloned have a distinctive artificial label in addition to "omp
11201 declare simd". */
11202 bool cilk_clone
11203 = (flag_cilkplus
11204 && lookup_attribute ("cilk simd function",
11205 DECL_ATTRIBUTES (node->decl)));
11207 /* Allocate one more than needed just in case this is an in-branch
11208 clone which will require a mask argument. */
11209 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11210 clone_info->nargs = n;
11211 clone_info->cilk_elemental = cilk_clone;
11213 if (!clauses)
11215 args.release ();
11216 return clone_info;
11218 clauses = TREE_VALUE (clauses);
11219 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11220 return clone_info;
11222 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11224 switch (OMP_CLAUSE_CODE (t))
11226 case OMP_CLAUSE_INBRANCH:
11227 clone_info->inbranch = 1;
11228 *inbranch_specified = true;
11229 break;
11230 case OMP_CLAUSE_NOTINBRANCH:
11231 clone_info->inbranch = 0;
11232 *inbranch_specified = true;
11233 break;
11234 case OMP_CLAUSE_SIMDLEN:
11235 clone_info->simdlen
11236 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11237 break;
11238 case OMP_CLAUSE_LINEAR:
11240 tree decl = OMP_CLAUSE_DECL (t);
11241 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11242 int argno = TREE_INT_CST_LOW (decl);
11243 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11245 clone_info->args[argno].arg_type
11246 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11247 clone_info->args[argno].linear_step = tree_to_shwi (step);
11248 gcc_assert (clone_info->args[argno].linear_step >= 0
11249 && clone_info->args[argno].linear_step < n);
11251 else
11253 if (POINTER_TYPE_P (args[argno]))
11254 step = fold_convert (ssizetype, step);
11255 if (!tree_fits_shwi_p (step))
11257 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11258 "ignoring large linear step");
11259 args.release ();
11260 return NULL;
11262 else if (integer_zerop (step))
11264 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11265 "ignoring zero linear step");
11266 args.release ();
11267 return NULL;
11269 else
11271 clone_info->args[argno].arg_type
11272 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11273 clone_info->args[argno].linear_step = tree_to_shwi (step);
11276 break;
11278 case OMP_CLAUSE_UNIFORM:
11280 tree decl = OMP_CLAUSE_DECL (t);
11281 int argno = tree_to_uhwi (decl);
11282 clone_info->args[argno].arg_type
11283 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11284 break;
11286 case OMP_CLAUSE_ALIGNED:
11288 tree decl = OMP_CLAUSE_DECL (t);
11289 int argno = tree_to_uhwi (decl);
11290 clone_info->args[argno].alignment
11291 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11292 break;
11294 default:
11295 break;
11298 args.release ();
11299 return clone_info;
11302 /* Given a SIMD clone in NODE, calculate the characteristic data
11303 type and return the coresponding type. The characteristic data
11304 type is computed as described in the Intel Vector ABI. */
11306 static tree
11307 simd_clone_compute_base_data_type (struct cgraph_node *node,
11308 struct cgraph_simd_clone *clone_info)
11310 tree type = integer_type_node;
11311 tree fndecl = node->decl;
11313 /* a) For non-void function, the characteristic data type is the
11314 return type. */
11315 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11316 type = TREE_TYPE (TREE_TYPE (fndecl));
11318 /* b) If the function has any non-uniform, non-linear parameters,
11319 then the characteristic data type is the type of the first
11320 such parameter. */
11321 else
11323 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11324 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11325 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11327 type = map[i];
11328 break;
11330 map.release ();
11333 /* c) If the characteristic data type determined by a) or b) above
11334 is struct, union, or class type which is pass-by-value (except
11335 for the type that maps to the built-in complex data type), the
11336 characteristic data type is int. */
11337 if (RECORD_OR_UNION_TYPE_P (type)
11338 && !aggregate_value_p (type, NULL)
11339 && TREE_CODE (type) != COMPLEX_TYPE)
11340 return integer_type_node;
11342 /* d) If none of the above three classes is applicable, the
11343 characteristic data type is int. */
11345 return type;
11347 /* e) For Intel Xeon Phi native and offload compilation, if the
11348 resulting characteristic data type is 8-bit or 16-bit integer
11349 data type, the characteristic data type is int. */
11350 /* Well, we don't handle Xeon Phi yet. */
11353 static tree
11354 simd_clone_mangle (struct cgraph_node *node,
11355 struct cgraph_simd_clone *clone_info)
11357 char vecsize_mangle = clone_info->vecsize_mangle;
11358 char mask = clone_info->inbranch ? 'M' : 'N';
11359 unsigned int simdlen = clone_info->simdlen;
11360 unsigned int n;
11361 pretty_printer pp;
11363 gcc_assert (vecsize_mangle && simdlen);
11365 pp_string (&pp, "_ZGV");
11366 pp_character (&pp, vecsize_mangle);
11367 pp_character (&pp, mask);
11368 pp_decimal_int (&pp, simdlen);
11370 for (n = 0; n < clone_info->nargs; ++n)
11372 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11374 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11375 pp_character (&pp, 'u');
11376 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11378 gcc_assert (arg.linear_step != 0);
11379 pp_character (&pp, 'l');
11380 if (arg.linear_step > 1)
11381 pp_unsigned_wide_integer (&pp, arg.linear_step);
11382 else if (arg.linear_step < 0)
11384 pp_character (&pp, 'n');
11385 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11386 arg.linear_step));
11389 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11391 pp_character (&pp, 's');
11392 pp_unsigned_wide_integer (&pp, arg.linear_step);
11394 else
11395 pp_character (&pp, 'v');
11396 if (arg.alignment)
11398 pp_character (&pp, 'a');
11399 pp_decimal_int (&pp, arg.alignment);
11403 pp_underscore (&pp);
11404 pp_string (&pp,
11405 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11406 const char *str = pp_formatted_text (&pp);
11408 /* If there already is a SIMD clone with the same mangled name, don't
11409 add another one. This can happen e.g. for
11410 #pragma omp declare simd
11411 #pragma omp declare simd simdlen(8)
11412 int foo (int, int);
11413 if the simdlen is assumed to be 8 for the first one, etc. */
11414 for (struct cgraph_node *clone = node->simd_clones; clone;
11415 clone = clone->simdclone->next_clone)
11416 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11417 str) == 0)
11418 return NULL_TREE;
11420 return get_identifier (str);
11423 /* Create a simd clone of OLD_NODE and return it. */
11425 static struct cgraph_node *
11426 simd_clone_create (struct cgraph_node *old_node)
11428 struct cgraph_node *new_node;
11429 if (old_node->definition)
11431 if (!old_node->has_gimple_body_p ())
11432 return NULL;
11433 old_node->get_body ();
11434 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11435 false, NULL, NULL,
11436 "simdclone");
11438 else
11440 tree old_decl = old_node->decl;
11441 tree new_decl = copy_node (old_node->decl);
11442 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11443 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11444 SET_DECL_RTL (new_decl, NULL);
11445 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11446 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11447 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11448 symtab->call_cgraph_insertion_hooks (new_node);
11450 if (new_node == NULL)
11451 return new_node;
11453 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11455 /* The function cgraph_function_versioning () will force the new
11456 symbol local. Undo this, and inherit external visability from
11457 the old node. */
11458 new_node->local.local = old_node->local.local;
11459 new_node->externally_visible = old_node->externally_visible;
11461 return new_node;
11464 /* Adjust the return type of the given function to its appropriate
11465 vector counterpart. Returns a simd array to be used throughout the
11466 function as a return value. */
11468 static tree
11469 simd_clone_adjust_return_type (struct cgraph_node *node)
11471 tree fndecl = node->decl;
11472 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11473 unsigned int veclen;
11474 tree t;
11476 /* Adjust the function return type. */
11477 if (orig_rettype == void_type_node)
11478 return NULL_TREE;
11479 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11480 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11481 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11482 veclen = node->simdclone->vecsize_int;
11483 else
11484 veclen = node->simdclone->vecsize_float;
11485 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11486 if (veclen > node->simdclone->simdlen)
11487 veclen = node->simdclone->simdlen;
11488 if (veclen == node->simdclone->simdlen)
11489 TREE_TYPE (TREE_TYPE (fndecl))
11490 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11491 node->simdclone->simdlen);
11492 else
11494 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11495 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11496 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11498 if (!node->definition)
11499 return NULL_TREE;
11501 t = DECL_RESULT (fndecl);
11502 /* Adjust the DECL_RESULT. */
11503 gcc_assert (TREE_TYPE (t) != void_type_node);
11504 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11505 relayout_decl (t);
11507 tree atype = build_array_type_nelts (orig_rettype,
11508 node->simdclone->simdlen);
11509 if (veclen != node->simdclone->simdlen)
11510 return build1 (VIEW_CONVERT_EXPR, atype, t);
11512 /* Set up a SIMD array to use as the return value. */
11513 tree retval = create_tmp_var_raw (atype, "retval");
11514 gimple_add_tmp_var (retval);
11515 return retval;
11518 /* Each vector argument has a corresponding array to be used locally
11519 as part of the eventual loop. Create such temporary array and
11520 return it.
11522 PREFIX is the prefix to be used for the temporary.
11524 TYPE is the inner element type.
11526 SIMDLEN is the number of elements. */
11528 static tree
11529 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11531 tree atype = build_array_type_nelts (type, simdlen);
11532 tree avar = create_tmp_var_raw (atype, prefix);
11533 gimple_add_tmp_var (avar);
11534 return avar;
11537 /* Modify the function argument types to their corresponding vector
11538 counterparts if appropriate. Also, create one array for each simd
11539 argument to be used locally when using the function arguments as
11540 part of the loop.
11542 NODE is the function whose arguments are to be adjusted.
11544 Returns an adjustment vector that will be filled describing how the
11545 argument types will be adjusted. */
11547 static ipa_parm_adjustment_vec
11548 simd_clone_adjust_argument_types (struct cgraph_node *node)
11550 vec<tree> args;
11551 ipa_parm_adjustment_vec adjustments;
11553 if (node->definition)
11554 args = ipa_get_vector_of_formal_parms (node->decl);
11555 else
11556 args = simd_clone_vector_of_formal_parm_types (node->decl);
11557 adjustments.create (args.length ());
11558 unsigned i, j, veclen;
11559 struct ipa_parm_adjustment adj;
11560 for (i = 0; i < node->simdclone->nargs; ++i)
11562 memset (&adj, 0, sizeof (adj));
11563 tree parm = args[i];
11564 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11565 adj.base_index = i;
11566 adj.base = parm;
11568 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11569 node->simdclone->args[i].orig_type = parm_type;
11571 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11573 /* No adjustment necessary for scalar arguments. */
11574 adj.op = IPA_PARM_OP_COPY;
11576 else
11578 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11579 veclen = node->simdclone->vecsize_int;
11580 else
11581 veclen = node->simdclone->vecsize_float;
11582 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11583 if (veclen > node->simdclone->simdlen)
11584 veclen = node->simdclone->simdlen;
11585 adj.arg_prefix = "simd";
11586 adj.type = build_vector_type (parm_type, veclen);
11587 node->simdclone->args[i].vector_type = adj.type;
11588 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11590 adjustments.safe_push (adj);
11591 if (j == veclen)
11593 memset (&adj, 0, sizeof (adj));
11594 adj.op = IPA_PARM_OP_NEW;
11595 adj.arg_prefix = "simd";
11596 adj.base_index = i;
11597 adj.type = node->simdclone->args[i].vector_type;
11601 if (node->definition)
11602 node->simdclone->args[i].simd_array
11603 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11604 parm_type, node->simdclone->simdlen);
11606 adjustments.safe_push (adj);
11609 if (node->simdclone->inbranch)
11611 tree base_type
11612 = simd_clone_compute_base_data_type (node->simdclone->origin,
11613 node->simdclone);
11615 memset (&adj, 0, sizeof (adj));
11616 adj.op = IPA_PARM_OP_NEW;
11617 adj.arg_prefix = "mask";
11619 adj.base_index = i;
11620 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11621 veclen = node->simdclone->vecsize_int;
11622 else
11623 veclen = node->simdclone->vecsize_float;
11624 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11625 if (veclen > node->simdclone->simdlen)
11626 veclen = node->simdclone->simdlen;
11627 adj.type = build_vector_type (base_type, veclen);
11628 adjustments.safe_push (adj);
11630 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11631 adjustments.safe_push (adj);
11633 /* We have previously allocated one extra entry for the mask. Use
11634 it and fill it. */
11635 struct cgraph_simd_clone *sc = node->simdclone;
11636 sc->nargs++;
11637 if (node->definition)
11639 sc->args[i].orig_arg
11640 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11641 sc->args[i].simd_array
11642 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11644 sc->args[i].orig_type = base_type;
11645 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11648 if (node->definition)
11649 ipa_modify_formal_parameters (node->decl, adjustments);
11650 else
11652 tree new_arg_types = NULL_TREE, new_reversed;
11653 bool last_parm_void = false;
11654 if (args.length () > 0 && args.last () == void_type_node)
11655 last_parm_void = true;
11657 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11658 j = adjustments.length ();
11659 for (i = 0; i < j; i++)
11661 struct ipa_parm_adjustment *adj = &adjustments[i];
11662 tree ptype;
11663 if (adj->op == IPA_PARM_OP_COPY)
11664 ptype = args[adj->base_index];
11665 else
11666 ptype = adj->type;
11667 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11669 new_reversed = nreverse (new_arg_types);
11670 if (last_parm_void)
11672 if (new_reversed)
11673 TREE_CHAIN (new_arg_types) = void_list_node;
11674 else
11675 new_reversed = void_list_node;
11678 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11679 TYPE_ARG_TYPES (new_type) = new_reversed;
11680 TREE_TYPE (node->decl) = new_type;
11682 adjustments.release ();
11684 args.release ();
11685 return adjustments;
11688 /* Initialize and copy the function arguments in NODE to their
11689 corresponding local simd arrays. Returns a fresh gimple_seq with
11690 the instruction sequence generated. */
11692 static gimple_seq
11693 simd_clone_init_simd_arrays (struct cgraph_node *node,
11694 ipa_parm_adjustment_vec adjustments)
11696 gimple_seq seq = NULL;
11697 unsigned i = 0, j = 0, k;
11699 for (tree arg = DECL_ARGUMENTS (node->decl);
11700 arg;
11701 arg = DECL_CHAIN (arg), i++, j++)
11703 if (adjustments[j].op == IPA_PARM_OP_COPY)
11704 continue;
11706 node->simdclone->args[i].vector_arg = arg;
11708 tree array = node->simdclone->args[i].simd_array;
11709 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11711 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11712 tree ptr = build_fold_addr_expr (array);
11713 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11714 build_int_cst (ptype, 0));
11715 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11716 gimplify_and_add (t, &seq);
11718 else
11720 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11721 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11722 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11724 tree ptr = build_fold_addr_expr (array);
11725 int elemsize;
11726 if (k)
11728 arg = DECL_CHAIN (arg);
11729 j++;
11731 elemsize
11732 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11733 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11734 build_int_cst (ptype, k * elemsize));
11735 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11736 gimplify_and_add (t, &seq);
11740 return seq;
11743 /* Callback info for ipa_simd_modify_stmt_ops below. */
11745 struct modify_stmt_info {
11746 ipa_parm_adjustment_vec adjustments;
11747 gimple stmt;
11748 /* True if the parent statement was modified by
11749 ipa_simd_modify_stmt_ops. */
11750 bool modified;
11753 /* Callback for walk_gimple_op.
11755 Adjust operands from a given statement as specified in the
11756 adjustments vector in the callback data. */
11758 static tree
11759 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11761 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11762 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11763 tree *orig_tp = tp;
11764 if (TREE_CODE (*tp) == ADDR_EXPR)
11765 tp = &TREE_OPERAND (*tp, 0);
11766 struct ipa_parm_adjustment *cand = NULL;
11767 if (TREE_CODE (*tp) == PARM_DECL)
11768 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11769 else
11771 if (TYPE_P (*tp))
11772 *walk_subtrees = 0;
11775 tree repl = NULL_TREE;
11776 if (cand)
11777 repl = unshare_expr (cand->new_decl);
11778 else
11780 if (tp != orig_tp)
11782 *walk_subtrees = 0;
11783 bool modified = info->modified;
11784 info->modified = false;
11785 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11786 if (!info->modified)
11788 info->modified = modified;
11789 return NULL_TREE;
11791 info->modified = modified;
11792 repl = *tp;
11794 else
11795 return NULL_TREE;
11798 if (tp != orig_tp)
11800 repl = build_fold_addr_expr (repl);
11801 gimple stmt;
11802 if (is_gimple_debug (info->stmt))
11804 tree vexpr = make_node (DEBUG_EXPR_DECL);
11805 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11806 DECL_ARTIFICIAL (vexpr) = 1;
11807 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11808 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11809 repl = vexpr;
11811 else
11813 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11814 NULL), repl);
11815 repl = gimple_assign_lhs (stmt);
11817 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11818 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11819 *orig_tp = repl;
11821 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11823 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11824 *tp = vce;
11826 else
11827 *tp = repl;
11829 info->modified = true;
11830 return NULL_TREE;
11833 /* Traverse the function body and perform all modifications as
11834 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11835 modified such that the replacement/reduction value will now be an
11836 offset into the corresponding simd_array.
11838 This function will replace all function argument uses with their
11839 corresponding simd array elements, and ajust the return values
11840 accordingly. */
11842 static void
11843 ipa_simd_modify_function_body (struct cgraph_node *node,
11844 ipa_parm_adjustment_vec adjustments,
11845 tree retval_array, tree iter)
11847 basic_block bb;
11848 unsigned int i, j, l;
11850 /* Re-use the adjustments array, but this time use it to replace
11851 every function argument use to an offset into the corresponding
11852 simd_array. */
11853 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11855 if (!node->simdclone->args[i].vector_arg)
11856 continue;
11858 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11859 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11860 adjustments[j].new_decl
11861 = build4 (ARRAY_REF,
11862 basetype,
11863 node->simdclone->args[i].simd_array,
11864 iter,
11865 NULL_TREE, NULL_TREE);
11866 if (adjustments[j].op == IPA_PARM_OP_NONE
11867 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11868 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11871 l = adjustments.length ();
11872 for (i = 1; i < num_ssa_names; i++)
11874 tree name = ssa_name (i);
11875 if (name
11876 && SSA_NAME_VAR (name)
11877 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11879 for (j = 0; j < l; j++)
11880 if (SSA_NAME_VAR (name) == adjustments[j].base
11881 && adjustments[j].new_decl)
11883 tree base_var;
11884 if (adjustments[j].new_ssa_base == NULL_TREE)
11886 base_var
11887 = copy_var_decl (adjustments[j].base,
11888 DECL_NAME (adjustments[j].base),
11889 TREE_TYPE (adjustments[j].base));
11890 adjustments[j].new_ssa_base = base_var;
11892 else
11893 base_var = adjustments[j].new_ssa_base;
11894 if (SSA_NAME_IS_DEFAULT_DEF (name))
11896 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11897 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11898 tree new_decl = unshare_expr (adjustments[j].new_decl);
11899 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11900 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11901 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11902 gimple stmt = gimple_build_assign (name, new_decl);
11903 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11905 else
11906 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11911 struct modify_stmt_info info;
11912 info.adjustments = adjustments;
11914 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11916 gimple_stmt_iterator gsi;
11918 gsi = gsi_start_bb (bb);
11919 while (!gsi_end_p (gsi))
11921 gimple stmt = gsi_stmt (gsi);
11922 info.stmt = stmt;
11923 struct walk_stmt_info wi;
11925 memset (&wi, 0, sizeof (wi));
11926 info.modified = false;
11927 wi.info = &info;
11928 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11930 if (gimple_code (stmt) == GIMPLE_RETURN)
11932 tree retval = gimple_return_retval (stmt);
11933 if (!retval)
11935 gsi_remove (&gsi, true);
11936 continue;
11939 /* Replace `return foo' with `retval_array[iter] = foo'. */
11940 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11941 retval_array, iter, NULL, NULL);
11942 stmt = gimple_build_assign (ref, retval);
11943 gsi_replace (&gsi, stmt, true);
11944 info.modified = true;
11947 if (info.modified)
11949 update_stmt (stmt);
11950 if (maybe_clean_eh_stmt (stmt))
11951 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11953 gsi_next (&gsi);
11958 /* Adjust the argument types in NODE to their appropriate vector
11959 counterparts. */
11961 static void
11962 simd_clone_adjust (struct cgraph_node *node)
11964 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11966 targetm.simd_clone.adjust (node);
11968 tree retval = simd_clone_adjust_return_type (node);
11969 ipa_parm_adjustment_vec adjustments
11970 = simd_clone_adjust_argument_types (node);
11972 push_gimplify_context ();
11974 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11976 /* Adjust all uses of vector arguments accordingly. Adjust all
11977 return values accordingly. */
11978 tree iter = create_tmp_var (unsigned_type_node, "iter");
11979 tree iter1 = make_ssa_name (iter, NULL);
11980 tree iter2 = make_ssa_name (iter, NULL);
11981 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11983 /* Initialize the iteration variable. */
11984 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11985 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11986 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11987 /* Insert the SIMD array and iv initialization at function
11988 entry. */
11989 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11991 pop_gimplify_context (NULL);
11993 /* Create a new BB right before the original exit BB, to hold the
11994 iteration increment and the condition/branch. */
11995 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11996 basic_block incr_bb = create_empty_bb (orig_exit);
11997 add_bb_to_loop (incr_bb, body_bb->loop_father);
11998 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11999 flag. Set it now to be a FALLTHRU_EDGE. */
12000 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12001 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12002 for (unsigned i = 0;
12003 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12005 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12006 redirect_edge_succ (e, incr_bb);
12008 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12009 e->probability = REG_BR_PROB_BASE;
12010 gsi = gsi_last_bb (incr_bb);
12011 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12012 build_int_cst (unsigned_type_node,
12013 1));
12014 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12016 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12017 struct loop *loop = alloc_loop ();
12018 cfun->has_force_vectorize_loops = true;
12019 loop->safelen = node->simdclone->simdlen;
12020 loop->force_vectorize = true;
12021 loop->header = body_bb;
12023 /* Branch around the body if the mask applies. */
12024 if (node->simdclone->inbranch)
12026 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12027 tree mask_array
12028 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12029 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12030 tree aref = build4 (ARRAY_REF,
12031 TREE_TYPE (TREE_TYPE (mask_array)),
12032 mask_array, iter1,
12033 NULL, NULL);
12034 g = gimple_build_assign (mask, aref);
12035 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12036 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12037 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12039 aref = build1 (VIEW_CONVERT_EXPR,
12040 build_nonstandard_integer_type (bitsize, 0), mask);
12041 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12042 g = gimple_build_assign (mask, aref);
12043 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12046 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12047 NULL, NULL);
12048 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12049 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12050 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12053 /* Generate the condition. */
12054 g = gimple_build_cond (LT_EXPR,
12055 iter2,
12056 build_int_cst (unsigned_type_node,
12057 node->simdclone->simdlen),
12058 NULL, NULL);
12059 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12060 e = split_block (incr_bb, gsi_stmt (gsi));
12061 basic_block latch_bb = e->dest;
12062 basic_block new_exit_bb;
12063 new_exit_bb = split_block (latch_bb, NULL)->dest;
12064 loop->latch = latch_bb;
12066 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12068 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12069 /* The successor of incr_bb is already pointing to latch_bb; just
12070 change the flags.
12071 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12072 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12074 gimple phi = create_phi_node (iter1, body_bb);
12075 edge preheader_edge = find_edge (entry_bb, body_bb);
12076 edge latch_edge = single_succ_edge (latch_bb);
12077 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12078 UNKNOWN_LOCATION);
12079 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12081 /* Generate the new return. */
12082 gsi = gsi_last_bb (new_exit_bb);
12083 if (retval
12084 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12085 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12086 retval = TREE_OPERAND (retval, 0);
12087 else if (retval)
12089 retval = build1 (VIEW_CONVERT_EXPR,
12090 TREE_TYPE (TREE_TYPE (node->decl)),
12091 retval);
12092 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12093 false, GSI_CONTINUE_LINKING);
12095 g = gimple_build_return (retval);
12096 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12098 /* Handle aligned clauses by replacing default defs of the aligned
12099 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12100 lhs. Handle linear by adding PHIs. */
12101 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12102 if (node->simdclone->args[i].alignment
12103 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12104 && (node->simdclone->args[i].alignment
12105 & (node->simdclone->args[i].alignment - 1)) == 0
12106 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12107 == POINTER_TYPE)
12109 unsigned int alignment = node->simdclone->args[i].alignment;
12110 tree orig_arg = node->simdclone->args[i].orig_arg;
12111 tree def = ssa_default_def (cfun, orig_arg);
12112 if (def && !has_zero_uses (def))
12114 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12115 gimple_seq seq = NULL;
12116 bool need_cvt = false;
12117 gimple call
12118 = gimple_build_call (fn, 2, def, size_int (alignment));
12119 g = call;
12120 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12121 ptr_type_node))
12122 need_cvt = true;
12123 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12124 gimple_call_set_lhs (g, t);
12125 gimple_seq_add_stmt_without_update (&seq, g);
12126 if (need_cvt)
12128 t = make_ssa_name (orig_arg, NULL);
12129 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12130 gimple_call_lhs (g),
12131 NULL_TREE);
12132 gimple_seq_add_stmt_without_update (&seq, g);
12134 gsi_insert_seq_on_edge_immediate
12135 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12137 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12138 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12139 entry_bb);
12140 node->create_edge (cgraph_node::get_create (fn),
12141 call, entry_bb->count, freq);
12143 imm_use_iterator iter;
12144 use_operand_p use_p;
12145 gimple use_stmt;
12146 tree repl = gimple_get_lhs (g);
12147 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12148 if (is_gimple_debug (use_stmt) || use_stmt == call)
12149 continue;
12150 else
12151 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12152 SET_USE (use_p, repl);
12155 else if (node->simdclone->args[i].arg_type
12156 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12158 tree orig_arg = node->simdclone->args[i].orig_arg;
12159 tree def = ssa_default_def (cfun, orig_arg);
12160 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12161 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12162 if (def && !has_zero_uses (def))
12164 iter1 = make_ssa_name (orig_arg, NULL);
12165 iter2 = make_ssa_name (orig_arg, NULL);
12166 phi = create_phi_node (iter1, body_bb);
12167 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12168 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12169 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12170 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12171 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12172 ? TREE_TYPE (orig_arg) : sizetype;
12173 tree addcst
12174 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12175 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12176 gsi = gsi_last_bb (incr_bb);
12177 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12179 imm_use_iterator iter;
12180 use_operand_p use_p;
12181 gimple use_stmt;
12182 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12183 if (use_stmt == phi)
12184 continue;
12185 else
12186 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12187 SET_USE (use_p, iter1);
12191 calculate_dominance_info (CDI_DOMINATORS);
12192 add_loop (loop, loop->header->loop_father);
12193 update_ssa (TODO_update_ssa);
12195 pop_cfun ();
12198 /* If the function in NODE is tagged as an elemental SIMD function,
12199 create the appropriate SIMD clones. */
12201 static void
12202 expand_simd_clones (struct cgraph_node *node)
12204 tree attr = lookup_attribute ("omp declare simd",
12205 DECL_ATTRIBUTES (node->decl));
12206 if (attr == NULL_TREE
12207 || node->global.inlined_to
12208 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12209 return;
12211 /* Ignore
12212 #pragma omp declare simd
12213 extern int foo ();
12214 in C, there we don't know the argument types at all. */
12215 if (!node->definition
12216 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12217 return;
12221 /* Start with parsing the "omp declare simd" attribute(s). */
12222 bool inbranch_clause_specified;
12223 struct cgraph_simd_clone *clone_info
12224 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12225 &inbranch_clause_specified);
12226 if (clone_info == NULL)
12227 continue;
12229 int orig_simdlen = clone_info->simdlen;
12230 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12231 /* The target can return 0 (no simd clones should be created),
12232 1 (just one ISA of simd clones should be created) or higher
12233 count of ISA variants. In that case, clone_info is initialized
12234 for the first ISA variant. */
12235 int count
12236 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12237 base_type, 0);
12238 if (count == 0)
12239 continue;
12241 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12242 also create one inbranch and one !inbranch clone of it. */
12243 for (int i = 0; i < count * 2; i++)
12245 struct cgraph_simd_clone *clone = clone_info;
12246 if (inbranch_clause_specified && (i & 1) != 0)
12247 continue;
12249 if (i != 0)
12251 clone = simd_clone_struct_alloc (clone_info->nargs
12252 + ((i & 1) != 0));
12253 simd_clone_struct_copy (clone, clone_info);
12254 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12255 and simd_clone_adjust_argument_types did to the first
12256 clone's info. */
12257 clone->nargs -= clone_info->inbranch;
12258 clone->simdlen = orig_simdlen;
12259 /* And call the target hook again to get the right ISA. */
12260 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12261 base_type,
12262 i / 2);
12263 if ((i & 1) != 0)
12264 clone->inbranch = 1;
12267 /* simd_clone_mangle might fail if such a clone has been created
12268 already. */
12269 tree id = simd_clone_mangle (node, clone);
12270 if (id == NULL_TREE)
12271 continue;
12273 /* Only when we are sure we want to create the clone actually
12274 clone the function (or definitions) or create another
12275 extern FUNCTION_DECL (for prototypes without definitions). */
12276 struct cgraph_node *n = simd_clone_create (node);
12277 if (n == NULL)
12278 continue;
12280 n->simdclone = clone;
12281 clone->origin = node;
12282 clone->next_clone = NULL;
12283 if (node->simd_clones == NULL)
12285 clone->prev_clone = n;
12286 node->simd_clones = n;
12288 else
12290 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12291 clone->prev_clone->simdclone->next_clone = n;
12292 node->simd_clones->simdclone->prev_clone = n;
12294 symtab->change_decl_assembler_name (n->decl, id);
12295 /* And finally adjust the return type, parameters and for
12296 definitions also function body. */
12297 if (node->definition)
12298 simd_clone_adjust (n);
12299 else
12301 simd_clone_adjust_return_type (n);
12302 simd_clone_adjust_argument_types (n);
12306 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12309 /* Entry point for IPA simd clone creation pass. */
12311 static unsigned int
12312 ipa_omp_simd_clone (void)
12314 struct cgraph_node *node;
12315 FOR_EACH_FUNCTION (node)
12316 expand_simd_clones (node);
12317 return 0;
12320 namespace {
12322 const pass_data pass_data_omp_simd_clone =
12324 SIMPLE_IPA_PASS, /* type */
12325 "simdclone", /* name */
12326 OPTGROUP_NONE, /* optinfo_flags */
12327 TV_NONE, /* tv_id */
12328 ( PROP_ssa | PROP_cfg ), /* properties_required */
12329 0, /* properties_provided */
12330 0, /* properties_destroyed */
12331 0, /* todo_flags_start */
12332 0, /* todo_flags_finish */
12335 class pass_omp_simd_clone : public simple_ipa_opt_pass
12337 public:
12338 pass_omp_simd_clone(gcc::context *ctxt)
12339 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12342 /* opt_pass methods: */
12343 virtual bool gate (function *);
12344 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12347 bool
12348 pass_omp_simd_clone::gate (function *)
12350 return ((flag_openmp || flag_openmp_simd
12351 || flag_cilkplus
12352 || (in_lto_p && !flag_wpa))
12353 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12356 } // anon namespace
12358 simple_ipa_opt_pass *
12359 make_pass_omp_simd_clone (gcc::context *ctxt)
12361 return new pass_omp_simd_clone (ctxt);
12364 #include "gt-omp-low.h"